M5Unit-IMU 0.0.2 git rev:e5b00aa
Loading...
Searching...
No Matches
ahrs_imu.hpp
Go to the documentation of this file.
1/*
2 * SPDX-FileCopyrightText: 2026 M5Stack Technology CO LTD
3 *
4 * SPDX-License-Identifier: MIT
5 */
18#ifndef M5_UNIT_IMU_IMU_AHRS_IMU_HPP
19#define M5_UNIT_IMU_IMU_AHRS_IMU_HPP
20
21#include <cstdint>
22
23#include "ahrs_controller.hpp"
24
25namespace m5 {
26namespace imu {
27
38class AhrsImu : public AhrsController {
39public:
44 struct imu_3d_t {
45 union {
46 float value[3];
47 struct {
48 float x;
49 float y;
50 float z;
51 };
52 };
53 };
54
59 struct imu_data_t {
60 uint32_t usec;
61 union {
62 float value[9];
63 imu_3d_t sensor[3];
64 struct {
65 imu_3d_t accel;
66 imu_3d_t gyro;
67 imu_3d_t mag;
68 };
69 };
70 };
71
85
93 inline bool getAccel(float* const ax, float* const ay, float* const az) const
94 {
95 const imu_physical_data_t& s = latest();
96 if (ax != nullptr) {
97 *ax = s.accel[0];
98 }
99 if (ay != nullptr) {
100 *ay = s.accel[1];
101 }
102 if (az != nullptr) {
103 *az = s.accel[2];
104 }
105 return hasAccel();
106 }
107
115 inline bool getGyro(float* const gx, float* const gy, float* const gz) const
116 {
117 const imu_physical_data_t& s = latest();
118 if (gx != nullptr) {
119 *gx = s.gyro[0];
120 }
121 if (gy != nullptr) {
122 *gy = s.gyro[1];
123 }
124 if (gz != nullptr) {
125 *gz = s.gyro[2];
126 }
127 return hasGyro();
128 }
129
137 inline bool getMag(float* const mx, float* const my, float* const mz) const
138 {
139 const imu_physical_data_t& s = latest();
140 if (mx != nullptr) {
141 *mx = s.mag[0];
142 }
143 if (my != nullptr) {
144 *my = s.mag[1];
145 }
146 if (mz != nullptr) {
147 *mz = s.mag[2];
148 }
149 return hasValidMag();
150 }
151
157 inline bool getTemp(float* const t) const
158 {
159 if (t != nullptr) {
160 *t = latest().temp;
161 }
162 return hasTemp();
163 }
164
171 inline void getImuData(imu_data_t* const data) const
172 {
173 if (data == nullptr) {
174 return;
175 }
176 const imu_physical_data_t& s = latest();
177 data->usec = static_cast<uint32_t>(lastMicros());
178 data->accel.x = s.accel[0];
179 data->accel.y = s.accel[1];
180 data->accel.z = s.accel[2];
181 data->gyro.x = s.gyro[0];
182 data->gyro.y = s.gyro[1];
183 data->gyro.z = s.gyro[2];
184 data->mag.x = s.mag[0];
185 data->mag.y = s.mag[1];
186 data->mag.z = s.mag[2];
187 }
188
193 inline const imu_data_t& getImuData()
194 {
195 getImuData(&_compat_data);
196 return _compat_data;
197 }
198
208 inline void getAhrsData(float* const pitch, float* const roll, float* const yaw) const
209 {
210 float roll_deg{}, pitch_deg{}, yaw_deg{};
211 euler(roll_deg, pitch_deg, yaw_deg);
212 if (pitch != nullptr) {
213 *pitch = pitch_deg;
214 }
215 if (roll != nullptr) {
216 *roll = roll_deg;
217 }
218 if (yaw != nullptr) {
219 *yaw = yaw_deg;
220 }
221 }
222
224 inline bool getAccelData(float* const ax, float* const ay, float* const az) const
225 {
226 return getAccel(ax, ay, az);
227 }
228
230 inline bool getGyroData(float* const gx, float* const gy, float* const gz) const
231 {
232 return getGyro(gx, gy, gz);
233 }
234
236 inline bool getGyroMag(float* const mx, float* const my, float* const mz) const
237 {
238 return getMag(mx, my, mz);
239 }
240
245 inline bool isEnabled() const
246 {
247 return hasAccel() && hasGyro();
248 }
249
257 inline void setCalibration(const uint8_t accel_strength, const uint8_t gyro_strength, const uint8_t mag_strength)
258 {
259 writeAutoCalibration(accel_strength, gyro_strength, mag_strength);
260 }
261
268 inline void clearOffsetData()
269 {
271 }
272
283 inline bool setAxisOrder(const axis_t axis0, const axis_t axis1, const axis_t axis2)
284 {
285 const uint8_t idx[3] = {
286 static_cast<uint8_t>(axis0 >> 1),
287 static_cast<uint8_t>(axis1 >> 1),
288 static_cast<uint8_t>(axis2 >> 1),
289 };
290 if (idx[0] > 2 || idx[1] > 2 || idx[2] > 2 || idx[0] == idx[1] || idx[1] == idx[2] || idx[0] == idx[2]) {
291 return false;
292 }
293 AxisOrder order;
295 order.invert_x = (axis0 & 1) != 0;
296 order.invert_y = (axis1 & 1) != 0;
297 order.invert_z = (axis2 & 1) != 0;
298 writeUserAxisOrder(order);
299 return true;
300 }
301
309 inline bool setAxisOrderRightHanded(const axis_t axis0, const axis_t axis1)
310 {
311 return setAxisOrder(axis0, axis1, getAxis2(axis0, axis1));
312 }
313
322 inline bool setAxisOrderLeftHanded(const axis_t axis0, const axis_t axis1)
323 {
324 return setAxisOrder(axis0, axis1, static_cast<axis_t>(getAxis2(axis0, axis1) ^ 1));
325 }
326
327private:
328 // Right-handed third axis for a given first two (ported from m5::IMU_Class getAxis2)
329 static inline axis_t getAxis2(const axis_t axis0, const axis_t axis1)
330 {
331 uint8_t axis2 = static_cast<uint8_t>(((1 << (axis0 >> 1)) | (1 << (axis1 >> 1))) ^ 0x07);
332 axis2 = static_cast<uint8_t>(axis2 & 0x06);
333 const uint8_t ax0 = axis2 ? static_cast<uint8_t>(axis2 - 2) : 4;
334 axis2 = static_cast<uint8_t>(axis2 + (((axis0 & 0x06) == ax0) == ((axis0 & 1) == (axis1 & 1))));
335 return static_cast<axis_t>(axis2);
336 }
337
338 imu_data_t _compat_data{}; // Scratch for the reference-returning getImuData() overload
339};
340
341} // namespace imu
342} // namespace m5
343#endif
Layer-2 AHRS controller: merges IMUDataSource capabilities and drives an AhrsFilterBase.
AxisPermutation permutation_from_indices(const uint8_t(&p)[3])
Map a source-axis index triplet back to an AxisPermutation.
Definition axis_order.hpp:123
Merges up to 4 IMUDataSource instances by capability and fuses their samples into an attitude estimat...
Definition ahrs_controller.hpp:58
bool hasAccel() const
Whether an accelerometer source has been registered (see add())
Definition ahrs_controller.hpp:367
unsigned long lastMicros() const
Microsecond timestamp of the most recent self-clocked update()
Definition ahrs_controller.hpp:401
void writeAutoCalibration(const uint8_t accel, const uint8_t gyro, const uint8_t mag)
Enable/disable continuous background auto-calibration per capability.
Definition ahrs_controller.cpp:271
const imu_physical_data_t & latest() const
Most recently fused physical-unit sample.
Definition ahrs_controller.hpp:361
bool hasGyro() const
Whether a gyroscope source has been registered (see add())
Definition ahrs_controller.hpp:373
bool writeCalibration(const calibration_data_t &data)
Overwrite every capability's auto-calibration offset from a snapshot.
Definition ahrs_controller.cpp:363
void euler(float &roll_deg, float &pitch_deg, float &yaw_deg) const
Current fused attitude as aerospace ZYX Euler angles.
Definition ahrs_controller.cpp:446
bool hasTemp() const
Whether a temperature source has been registered (see add())
Definition ahrs_controller.hpp:379
void writeUserAxisOrder(const AxisOrder &order)
Set a global user axis remap composed on top of every source's fixed order.
Definition ahrs_controller.cpp:223
bool hasValidMag() const
Whether at least one valid magnetometer sample has been seen.
Definition ahrs_controller.hpp:390
AhrsController plus an M5Unified IMU_Class-compatible API.
Definition ahrs_imu.hpp:38
const imu_data_t & getImuData()
Latest accel/gyro/mag sample, by const reference.
Definition ahrs_imu.hpp:193
bool isEnabled() const
Whether accelerometer and gyroscope sources are both registered.
Definition ahrs_imu.hpp:245
void clearOffsetData()
Zero every capability's auto-calibration offset.
Definition ahrs_imu.hpp:268
void setCalibration(const uint8_t accel_strength, const uint8_t gyro_strength, const uint8_t mag_strength)
Set per-capability auto-calibration strength (0 = off, 1-255 = adjustment speed)
Definition ahrs_imu.hpp:257
bool getTemp(float *const t) const
Latest temperature reading (degC)
Definition ahrs_imu.hpp:157
void getImuData(imu_data_t *const data) const
Copy the latest accel/gyro/mag sample into an imu_data_t.
Definition ahrs_imu.hpp:171
bool getGyro(float *const gx, float *const gy, float *const gz) const
Latest gyroscope reading (dps)
Definition ahrs_imu.hpp:115
bool getAccel(float *const ax, float *const ay, float *const az) const
Latest accelerometer reading (G)
Definition ahrs_imu.hpp:93
bool setAxisOrder(const axis_t axis0, const axis_t axis1, const axis_t axis2)
Assign which signed source axis feeds each output slot.
Definition ahrs_imu.hpp:283
void getAhrsData(float *const pitch, float *const roll, float *const yaw) const
Current fused attitude as aerospace Euler angles (degrees)
Definition ahrs_imu.hpp:208
bool getMag(float *const mx, float *const my, float *const mz) const
Latest magnetometer reading (uT)
Definition ahrs_imu.hpp:137
bool setAxisOrderRightHanded(const axis_t axis0, const axis_t axis1)
Assign the first two output axes; derive the third as a right-handed frame.
Definition ahrs_imu.hpp:309
bool getAccelData(float *const ax, float *const ay, float *const az) const
Alias for getAccel()
Definition ahrs_imu.hpp:224
bool setAxisOrderLeftHanded(const axis_t axis0, const axis_t axis1)
Assign the first two output axes; derive the third as a left-handed frame.
Definition ahrs_imu.hpp:322
bool getGyroData(float *const gx, float *const gy, float *const gz) const
Alias for getGyro()
Definition ahrs_imu.hpp:230
bool getGyroMag(float *const mx, float *const my, float *const mz) const
Alias for getMag() (name mirrors m5::IMU_Class::getGyroMag)
Definition ahrs_imu.hpp:236
axis_t
A source axis with a sign, layout-compatible with m5::IMU_Class::axis_t.
Definition ahrs_imu.hpp:77
@ axis_z_neg
-Z
Definition ahrs_imu.hpp:83
@ axis_z_pos
+Z
Definition ahrs_imu.hpp:82
@ axis_x_neg
-X
Definition ahrs_imu.hpp:79
@ axis_x_pos
+X
Definition ahrs_imu.hpp:78
@ axis_y_neg
-Y
Definition ahrs_imu.hpp:81
@ axis_y_pos
+Y
Definition ahrs_imu.hpp:80
Top level namespace of M5Stack.
Definition ahrs_controller.cpp:26
Exportable/importable snapshot of every capability's auto-calibration offset.
Definition ahrs_controller.hpp:66
3-axis float vector, layout-compatible with m5::IMU_Class::imu_3d_t
Definition ahrs_imu.hpp:44
Merged accel/gyro/mag sample, layout-compatible with m5::IMU_Class::imu_data_t.
Definition ahrs_imu.hpp:59
uint32_t usec
Timestamp of the sample's update() call (microseconds)
Definition ahrs_imu.hpp:60
Chip-frame-to-body-frame axis remap: a permutation plus a per-output-axis sign flip.
Definition axis_order.hpp:43
bool invert_y
Negate output Y after permutation.
Definition axis_order.hpp:46
AxisPermutation permutation
Axis permutation.
Definition axis_order.hpp:44
bool invert_z
Negate output Z after permutation.
Definition axis_order.hpp:47
bool invert_x
Negate output X after permutation.
Definition axis_order.hpp:45
Merged, converted physical-unit IMU sample (AhrsController::latest())
Definition imu_types.hpp:81
float gyro[3]
Gyroscope X/Y/Z (dps)
Definition imu_types.hpp:83
float accel[3]
Accelerometer X/Y/Z (G)
Definition imu_types.hpp:82
float temp
Temperature (degC)
Definition imu_types.hpp:85
float mag[3]
Magnetometer X/Y/Z (uT)
Definition imu_types.hpp:84