1use std::error::Error as StdError;
2use std::fmt;
3use std::io;
4use std::sync::mpsc;
5
6#[derive(Debug, Clone, Copy, Default, PartialEq)]
8pub struct Vector3 {
9 pub x: f32,
10 pub y: f32,
11 pub z: f32,
12}
13
14#[derive(Debug, Clone, Copy, Default, PartialEq)]
15pub struct Quaternion {
16 pub w: f32,
17 pub x: f32,
18 pub y: f32,
19 pub z: f32,
20}
21
22impl Vector3 {
23 pub fn new(x: f32, y: f32, z: f32) -> Self {
24 Self { x, y, z }
25 }
26
27 pub fn euler_to_quaternion(&self) -> Quaternion {
28 let (roll, pitch, yaw) = (self.x, self.y, self.z);
31
32 let cr = (roll * 0.5).cos();
33 let sr = (roll * 0.5).sin();
34 let cp = (pitch * 0.5).cos();
35 let sp = (pitch * 0.5).sin();
36 let cy = (yaw * 0.5).cos();
37 let sy = (yaw * 0.5).sin();
38
39 let w = cr * cp * cy + sr * sp * sy;
40 let x = sr * cp * cy - cr * sp * sy;
41 let y = cr * sp * cy + sr * cp * sy;
42 let z = cr * cp * sy - sr * sp * cy;
43
44 Quaternion { w, x, y, z }
45 }
46}
47
48impl fmt::Display for Vector3 {
49 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
50 write!(f, "Vector3(x={}, y={}, z={})", self.x, self.y, self.z)
51 }
52}
53
54impl Quaternion {
55 pub fn rotate(&self, vector: Vector3) -> Vector3 {
56 let qw = self.w;
60 let qx = self.x;
61 let qy = self.y;
62 let qz = self.z;
63 let vx = vector.x;
64 let vy = vector.y;
65 let vz = vector.z;
66
67 let x = (1.0 - 2.0 * qy * qy - 2.0 * qz * qz) * vx
69 + (2.0 * qx * qy - 2.0 * qz * qw) * vy
70 + (2.0 * qx * qz + 2.0 * qy * qw) * vz;
71 let y = (2.0 * qx * qy + 2.0 * qz * qw) * vx
72 + (1.0 - 2.0 * qx * qx - 2.0 * qz * qz) * vy
73 + (2.0 * qy * qz - 2.0 * qx * qw) * vz;
74 let z = (2.0 * qx * qz - 2.0 * qy * qw) * vx
75 + (2.0 * qy * qz + 2.0 * qx * qw) * vy
76 + (1.0 - 2.0 * qx * qx - 2.0 * qy * qy) * vz;
77
78 Vector3 { x, y, z }
79 }
80}
81
82impl fmt::Display for Quaternion {
83 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84 write!(
85 f,
86 "Quaternion(w={}, x={}, y={}, z={})",
87 self.w, self.x, self.y, self.z
88 )
89 }
90}
91
92#[derive(Debug, Clone, Copy, Default)]
94pub struct ImuData {
95 pub accelerometer: Option<Vector3>,
97 pub gyroscope: Option<Vector3>,
99 pub magnetometer: Option<Vector3>,
101 pub quaternion: Option<Quaternion>,
103 pub euler: Option<Vector3>,
105 pub linear_acceleration: Option<Vector3>,
107 pub gravity: Option<Vector3>,
109 pub temperature: Option<f32>,
111 pub calibration_status: Option<u8>,
113}
114
115#[derive(Debug)]
117pub enum ImuError {
118 DeviceError(String),
120 ReadError(String),
122 WriteError(String),
124 ConfigurationError(String),
126 LockError(String),
128 CommandSendError(String),
130 NotSupported(String),
132 InvalidPacket(String),
134 Other(String),
136}
137
138impl fmt::Display for ImuError {
139 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
140 match self {
141 ImuError::DeviceError(s) => write!(f, "Device error: {}", s),
142 ImuError::ReadError(s) => write!(f, "Read error: {}", s),
143 ImuError::WriteError(s) => write!(f, "Write error: {}", s),
144 ImuError::ConfigurationError(s) => write!(f, "Configuration error: {}", s),
145 ImuError::LockError(s) => write!(f, "Lock error: {}", s),
146 ImuError::CommandSendError(s) => write!(f, "Command send error: {}", s),
147 ImuError::NotSupported(s) => write!(f, "Not supported: {}", s),
148 ImuError::InvalidPacket(s) => write!(f, "Invalid packet: {}", s),
149 ImuError::Other(s) => write!(f, "Other IMU error: {}", s),
150 }
151 }
152}
153
154impl StdError for ImuError {}
155
156impl From<io::Error> for ImuError {
158 fn from(err: io::Error) -> Self {
159 ImuError::DeviceError(err.to_string())
160 }
161}
162
163impl From<serialport::Error> for ImuError {
164 fn from(err: serialport::Error) -> Self {
165 ImuError::DeviceError(err.to_string())
166 }
167}
168
169impl<T> From<std::sync::PoisonError<T>> for ImuError {
170 fn from(err: std::sync::PoisonError<T>) -> Self {
171 ImuError::LockError(err.to_string())
172 }
173}
174
175impl<T> From<mpsc::SendError<T>> for ImuError {
176 fn from(err: mpsc::SendError<T>) -> Self {
177 ImuError::CommandSendError(err.to_string())
178 }
179}
180
181impl From<mpsc::RecvError> for ImuError {
182 fn from(err: mpsc::RecvError) -> Self {
183 ImuError::CommandSendError(err.to_string())
184 }
185}
186
187pub trait ImuReader {
188 fn get_data(&self) -> Result<ImuData, ImuError>;
190
191 fn stop(&self) -> Result<(), ImuError>;
192}
193
194#[derive(Debug, Clone, Copy)]
195pub enum ImuFrequency {
196 Hz0_2, Hz0_5, Hz1, Hz2, Hz5, Hz10, Hz20, Hz50, Hz100, Hz200, Single, None, }