lidar_utils/velodyne/
point.rs1use crate::common::*;
4
5pub use dual_return_point::*;
6pub use dynamic_return_points::*;
7pub use single_return_point::*;
8
9pub trait VelodynePoint {
11 fn laser_id(&self) -> u32;
12 fn timestamp(&self) -> Time;
13 fn original_azimuth_angle(&self) -> Angle;
14 fn corrected_azimuth_angle(&self) -> Angle;
15}
16
17#[derive(Debug, Clone)]
19pub struct PointData {
20 pub distance: Length,
21 pub intensity: u8,
22 pub position: [Length; 3],
23}
24
25mod single_return_point {
26 use super::*;
27
28 #[derive(Debug, Clone)]
30 pub struct SingleReturnPoint {
31 pub laser_id: u32,
32 pub timestamp: Time,
33 pub original_azimuth_angle: Angle,
34 pub corrected_azimuth_angle: Angle,
35 pub data: PointData,
36 }
37
38 impl VelodynePoint for SingleReturnPoint {
39 fn laser_id(&self) -> u32 {
40 self.laser_id
41 }
42
43 fn timestamp(&self) -> Time {
44 self.timestamp
45 }
46
47 fn original_azimuth_angle(&self) -> Angle {
48 self.original_azimuth_angle
49 }
50
51 fn corrected_azimuth_angle(&self) -> Angle {
52 self.corrected_azimuth_angle
53 }
54 }
55}
56
57mod dual_return_point {
58 use super::*;
59
60 #[derive(Debug, Clone)]
62 pub struct DualReturnPoint {
63 pub laser_id: u32,
64 pub timestamp: Time,
65 pub original_azimuth_angle: Angle,
66 pub corrected_azimuth_angle: Angle,
67 pub strongest_return_data: PointData,
68 pub last_return_data: PointData,
69 }
70
71 impl DualReturnPoint {
72 pub fn try_from_pair(
73 strongest_return_point: SingleReturnPoint,
74 last_return_point: SingleReturnPoint,
75 ) -> Result<Self> {
76 let SingleReturnPoint {
77 laser_id: laser_id_strongest,
78 timestamp: timestamp_strongest,
79 original_azimuth_angle: original_azimuth_angle_strongest,
80 corrected_azimuth_angle: corrected_azimuth_angle_strongest,
81 data: strongest_return_data,
82 } = strongest_return_point;
83
84 let SingleReturnPoint {
85 laser_id: laser_id_last,
86 timestamp: timestamp_last,
87 original_azimuth_angle: original_azimuth_angle_last,
88 corrected_azimuth_angle: corrected_azimuth_angle_last,
89 data: last_return_data,
90 } = last_return_point;
91
92 ensure!(
93 laser_id_strongest == laser_id_last,
94 "laser ID does not match"
95 );
96 ensure!(
97 timestamp_strongest == timestamp_last,
98 "timestamp does not match"
99 );
100 ensure!(
101 original_azimuth_angle_strongest == original_azimuth_angle_last,
102 "original azimuth angle does not match"
103 );
104 ensure!(
105 corrected_azimuth_angle_strongest == corrected_azimuth_angle_last,
106 "corrected azimuth angle does not match"
107 );
108
109 let dual_return_point = DualReturnPoint {
110 laser_id: laser_id_strongest,
111 timestamp: timestamp_strongest,
112 original_azimuth_angle: original_azimuth_angle_strongest,
113 corrected_azimuth_angle: corrected_azimuth_angle_strongest,
114 strongest_return_data,
115 last_return_data,
116 };
117
118 Ok(dual_return_point)
119 }
120 }
121
122 impl VelodynePoint for DualReturnPoint {
123 fn laser_id(&self) -> u32 {
124 self.laser_id
125 }
126
127 fn timestamp(&self) -> Time {
128 self.timestamp
129 }
130
131 fn original_azimuth_angle(&self) -> Angle {
132 self.original_azimuth_angle
133 }
134
135 fn corrected_azimuth_angle(&self) -> Angle {
136 self.corrected_azimuth_angle
137 }
138 }
139}
140
141mod dynamic_return_points {
142 use super::*;
143
144 #[derive(Debug, Clone)]
146 pub enum DynamicReturnPoints {
147 Single(Vec<SingleReturnPoint>),
148 Dual(Vec<DualReturnPoint>),
149 }
150
151 impl DynamicReturnPoints {
152 pub fn is_empty(&self) -> bool {
153 match self {
154 Self::Single(points) => points.is_empty(),
155 Self::Dual(points) => points.is_empty(),
156 }
157 }
158
159 pub(crate) fn empty_like(&self) -> Self {
160 match self {
161 Self::Single(_) => Self::Single(vec![]),
162 Self::Dual(_) => Self::Dual(vec![]),
163 }
164 }
165 }
166
167 impl IntoIterator for DynamicReturnPoints {
168 type Item = DynamicReturnPoint;
169 type IntoIter = DynamicReturnPointsIter;
170
171 fn into_iter(self) -> Self::IntoIter {
172 let iter: Box<dyn Iterator<Item = DynamicReturnPoint> + Sync + Send> = match self {
173 Self::Single(points) => {
174 Box::new(points.into_iter().map(DynamicReturnPoint::Single))
175 }
176 Self::Dual(points) => Box::new(points.into_iter().map(DynamicReturnPoint::Dual)),
177 };
178 Self::IntoIter { iter }
179 }
180 }
181
182 impl From<Vec<SingleReturnPoint>> for DynamicReturnPoints {
183 fn from(points: Vec<SingleReturnPoint>) -> Self {
184 Self::Single(points)
185 }
186 }
187
188 impl From<Vec<DualReturnPoint>> for DynamicReturnPoints {
189 fn from(points: Vec<DualReturnPoint>) -> Self {
190 Self::Dual(points)
191 }
192 }
193
194 #[derive(Derivative)]
196 #[derivative(Debug)]
197 pub struct DynamicReturnPointsIter {
198 #[derivative(Debug = "ignore")]
199 iter: Box<dyn Iterator<Item = DynamicReturnPoint> + Sync + Send>,
200 }
201
202 impl Iterator for DynamicReturnPointsIter {
203 type Item = DynamicReturnPoint;
204
205 fn next(&mut self) -> Option<Self::Item> {
206 self.iter.next()
207 }
208 }
209
210 #[derive(Debug, Clone)]
212 pub enum DynamicReturnPoint {
213 Single(SingleReturnPoint),
214 Dual(DualReturnPoint),
215 }
216
217 impl DynamicReturnPoint {
218 pub fn laser_id(&self) -> u32 {
219 match self {
220 Self::Single(point) => point.laser_id,
221 Self::Dual(point) => point.laser_id,
222 }
223 }
224
225 pub fn timestamp(&self) -> Time {
226 match self {
227 Self::Single(point) => point.timestamp,
228 Self::Dual(point) => point.timestamp,
229 }
230 }
231
232 pub fn original_azimuth_angle(&self) -> Angle {
233 match self {
234 Self::Single(point) => point.original_azimuth_angle,
235 Self::Dual(point) => point.original_azimuth_angle,
236 }
237 }
238
239 pub fn corrected_azimuth_angle(&self) -> Angle {
240 match self {
241 Self::Single(point) => point.corrected_azimuth_angle,
242 Self::Dual(point) => point.corrected_azimuth_angle,
243 }
244 }
245 }
246}