lidar_utils/ouster/
frame_converter.rs1use super::{
4 config::Config,
5 consts::COLUMNS_PER_PACKET,
6 packet::{Column, Packet},
7 pcd_converter::{Point, PointCloudConverter},
8};
9use crate::common::*;
10
11#[derive(Debug, Clone)]
14pub struct Frame {
15 pub frame_id: u16,
17 pub skipped_frame_ids: Range<u16>,
19 pub timestamps: Vec<(u16, u64)>,
21 pub points: Vec<Point>,
23}
24
25#[derive(Debug)]
34pub struct FrameConverter {
35 pcd_converter: PointCloudConverter,
36 state: Option<FrameConverterState>,
37}
38
39impl FrameConverter {
40 pub fn from_config(config: Config) -> Self {
42 Self {
43 pcd_converter: PointCloudConverter::from_config(config),
44 state: None,
45 }
46 }
47
48 pub fn resolution(&self) -> (u16, u16) {
50 let width = self.pcd_converter.columns_per_revolution();
51 (width, 64)
52 }
53
54 pub fn columns_per_revolution(&self) -> u16 {
56 self.pcd_converter.columns_per_revolution()
57 }
58
59 pub fn push_column(&mut self, column: &Column) -> Result<Vec<Frame>> {
61 let curr_fid = column.frame_id;
62 let curr_mid = column.measurement_id;
63 let curr_ts = column.timestamp;
64 let curr_points = self.pcd_converter.column_to_points(column)?;
65
66 if !column.valid() {
68 let (frame_opt, new_state) = match self.state.take() {
69 Some(mut state) => {
70 let frame_opt = match state.last_fid.cmp(&curr_fid) {
71 Ordering::Less => state.frame.take(),
72 Ordering::Equal => None,
73 Ordering::Greater => {
74 bail!(
75 "Measurement ID of received column is less than that of previous column"
76 );
77 }
78 };
79
80 state.last_fid = curr_fid;
81 state.last_mid = curr_mid;
82 (frame_opt, state)
83 }
84 None => {
85 let new_state = FrameConverterState {
86 last_fid: curr_fid,
87 last_mid: curr_mid,
88 frame: None,
89 };
90 (None, new_state)
91 }
92 };
93
94 self.state = Some(new_state);
95 return Ok(frame_opt.into_iter().collect());
96 }
97
98 let (new_state, output_frames) = match self.state.take() {
99 Some(mut state) => {
100 match state.last_fid.cmp(&curr_fid) {
101 Ordering::Less => {
102 let first_frame_opt = state.frame.take();
106 let second_frame = Frame {
107 frame_id: curr_fid,
108 skipped_frame_ids: (state.last_fid + 1)..curr_fid,
109 timestamps: {
110 let mut timestamps = Vec::with_capacity(COLUMNS_PER_PACKET);
111 timestamps.push((curr_mid, curr_ts));
112 timestamps
113 },
114 points: curr_points,
115 };
116 let mut new_state = FrameConverterState {
117 last_mid: curr_mid,
118 last_fid: curr_fid,
119 frame: None,
120 };
121
122 let (second_frame_opt, new_state) =
124 if curr_mid + 1 == self.pcd_converter.columns_per_revolution() {
125 (Some(second_frame), new_state)
126 } else {
127 new_state.frame = Some(second_frame);
128 (None, new_state)
129 };
130
131 let output_frames = first_frame_opt
132 .into_iter()
133 .chain(second_frame_opt.into_iter())
134 .collect();
135
136 (new_state, output_frames)
137 }
138 Ordering::Equal => {
139 if state.last_mid >= curr_mid {
140 let error = format_err!(
141 "Measurement ID of received column is less than that of previous column"
142 );
143 return Err(error);
144 }
145
146 let mut new_state = FrameConverterState {
148 last_mid: curr_mid,
149 last_fid: curr_fid,
150 frame: None,
151 };
152 let frame = {
153 let mut frame = state.frame.take().unwrap_or_else(|| {
154 unreachable!("Please report bug to upstream");
155 });
156 frame.timestamps.push((curr_mid, curr_ts));
157 frame.points.extend(curr_points);
158 frame
159 };
160
161 let (frame_opt, new_state) =
162 if curr_mid + 1 == self.pcd_converter.columns_per_revolution() {
163 (Some(frame), new_state)
164 } else {
165 new_state.frame = Some(frame);
166 (None, new_state)
167 };
168
169 let output_frames = frame_opt.into_iter().collect();
170 (new_state, output_frames)
171 }
172 Ordering::Greater => {
173 let error = format_err!(
174 "Frame ID of received column is less than that of previous column"
175 );
176 return Err(error);
177 }
178 }
179 }
180 None => {
181 let frame = Frame {
182 frame_id: curr_fid,
183 skipped_frame_ids: curr_fid..curr_fid,
184 timestamps: {
185 let mut timestamps = Vec::with_capacity(COLUMNS_PER_PACKET);
186 timestamps.push((curr_mid, curr_ts));
187 timestamps
188 },
189 points: curr_points,
190 };
191 let mut new_state = FrameConverterState {
192 last_mid: curr_mid,
193 last_fid: curr_fid,
194 frame: None,
195 };
196
197 let frame_opt = if curr_mid + 1 == self.pcd_converter.columns_per_revolution() {
198 Some(frame)
199 } else {
200 new_state.frame = Some(frame);
201 None
202 };
203
204 (new_state, frame_opt.into_iter().collect())
205 }
206 };
207
208 self.state = Some(new_state);
209 Ok(output_frames)
210 }
211
212 pub fn push_packet<P>(&mut self, packet: P) -> Result<Vec<Frame>>
214 where
215 P: AsRef<Packet>,
216 {
217 let mut frames = vec![];
218 for column in packet.as_ref().columns.iter() {
219 frames.extend(self.push_column(column)?);
220 }
221 Ok(frames)
222 }
223
224 pub fn finish(mut self) -> Option<Frame> {
227 self.state
228 .take()
229 .map(|mut state| state.frame.take())
230 .unwrap_or(None)
231 }
232}
233
234#[derive(Clone, Debug)]
235struct FrameConverterState {
236 last_mid: u16,
237 last_fid: u16,
238 frame: Option<Frame>,
239}