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