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}