TinyRobotics
Loading...
Searching...
No Matches
IMU3D.h
1#pragma once
2#include <math.h>
3#include <stdint.h>
4
5#include "TinyRobotics/communication/Message.h"
6#include "TinyRobotics/communication/MessageHandler.h"
7#include "TinyRobotics/communication/MessageSource.h"
8#include "TinyRobotics/control/MotionState2D.h"
9#include "TinyRobotics/control/MotionState3D.h"
10#include "TinyRobotics/coordinates/Coordinate.h"
11#include "TinyRobotics/coordinates/Orientation3D.h"
12#include "TinyRobotics/units/Speed.h"
13#include "TinyRobotics/units/Distance.h"
14#include "TinyRobotics/units/AngularVelocity.h"
15
16namespace tinyrobotics {
17
18/**
19 * @class IMU3D
20 * @ingroup imu
21 * @brief Basic 3D IMU dead-reckoning class.
22 *
23 * This class estimates 3D position, velocity, and orientation (yaw, pitch,
24 * roll) for robotics applications by integrating gyroscope and accelerometer
25 * data over time.
26 *
27 * - Integrates gyro (roll, pitch, yaw rates) to estimate orientation (radians)
28 * - Integrates accelerometer (X, Y, Z) in the robot frame, rotated to world
29 * frame, to estimate velocity and position
30 * - All units SI (meters, seconds, radians)
31 *
32 * Limitations:
33 * - No sensor fusion with magnetometer or GPS
34 * - No Kalman filter or bias estimation
35 * - Subject to drift over time (no correction)
36 *
37 * @tparam T Numeric type (float or double recommended)
38 */
39template <typename T = float>
40class IMU3D : public MessageSource, public IMotionState3D {
41 public:
42 IMU3D() = default;
43
44 bool begin(const Coordinate<T>& initialPosition = {0, 0, 0},
45 Orientation3D initialOrientation = Orientation3D()) {
46 position = initialPosition;
47 orientation.yaw = initialOrientation.yaw;
48 orientation.pitch = initialOrientation.pitch;
49 orientation.roll = initialOrientation.roll;
50 speed = Speed3D(0.0f, 0.0f, 0.0f, SpeedUnit::MPS);
51 lastUpdateMillis = 0;
52 is_active = true;
53 return true;
54 }
55
56 void end() { is_active = false; }
57
58 /// Update with accelerometer and gyro measurements
59 /// accelX, accelY, accelZ in sensor frame (m/s^2)
60 /// gyroX, gyroY, gyroZ in rad/s (roll, pitch, yaw rates)
61 void update(T accelX, T accelY, T accelZ, T gyroX, T gyroY, T gyroZ,
62 unsigned long nowMillis) {
63 if (!is_active) return;
64 if (lastUpdateMillis == 0) {
65 lastUpdateMillis = nowMillis;
66 return;
67 }
68 T dt = (nowMillis - lastUpdateMillis) / (T)1000;
69 lastUpdateMillis = nowMillis;
70 if (dt <= 0) return;
71
72 // Integrate gyro for orientation (Euler angles, simple integration)
73 orientation.roll += gyroX * dt;
74 orientation.pitch += gyroY * dt;
75 orientation.yaw += gyroZ * dt;
76 orientation.wrap();
77
78 // Rotate acceleration to world frame (using current orientation)
79 // Rotation order: roll (X), pitch (Y), yaw (Z)
80 T cr = cos(orientation.roll), sr = sin(orientation.roll);
81 T cp = cos(orientation.pitch), sp = sin(orientation.pitch);
82 T cy = cos(orientation.yaw), sy = sin(orientation.yaw);
83 // Rotation matrix (ZYX convention)
84 T ax_world = cy * cp * accelX + (cy * sp * sr - sy * cr) * accelY +
85 (cy * sp * cr + sy * sr) * accelZ;
86 T ay_world = sy * cp * accelX + (sy * sp * sr + cy * cr) * accelY +
87 (sy * sp * cr - cy * sr) * accelZ;
88 T az_world = -sp * accelX + cp * sr * accelY + cp * cr * accelZ;
89
90 // Integrate acceleration for velocity
91 speed = Speed3D(
92 speed.getX(SpeedUnit::MPS) + ax_world * dt,
93 speed.getY(SpeedUnit::MPS) + ay_world * dt,
94 speed.getZ(SpeedUnit::MPS) + az_world * dt,
95 SpeedUnit::MPS);
96
97 // Integrate velocity for position
98 float dx = speed.getX(SpeedUnit::MPS) * dt;
99 float dy = speed.getY(SpeedUnit::MPS) * dt;
100 float dz = speed.getZ(SpeedUnit::MPS) * dt;
101 position.x += dx;
102 position.y += dy;
103 position.z += dz;
104
105 lastDelta = Distance3D(dx, dy, dz, DistanceUnit::M);
106 lastAngularVelocity = AngularVelocity3D(static_cast<float>(gyroX), static_cast<float>(gyroY), static_cast<float>(gyroZ), AngularVelocityUnit::RadPerSec);
107 publish();
108 }
109
110 /// @brief Get the last delta update (dx, dy, dz)
111 Distance3D getLastDelta() const { return lastDelta; }
112 /// @brief Get the last angular velocity (rad/s)
114 return lastAngularVelocity;
115 }
116 /// @brief Get the current linear velocity (m/s)
117 Speed3D getLinearVelocity() const { return speed; }
118 /// @brief Get the current position (IMotionState3D)
119 Coordinate<DistanceM> getPosition() const override {
120 return Coordinate<DistanceM>(static_cast<float>(position.x), static_cast<float>(position.y), static_cast<float>(position.z));
121 }
122 /// @brief Get the current orientation (IMotionState3D)
123 Orientation3D getOrientation() const override {
124 return orientation;
125 }
126 Speed3D getSpeed() const override {
127 return speed;
128 }
129 AngularVelocity3D getAngularVelocity() const override {
130 return lastAngularVelocity;
131 }
132
133 protected:
134 bool is_active = false;
135 Orientation3D orientation;
136 Speed3D speed = Speed3D(0.0f, 0.0f, 0.0f, SpeedUnit::MPS);
137 Coordinate<T> position;
138 unsigned long lastUpdateMillis = 0;
139 Distance3D lastDelta = Distance3D(0.0f, 0.0f, 0.0f, DistanceUnit::M);
140 AngularVelocity3D lastAngularVelocity = AngularVelocity3D(0.0f, 0.0f, 0.0f, AngularVelocityUnit::RadPerSec);
141
142 void publish() {
143 // Publish position as message
144 Message<Coordinate<T>> msgPos{MessageContent::Position, position,
146 msgPos.origin = MessageOrigin::IMU;
147 sendMessage(msgPos);
148 // Publish orientation as float[3] (yaw, pitch, roll)
149 // (You may want to define a custom message type for 3D orientation)
150 // Publish velocity as message
151 // (You may want to define a custom message type for 3D velocity)
152 }
153};
154
155} // namespace tinyrobotics
Represents a 3D angular velocity vector with unit support.
Definition: AngularVelocity.h:134
A generic 3D coordinate class for robotics, navigation, and spatial calculations.
Definition: Coordinate.h:57
Represents a 3D distance or position vector with unit support.
Definition: Distance.h:164
Basic 3D IMU dead-reckoning class.
Definition: IMU3D.h:40
Distance3D getLastDelta() const
Get the last delta update (dx, dy, dz)
Definition: IMU3D.h:111
Speed3D getLinearVelocity() const
Get the current linear velocity (m/s)
Definition: IMU3D.h:117
void update(T accelX, T accelY, T accelZ, T gyroX, T gyroY, T gyroZ, unsigned long nowMillis)
Definition: IMU3D.h:61
Orientation3D getOrientation() const override
Get the current orientation (IMotionState3D)
Definition: IMU3D.h:123
AngularVelocity3D getLastAngularVelocity() const
Get the last angular velocity (rad/s)
Definition: IMU3D.h:113
Coordinate< DistanceM > getPosition() const override
Get the current position (IMotionState3D)
Definition: IMU3D.h:119
Interface for representing the motion state of a robot in 3D space.
Definition: MotionState3D.h:34
Base class for message sources in the TinyRobotics communication framework.
Definition: MessageSource.h:35
Simple 3D orientation class (yaw, pitch, roll in radians)
Definition: Orientation3D.h:13
float roll
Roll angle (radians)
Definition: Orientation3D.h:22
float pitch
Pitch angle (radians)
Definition: Orientation3D.h:21
float yaw
Yaw angle (radians)
Definition: Orientation3D.h:20
AngularVelocityUnit
Supported angular velocity units for conversion and representation.
Definition: AngularVelocity.h:11
DistanceUnit
Supported distance units for conversion and representation.
Definition: Distance.h:10
SpeedUnit
Supported speed units for conversion and representation.
Definition: Speed.h:10
Unit
Units for message values.
Definition: Common.h:45
@ Meters
Distance in meters.
Generic message structure for communication, parameterized by value type.
Definition: Message.h:72