mecha10_controllers/camera.rs
1//! Camera controller trait and types
2
3use crate::Controller;
4use async_trait::async_trait;
5use mecha10_core::sensor::{CameraInfo, DepthImage, RgbImage};
6use serde::{Deserialize, Serialize};
7
8/// Camera controller trait
9///
10/// Provides a unified interface for different camera types including:
11/// - RGB cameras (webcams, CSI cameras)
12/// - Depth cameras (RealSense, structured light)
13/// - RGBD cameras (RealSense D400 series)
14/// - Network cameras (RTSP streams)
15#[async_trait]
16pub trait CameraController: Controller {
17 /// Frame type produced by this camera
18 type Frame: Send + Sync;
19
20 /// Capture a single frame from the camera
21 ///
22 /// This will block until a frame is available or an error occurs.
23 async fn capture_frame(&mut self) -> Result<Self::Frame, Self::Error>;
24
25 /// Get camera intrinsics if available
26 ///
27 /// Returns calibration data including focal length, principal point,
28 /// and distortion coefficients. May return None if not calibrated.
29 fn intrinsics(&self) -> Option<CameraIntrinsics>;
30
31 /// Set camera parameters
32 ///
33 /// Adjust camera settings like exposure, gain, white balance, etc.
34 /// Not all parameters may be supported by all cameras.
35 async fn set_parameters(&mut self, params: CameraParameters) -> Result<(), Self::Error>;
36
37 /// Get current camera parameters
38 async fn get_parameters(&self) -> Result<CameraParameters, Self::Error>;
39
40 /// Get camera information
41 fn info(&self) -> CameraInfo;
42
43 /// Check if the camera supports depth
44 fn supports_depth(&self) -> bool {
45 self.capabilities().features.get("depth").copied().unwrap_or(false)
46 }
47
48 /// Check if the camera supports infrared
49 fn supports_infrared(&self) -> bool {
50 self.capabilities().features.get("infrared").copied().unwrap_or(false)
51 }
52}
53
54// ============================================================================
55// Camera Types
56// ============================================================================
57
58/// Camera frame types
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub enum CameraFrame {
61 /// RGB color image only
62 Rgb(RgbImage),
63
64 /// Depth image only
65 Depth(DepthImage),
66
67 /// Combined RGB + Depth (RGBD cameras)
68 Rgbd {
69 color: RgbImage,
70 depth: DepthImage,
71 aligned: bool,
72 },
73
74 /// Infrared image
75 Infrared {
76 timestamp: u64,
77 frame_id: u64,
78 width: u32,
79 height: u32,
80 data: Vec<u8>,
81 },
82}
83
84/// Camera intrinsics (calibration parameters)
85#[derive(Debug, Clone, Serialize, Deserialize)]
86pub struct CameraIntrinsics {
87 /// Image width in pixels
88 pub width: u32,
89
90 /// Image height in pixels
91 pub height: u32,
92
93 /// Focal length in X (pixels)
94 pub fx: f64,
95
96 /// Focal length in Y (pixels)
97 pub fy: f64,
98
99 /// Principal point X (pixels)
100 pub cx: f64,
101
102 /// Principal point Y (pixels)
103 pub cy: f64,
104
105 /// Distortion coefficients [k1, k2, p1, p2, k3]
106 pub distortion: Vec<f64>,
107
108 /// Distortion model ("plumb_bob", "fisheye", etc.)
109 pub distortion_model: String,
110}
111
112impl Default for CameraIntrinsics {
113 fn default() -> Self {
114 Self {
115 width: 640,
116 height: 480,
117 fx: 500.0,
118 fy: 500.0,
119 cx: 320.0,
120 cy: 240.0,
121 distortion: vec![0.0; 5],
122 distortion_model: "plumb_bob".to_string(),
123 }
124 }
125}
126
127/// Camera parameters that can be adjusted
128#[derive(Debug, Clone, Default, Serialize, Deserialize)]
129pub struct CameraParameters {
130 /// Auto exposure enabled
131 pub auto_exposure: Option<bool>,
132
133 /// Exposure time in microseconds (if manual exposure)
134 pub exposure_us: Option<u32>,
135
136 /// Auto white balance enabled
137 pub auto_white_balance: Option<bool>,
138
139 /// White balance temperature in Kelvin (if manual)
140 pub white_balance_k: Option<u32>,
141
142 /// Gain (0.0 - 1.0)
143 pub gain: Option<f32>,
144
145 /// Brightness (0.0 - 1.0)
146 pub brightness: Option<f32>,
147
148 /// Contrast (0.0 - 1.0)
149 pub contrast: Option<f32>,
150
151 /// Saturation (0.0 - 1.0)
152 pub saturation: Option<f32>,
153
154 /// Sharpness (0.0 - 1.0)
155 pub sharpness: Option<f32>,
156
157 /// Gamma (0.0 - 1.0)
158 pub gamma: Option<f32>,
159
160 /// Frame rate (fps)
161 pub frame_rate: Option<u32>,
162
163 /// Enable depth post-processing filters (for depth cameras)
164 pub depth_filtering: Option<bool>,
165
166 /// Depth units in meters per unit
167 pub depth_scale: Option<f32>,
168}
169
170// ============================================================================
171// Helper Types
172// ============================================================================
173
174/// Camera streaming state
175#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
176pub enum CameraStreamState {
177 /// Camera is not streaming
178 Stopped,
179
180 /// Camera is streaming
181 Streaming,
182
183 /// Camera stream is paused
184 Paused,
185
186 /// Camera encountered an error
187 Error,
188}
189
190/// Camera resolution
191#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
192pub struct Resolution {
193 pub width: u32,
194 pub height: u32,
195}
196
197impl Resolution {
198 pub fn new(width: u32, height: u32) -> Self {
199 Self { width, height }
200 }
201
202 /// VGA resolution (640x480)
203 pub const VGA: Self = Self {
204 width: 640,
205 height: 480,
206 };
207
208 /// HD resolution (1280x720)
209 pub const HD: Self = Self {
210 width: 1280,
211 height: 720,
212 };
213
214 /// Full HD resolution (1920x1080)
215 pub const FULL_HD: Self = Self {
216 width: 1920,
217 height: 1080,
218 };
219
220 /// 4K resolution (3840x2160)
221 pub const UHD_4K: Self = Self {
222 width: 3840,
223 height: 2160,
224 };
225}
226
227/// Pixel format
228#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
229pub enum PixelFormat {
230 /// 8-bit RGB
231 Rgb8,
232
233 /// 8-bit RGBA
234 Rgba8,
235
236 /// 8-bit BGR
237 Bgr8,
238
239 /// 8-bit BGRA
240 Bgra8,
241
242 /// Grayscale 8-bit
243 Gray8,
244
245 /// Grayscale 16-bit
246 Gray16,
247
248 /// Motion JPEG
249 Mjpeg,
250
251 /// H.264
252 H264,
253
254 /// YUV 4:2:2
255 Yuyv,
256}