Skip to main content

mecha10_controllers/
lib.rs

1//! Hardware Controller Abstractions for Mecha10
2//!
3//! This crate provides a composable layer between hardware drivers and nodes.
4//! Controllers wrap device SDKs/libraries and provide standardized interfaces
5//! for nodes to manage hardware.
6//!
7//! # Architecture
8//!
9//! ```text
10//! ┌─────────────────┐
11//! │     Node        │  (Business logic)
12//! └────────┬────────┘
13//!          │
14//!          ▼
15//! ┌─────────────────┐
16//! │   Controller    │  (Device management + SDK abstraction)
17//! └────────┬────────┘
18//!          │
19//!          ▼
20//!   ┌──────────────┐
21//!   │ Hardware SDK │  (realsense-rust, bno055, etc.)
22//!   └──────────────┘
23//! ```
24//!
25//! # Core Concepts
26//!
27//! - **Controller**: Base trait for all hardware controllers
28//! - **Domain-specific traits**: CameraController, ImuController, etc.
29//! - **Health monitoring**: Built-in health checks and diagnostics
30//! - **Capability discovery**: Query what a controller can do
31//! - **Testing support**: Mock implementations for easy testing
32//!
33//! # Example
34//!
35//! ```rust,no_run
36//! use mecha10_controllers::{Controller, CameraController};
37//! use mecha10_controllers::camera::RealSenseController;
38//!
39//! #[tokio::main]
40//! async fn main() -> anyhow::Result<()> {
41//!     // Initialize controller
42//!     let config = RealSenseConfig::default();
43//!     let mut camera = RealSenseController::init(config).await?;
44//!
45//!     // Start acquisition
46//!     camera.start().await?;
47//!
48//!     // Use controller
49//!     let frame = camera.capture_frame().await?;
50//!     println!("Captured frame: {}x{}", frame.width, frame.height);
51//!
52//!     // Clean shutdown
53//!     camera.stop().await?;
54//!     Ok(())
55//! }
56//! ```
57
58use async_trait::async_trait;
59use serde::{Deserialize, Serialize};
60use std::collections::HashMap;
61use std::fmt;
62
63pub mod camera;
64pub mod imu;
65pub mod l298n;
66pub mod lidar;
67pub mod mock;
68pub mod motor;
69
70#[cfg(feature = "mpu6050")]
71pub mod mpu6050;
72
73// Re-export traits
74pub use camera::CameraController;
75pub use imu::ImuController;
76pub use lidar::LidarController;
77pub use motor::MotorController;
78
79// Re-export L298N controller
80pub use l298n::{L298nControllerConfig, L298nMotorController, L298nMotorPins};
81
82// ============================================================================
83// Core Controller Trait
84// ============================================================================
85
86/// Base trait for all hardware controllers
87///
88/// Controllers manage the lifecycle and interaction with physical hardware
89/// or simulated devices. They abstract device SDKs and provide consistent
90/// interfaces for nodes to use.
91#[async_trait]
92pub trait Controller: Send + Sync {
93    /// Configuration type for this controller
94    type Config: Send + Sync;
95
96    /// Error type for this controller
97    type Error: std::error::Error + Send + Sync + 'static;
98
99    /// Initialize the controller with the given configuration
100    ///
101    /// This should perform all necessary setup including:
102    /// - Opening device connections
103    /// - Configuring device parameters
104    /// - Running initialization sequences
105    /// - Loading calibration data
106    async fn init(config: Self::Config) -> Result<Self, Self::Error>
107    where
108        Self: Sized;
109
110    /// Start the controller
111    ///
112    /// Begin data acquisition, motor control, or other active operations.
113    /// This may start background threads or async tasks.
114    async fn start(&mut self) -> Result<(), Self::Error>;
115
116    /// Stop the controller
117    ///
118    /// Stop all active operations gracefully. The controller should still
119    /// be in a valid state and can be restarted with `start()`.
120    async fn stop(&mut self) -> Result<(), Self::Error>;
121
122    /// Check the health status of the controller
123    async fn health_check(&self) -> ControllerHealth;
124
125    /// Get the capabilities of this controller
126    ///
127    /// Returns metadata about what features and operations this controller
128    /// supports. This is useful for runtime capability detection.
129    fn capabilities(&self) -> ControllerCapabilities;
130
131    /// Get controller-specific diagnostics
132    ///
133    /// Returns detailed diagnostic information for debugging and monitoring.
134    async fn diagnostics(&self) -> HashMap<String, String> {
135        HashMap::new()
136    }
137}
138
139// ============================================================================
140// Health and Capabilities
141// ============================================================================
142
143/// Health status of a controller
144#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
145pub enum ControllerHealth {
146    /// Controller is healthy and ready
147    Healthy,
148
149    /// Controller is running but degraded (e.g., some sensors failing)
150    Degraded { reason: String },
151
152    /// Controller is unhealthy and not functioning
153    Unhealthy { reason: String },
154
155    /// Controller health is unknown (e.g., not initialized)
156    Unknown,
157}
158
159impl fmt::Display for ControllerHealth {
160    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
161        match self {
162            Self::Healthy => write!(f, "Healthy"),
163            Self::Degraded { reason } => write!(f, "Degraded: {}", reason),
164            Self::Unhealthy { reason } => write!(f, "Unhealthy: {}", reason),
165            Self::Unknown => write!(f, "Unknown"),
166        }
167    }
168}
169
170/// Capabilities of a controller
171///
172/// Describes what features and operations a controller supports.
173/// This allows runtime capability detection and adaptation.
174#[derive(Debug, Clone, Serialize, Deserialize)]
175pub struct ControllerCapabilities {
176    /// Controller type identifier (e.g., "camera", "imu", "lidar")
177    pub controller_type: String,
178
179    /// Specific implementation (e.g., "realsense", "bno055", "rplidar")
180    pub implementation: String,
181
182    /// Hardware vendor (e.g., "Intel", "Bosch", "Slamtec")
183    pub vendor: Option<String>,
184
185    /// Hardware model (e.g., "D435i", "BNO055", "A2M8")
186    pub model: Option<String>,
187
188    /// Firmware version if available
189    pub firmware_version: Option<String>,
190
191    /// Feature flags indicating what operations are supported
192    pub features: HashMap<String, bool>,
193
194    /// Additional metadata
195    pub metadata: HashMap<String, String>,
196}
197
198impl ControllerCapabilities {
199    /// Create a new capabilities struct
200    pub fn new(controller_type: impl Into<String>, implementation: impl Into<String>) -> Self {
201        Self {
202            controller_type: controller_type.into(),
203            implementation: implementation.into(),
204            vendor: None,
205            model: None,
206            firmware_version: None,
207            features: HashMap::new(),
208            metadata: HashMap::new(),
209        }
210    }
211
212    /// Add a feature flag
213    pub fn with_feature(mut self, name: impl Into<String>, supported: bool) -> Self {
214        self.features.insert(name.into(), supported);
215        self
216    }
217
218    /// Add metadata
219    pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
220        self.metadata.insert(key.into(), value.into());
221        self
222    }
223
224    /// Set vendor
225    pub fn with_vendor(mut self, vendor: impl Into<String>) -> Self {
226        self.vendor = Some(vendor.into());
227        self
228    }
229
230    /// Set model
231    pub fn with_model(mut self, model: impl Into<String>) -> Self {
232        self.model = Some(model.into());
233        self
234    }
235
236    /// Check if a feature is supported
237    pub fn supports(&self, feature: &str) -> bool {
238        self.features.get(feature).copied().unwrap_or(false)
239    }
240}
241
242// ============================================================================
243// Common Errors
244// ============================================================================
245
246/// Common controller errors
247#[derive(Debug, thiserror::Error)]
248pub enum ControllerError {
249    /// Device not found or not connected
250    #[error("Device not found: {0}")]
251    DeviceNotFound(String),
252
253    /// Device initialization failed
254    #[error("Initialization failed: {0}")]
255    InitializationFailed(String),
256
257    /// Device communication error
258    #[error("Communication error: {0}")]
259    CommunicationError(String),
260
261    /// Invalid configuration
262    #[error("Invalid configuration: {0}")]
263    InvalidConfiguration(String),
264
265    /// Operation timeout
266    #[error("Operation timed out: {0}")]
267    Timeout(String),
268
269    /// Device is not in the correct state for this operation
270    #[error("Invalid state: {0}")]
271    InvalidState(String),
272
273    /// Hardware fault detected
274    #[error("Hardware fault: {0}")]
275    HardwareFault(String),
276
277    /// Feature not supported by this controller
278    #[error("Feature not supported: {0}")]
279    NotSupported(String),
280
281    /// Generic error
282    #[error("Controller error: {0}")]
283    Other(String),
284}
285
286// ============================================================================
287// Controller State
288// ============================================================================
289
290/// Common controller states
291#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
292pub enum ControllerState {
293    /// Not initialized
294    Uninitialized,
295
296    /// Initialized but not started
297    Initialized,
298
299    /// Running normally
300    Running,
301
302    /// Stopped
303    Stopped,
304
305    /// Error state
306    Error,
307}
308
309impl fmt::Display for ControllerState {
310    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
311        match self {
312            Self::Uninitialized => write!(f, "Uninitialized"),
313            Self::Initialized => write!(f, "Initialized"),
314            Self::Running => write!(f, "Running"),
315            Self::Stopped => write!(f, "Stopped"),
316            Self::Error => write!(f, "Error"),
317        }
318    }
319}