imu_traits/
lib.rs

1use serialport;
2use std::error::Error as StdError;
3use std::fmt;
4use std::io;
5use std::sync::mpsc;
6
7// --- Basic Types ---
8#[derive(Debug, Clone, Copy, Default)]
9pub struct Vector3 {
10    pub x: f32,
11    pub y: f32,
12    pub z: f32,
13}
14
15impl fmt::Display for Vector3 {
16    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
17        write!(f, "Vector3(x={}, y={}, z={})", self.x, self.y, self.z)
18    }
19}
20
21#[derive(Debug, Clone, Copy, Default)]
22pub struct Quaternion {
23    pub w: f32,
24    pub x: f32,
25    pub y: f32,
26    pub z: f32,
27}
28
29impl fmt::Display for Quaternion {
30    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31        write!(
32            f,
33            "Quaternion(w={}, x={}, y={}, z={})",
34            self.w, self.x, self.y, self.z
35        )
36    }
37}
38
39// --- Standard IMU Data ---
40#[derive(Debug, Clone, Copy, Default)]
41pub struct ImuData {
42    /// Acceleration including gravity (m/s²)
43    pub accelerometer: Option<Vector3>,
44    /// Angular velocity (deg/s)
45    pub gyroscope: Option<Vector3>,
46    /// Magnetic field vector (micro Tesla, µT)
47    pub magnetometer: Option<Vector3>,
48    /// Orientation as a unit quaternion (WXYZ order)
49    pub quaternion: Option<Quaternion>,
50    /// Orientation as Euler angles (deg)
51    pub euler: Option<Vector3>,
52    /// Linear acceleration (acceleration without gravity) (m/s²)
53    pub linear_acceleration: Option<Vector3>,
54    /// Estimated gravity vector (m/s²)
55    pub gravity: Option<Vector3>,
56    /// Temperature (°C)
57    pub temperature: Option<f32>,
58    /// Calibration status
59    pub calibration_status: Option<u8>,
60}
61
62// --- Standard Error Type ---
63#[derive(Debug)]
64pub enum ImuError {
65    /// Error originating from the underlying device communication (I2C, Serial, CAN)
66    DeviceError(String),
67    /// Error reading data from the device or internal state
68    ReadError(String),
69    /// Error writing commands or configuration to the device
70    WriteError(String),
71    /// Error during device configuration or setup
72    ConfigurationError(String),
73    /// Error related to multithreading locks (e.g., poisoned)
74    LockError(String),
75    /// Error sending a command to the reader thread
76    CommandSendError(String),
77    /// Functionality not supported by this specific IMU implementation
78    NotSupported(String),
79    /// Invalid packet received from the device
80    InvalidPacket(String),
81    /// Catch-all for other errors
82    Other(String),
83}
84
85impl fmt::Display for ImuError {
86    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
87        match self {
88            ImuError::DeviceError(s) => write!(f, "Device error: {}", s),
89            ImuError::ReadError(s) => write!(f, "Read error: {}", s),
90            ImuError::WriteError(s) => write!(f, "Write error: {}", s),
91            ImuError::ConfigurationError(s) => write!(f, "Configuration error: {}", s),
92            ImuError::LockError(s) => write!(f, "Lock error: {}", s),
93            ImuError::CommandSendError(s) => write!(f, "Command send error: {}", s),
94            ImuError::NotSupported(s) => write!(f, "Not supported: {}", s),
95            ImuError::InvalidPacket(s) => write!(f, "Invalid packet: {}", s),
96            ImuError::Other(s) => write!(f, "Other IMU error: {}", s),
97        }
98    }
99}
100
101impl StdError for ImuError {}
102
103// Add From implementations for common error types
104impl From<io::Error> for ImuError {
105    fn from(err: io::Error) -> Self {
106        ImuError::DeviceError(err.to_string())
107    }
108}
109
110impl From<serialport::Error> for ImuError {
111    fn from(err: serialport::Error) -> Self {
112        ImuError::DeviceError(err.to_string())
113    }
114}
115
116impl<T> From<std::sync::PoisonError<T>> for ImuError {
117    fn from(err: std::sync::PoisonError<T>) -> Self {
118        ImuError::LockError(err.to_string())
119    }
120}
121
122impl<T> From<mpsc::SendError<T>> for ImuError {
123    fn from(err: mpsc::SendError<T>) -> Self {
124        ImuError::CommandSendError(err.to_string())
125    }
126}
127
128impl From<mpsc::RecvError> for ImuError {
129    fn from(err: mpsc::RecvError) -> Self {
130        ImuError::CommandSendError(err.to_string())
131    }
132}
133
134pub trait ImuReader {
135    /// Retrieves the latest available IMU data.
136    fn get_data(&self) -> Result<ImuData, ImuError>;
137
138    fn stop(&self) -> Result<(), ImuError>;
139}
140
141#[derive(Debug, Clone, Copy)]
142pub enum ImuFrequency {
143    Hz0_2,  // 0.2 Hz
144    Hz0_5,  // 0.5 Hz
145    Hz1,    // 1 Hz
146    Hz2,    // 2 Hz
147    Hz5,    // 5 Hz
148    Hz10,   // 10 Hz
149    Hz20,   // 20 Hz
150    Hz50,   // 50 Hz
151    Hz100,  // 100 Hz
152    Hz200,  // 200 Hz
153    Single, // Single reading
154    None,   // No readings
155}