1 /*
2  * Copyright (c) 2021 Kevin Townsend
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 /**
8  * @defgroup AHRS Attitude and Heading Reference System
9  *
10  * @brief Functions and structs for dealing with 'Attitude' and AHRS.
11  *
12  * Structs like @ref zsl_attitude are inteded to be used as 'last-mile'
13  * represetnations, to convert Euler angles (in radians) to something more
14  * human-friendly like degrees. Most calculations should make use of Euler
15  * angles, and the richer API around them, with conversion to degrees as the
16  * final step.
17  *
18  * @ingroup ORIENTATION
19  *  @{ */
20 
21 /**
22  * @file
23  * @brief API header file for attitude and AHRS in zscilib.
24  *
25  * This file contains the zscilib AHRS APIs.
26  */
27 
28 #ifndef ZEPHYR_INCLUDE_ZSL_AHRS_H_
29 #define ZEPHYR_INCLUDE_ZSL_AHRS_H_
30 
31 #include <zsl/zsl.h>
32 #include <zsl/vectors.h>
33 #include <zsl/orientation/euler.h>
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /**
40  * @brief Represents the orientation of a rigid body with respect to
41  *        the world frame in terms of roll, pitch and yaw (heading),
42  *        expressed in degrees.
43  *
44  * @note This is functionally identical to @ref zsl_euler, but attitude is
45  *       usually repesented in degrees, not radians. This struct has been
46  *       defined to differentiate between the two representations.
47  */
48 struct zsl_attitude {
49 	union {
50 		struct {
51 			/** @brief Longitudinal axis in degrees. A positive rolling motion
52 			 *         lifts the left wing and lowers the right wing of an
53 			 *         airplane. */
54 			zsl_real_t roll;
55 			/** @brief Transverse axis in degrees. A positive pitching motion
56 			*         raises the nose of the aircraft and lowers the tail. */
57 			zsl_real_t pitch;
58 			/** @brief Vertical axis in degrees. A positive yawing motion moves
59 			 *         the nose of the aircraft to the right. AKA heading. */
60 			zsl_real_t yaw;
61 		};
62 		/** @brief Array-based access. */
63 		zsl_real_t idx[3];
64 	};
65 	union {
66 		struct {
67 			/** @brief If non-zero, indicates that #roll is invalid. */
68 			uint8_t roll_invalid : 1;
69 			/** @brief If non-zero, indicates that #pitch is invalid. */
70 			uint8_t pitch_invalid : 1;
71 			/** @brief If non-zero, indicates that #yaw is invalid. */
72 			uint8_t yaw_invalid : 1;
73 		} status;
74 		/** @brief Invalid field indicators. */
75 		uint8_t status_bits;
76 	};
77 };
78 
79 /**
80  * @brief Takes the values in the supplied @ref zsl_attitude, and assigns the
81  *        same memory address to a @ref zsl_vec, allowing for vector functions
82  *        to be used on the zsl_attitude values.
83  *
84  * @param a     Pointer to the zsl_attitude struct to use.
85  * @param v     Pointer to the zsl_vec struct to use.
86  *
87  * @return 0 if everything executed correctly, otherwise a negative error code.
88  */
89 int zsl_att_to_vec(struct zsl_attitude *a, struct zsl_vec *v);
90 
91 /**
92  * @brief Converts the input @ref zsl_attitude, expessed in degrees, to it's
93  *        equivalent in radians in the output @ref zsl_euler.
94  *
95  * @param a     Pointer to the zsl_attitued struct to use.
96  * @param e     Pointer to the zsl_euler struct to use.
97  *
98  * @return 0 if everything executed correctly, otherwise a negative error code.
99  */
100 int zsl_att_to_euler(struct zsl_attitude *a, struct zsl_euler *e);
101 
102 /**
103  * @brief Converts the input @ref zsl_euler, expessed in radians, to it's
104  *        equivalent in degrees in the output @ref zsl_attitude.
105  *
106  * @param e     Pointer to the zsl_euler struct to use.
107  * @param a     Pointer to the zsl_attitued struct to use.
108  *
109  * @return 0 if everything executed correctly, otherwise a negative error code.
110  */
111 int zsl_att_from_euler(struct zsl_euler *e, struct zsl_attitude *a);
112 
113 /**
114  * @brief Converts a three-axis accelerometer (in m/s^2) and a three-axis
115  *        magnetometer sample (in micro-Tesla) to attitude.
116  *
117  * @param accel     Acceleration triplet in m/s^2.
118  * @param mag       Magnetometer triplet in micro-Tesla.
119  * @param a         Pointer the the output @ref zsl_attitude struct.
120  *
121  * @return 0 if everything executed correctly, otherwise a negative error code.
122  */
123 int zsl_att_from_accelmag(struct zsl_vec *accel, struct zsl_vec *mag,
124 			  struct zsl_attitude *a);
125 
126 /**
127  * @brief Converts a three-axis accelerometer sample (in m/s^2) to roll and
128  *        pitch.
129  *
130  * @param accel     Acceleration triplet in m/s^2.
131  * @param a         Pointer the the output @ref zsl_attitude struct.
132  *
133  * @return 0 if everything executed correctly, otherwise a negative error code.
134  */
135 int zsl_att_from_accel(struct zsl_vec *accel, struct zsl_attitude *a);
136 
137 /**
138  * @brief Calculates the angle between two accelerometers.
139  *
140  * @param a1    First acceleration triplet in m/s^2.
141  * @param a2    First acceleration triplet in m/s^2.
142  * @param b     Angle between the accelerometers, in radians.
143  *
144  * @return 0 if everything executed correctly, otherwise a negative error code
145  *         if the accelerometer data is not tridimensional.
146  */
147 int zsl_att_accel_angle(struct zsl_vec *a1, struct zsl_vec *a2, zsl_real_t *b);
148 
149 #ifdef __cplusplus
150 }
151 #endif
152 
153 #endif /* ZEPHYR_INCLUDE_ZSL_AHRS_H_ */
154 
155 /** @} */ /* End of ahrs group */
156