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// Re-export traits
71pub use camera::CameraController;
72pub use imu::ImuController;
73pub use lidar::LidarController;
74pub use motor::MotorController;
75
76// Re-export L298N controller
77pub use l298n::{L298nControllerConfig, L298nMotorController, L298nMotorPins};
78
79// ============================================================================
80// Core Controller Trait
81// ============================================================================
82
83/// Base trait for all hardware controllers
84///
85/// Controllers manage the lifecycle and interaction with physical hardware
86/// or simulated devices. They abstract device SDKs and provide consistent
87/// interfaces for nodes to use.
88#[async_trait]
89pub trait Controller: Send + Sync {
90    /// Configuration type for this controller
91    type Config: Send + Sync;
92
93    /// Error type for this controller
94    type Error: std::error::Error + Send + Sync + 'static;
95
96    /// Initialize the controller with the given configuration
97    ///
98    /// This should perform all necessary setup including:
99    /// - Opening device connections
100    /// - Configuring device parameters
101    /// - Running initialization sequences
102    /// - Loading calibration data
103    async fn init(config: Self::Config) -> Result<Self, Self::Error>
104    where
105        Self: Sized;
106
107    /// Start the controller
108    ///
109    /// Begin data acquisition, motor control, or other active operations.
110    /// This may start background threads or async tasks.
111    async fn start(&mut self) -> Result<(), Self::Error>;
112
113    /// Stop the controller
114    ///
115    /// Stop all active operations gracefully. The controller should still
116    /// be in a valid state and can be restarted with `start()`.
117    async fn stop(&mut self) -> Result<(), Self::Error>;
118
119    /// Check the health status of the controller
120    async fn health_check(&self) -> ControllerHealth;
121
122    /// Get the capabilities of this controller
123    ///
124    /// Returns metadata about what features and operations this controller
125    /// supports. This is useful for runtime capability detection.
126    fn capabilities(&self) -> ControllerCapabilities;
127
128    /// Get controller-specific diagnostics
129    ///
130    /// Returns detailed diagnostic information for debugging and monitoring.
131    async fn diagnostics(&self) -> HashMap<String, String> {
132        HashMap::new()
133    }
134}
135
136// ============================================================================
137// Health and Capabilities
138// ============================================================================
139
140/// Health status of a controller
141#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
142pub enum ControllerHealth {
143    /// Controller is healthy and ready
144    Healthy,
145
146    /// Controller is running but degraded (e.g., some sensors failing)
147    Degraded { reason: String },
148
149    /// Controller is unhealthy and not functioning
150    Unhealthy { reason: String },
151
152    /// Controller health is unknown (e.g., not initialized)
153    Unknown,
154}
155
156impl fmt::Display for ControllerHealth {
157    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
158        match self {
159            Self::Healthy => write!(f, "Healthy"),
160            Self::Degraded { reason } => write!(f, "Degraded: {}", reason),
161            Self::Unhealthy { reason } => write!(f, "Unhealthy: {}", reason),
162            Self::Unknown => write!(f, "Unknown"),
163        }
164    }
165}
166
167/// Capabilities of a controller
168///
169/// Describes what features and operations a controller supports.
170/// This allows runtime capability detection and adaptation.
171#[derive(Debug, Clone, Serialize, Deserialize)]
172pub struct ControllerCapabilities {
173    /// Controller type identifier (e.g., "camera", "imu", "lidar")
174    pub controller_type: String,
175
176    /// Specific implementation (e.g., "realsense", "bno055", "rplidar")
177    pub implementation: String,
178
179    /// Hardware vendor (e.g., "Intel", "Bosch", "Slamtec")
180    pub vendor: Option<String>,
181
182    /// Hardware model (e.g., "D435i", "BNO055", "A2M8")
183    pub model: Option<String>,
184
185    /// Firmware version if available
186    pub firmware_version: Option<String>,
187
188    /// Feature flags indicating what operations are supported
189    pub features: HashMap<String, bool>,
190
191    /// Additional metadata
192    pub metadata: HashMap<String, String>,
193}
194
195impl ControllerCapabilities {
196    /// Create a new capabilities struct
197    pub fn new(controller_type: impl Into<String>, implementation: impl Into<String>) -> Self {
198        Self {
199            controller_type: controller_type.into(),
200            implementation: implementation.into(),
201            vendor: None,
202            model: None,
203            firmware_version: None,
204            features: HashMap::new(),
205            metadata: HashMap::new(),
206        }
207    }
208
209    /// Add a feature flag
210    pub fn with_feature(mut self, name: impl Into<String>, supported: bool) -> Self {
211        self.features.insert(name.into(), supported);
212        self
213    }
214
215    /// Add metadata
216    pub fn with_metadata(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
217        self.metadata.insert(key.into(), value.into());
218        self
219    }
220
221    /// Set vendor
222    pub fn with_vendor(mut self, vendor: impl Into<String>) -> Self {
223        self.vendor = Some(vendor.into());
224        self
225    }
226
227    /// Set model
228    pub fn with_model(mut self, model: impl Into<String>) -> Self {
229        self.model = Some(model.into());
230        self
231    }
232
233    /// Check if a feature is supported
234    pub fn supports(&self, feature: &str) -> bool {
235        self.features.get(feature).copied().unwrap_or(false)
236    }
237}
238
239// ============================================================================
240// Common Errors
241// ============================================================================
242
243/// Common controller errors
244#[derive(Debug, thiserror::Error)]
245pub enum ControllerError {
246    /// Device not found or not connected
247    #[error("Device not found: {0}")]
248    DeviceNotFound(String),
249
250    /// Device initialization failed
251    #[error("Initialization failed: {0}")]
252    InitializationFailed(String),
253
254    /// Device communication error
255    #[error("Communication error: {0}")]
256    CommunicationError(String),
257
258    /// Invalid configuration
259    #[error("Invalid configuration: {0}")]
260    InvalidConfiguration(String),
261
262    /// Operation timeout
263    #[error("Operation timed out: {0}")]
264    Timeout(String),
265
266    /// Device is not in the correct state for this operation
267    #[error("Invalid state: {0}")]
268    InvalidState(String),
269
270    /// Hardware fault detected
271    #[error("Hardware fault: {0}")]
272    HardwareFault(String),
273
274    /// Feature not supported by this controller
275    #[error("Feature not supported: {0}")]
276    NotSupported(String),
277
278    /// Generic error
279    #[error("Controller error: {0}")]
280    Other(String),
281}
282
283// ============================================================================
284// Controller State
285// ============================================================================
286
287/// Common controller states
288#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
289pub enum ControllerState {
290    /// Not initialized
291    Uninitialized,
292
293    /// Initialized but not started
294    Initialized,
295
296    /// Running normally
297    Running,
298
299    /// Stopped
300    Stopped,
301
302    /// Error state
303    Error,
304}
305
306impl fmt::Display for ControllerState {
307    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308        match self {
309            Self::Uninitialized => write!(f, "Uninitialized"),
310            Self::Initialized => write!(f, "Initialized"),
311            Self::Running => write!(f, "Running"),
312            Self::Stopped => write!(f, "Stopped"),
313            Self::Error => write!(f, "Error"),
314        }
315    }
316}