mecha10_controllers/mock/
lidar.rs1use crate::lidar::*;
4use crate::{Controller, ControllerCapabilities, ControllerError, ControllerHealth, ControllerState};
5use async_trait::async_trait;
6use std::time::{SystemTime, UNIX_EPOCH};
7
8#[derive(Debug, Clone)]
9pub struct MockLidarConfig {
10 pub scan_frequency: f32,
11 pub angular_resolution: f32,
12 pub range_max: f32,
13}
14
15impl Default for MockLidarConfig {
16 fn default() -> Self {
17 Self {
18 scan_frequency: 10.0,
19 angular_resolution: 0.36,
20 range_max: 12.0,
21 }
22 }
23}
24
25pub struct MockLidarController {
26 config: MockLidarConfig,
27 state: ControllerState,
28 scan_count: u64,
29}
30
31#[async_trait]
32impl Controller for MockLidarController {
33 type Config = MockLidarConfig;
34 type Error = ControllerError;
35
36 async fn init(config: Self::Config) -> Result<Self, Self::Error> {
37 Ok(Self {
38 config,
39 state: ControllerState::Initialized,
40 scan_count: 0,
41 })
42 }
43
44 async fn start(&mut self) -> Result<(), Self::Error> {
45 self.state = ControllerState::Running;
46 Ok(())
47 }
48
49 async fn stop(&mut self) -> Result<(), Self::Error> {
50 self.state = ControllerState::Stopped;
51 Ok(())
52 }
53
54 async fn health_check(&self) -> ControllerHealth {
55 match self.state {
56 ControllerState::Running => ControllerHealth::Healthy,
57 _ => ControllerHealth::Unknown,
58 }
59 }
60
61 fn capabilities(&self) -> ControllerCapabilities {
62 ControllerCapabilities::new("lidar", "mock")
63 .with_vendor("Mecha10")
64 .with_model("Mock LiDAR")
65 .with_feature("intensity", true)
66 }
67}
68
69#[async_trait]
70impl LidarController for MockLidarController {
71 type Scan = LaserScan2D;
72
73 async fn get_scan(&mut self) -> Result<Self::Scan, Self::Error> {
74 if self.state != ControllerState::Running {
75 return Err(ControllerError::InvalidState("LiDAR not running".to_string()));
76 }
77
78 self.scan_count += 1;
79
80 let num_points = (360.0 / self.config.angular_resolution) as usize;
81 let mut ranges = Vec::with_capacity(num_points);
82 let mut intensities = Vec::with_capacity(num_points);
83
84 for i in 0..num_points {
86 let angle = (i as f32) * self.config.angular_resolution.to_radians();
87 let base_range = 2.0 + (angle.sin() * 0.5);
88 ranges.push(base_range);
89 intensities.push(((i % 100) as f32) / 100.0);
90 }
91
92 Ok(LaserScan2D {
93 timestamp: SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_micros() as u64,
94 scan_id: self.scan_count,
95 angle_min: 0.0,
96 angle_max: 2.0 * std::f32::consts::PI,
97 angle_increment: self.config.angular_resolution.to_radians(),
98 range_min: 0.15,
99 range_max: self.config.range_max,
100 ranges,
101 intensities,
102 quality: vec![],
103 })
104 }
105
106 fn info(&self) -> LidarInfo {
107 LidarInfo {
108 model: "Mock LiDAR".to_string(),
109 scan_type: ScanType::Planar2D,
110 range_min: 0.15,
111 range_max: self.config.range_max,
112 angular_resolution: self.config.angular_resolution,
113 scan_frequency: self.config.scan_frequency,
114 points_per_scan: Some((360.0 / self.config.angular_resolution) as usize),
115 }
116 }
117
118 fn field_of_view(&self) -> FieldOfView {
119 FieldOfView {
120 horizontal: 2.0 * std::f32::consts::PI,
121 vertical: None,
122 angle_min: 0.0,
123 angle_max: 2.0 * std::f32::consts::PI,
124 }
125 }
126}