1use super::{
4 consts::PIXELS_PER_COLUMN,
5 enums::{LidarMode, MultipurposeIoMode, NmeaBaudRate, OnOffMode, Polarity, TimestampMode},
6};
7use crate::common::*;
8
9big_array! { BigArray; }
12
13#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
14pub struct ConfigText {
15 pub timestamp_mode: TimestampMode,
16 pub multipurpose_io_mode: MultipurposeIoMode,
17 pub lidar_mode: LidarMode,
18 pub sync_pulse_in_polarity: Polarity,
19 pub nmea_in_polarity: Polarity,
20 pub sync_pulse_out_polarity: Polarity,
21 pub udp_ip: Ipv4Addr,
22 #[serde(with = "serde_bool_to_int")]
23 pub nmea_ignore_valid_char: bool,
24 #[serde(with = "serde_bool_to_int")]
25 pub auto_start_flag: bool,
26 pub sync_pulse_out_pulse_width: u64,
27 pub nmea_baud_rate: NmeaBaudRate,
28 pub sync_pulse_out_angle: u64,
29 pub sync_pulse_out_frequency: u64,
30 pub udp_port_imu: u16,
31 pub udp_port_lidar: u16,
32 pub azimuth_window: [u64; 2],
33}
34
35#[derive(Clone, PartialEq, Eq, Hash, Serialize, Deserialize, Derivative)]
36#[derivative(Debug)]
37pub struct BeamIntrinsics {
38 #[serde(with = "BigArray")]
39 #[derivative(Debug(format_with = "self::large_array_fmt"))]
40 pub beam_altitude_angles: [R64; PIXELS_PER_COLUMN],
41 #[serde(with = "BigArray")]
42 #[derivative(Debug(format_with = "self::large_array_fmt"))]
43 pub beam_azimuth_angles: [R64; PIXELS_PER_COLUMN],
44}
45
46#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
47pub struct LidarIntrinsics {
48 pub lidar_to_sensor_transform: [R64; 16],
49}
50
51#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
52pub struct ImuIntrinsics {
53 pub imu_to_sensor_transform: [R64; 16],
54}
55
56#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
57pub struct TimeInfo {
58 pub timestamp: TimestampInfo,
59 pub sync_pulse_in: SyncPulseInInfo,
60 pub multipurpose_io: MultiPurposeIo,
61}
62
63#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
64pub struct MultiPurposeIo {
65 pub mode: OnOffMode,
66 pub sync_pulse_out: SyncPulseOutInfo,
67 pub nmea: NmeaInfo,
68}
69
70#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
71pub struct SyncPulseInInfo {
72 pub diagnostics: SyncPulseInDiagnosticsInfo,
73 pub polarity: Polarity,
74 #[serde(with = "serde_bool_to_int")]
75 pub locked: bool,
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
79pub struct NmeaInfo {
80 pub polarity: Polarity,
81 pub baud_rate: NmeaBaudRate,
82 pub diagnostics: NmeaDiagnosticsInfo,
83 pub leap_seconds: u64,
84 #[serde(with = "serde_bool_to_int")]
85 pub ignore_valid_char: bool,
86 #[serde(with = "serde_bool_to_int")]
87 pub locked: bool,
88}
89
90#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
91pub struct SyncPulseOutInfo {
92 pub frequency_hz: u64,
93 pub angle_deg: u64,
94 pub pulse_width_ms: u64,
95 pub polarity: Polarity,
96}
97
98#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
99pub struct TimestampInfo {
100 pub time_options: TimeOptionsInfo,
101 pub mode: TimestampMode,
102 pub time: R64,
103}
104
105#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
106pub struct SyncPulseInDiagnosticsInfo {
107 pub count_unfiltered: u64,
108 pub last_period_nsec: u64,
109 pub count: u64,
110}
111
112#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
113pub struct NmeaDiagnosticsInfo {
114 pub io_checks: NmeaIoChecksInfo,
115 pub decoding: NmeaDecodingInfo,
116}
117
118#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
119pub struct TimeOptionsInfo {
120 pub ptp_1588: u64,
121 #[serde(with = "serde_bool_to_int")]
122 pub sync_pulse_in: bool,
123 pub internal_osc: u64,
124}
125
126#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
127pub struct NmeaIoChecksInfo {
128 pub bit_count: u64,
129 pub start_char_count: u64,
130 pub bit_count_unfilterd: u64,
131 pub char_count: u64,
132}
133
134#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
135pub struct NmeaDecodingInfo {
136 pub not_valid_count: u64,
137 pub last_read_message: String,
138 pub utc_decoded_count: u64,
139 pub date_decoded_count: u64,
140}
141
142#[derive(Debug)]
143pub struct CommandClient {
144 reader: Lines<BufReader<TcpStream>>,
145 writer: LineWriter<TcpStream>,
146}
147
148impl CommandClient {
149 pub fn connect<A>(address: A, timeout: Option<Duration>) -> Result<CommandClient>
150 where
151 A: ToSocketAddrs,
152 {
153 let stream = TcpStream::connect(&address)?;
154 stream.set_read_timeout(timeout)?;
155 stream.set_write_timeout(timeout)?;
156
157 let reader = BufReader::new(stream.try_clone()?).lines();
158 let writer = LineWriter::new(stream);
159 let client = CommandClient { reader, writer };
160 Ok(client)
161 }
162
163 pub fn get_config_txt(&mut self) -> Result<ConfigText> {
164 self.writer.write_all(b"get_config_txt\n")?;
165 let line = self
166 .reader
167 .next()
168 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
169 let config = serde_json::from_str(&line)?;
170 Ok(config)
171 }
172
173 pub fn get_time_info(&mut self) -> Result<TimeInfo> {
174 self.writer.write_all(b"get_time_info\n")?;
175 let line = self
176 .reader
177 .next()
178 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
179 let config = serde_json::from_str(&line)?;
180 Ok(config)
181 }
182
183 pub fn get_lidar_intrinsics(&mut self) -> Result<LidarIntrinsics> {
184 self.writer.write_all(b"get_lidar_intrinsics\n")?;
185 let line = self
186 .reader
187 .next()
188 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
189 let config = serde_json::from_str(&line)?;
190 Ok(config)
191 }
192
193 pub fn get_imu_intrinsics(&mut self) -> Result<ImuIntrinsics> {
194 self.writer.write_all(b"get_imu_intrinsics\n")?;
195 let line = self
196 .reader
197 .next()
198 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
199 let config = serde_json::from_str(&line)?;
200 Ok(config)
201 }
202
203 pub fn get_beam_intrinsics(&mut self) -> Result<BeamIntrinsics> {
204 self.writer.write_all(b"get_beam_intrinsics\n")?;
205 let line = self
206 .reader
207 .next()
208 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
209 let config = serde_json::from_str(&line)?;
210 Ok(config)
211 }
212
213 pub fn reinitialize(mut self) -> Result<()> {
214 self.writer.write_all(b"reinitialize\n")?;
215 let line = self
216 .reader
217 .next()
218 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
219 ensure!(line == "reinitialize", "Unexpected response {:?}", line);
220 Ok(())
221 }
222
223 pub fn write_config_txt(&mut self) -> Result<()> {
224 self.writer.write_all(b"write_config_txt\n")?;
225 let line = self
226 .reader
227 .next()
228 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
229 ensure!(line == "write_config_txt", "Unexpected response {:?}", line);
230 Ok(())
231 }
232
233 pub fn set_udp_ip(&mut self, ip: Ipv4Addr) -> Result<()> {
234 self.set_config_param("udp_ip", ip)?;
235 Ok(())
236 }
237
238 pub fn set_udp_port_lidar(&mut self, port: u16) -> Result<()> {
239 self.set_config_param("udp_port_lidar", port)?;
240 Ok(())
241 }
242
243 pub fn set_udp_port_imu(&mut self, port: u16) -> Result<()> {
244 self.set_config_param("udp_port_imu", port)?;
245 Ok(())
246 }
247
248 pub fn set_lidar_mode(&mut self, mode: LidarMode) -> Result<()> {
249 self.set_config_param("lidar_mode", mode)?;
250 Ok(())
251 }
252
253 pub fn set_timestamp_mode(&mut self, mode: TimestampMode) -> Result<()> {
254 self.set_config_param("timestamp_mode", mode)?;
255 Ok(())
256 }
257
258 pub fn set_sync_pulse_in_polarity(&mut self, polarity: Polarity) -> Result<()> {
259 self.set_config_param("sync_pulse_in_polarity", polarity)?;
260 Ok(())
261 }
262
263 pub fn set_nmea_in_polarity(&mut self, polarity: Polarity) -> Result<()> {
264 self.set_config_param("nmea_in_polarity", polarity)?;
265 Ok(())
266 }
267
268 fn set_config_param<T: Display>(&mut self, param: &str, arg: T) -> Result<()> {
269 let command = format!("set_config_param {} {}\n", param, arg);
270 self.writer.write_all(command.as_bytes())?;
271 let line = self
272 .reader
273 .next()
274 .ok_or_else(|| format_err!("Unexpected end of stream"))??;
275 ensure!(line == "set_config_param", "Unexpected response {:?}", line);
276 Ok(())
277 }
278}
279
280mod serde_bool_to_int {
281 use super::*;
282
283 pub fn serialize<S>(value: &bool, serializer: S) -> Result<S::Ok, S::Error>
284 where
285 S: Serializer,
286 {
287 match value {
288 true => serializer.serialize_u64(1),
289 false => serializer.serialize_u64(0),
290 }
291 }
292
293 pub fn deserialize<'de, D>(deserializer: D) -> Result<bool, D::Error>
294 where
295 D: Deserializer<'de>,
296 {
297 match u64::deserialize(deserializer)? {
298 1 => Ok(true),
299 0 => Ok(false),
300 other => {
301 use serde::de::{Error, Unexpected};
302 let error = Error::invalid_value(Unexpected::Unsigned(other), &"Expect 0 or 1");
303 Err(error)
304 }
305 }
306 }
307}
308
309fn large_array_fmt<T: Debug>(
310 array: &[T; PIXELS_PER_COLUMN],
311 formatter: &mut Formatter,
312) -> Result<(), fmt::Error> {
313 write!(formatter, "{:?}", &array[..])
314}