libstp
Robotics library for Botball
Loading...
Searching...
No Matches
IIMU.hpp
Go to the documentation of this file.
1//
2// IIMU interface for dependency injection and testing
3//
4#pragma once
5
6#include <algorithm>
7#include <cctype>
8#include <stdexcept>
9#include <string>
10
11namespace libstp::hal::imu
12{
13 enum class TurnAxisMode
14 {
19 };
20
21 inline const char* toString(const TurnAxisMode mode)
22 {
23 switch (mode)
24 {
25 case TurnAxisMode::WorldZ: return "world_z";
26 case TurnAxisMode::BodyX: return "body_x";
27 case TurnAxisMode::BodyY: return "body_y";
28 case TurnAxisMode::BodyZ: return "body_z";
29 }
30 return "world_z";
31 }
32
33 inline std::string normalizeTurnAxisMode(std::string mode)
34 {
35 std::transform(mode.begin(), mode.end(), mode.begin(), [](unsigned char c) {
36 if (c == '-' || c == ' ') return static_cast<char>('_');
37 return static_cast<char>(std::tolower(c));
38 });
39 return mode;
40 }
41
43 {
45 float sign{1.0f}; // +1 or -1
46 };
47
48 inline TurnAxisConfig parseTurnAxisConfig(const std::string& mode)
49 {
50 // Check for leading '-' to negate the axis
51 float sign = 1.0f;
52 std::string rest = mode;
53 if (!rest.empty() && rest[0] == '-') {
54 sign = -1.0f;
55 rest = rest.substr(1);
56 }
57
58 const std::string normalized = normalizeTurnAxisMode(rest);
59
60 if (normalized.empty() || normalized == "world_z" || normalized == "yaw" || normalized == "heading")
61 return {TurnAxisMode::WorldZ, sign};
62 if (normalized == "body_x" || normalized == "x")
63 return {TurnAxisMode::BodyX, sign};
64 if (normalized == "body_y" || normalized == "y")
65 return {TurnAxisMode::BodyY, sign};
66 if (normalized == "body_z" || normalized == "z")
67 return {TurnAxisMode::BodyZ, sign};
68
69 throw std::invalid_argument(
70 "Invalid turn axis mode '" + mode +
71 "'. Expected one of: [-]world_z, [-]body_x, [-]body_y, [-]body_z");
72 }
73
74 inline TurnAxisMode parseTurnAxisMode(const std::string& mode)
75 {
76 return parseTurnAxisConfig(mode).mode;
77 }
78
79 inline TurnAxisMode parseBodyAxisMode(const std::string& mode)
80 {
81 const TurnAxisMode parsed = parseTurnAxisMode(mode);
82 if (parsed == TurnAxisMode::WorldZ)
83 {
84 throw std::invalid_argument(
85 "Invalid body axis '" + mode + "'. Expected one of: body_x, body_y, body_z");
86 }
87 return parsed;
88 }
89
96 struct IIMU
97 {
98 virtual ~IIMU() = default;
99
101 virtual void read(float* accel, float* gyro, float* magneto) = 0;
103 virtual void calibrate() = 0;
104
109 [[nodiscard]] virtual float getHeading() = 0;
110
115 virtual void getAngularVelocity(float* gyro)
116 {
117 float accel[3], g[3], magneto[3];
118 read(accel, g, magneto);
119 gyro[0] = g[0]; gyro[1] = g[1]; gyro[2] = g[2];
120 }
121
124 {
125 yaw_rate_axis_mode_ = mode;
126 yaw_rate_sign_ = 1.0f;
127 }
128
130 void setYawRateAxisMode(const std::string& mode)
131 {
132 const auto cfg = parseTurnAxisConfig(mode);
133 yaw_rate_axis_mode_ = cfg.mode;
134 yaw_rate_sign_ = cfg.sign;
135 }
136
137 [[nodiscard]] TurnAxisMode getYawRateAxisMode() const
138 {
139 return yaw_rate_axis_mode_;
140 }
141
142 [[nodiscard]] std::string getYawRateAxisModeName() const
143 {
144 return toString(yaw_rate_axis_mode_);
145 }
146
155 {
156 float g[3];
158
159 float rate = 0.0f;
160 switch (yaw_rate_axis_mode_)
161 {
163 rate = g[0]; break;
165 rate = g[1]; break;
167 rate = g[2]; break;
169 default:
170 rate = g[2]; break;
171 }
172 return yaw_rate_sign_ * rate;
173 }
174
179 virtual void getLinearAcceleration(float* linear_accel) = 0;
180
192 virtual void getQuaternion(float* quat) = 0;
193
198 virtual void getIntegratedVelocity(float* vel) { vel[0] = vel[1] = vel[2] = 0; }
199
203 virtual void resetIntegratedVelocity() {}
204
206 virtual bool waitForReady(int timeout_ms = 1000) = 0;
207
208 private:
209 TurnAxisMode yaw_rate_axis_mode_{TurnAxisMode::WorldZ};
210 float yaw_rate_sign_{1.0f};
211 };
212}
const char * toString(const TurnAxisMode mode)
Definition IIMU.hpp:21
TurnAxisConfig parseTurnAxisConfig(const std::string &mode)
Definition IIMU.hpp:48
std::string normalizeTurnAxisMode(std::string mode)
Definition IIMU.hpp:33
TurnAxisMode parseTurnAxisMode(const std::string &mode)
Definition IIMU.hpp:74
TurnAxisMode parseBodyAxisMode(const std::string &mode)
Definition IIMU.hpp:79
Interface for IMU abstraction.
Definition IIMU.hpp:97
virtual void getAngularVelocity(float *gyro)
Definition IIMU.hpp:115
virtual void getIntegratedVelocity(float *vel)
Definition IIMU.hpp:198
void setYawRateAxisMode(const std::string &mode)
Configure which axis getYawRate() reports, using a string alias.
Definition IIMU.hpp:130
virtual ~IIMU()=default
virtual void calibrate()=0
Run platform-specific IMU calibration if implemented.
void setYawRateAxisMode(const TurnAxisMode mode)
Configure which axis getYawRate() reports, using the enum form.
Definition IIMU.hpp:123
std::string getYawRateAxisModeName() const
Definition IIMU.hpp:142
virtual void resetIntegratedVelocity()
Definition IIMU.hpp:203
virtual void getLinearAcceleration(float *linear_accel)=0
virtual void getQuaternion(float *quat)=0
virtual float getHeading()=0
TurnAxisMode getYawRateAxisMode() const
Definition IIMU.hpp:137
virtual void read(float *accel, float *gyro, float *magneto)=0
Read accel, gyro, and magnetometer vectors into caller-owned buffers.
virtual bool waitForReady(int timeout_ms=1000)=0
Wait until the implementation has enough data to provide orientation.