1pub mod pointcloud;
16
17use crate::builtin_interfaces::Time;
18use crate::cdr::*;
19use crate::geometry_msgs::{Quaternion, Vector3};
20use crate::std_msgs::Header;
21
22#[derive(PartialEq, Clone, Copy, Debug)]
25pub struct NavSatStatus {
26 pub status: i8,
27 pub service: u16,
28}
29
30impl CdrFixed for NavSatStatus {
31 const CDR_SIZE: usize = 4; fn read_cdr(cursor: &mut CdrCursor<'_>) -> Result<Self, CdrError> {
38 let status = cursor.read_i8()?;
39 let service = cursor.read_u16()?;
40 Ok(NavSatStatus { status, service })
41 }
42 fn write_cdr(&self, writer: &mut CdrWriter<'_>) {
43 writer.write_i8(self.status);
44 writer.write_u16(self.service);
45 }
46 fn size_cdr(sizer: &mut CdrSizer) {
47 sizer.size_i8();
48 sizer.size_u16();
49 }
50}
51
52#[derive(PartialEq, Clone, Copy, Debug)]
53pub struct RegionOfInterest {
54 pub x_offset: u32,
55 pub y_offset: u32,
56 pub height: u32,
57 pub width: u32,
58 pub do_rectify: bool,
59}
60
61impl CdrFixed for RegionOfInterest {
62 const CDR_SIZE: usize = 17; fn read_cdr(cursor: &mut CdrCursor<'_>) -> Result<Self, CdrError> {
64 Ok(RegionOfInterest {
65 x_offset: cursor.read_u32()?,
66 y_offset: cursor.read_u32()?,
67 height: cursor.read_u32()?,
68 width: cursor.read_u32()?,
69 do_rectify: cursor.read_bool()?,
70 })
71 }
72 fn write_cdr(&self, writer: &mut CdrWriter<'_>) {
73 writer.write_u32(self.x_offset);
74 writer.write_u32(self.y_offset);
75 writer.write_u32(self.height);
76 writer.write_u32(self.width);
77 writer.write_bool(self.do_rectify);
78 }
79 fn size_cdr(sizer: &mut CdrSizer) {
80 sizer.size_u32();
81 sizer.size_u32();
82 sizer.size_u32();
83 sizer.size_u32();
84 sizer.size_bool();
85 }
86}
87
88fn read_f64_array9(c: &mut CdrCursor<'_>) -> Result<[f64; 9], CdrError> {
91 Ok([
92 c.read_f64()?,
93 c.read_f64()?,
94 c.read_f64()?,
95 c.read_f64()?,
96 c.read_f64()?,
97 c.read_f64()?,
98 c.read_f64()?,
99 c.read_f64()?,
100 c.read_f64()?,
101 ])
102}
103
104fn write_f64_array9(w: &mut CdrWriter<'_>, a: &[f64; 9]) {
105 for v in a {
106 w.write_f64(*v);
107 }
108}
109
110fn size_f64_array9(s: &mut CdrSizer) {
111 for _ in 0..9 {
112 s.size_f64();
113 }
114}
115
116fn read_f64_array12(c: &mut CdrCursor<'_>) -> Result<[f64; 12], CdrError> {
117 Ok([
118 c.read_f64()?,
119 c.read_f64()?,
120 c.read_f64()?,
121 c.read_f64()?,
122 c.read_f64()?,
123 c.read_f64()?,
124 c.read_f64()?,
125 c.read_f64()?,
126 c.read_f64()?,
127 c.read_f64()?,
128 c.read_f64()?,
129 c.read_f64()?,
130 ])
131}
132
133fn write_f64_array12(w: &mut CdrWriter<'_>, a: &[f64; 12]) {
134 for v in a {
135 w.write_f64(*v);
136 }
137}
138
139fn size_f64_array12(s: &mut CdrSizer) {
140 for _ in 0..12 {
141 s.size_f64();
142 }
143}
144
145pub struct PointFieldView<'a> {
149 pub name: &'a str,
150 pub offset: u32,
151 pub datatype: u8,
152 pub count: u32,
153}
154
155fn scan_point_field_element<'a>(c: &mut CdrCursor<'a>) -> Result<PointFieldView<'a>, CdrError> {
156 let name = c.read_string()?;
157 let offset = c.read_u32()?;
158 let datatype = c.read_u8()?;
159 let count = c.read_u32()?;
160 Ok(PointFieldView {
161 name,
162 offset,
163 datatype,
164 count,
165 })
166}
167
168fn write_point_field_element(w: &mut CdrWriter<'_>, f: &PointFieldView<'_>) {
169 w.write_string(f.name);
170 w.write_u32(f.offset);
171 w.write_u8(f.datatype);
172 w.write_u32(f.count);
173}
174
175fn size_point_field_element(s: &mut CdrSizer, name: &str) {
176 s.size_string(name);
177 s.size_u32();
178 s.size_u8();
179 s.size_u32();
180}
181
182pub struct PointFieldIter<'a> {
191 cursor: CdrCursor<'a>,
192 remaining: usize,
193}
194
195impl<'a> Iterator for PointFieldIter<'a> {
196 type Item = PointFieldView<'a>;
197
198 fn next(&mut self) -> Option<Self::Item> {
199 if self.remaining == 0 {
200 return None;
201 }
202 self.remaining -= 1;
203 Some(
204 scan_point_field_element(&mut self.cursor)
205 .expect("point field elements validated during from_cdr"),
206 )
207 }
208
209 fn size_hint(&self) -> (usize, Option<usize>) {
210 (self.remaining, Some(self.remaining))
211 }
212}
213
214impl ExactSizeIterator for PointFieldIter<'_> {}
215
216pub struct CompressedImage<B> {
227 buf: B,
228 offsets: [usize; 3],
229}
230
231impl<B> CompressedImage<B> {
232 #[inline]
234 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> CompressedImage<C> {
235 CompressedImage {
236 buf: f(self.buf),
237 offsets: self.offsets,
238 }
239 }
240}
241
242impl<B: AsRef<[u8]>> CompressedImage<B> {
243 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
244 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
245 let o0 = header.end_offset();
246 let mut c = CdrCursor::resume(buf.as_ref(), o0);
247 let _ = c.read_string()?; let o1 = c.offset();
249 let _ = c.read_bytes()?; let o2 = c.offset();
251 Ok(CompressedImage {
252 offsets: [o0, o1, o2],
253 buf,
254 })
255 }
256
257 pub fn header(&self) -> Header<&[u8]> {
259 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
260 }
261 pub fn stamp(&self) -> Time {
262 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
263 }
264 pub fn frame_id(&self) -> &str {
265 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
266 }
267 pub fn format(&self) -> &str {
268 rd_string(self.buf.as_ref(), self.offsets[0]).0
269 }
270 pub fn data(&self) -> &[u8] {
271 rd_bytes(self.buf.as_ref(), self.offsets[1]).0
272 }
273 pub fn as_cdr(&self) -> &[u8] {
274 self.buf.as_ref()
275 }
276 pub fn cdr_size(&self) -> usize {
277 self.buf.as_ref().len()
278 }
279 pub fn to_cdr(&self) -> Vec<u8> {
280 self.buf.as_ref().to_vec()
281 }
282}
283
284impl CompressedImage<Vec<u8>> {
285 #[deprecated(
286 since = "3.2.0",
287 note = "use CompressedImage::builder() for allocation-free buffer reuse; CompressedImage::new will be removed in 4.0"
288 )]
289 pub fn new(stamp: Time, frame_id: &str, format: &str, data: &[u8]) -> Result<Self, CdrError> {
290 let mut sizer = CdrSizer::new();
291 Time::size_cdr(&mut sizer);
292 sizer.size_string(frame_id);
293 let o0 = sizer.offset();
294 sizer.size_string(format);
295 let o1 = sizer.offset();
296 sizer.size_bytes(data.len());
297 let o2 = sizer.offset();
298
299 let mut buf = vec![0u8; sizer.size()];
300 let mut w = CdrWriter::new(&mut buf)?;
301 stamp.write_cdr(&mut w);
302 w.write_string(frame_id);
303 w.write_string(format);
304 w.write_bytes(data);
305 w.finish()?;
306
307 Ok(CompressedImage {
308 offsets: [o0, o1, o2],
309 buf,
310 })
311 }
312
313 pub fn into_cdr(self) -> Vec<u8> {
314 self.buf
315 }
316
317 pub fn builder<'a>() -> CompressedImageBuilder<'a> {
322 CompressedImageBuilder::new()
323 }
324}
325
326pub struct CompressedImageBuilder<'a> {
330 stamp: Time,
331 frame_id: std::borrow::Cow<'a, str>,
332 format: std::borrow::Cow<'a, str>,
333 data: &'a [u8],
334}
335
336impl<'a> Default for CompressedImageBuilder<'a> {
337 fn default() -> Self {
338 Self {
339 stamp: Time { sec: 0, nanosec: 0 },
340 frame_id: std::borrow::Cow::Borrowed(""),
341 format: std::borrow::Cow::Borrowed(""),
342 data: &[],
343 }
344 }
345}
346
347impl<'a> CompressedImageBuilder<'a> {
348 pub fn new() -> Self {
349 Self::default()
350 }
351
352 pub fn stamp(&mut self, t: Time) -> &mut Self {
353 self.stamp = t;
354 self
355 }
356 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
357 self.frame_id = s.into();
358 self
359 }
360 pub fn format(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
361 self.format = s.into();
362 self
363 }
364 pub fn data(&mut self, d: &'a [u8]) -> &mut Self {
365 self.data = d;
366 self
367 }
368
369 fn size(&self) -> usize {
370 let mut s = CdrSizer::new();
371 Time::size_cdr(&mut s);
372 s.size_string(&self.frame_id);
373 s.size_string(&self.format);
374 s.size_bytes(self.data.len());
375 s.size()
376 }
377
378 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
379 let mut w = CdrWriter::new(buf)?;
380 self.stamp.write_cdr(&mut w);
381 w.write_string(&self.frame_id);
382 w.write_string(&self.format);
383 w.write_bytes(self.data);
384 w.finish()
385 }
386
387 pub fn build(&self) -> Result<CompressedImage<Vec<u8>>, CdrError> {
389 let mut buf = vec![0u8; self.size()];
390 self.write_into(&mut buf)?;
391 CompressedImage::from_cdr(buf)
392 }
393
394 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
396 buf.resize(self.size(), 0);
397 self.write_into(buf)
398 }
399
400 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
403 let need = self.size();
404 if buf.len() < need {
405 return Err(CdrError::BufferTooShort {
406 need,
407 have: buf.len(),
408 });
409 }
410 self.write_into(&mut buf[..need])?;
411 Ok(need)
412 }
413}
414
415impl<B: AsRef<[u8]> + AsMut<[u8]>> CompressedImage<B> {
416 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
417 let b = self.buf.as_mut();
418 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
419 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
420 }
421}
422
423pub struct Image<B> {
435 buf: B,
436 offsets: [usize; 3],
437}
438
439impl<B> Image<B> {
440 #[inline]
442 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Image<C> {
443 Image {
444 buf: f(self.buf),
445 offsets: self.offsets,
446 }
447 }
448}
449
450impl<B: AsRef<[u8]>> Image<B> {
451 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
452 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
453 let o0 = header.end_offset();
454 let mut c = CdrCursor::resume(buf.as_ref(), o0);
455 let _ = c.read_u32()?; let _ = c.read_u32()?; let _ = c.read_string()?; let o1 = c.offset();
459 let _ = c.read_u8()?; let _ = c.read_u32()?; let _ = c.read_bytes()?; let o2 = c.offset();
463 Ok(Image {
464 offsets: [o0, o1, o2],
465 buf,
466 })
467 }
468
469 pub fn header(&self) -> Header<&[u8]> {
471 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
472 }
473 pub fn stamp(&self) -> Time {
474 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
475 }
476 pub fn frame_id(&self) -> &str {
477 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
478 }
479
480 pub fn height(&self) -> u32 {
481 let p = align(self.offsets[0], 4);
482 rd_u32(self.buf.as_ref(), p)
483 }
484
485 pub fn width(&self) -> u32 {
486 let p = align(self.offsets[0], 4) + 4;
487 rd_u32(self.buf.as_ref(), p)
488 }
489
490 pub fn encoding(&self) -> &str {
491 let p = align(self.offsets[0], 4) + 8;
492 rd_string(self.buf.as_ref(), p).0
493 }
494
495 pub fn is_bigendian(&self) -> u8 {
496 rd_u8(self.buf.as_ref(), self.offsets[1])
497 }
498
499 pub fn step(&self) -> u32 {
500 let p = align(self.offsets[1] + 1, 4);
501 rd_u32(self.buf.as_ref(), p)
502 }
503
504 pub fn data(&self) -> &[u8] {
505 let p = align(self.offsets[1] + 1, 4) + 4;
506 rd_bytes(self.buf.as_ref(), p).0
507 }
508
509 pub fn as_cdr(&self) -> &[u8] {
510 self.buf.as_ref()
511 }
512 pub fn cdr_size(&self) -> usize {
513 self.buf.as_ref().len()
514 }
515 pub fn to_cdr(&self) -> Vec<u8> {
516 self.buf.as_ref().to_vec()
517 }
518}
519
520impl Image<Vec<u8>> {
521 #[deprecated(
522 since = "3.2.0",
523 note = "use Image::builder() for allocation-free buffer reuse; Image::new will be removed in 4.0"
524 )]
525 pub fn new(
526 stamp: Time,
527 frame_id: &str,
528 height: u32,
529 width: u32,
530 encoding: &str,
531 is_bigendian: u8,
532 step: u32,
533 data: &[u8],
534 ) -> Result<Self, CdrError> {
535 let mut sizer = CdrSizer::new();
536 Time::size_cdr(&mut sizer);
537 sizer.size_string(frame_id);
538 let o0 = sizer.offset();
539 sizer.size_u32(); sizer.size_u32(); sizer.size_string(encoding);
542 let o1 = sizer.offset();
543 sizer.size_u8(); sizer.size_u32(); sizer.size_bytes(data.len());
546 let o2 = sizer.offset();
547
548 let mut buf = vec![0u8; sizer.size()];
549 let mut w = CdrWriter::new(&mut buf)?;
550 stamp.write_cdr(&mut w);
551 w.write_string(frame_id);
552 w.write_u32(height);
553 w.write_u32(width);
554 w.write_string(encoding);
555 w.write_u8(is_bigendian);
556 w.write_u32(step);
557 w.write_bytes(data);
558 w.finish()?;
559
560 Ok(Image {
561 offsets: [o0, o1, o2],
562 buf,
563 })
564 }
565
566 pub fn into_cdr(self) -> Vec<u8> {
567 self.buf
568 }
569
570 pub fn builder<'a>() -> ImageBuilder<'a> {
576 ImageBuilder::new()
577 }
578}
579
580impl<B: AsRef<[u8]> + AsMut<[u8]>> Image<B> {
581 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
582 let b = self.buf.as_mut();
583 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
584 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
585 }
586
587 pub fn set_height(&mut self, h: u32) -> Result<(), CdrError> {
588 let p = align(self.offsets[0], 4);
589 wr_u32(self.buf.as_mut(), p, h)
590 }
591
592 pub fn set_width(&mut self, w: u32) -> Result<(), CdrError> {
593 let p = align(self.offsets[0], 4) + 4;
594 wr_u32(self.buf.as_mut(), p, w)
595 }
596
597 pub fn set_is_bigendian(&mut self, v: u8) -> Result<(), CdrError> {
598 wr_u8(self.buf.as_mut(), self.offsets[1], v)
599 }
600
601 pub fn set_step(&mut self, v: u32) -> Result<(), CdrError> {
602 let p = align(self.offsets[1] + 1, 4);
603 wr_u32(self.buf.as_mut(), p, v)
604 }
605}
606
607pub struct ImageBuilder<'a> {
616 stamp: Time,
617 frame_id: std::borrow::Cow<'a, str>,
618 height: u32,
619 width: u32,
620 encoding: std::borrow::Cow<'a, str>,
621 is_bigendian: u8,
622 step: u32,
623 data: &'a [u8],
624}
625
626impl<'a> Default for ImageBuilder<'a> {
627 fn default() -> Self {
628 Self {
629 stamp: Time { sec: 0, nanosec: 0 },
630 frame_id: std::borrow::Cow::Borrowed(""),
631 height: 0,
632 width: 0,
633 encoding: std::borrow::Cow::Borrowed(""),
634 is_bigendian: 0,
635 step: 0,
636 data: &[],
637 }
638 }
639}
640
641impl<'a> ImageBuilder<'a> {
642 pub fn new() -> Self {
643 Self::default()
644 }
645
646 pub fn stamp(&mut self, t: Time) -> &mut Self {
647 self.stamp = t;
648 self
649 }
650 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
651 self.frame_id = s.into();
652 self
653 }
654 pub fn height(&mut self, h: u32) -> &mut Self {
655 self.height = h;
656 self
657 }
658 pub fn width(&mut self, w: u32) -> &mut Self {
659 self.width = w;
660 self
661 }
662 pub fn encoding(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
663 self.encoding = s.into();
664 self
665 }
666 pub fn is_bigendian(&mut self, v: u8) -> &mut Self {
667 self.is_bigendian = v;
668 self
669 }
670 pub fn step(&mut self, v: u32) -> &mut Self {
671 self.step = v;
672 self
673 }
674 pub fn data(&mut self, d: &'a [u8]) -> &mut Self {
675 self.data = d;
676 self
677 }
678
679 fn size(&self) -> usize {
680 let mut s = CdrSizer::new();
681 Time::size_cdr(&mut s);
682 s.size_string(&self.frame_id);
683 s.size_u32(); s.size_u32(); s.size_string(&self.encoding);
686 s.size_u8(); s.size_u32(); s.size_bytes(self.data.len());
689 s.size()
690 }
691
692 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
693 let mut w = CdrWriter::new(buf)?;
694 self.stamp.write_cdr(&mut w);
695 w.write_string(&self.frame_id);
696 w.write_u32(self.height);
697 w.write_u32(self.width);
698 w.write_string(&self.encoding);
699 w.write_u8(self.is_bigendian);
700 w.write_u32(self.step);
701 w.write_bytes(self.data);
702 w.finish()
703 }
704
705 pub fn build(&self) -> Result<Image<Vec<u8>>, CdrError> {
707 let mut buf = vec![0u8; self.size()];
708 self.write_into(&mut buf)?;
709 Image::from_cdr(buf)
710 }
711
712 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
716 buf.resize(self.size(), 0);
717 self.write_into(buf)
718 }
719
720 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
724 let need = self.size();
725 if buf.len() < need {
726 return Err(CdrError::BufferTooShort {
727 need,
728 have: buf.len(),
729 });
730 }
731 self.write_into(&mut buf[..need])?;
732 Ok(need)
733 }
734}
735
736pub struct Imu<B> {
743 buf: B,
744 offsets: [usize; 1],
745}
746
747impl<B> Imu<B> {
748 #[inline]
750 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Imu<C> {
751 Imu {
752 buf: f(self.buf),
753 offsets: self.offsets,
754 }
755 }
756}
757
758impl<B: AsRef<[u8]>> Imu<B> {
759 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
760 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
761 let o0 = header.end_offset();
762 let mut c = CdrCursor::resume(buf.as_ref(), o0);
763 Quaternion::read_cdr(&mut c)?;
764 read_f64_array9(&mut c)?;
765 Vector3::read_cdr(&mut c)?;
766 read_f64_array9(&mut c)?;
767 Vector3::read_cdr(&mut c)?;
768 read_f64_array9(&mut c)?;
769 Ok(Imu { offsets: [o0], buf })
770 }
771
772 pub fn header(&self) -> Header<&[u8]> {
774 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
775 }
776 pub fn stamp(&self) -> Time {
777 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
778 }
779 pub fn frame_id(&self) -> &str {
780 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
781 }
782
783 fn fixed_base(&self) -> usize {
787 cdr_align(self.offsets[0], 8)
788 }
789
790 pub fn orientation(&self) -> Quaternion {
791 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
792 Quaternion::read_cdr(&mut c).expect("orientation field validated during from_cdr")
793 }
794
795 pub fn orientation_covariance(&self) -> [f64; 9] {
796 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 32);
797 read_f64_array9(&mut c).expect("covariance field validated during from_cdr")
798 }
799
800 pub fn angular_velocity(&self) -> Vector3 {
801 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 104);
802 Vector3::read_cdr(&mut c).expect("vector3 field validated during from_cdr")
803 }
804
805 pub fn angular_velocity_covariance(&self) -> [f64; 9] {
806 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 128);
807 read_f64_array9(&mut c).expect("covariance field validated during from_cdr")
808 }
809
810 pub fn linear_acceleration(&self) -> Vector3 {
811 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 200);
812 Vector3::read_cdr(&mut c).expect("vector3 field validated during from_cdr")
813 }
814
815 pub fn linear_acceleration_covariance(&self) -> [f64; 9] {
816 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 224);
817 read_f64_array9(&mut c).expect("covariance field validated during from_cdr")
818 }
819
820 pub fn as_cdr(&self) -> &[u8] {
821 self.buf.as_ref()
822 }
823 pub fn to_cdr(&self) -> Vec<u8> {
824 self.buf.as_ref().to_vec()
825 }
826}
827
828impl Imu<Vec<u8>> {
829 #[deprecated(
830 since = "3.2.0",
831 note = "use Imu::builder() for allocation-free buffer reuse; Imu::new will be removed in 4.0"
832 )]
833 pub fn new(
834 stamp: Time,
835 frame_id: &str,
836 orientation: Quaternion,
837 orientation_covariance: [f64; 9],
838 angular_velocity: Vector3,
839 angular_velocity_covariance: [f64; 9],
840 linear_acceleration: Vector3,
841 linear_acceleration_covariance: [f64; 9],
842 ) -> Result<Self, CdrError> {
843 let mut sizer = CdrSizer::new();
844 Time::size_cdr(&mut sizer);
845 sizer.size_string(frame_id);
846 let o0 = sizer.offset();
847 Quaternion::size_cdr(&mut sizer);
848 size_f64_array9(&mut sizer);
849 Vector3::size_cdr(&mut sizer);
850 size_f64_array9(&mut sizer);
851 Vector3::size_cdr(&mut sizer);
852 size_f64_array9(&mut sizer);
853
854 let mut buf = vec![0u8; sizer.size()];
855 let mut w = CdrWriter::new(&mut buf)?;
856 stamp.write_cdr(&mut w);
857 w.write_string(frame_id);
858 orientation.write_cdr(&mut w);
859 write_f64_array9(&mut w, &orientation_covariance);
860 angular_velocity.write_cdr(&mut w);
861 write_f64_array9(&mut w, &angular_velocity_covariance);
862 linear_acceleration.write_cdr(&mut w);
863 write_f64_array9(&mut w, &linear_acceleration_covariance);
864 w.finish()?;
865
866 Ok(Imu { offsets: [o0], buf })
867 }
868
869 pub fn into_cdr(self) -> Vec<u8> {
870 self.buf
871 }
872
873 pub fn builder<'a>() -> ImuBuilder<'a> {
875 ImuBuilder::new()
876 }
877}
878
879pub struct ImuBuilder<'a> {
883 stamp: Time,
884 frame_id: std::borrow::Cow<'a, str>,
885 orientation: Quaternion,
886 orientation_covariance: [f64; 9],
887 angular_velocity: Vector3,
888 angular_velocity_covariance: [f64; 9],
889 linear_acceleration: Vector3,
890 linear_acceleration_covariance: [f64; 9],
891}
892
893impl<'a> Default for ImuBuilder<'a> {
894 fn default() -> Self {
895 Self {
896 stamp: Time { sec: 0, nanosec: 0 },
897 frame_id: std::borrow::Cow::Borrowed(""),
898 orientation: Quaternion {
899 x: 0.0,
900 y: 0.0,
901 z: 0.0,
902 w: 0.0,
903 },
904 orientation_covariance: [0.0; 9],
905 angular_velocity: Vector3 {
906 x: 0.0,
907 y: 0.0,
908 z: 0.0,
909 },
910 angular_velocity_covariance: [0.0; 9],
911 linear_acceleration: Vector3 {
912 x: 0.0,
913 y: 0.0,
914 z: 0.0,
915 },
916 linear_acceleration_covariance: [0.0; 9],
917 }
918 }
919}
920
921impl<'a> ImuBuilder<'a> {
922 pub fn new() -> Self {
923 Self::default()
924 }
925
926 pub fn stamp(&mut self, t: Time) -> &mut Self {
927 self.stamp = t;
928 self
929 }
930 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
931 self.frame_id = s.into();
932 self
933 }
934 pub fn orientation(&mut self, q: Quaternion) -> &mut Self {
935 self.orientation = q;
936 self
937 }
938 pub fn orientation_covariance(&mut self, c: [f64; 9]) -> &mut Self {
939 self.orientation_covariance = c;
940 self
941 }
942 pub fn angular_velocity(&mut self, v: Vector3) -> &mut Self {
943 self.angular_velocity = v;
944 self
945 }
946 pub fn angular_velocity_covariance(&mut self, c: [f64; 9]) -> &mut Self {
947 self.angular_velocity_covariance = c;
948 self
949 }
950 pub fn linear_acceleration(&mut self, v: Vector3) -> &mut Self {
951 self.linear_acceleration = v;
952 self
953 }
954 pub fn linear_acceleration_covariance(&mut self, c: [f64; 9]) -> &mut Self {
955 self.linear_acceleration_covariance = c;
956 self
957 }
958
959 fn size(&self) -> usize {
960 let mut s = CdrSizer::new();
961 Time::size_cdr(&mut s);
962 s.size_string(&self.frame_id);
963 Quaternion::size_cdr(&mut s);
964 size_f64_array9(&mut s);
965 Vector3::size_cdr(&mut s);
966 size_f64_array9(&mut s);
967 Vector3::size_cdr(&mut s);
968 size_f64_array9(&mut s);
969 s.size()
970 }
971
972 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
973 let mut w = CdrWriter::new(buf)?;
974 self.stamp.write_cdr(&mut w);
975 w.write_string(&self.frame_id);
976 self.orientation.write_cdr(&mut w);
977 write_f64_array9(&mut w, &self.orientation_covariance);
978 self.angular_velocity.write_cdr(&mut w);
979 write_f64_array9(&mut w, &self.angular_velocity_covariance);
980 self.linear_acceleration.write_cdr(&mut w);
981 write_f64_array9(&mut w, &self.linear_acceleration_covariance);
982 w.finish()
983 }
984
985 pub fn build(&self) -> Result<Imu<Vec<u8>>, CdrError> {
986 let mut buf = vec![0u8; self.size()];
987 self.write_into(&mut buf)?;
988 Imu::from_cdr(buf)
989 }
990
991 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
992 buf.resize(self.size(), 0);
993 self.write_into(buf)
994 }
995
996 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
997 let need = self.size();
998 if buf.len() < need {
999 return Err(CdrError::BufferTooShort {
1000 need,
1001 have: buf.len(),
1002 });
1003 }
1004 self.write_into(&mut buf[..need])?;
1005 Ok(need)
1006 }
1007}
1008
1009impl<B: AsRef<[u8]> + AsMut<[u8]>> Imu<B> {
1010 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
1011 let b = self.buf.as_mut();
1012 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
1013 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
1014 }
1015
1016 pub fn set_orientation(&mut self, q: Quaternion) -> Result<(), CdrError> {
1017 let p = self.fixed_base();
1018 let b = self.buf.as_mut();
1019 wr_f64(b, p, q.x)?;
1020 wr_f64(b, p + 8, q.y)?;
1021 wr_f64(b, p + 16, q.z)?;
1022 wr_f64(b, p + 24, q.w)
1023 }
1024
1025 pub fn set_orientation_covariance(&mut self, c: [f64; 9]) -> Result<(), CdrError> {
1026 let p = self.fixed_base() + 32;
1027 let b = self.buf.as_mut();
1028 for (i, v) in c.iter().enumerate() {
1029 wr_f64(b, p + i * 8, *v)?;
1030 }
1031 Ok(())
1032 }
1033
1034 pub fn set_angular_velocity(&mut self, v: Vector3) -> Result<(), CdrError> {
1035 let p = self.fixed_base() + 104;
1036 let b = self.buf.as_mut();
1037 wr_f64(b, p, v.x)?;
1038 wr_f64(b, p + 8, v.y)?;
1039 wr_f64(b, p + 16, v.z)
1040 }
1041
1042 pub fn set_angular_velocity_covariance(&mut self, c: [f64; 9]) -> Result<(), CdrError> {
1043 let p = self.fixed_base() + 128;
1044 let b = self.buf.as_mut();
1045 for (i, v) in c.iter().enumerate() {
1046 wr_f64(b, p + i * 8, *v)?;
1047 }
1048 Ok(())
1049 }
1050
1051 pub fn set_linear_acceleration(&mut self, v: Vector3) -> Result<(), CdrError> {
1052 let p = self.fixed_base() + 200;
1053 let b = self.buf.as_mut();
1054 wr_f64(b, p, v.x)?;
1055 wr_f64(b, p + 8, v.y)?;
1056 wr_f64(b, p + 16, v.z)
1057 }
1058
1059 pub fn set_linear_acceleration_covariance(&mut self, c: [f64; 9]) -> Result<(), CdrError> {
1060 let p = self.fixed_base() + 224;
1061 let b = self.buf.as_mut();
1062 for (i, v) in c.iter().enumerate() {
1063 wr_f64(b, p + i * 8, *v)?;
1064 }
1065 Ok(())
1066 }
1067}
1068
1069pub struct NavSatFix<B> {
1084 buf: B,
1085 offsets: [usize; 2],
1086}
1087
1088impl<B> NavSatFix<B> {
1089 #[inline]
1091 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> NavSatFix<C> {
1092 NavSatFix {
1093 buf: f(self.buf),
1094 offsets: self.offsets,
1095 }
1096 }
1097}
1098
1099impl<B: AsRef<[u8]>> NavSatFix<B> {
1100 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
1101 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
1102 let o0 = header.end_offset();
1103 let mut c = CdrCursor::resume(buf.as_ref(), o0);
1104 NavSatStatus::read_cdr(&mut c)?;
1105 c.align(8);
1106 let o1 = c.offset();
1107 c.read_f64()?; c.read_f64()?; c.read_f64()?; read_f64_array9(&mut c)?; c.read_u8()?; Ok(NavSatFix {
1113 offsets: [o0, o1],
1114 buf,
1115 })
1116 }
1117
1118 pub fn header(&self) -> Header<&[u8]> {
1120 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
1121 }
1122 pub fn stamp(&self) -> Time {
1123 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
1124 }
1125 pub fn frame_id(&self) -> &str {
1126 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
1127 }
1128
1129 pub fn status(&self) -> NavSatStatus {
1130 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
1131 NavSatStatus::read_cdr(&mut c).expect("status field validated during from_cdr")
1132 }
1133
1134 #[inline]
1137 fn fixed_base(&self) -> usize {
1138 self.offsets[1]
1139 }
1140
1141 pub fn latitude(&self) -> f64 {
1142 rd_f64(self.buf.as_ref(), self.fixed_base())
1143 }
1144 pub fn longitude(&self) -> f64 {
1145 rd_f64(self.buf.as_ref(), self.fixed_base() + 8)
1146 }
1147 pub fn altitude(&self) -> f64 {
1148 rd_f64(self.buf.as_ref(), self.fixed_base() + 16)
1149 }
1150
1151 pub fn position_covariance(&self) -> [f64; 9] {
1152 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 24);
1153 read_f64_array9(&mut c).expect("covariance field validated during from_cdr")
1154 }
1155
1156 pub fn position_covariance_type(&self) -> u8 {
1157 rd_u8(self.buf.as_ref(), self.fixed_base() + 96)
1158 }
1159
1160 pub fn as_cdr(&self) -> &[u8] {
1161 self.buf.as_ref()
1162 }
1163 pub fn to_cdr(&self) -> Vec<u8> {
1164 self.buf.as_ref().to_vec()
1165 }
1166}
1167
1168impl NavSatFix<Vec<u8>> {
1169 #[deprecated(
1170 since = "3.2.0",
1171 note = "use NavSatFix::builder() for allocation-free buffer reuse; NavSatFix::new will be removed in 4.0"
1172 )]
1173 pub fn new(
1174 stamp: Time,
1175 frame_id: &str,
1176 status: NavSatStatus,
1177 latitude: f64,
1178 longitude: f64,
1179 altitude: f64,
1180 position_covariance: [f64; 9],
1181 position_covariance_type: u8,
1182 ) -> Result<Self, CdrError> {
1183 let mut sizer = CdrSizer::new();
1184 Time::size_cdr(&mut sizer);
1185 sizer.size_string(frame_id);
1186 let o0 = sizer.offset();
1187 NavSatStatus::size_cdr(&mut sizer);
1188 sizer.align(8);
1189 let o1 = sizer.offset();
1190 sizer.size_f64(); sizer.size_f64(); sizer.size_f64(); size_f64_array9(&mut sizer);
1194 sizer.size_u8(); let mut buf = vec![0u8; sizer.size()];
1197 let mut w = CdrWriter::new(&mut buf)?;
1198 stamp.write_cdr(&mut w);
1199 w.write_string(frame_id);
1200 status.write_cdr(&mut w);
1201 w.write_f64(latitude);
1202 w.write_f64(longitude);
1203 w.write_f64(altitude);
1204 write_f64_array9(&mut w, &position_covariance);
1205 w.write_u8(position_covariance_type);
1206 w.finish()?;
1207
1208 Ok(NavSatFix {
1209 offsets: [o0, o1],
1210 buf,
1211 })
1212 }
1213
1214 pub fn into_cdr(self) -> Vec<u8> {
1215 self.buf
1216 }
1217
1218 pub fn builder<'a>() -> NavSatFixBuilder<'a> {
1220 NavSatFixBuilder::new()
1221 }
1222}
1223
1224pub struct NavSatFixBuilder<'a> {
1228 stamp: Time,
1229 frame_id: std::borrow::Cow<'a, str>,
1230 status: NavSatStatus,
1231 latitude: f64,
1232 longitude: f64,
1233 altitude: f64,
1234 position_covariance: [f64; 9],
1235 position_covariance_type: u8,
1236}
1237
1238impl<'a> Default for NavSatFixBuilder<'a> {
1239 fn default() -> Self {
1240 Self {
1241 stamp: Time { sec: 0, nanosec: 0 },
1242 frame_id: std::borrow::Cow::Borrowed(""),
1243 status: NavSatStatus {
1244 status: 0,
1245 service: 0,
1246 },
1247 latitude: 0.0,
1248 longitude: 0.0,
1249 altitude: 0.0,
1250 position_covariance: [0.0; 9],
1251 position_covariance_type: 0,
1252 }
1253 }
1254}
1255
1256impl<'a> NavSatFixBuilder<'a> {
1257 pub fn new() -> Self {
1258 Self::default()
1259 }
1260
1261 pub fn stamp(&mut self, t: Time) -> &mut Self {
1262 self.stamp = t;
1263 self
1264 }
1265 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1266 self.frame_id = s.into();
1267 self
1268 }
1269 pub fn status(&mut self, s: NavSatStatus) -> &mut Self {
1270 self.status = s;
1271 self
1272 }
1273 pub fn latitude(&mut self, v: f64) -> &mut Self {
1274 self.latitude = v;
1275 self
1276 }
1277 pub fn longitude(&mut self, v: f64) -> &mut Self {
1278 self.longitude = v;
1279 self
1280 }
1281 pub fn altitude(&mut self, v: f64) -> &mut Self {
1282 self.altitude = v;
1283 self
1284 }
1285 pub fn position_covariance(&mut self, c: [f64; 9]) -> &mut Self {
1286 self.position_covariance = c;
1287 self
1288 }
1289 pub fn position_covariance_type(&mut self, v: u8) -> &mut Self {
1290 self.position_covariance_type = v;
1291 self
1292 }
1293
1294 fn size(&self) -> usize {
1295 let mut s = CdrSizer::new();
1296 Time::size_cdr(&mut s);
1297 s.size_string(&self.frame_id);
1298 NavSatStatus::size_cdr(&mut s);
1299 s.align(8);
1300 s.size_f64(); s.size_f64(); s.size_f64(); size_f64_array9(&mut s);
1304 s.size_u8(); s.size()
1306 }
1307
1308 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
1309 let mut w = CdrWriter::new(buf)?;
1310 self.stamp.write_cdr(&mut w);
1311 w.write_string(&self.frame_id);
1312 self.status.write_cdr(&mut w);
1313 w.write_f64(self.latitude);
1314 w.write_f64(self.longitude);
1315 w.write_f64(self.altitude);
1316 write_f64_array9(&mut w, &self.position_covariance);
1317 w.write_u8(self.position_covariance_type);
1318 w.finish()
1319 }
1320
1321 pub fn build(&self) -> Result<NavSatFix<Vec<u8>>, CdrError> {
1322 let mut buf = vec![0u8; self.size()];
1323 self.write_into(&mut buf)?;
1324 NavSatFix::from_cdr(buf)
1325 }
1326
1327 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
1328 buf.resize(self.size(), 0);
1329 self.write_into(buf)
1330 }
1331
1332 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
1333 let need = self.size();
1334 if buf.len() < need {
1335 return Err(CdrError::BufferTooShort {
1336 need,
1337 have: buf.len(),
1338 });
1339 }
1340 self.write_into(&mut buf[..need])?;
1341 Ok(need)
1342 }
1343}
1344
1345impl<B: AsRef<[u8]> + AsMut<[u8]>> NavSatFix<B> {
1346 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
1347 let b = self.buf.as_mut();
1348 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
1349 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
1350 }
1351
1352 pub fn set_status(&mut self, s: NavSatStatus) -> Result<(), CdrError> {
1359 let status_pos = self.offsets[0];
1360 let service_pos = cdr_align(status_pos + 1, 2);
1361 let b = self.buf.as_mut();
1362 wr_i8(b, status_pos, s.status)?;
1363 wr_u16(b, service_pos, s.service)
1364 }
1365
1366 pub fn set_latitude(&mut self, v: f64) -> Result<(), CdrError> {
1367 let p = self.fixed_base();
1368 wr_f64(self.buf.as_mut(), p, v)
1369 }
1370
1371 pub fn set_longitude(&mut self, v: f64) -> Result<(), CdrError> {
1372 let p = self.fixed_base() + 8;
1373 wr_f64(self.buf.as_mut(), p, v)
1374 }
1375
1376 pub fn set_altitude(&mut self, v: f64) -> Result<(), CdrError> {
1377 let p = self.fixed_base() + 16;
1378 wr_f64(self.buf.as_mut(), p, v)
1379 }
1380
1381 pub fn set_position_covariance(&mut self, c: [f64; 9]) -> Result<(), CdrError> {
1382 let p = self.fixed_base() + 24;
1383 let b = self.buf.as_mut();
1384 for (i, v) in c.iter().enumerate() {
1385 wr_f64(b, p + i * 8, *v)?;
1386 }
1387 Ok(())
1388 }
1389
1390 pub fn set_position_covariance_type(&mut self, v: u8) -> Result<(), CdrError> {
1391 let p = self.fixed_base() + 96;
1392 wr_u8(self.buf.as_mut(), p, v)
1393 }
1394}
1395
1396pub struct PointField<B> {
1401 buf: B,
1402 offsets: [usize; 1],
1403}
1404
1405impl<B> PointField<B> {
1406 #[inline]
1408 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> PointField<C> {
1409 PointField {
1410 buf: f(self.buf),
1411 offsets: self.offsets,
1412 }
1413 }
1414}
1415
1416impl<B: AsRef<[u8]>> PointField<B> {
1417 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
1418 let mut c = CdrCursor::new(buf.as_ref())?;
1419 let _ = c.read_string()?;
1420 let o0 = c.offset();
1421 c.read_u32()?;
1422 c.read_u8()?;
1423 c.read_u32()?;
1424 Ok(PointField { offsets: [o0], buf })
1425 }
1426
1427 #[inline]
1428 pub fn name(&self) -> &str {
1429 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE).0
1430 }
1431
1432 pub fn offset(&self) -> u32 {
1433 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
1434 c.read_u32()
1435 .expect("point field element validated during from_cdr")
1436 }
1437
1438 pub fn datatype(&self) -> u8 {
1439 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
1440 c.read_u32()
1441 .expect("point field element validated during from_cdr"); c.read_u8()
1443 .expect("point field element validated during from_cdr")
1444 }
1445
1446 pub fn count(&self) -> u32 {
1447 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
1448 c.read_u32()
1449 .expect("point field element validated during from_cdr"); c.read_u8()
1451 .expect("point field element validated during from_cdr"); c.read_u32()
1453 .expect("point field element validated during from_cdr")
1454 }
1455
1456 #[inline]
1457 pub fn as_cdr(&self) -> &[u8] {
1458 self.buf.as_ref()
1459 }
1460 pub fn to_cdr(&self) -> Vec<u8> {
1461 self.buf.as_ref().to_vec()
1462 }
1463}
1464
1465impl PointField<Vec<u8>> {
1466 #[deprecated(
1467 since = "3.2.0",
1468 note = "use PointField::builder() for allocation-free buffer reuse; PointField::new will be removed in 4.0"
1469 )]
1470 pub fn new(name: &str, offset: u32, datatype: u8, count: u32) -> Result<Self, CdrError> {
1471 let mut sizer = CdrSizer::new();
1472 sizer.size_string(name);
1473 let o0 = sizer.offset();
1474 sizer.size_u32();
1475 sizer.size_u8();
1476 sizer.size_u32();
1477
1478 let mut buf = vec![0u8; sizer.size()];
1479 let mut w = CdrWriter::new(&mut buf)?;
1480 w.write_string(name);
1481 w.write_u32(offset);
1482 w.write_u8(datatype);
1483 w.write_u32(count);
1484 w.finish()?;
1485
1486 Ok(PointField { offsets: [o0], buf })
1487 }
1488
1489 pub fn into_cdr(self) -> Vec<u8> {
1490 self.buf
1491 }
1492
1493 pub fn builder<'a>() -> PointFieldBuilder<'a> {
1495 PointFieldBuilder::new()
1496 }
1497}
1498
1499pub struct PointFieldBuilder<'a> {
1503 name: std::borrow::Cow<'a, str>,
1504 offset: u32,
1505 datatype: u8,
1506 count: u32,
1507}
1508
1509impl<'a> Default for PointFieldBuilder<'a> {
1510 fn default() -> Self {
1511 Self {
1512 name: std::borrow::Cow::Borrowed(""),
1513 offset: 0,
1514 datatype: 0,
1515 count: 0,
1516 }
1517 }
1518}
1519
1520impl<'a> PointFieldBuilder<'a> {
1521 pub fn new() -> Self {
1522 Self::default()
1523 }
1524
1525 pub fn name(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1526 self.name = s.into();
1527 self
1528 }
1529 pub fn offset(&mut self, v: u32) -> &mut Self {
1530 self.offset = v;
1531 self
1532 }
1533 pub fn datatype(&mut self, v: u8) -> &mut Self {
1534 self.datatype = v;
1535 self
1536 }
1537 pub fn count(&mut self, v: u32) -> &mut Self {
1538 self.count = v;
1539 self
1540 }
1541
1542 fn size(&self) -> usize {
1543 let mut s = CdrSizer::new();
1544 s.size_string(&self.name);
1545 s.size_u32();
1546 s.size_u8();
1547 s.size_u32();
1548 s.size()
1549 }
1550
1551 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
1552 let mut w = CdrWriter::new(buf)?;
1553 w.write_string(&self.name);
1554 w.write_u32(self.offset);
1555 w.write_u8(self.datatype);
1556 w.write_u32(self.count);
1557 w.finish()
1558 }
1559
1560 pub fn build(&self) -> Result<PointField<Vec<u8>>, CdrError> {
1561 let mut buf = vec![0u8; self.size()];
1562 self.write_into(&mut buf)?;
1563 PointField::from_cdr(buf)
1564 }
1565
1566 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
1567 buf.resize(self.size(), 0);
1568 self.write_into(buf)
1569 }
1570
1571 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
1572 let need = self.size();
1573 if buf.len() < need {
1574 return Err(CdrError::BufferTooShort {
1575 need,
1576 have: buf.len(),
1577 });
1578 }
1579 self.write_into(&mut buf[..need])?;
1580 Ok(need)
1581 }
1582}
1583
1584impl<B: AsRef<[u8]> + AsMut<[u8]>> PointField<B> {
1585 #[inline]
1587 fn offset_pos(&self) -> usize {
1588 cdr_align(self.offsets[0], 4)
1589 }
1590
1591 pub fn set_offset(&mut self, v: u32) -> Result<(), CdrError> {
1592 let p = self.offset_pos();
1593 wr_u32(self.buf.as_mut(), p, v)
1594 }
1595
1596 pub fn set_datatype(&mut self, v: u8) -> Result<(), CdrError> {
1597 let p = self.offset_pos() + 4;
1598 wr_u8(self.buf.as_mut(), p, v)
1599 }
1600
1601 pub fn set_count(&mut self, v: u32) -> Result<(), CdrError> {
1602 let p = cdr_align(self.offset_pos() + 5, 4);
1604 wr_u32(self.buf.as_mut(), p, v)
1605 }
1606}
1607
1608pub struct PointCloud2<B> {
1617 buf: B,
1618 offsets: [usize; 3],
1619}
1620
1621impl<B> PointCloud2<B> {
1622 #[inline]
1624 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> PointCloud2<C> {
1625 PointCloud2 {
1626 buf: f(self.buf),
1627 offsets: self.offsets,
1628 }
1629 }
1630}
1631
1632impl<B: AsRef<[u8]>> PointCloud2<B> {
1633 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
1634 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
1635 let o0 = header.end_offset();
1636 let mut c = CdrCursor::resume(buf.as_ref(), o0);
1637 c.read_u32()?; c.read_u32()?; let raw_fields = c.read_u32()?;
1640 let fields_count = c.check_seq_count(raw_fields, 9)?;
1641 for _ in 0..fields_count {
1642 scan_point_field_element(&mut c)?;
1643 }
1644 let o1 = c.offset();
1645 c.read_bool()?; c.read_u32()?; c.read_u32()?; let _ = c.read_bytes()?; let o2 = c.offset();
1650 c.read_bool()?; Ok(PointCloud2 {
1652 offsets: [o0, o1, o2],
1653 buf,
1654 })
1655 }
1656
1657 pub fn header(&self) -> Header<&[u8]> {
1659 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
1660 }
1661 pub fn stamp(&self) -> Time {
1662 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
1663 }
1664 pub fn frame_id(&self) -> &str {
1665 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
1666 }
1667
1668 pub fn height(&self) -> u32 {
1669 rd_u32(self.buf.as_ref(), align(self.offsets[0], 4))
1670 }
1671 pub fn width(&self) -> u32 {
1672 rd_u32(self.buf.as_ref(), align(self.offsets[0], 4) + 4)
1673 }
1674 pub fn fields_len(&self) -> u32 {
1675 rd_u32(self.buf.as_ref(), align(self.offsets[0], 4) + 8)
1676 }
1677
1678 pub fn fields(&self) -> Vec<PointFieldView<'_>> {
1679 let b = self.buf.as_ref();
1680 let p = align(self.offsets[0], 4) + 8;
1681 let count = rd_u32(b, p) as usize;
1682 let mut c = CdrCursor::resume(b, p + 4);
1683 (0..count)
1684 .map(|_| {
1685 scan_point_field_element(&mut c)
1686 .expect("point field elements validated during from_cdr")
1687 })
1688 .collect()
1689 }
1690
1691 pub fn fields_iter(&self) -> PointFieldIter<'_> {
1693 let b = self.buf.as_ref();
1694 let p = align(self.offsets[0], 4) + 8;
1695 let count = rd_u32(b, p) as usize;
1696 let cursor = CdrCursor::resume(b, p + 4);
1697 PointFieldIter {
1698 cursor,
1699 remaining: count,
1700 }
1701 }
1702
1703 pub fn point_count(&self) -> usize {
1705 (self.height() as usize) * (self.width() as usize)
1706 }
1707
1708 pub fn as_dyn_cloud(
1710 &self,
1711 ) -> Result<pointcloud::DynPointCloud<'_>, pointcloud::PointCloudError> {
1712 pointcloud::DynPointCloud::from_pointcloud2(self)
1713 }
1714
1715 pub fn as_typed_cloud<P: pointcloud::Point>(
1717 &self,
1718 ) -> Result<pointcloud::PointCloud<'_, P>, pointcloud::PointCloudError> {
1719 pointcloud::PointCloud::from_pointcloud2(self)
1720 }
1721
1722 pub fn is_bigendian(&self) -> bool {
1723 rd_bool(self.buf.as_ref(), self.offsets[1])
1724 }
1725 pub fn point_step(&self) -> u32 {
1726 rd_u32(self.buf.as_ref(), align(self.offsets[1] + 1, 4))
1727 }
1728 pub fn row_step(&self) -> u32 {
1729 rd_u32(self.buf.as_ref(), align(self.offsets[1] + 1, 4) + 4)
1730 }
1731
1732 pub fn data(&self) -> &[u8] {
1733 rd_bytes(self.buf.as_ref(), align(self.offsets[1] + 1, 4) + 8).0
1734 }
1735
1736 pub fn is_dense(&self) -> bool {
1737 rd_bool(self.buf.as_ref(), self.offsets[2])
1738 }
1739
1740 pub fn as_cdr(&self) -> &[u8] {
1741 self.buf.as_ref()
1742 }
1743 pub fn to_cdr(&self) -> Vec<u8> {
1744 self.buf.as_ref().to_vec()
1745 }
1746}
1747
1748impl PointCloud2<Vec<u8>> {
1749 #[deprecated(
1750 since = "3.2.0",
1751 note = "use PointCloud2::builder() for allocation-free buffer reuse; PointCloud2::new will be removed in 4.0"
1752 )]
1753 pub fn new(
1754 stamp: Time,
1755 frame_id: &str,
1756 height: u32,
1757 width: u32,
1758 fields: &[PointFieldView<'_>],
1759 is_bigendian: bool,
1760 point_step: u32,
1761 row_step: u32,
1762 data: &[u8],
1763 is_dense: bool,
1764 ) -> Result<Self, CdrError> {
1765 let mut sizer = CdrSizer::new();
1766 Time::size_cdr(&mut sizer);
1767 sizer.size_string(frame_id);
1768 let o0 = sizer.offset();
1769 sizer.size_u32(); sizer.size_u32(); sizer.size_u32(); for f in fields {
1773 size_point_field_element(&mut sizer, f.name);
1774 }
1775 let o1 = sizer.offset();
1776 sizer.size_bool(); sizer.size_u32(); sizer.size_u32(); sizer.size_bytes(data.len());
1780 let o2 = sizer.offset();
1781 sizer.size_bool(); let mut buf = vec![0u8; sizer.size()];
1784 let mut w = CdrWriter::new(&mut buf)?;
1785 stamp.write_cdr(&mut w);
1786 w.write_string(frame_id);
1787 w.write_u32(height);
1788 w.write_u32(width);
1789 w.write_u32(fields.len() as u32);
1790 for f in fields {
1791 write_point_field_element(&mut w, f);
1792 }
1793 w.write_bool(is_bigendian);
1794 w.write_u32(point_step);
1795 w.write_u32(row_step);
1796 w.write_bytes(data);
1797 w.write_bool(is_dense);
1798 w.finish()?;
1799
1800 Ok(PointCloud2 {
1801 offsets: [o0, o1, o2],
1802 buf,
1803 })
1804 }
1805
1806 pub fn into_cdr(self) -> Vec<u8> {
1807 self.buf
1808 }
1809
1810 pub fn builder<'a>() -> PointCloud2Builder<'a> {
1815 PointCloud2Builder::new()
1816 }
1817}
1818
1819pub struct PointCloud2Builder<'a> {
1827 stamp: Time,
1828 frame_id: std::borrow::Cow<'a, str>,
1829 height: u32,
1830 width: u32,
1831 fields: &'a [PointFieldView<'a>],
1832 is_bigendian: bool,
1833 point_step: u32,
1834 row_step: u32,
1835 data: &'a [u8],
1836 is_dense: bool,
1837}
1838
1839impl<'a> Default for PointCloud2Builder<'a> {
1840 fn default() -> Self {
1841 Self {
1842 stamp: Time { sec: 0, nanosec: 0 },
1843 frame_id: std::borrow::Cow::Borrowed(""),
1844 height: 0,
1845 width: 0,
1846 fields: &[],
1847 is_bigendian: false,
1848 point_step: 0,
1849 row_step: 0,
1850 data: &[],
1851 is_dense: false,
1852 }
1853 }
1854}
1855
1856impl<'a> PointCloud2Builder<'a> {
1857 pub fn new() -> Self {
1858 Self::default()
1859 }
1860
1861 pub fn stamp(&mut self, t: Time) -> &mut Self {
1862 self.stamp = t;
1863 self
1864 }
1865 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
1866 self.frame_id = s.into();
1867 self
1868 }
1869 pub fn height(&mut self, v: u32) -> &mut Self {
1870 self.height = v;
1871 self
1872 }
1873 pub fn width(&mut self, v: u32) -> &mut Self {
1874 self.width = v;
1875 self
1876 }
1877 pub fn fields(&mut self, f: &'a [PointFieldView<'a>]) -> &mut Self {
1878 self.fields = f;
1879 self
1880 }
1881 pub fn is_bigendian(&mut self, v: bool) -> &mut Self {
1882 self.is_bigendian = v;
1883 self
1884 }
1885 pub fn point_step(&mut self, v: u32) -> &mut Self {
1886 self.point_step = v;
1887 self
1888 }
1889 pub fn row_step(&mut self, v: u32) -> &mut Self {
1890 self.row_step = v;
1891 self
1892 }
1893 pub fn data(&mut self, d: &'a [u8]) -> &mut Self {
1894 self.data = d;
1895 self
1896 }
1897 pub fn is_dense(&mut self, v: bool) -> &mut Self {
1898 self.is_dense = v;
1899 self
1900 }
1901
1902 fn size(&self) -> usize {
1903 let mut s = CdrSizer::new();
1904 Time::size_cdr(&mut s);
1905 s.size_string(&self.frame_id);
1906 s.size_u32(); s.size_u32(); s.size_u32(); for f in self.fields {
1910 size_point_field_element(&mut s, f.name);
1911 }
1912 s.size_bool(); s.size_u32(); s.size_u32(); s.size_bytes(self.data.len());
1916 s.size_bool(); s.size()
1918 }
1919
1920 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
1921 let mut w = CdrWriter::new(buf)?;
1922 self.stamp.write_cdr(&mut w);
1923 w.write_string(&self.frame_id);
1924 w.write_u32(self.height);
1925 w.write_u32(self.width);
1926 w.write_u32(self.fields.len() as u32);
1927 for f in self.fields {
1928 write_point_field_element(&mut w, f);
1929 }
1930 w.write_bool(self.is_bigendian);
1931 w.write_u32(self.point_step);
1932 w.write_u32(self.row_step);
1933 w.write_bytes(self.data);
1934 w.write_bool(self.is_dense);
1935 w.finish()
1936 }
1937
1938 pub fn build(&self) -> Result<PointCloud2<Vec<u8>>, CdrError> {
1939 let mut buf = vec![0u8; self.size()];
1940 self.write_into(&mut buf)?;
1941 PointCloud2::from_cdr(buf)
1942 }
1943
1944 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
1945 buf.resize(self.size(), 0);
1946 self.write_into(buf)
1947 }
1948
1949 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
1950 let need = self.size();
1951 if buf.len() < need {
1952 return Err(CdrError::BufferTooShort {
1953 need,
1954 have: buf.len(),
1955 });
1956 }
1957 self.write_into(&mut buf[..need])?;
1958 Ok(need)
1959 }
1960}
1961
1962impl<B: AsRef<[u8]> + AsMut<[u8]>> PointCloud2<B> {
1963 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
1964 let b = self.buf.as_mut();
1965 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
1966 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
1967 }
1968
1969 pub fn set_height(&mut self, h: u32) -> Result<(), CdrError> {
1970 let p = align(self.offsets[0], 4);
1971 wr_u32(self.buf.as_mut(), p, h)
1972 }
1973
1974 pub fn set_width(&mut self, w: u32) -> Result<(), CdrError> {
1975 let p = align(self.offsets[0], 4) + 4;
1976 wr_u32(self.buf.as_mut(), p, w)
1977 }
1978
1979 pub fn set_is_bigendian(&mut self, v: bool) -> Result<(), CdrError> {
1980 wr_bool(self.buf.as_mut(), self.offsets[1], v)
1981 }
1982
1983 pub fn set_point_step(&mut self, v: u32) -> Result<(), CdrError> {
1984 let p = align(self.offsets[1] + 1, 4);
1985 wr_u32(self.buf.as_mut(), p, v)
1986 }
1987
1988 pub fn set_row_step(&mut self, v: u32) -> Result<(), CdrError> {
1989 let p = align(self.offsets[1] + 1, 4) + 4;
1990 wr_u32(self.buf.as_mut(), p, v)
1991 }
1992
1993 pub fn set_is_dense(&mut self, v: bool) -> Result<(), CdrError> {
1994 wr_bool(self.buf.as_mut(), self.offsets[2], v)
1995 }
1996}
1997
1998pub struct CameraInfo<B> {
2006 buf: B,
2007 offsets: [usize; 3],
2008}
2009
2010impl<B> CameraInfo<B> {
2011 #[inline]
2013 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> CameraInfo<C> {
2014 CameraInfo {
2015 buf: f(self.buf),
2016 offsets: self.offsets,
2017 }
2018 }
2019}
2020
2021impl<B: AsRef<[u8]>> CameraInfo<B> {
2022 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
2023 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
2024 let o0 = header.end_offset();
2025 let mut c = CdrCursor::resume(buf.as_ref(), o0);
2026 c.read_u32()?; c.read_u32()?; let _ = c.read_string()?; let o1 = c.offset();
2030 let d_count = c.read_u32()? as usize;
2031 c.skip_seq_8(d_count)?;
2032 let o2 = c.offset();
2033 read_f64_array9(&mut c)?; read_f64_array9(&mut c)?; read_f64_array12(&mut c)?; c.read_u32()?; c.read_u32()?; RegionOfInterest::read_cdr(&mut c)?;
2039 Ok(CameraInfo {
2040 offsets: [o0, o1, o2],
2041 buf,
2042 })
2043 }
2044
2045 pub fn header(&self) -> Header<&[u8]> {
2047 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
2048 }
2049 pub fn stamp(&self) -> Time {
2050 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
2051 }
2052 pub fn frame_id(&self) -> &str {
2053 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
2054 }
2055
2056 pub fn height(&self) -> u32 {
2057 rd_u32(self.buf.as_ref(), align(self.offsets[0], 4))
2058 }
2059 pub fn width(&self) -> u32 {
2060 rd_u32(self.buf.as_ref(), align(self.offsets[0], 4) + 4)
2061 }
2062
2063 pub fn distortion_model(&self) -> &str {
2064 rd_string(self.buf.as_ref(), align(self.offsets[0], 4) + 8).0
2065 }
2066
2067 pub fn d_len(&self) -> usize {
2069 rd_u32(self.buf.as_ref(), align(self.offsets[1], 4)) as usize
2070 }
2071
2072 pub fn d_get(&self, i: usize) -> f64 {
2074 let start = cdr_align(align(self.offsets[1], 4) + 4, 8);
2075 rd_f64(self.buf.as_ref(), start + i * 8)
2076 }
2077
2078 fn fixed_base(&self) -> usize {
2080 cdr_align(self.offsets[2], 8)
2081 }
2082
2083 pub fn k(&self) -> [f64; 9] {
2084 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base());
2085 read_f64_array9(&mut c).expect("covariance field validated during from_cdr")
2086 }
2087
2088 pub fn r(&self) -> [f64; 9] {
2089 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 72);
2090 read_f64_array9(&mut c).expect("covariance field validated during from_cdr")
2091 }
2092
2093 pub fn p(&self) -> [f64; 12] {
2094 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 144);
2095 read_f64_array12(&mut c).expect("projection matrix validated during from_cdr")
2096 }
2097
2098 pub fn binning_x(&self) -> u32 {
2099 rd_u32(self.buf.as_ref(), self.fixed_base() + 240)
2100 }
2101 pub fn binning_y(&self) -> u32 {
2102 rd_u32(self.buf.as_ref(), self.fixed_base() + 244)
2103 }
2104
2105 pub fn roi(&self) -> RegionOfInterest {
2106 let mut c = CdrCursor::resume(self.buf.as_ref(), self.fixed_base() + 248);
2107 RegionOfInterest::read_cdr(&mut c).expect("roi field validated during from_cdr")
2108 }
2109
2110 pub fn as_cdr(&self) -> &[u8] {
2111 self.buf.as_ref()
2112 }
2113 pub fn to_cdr(&self) -> Vec<u8> {
2114 self.buf.as_ref().to_vec()
2115 }
2116}
2117
2118impl CameraInfo<Vec<u8>> {
2119 #[deprecated(
2120 since = "3.2.0",
2121 note = "use CameraInfo::builder() for allocation-free buffer reuse; CameraInfo::new will be removed in 4.0"
2122 )]
2123 #[allow(clippy::too_many_arguments)]
2124 pub fn new(
2125 stamp: Time,
2126 frame_id: &str,
2127 height: u32,
2128 width: u32,
2129 distortion_model: &str,
2130 d: &[f64],
2131 k: [f64; 9],
2132 r: [f64; 9],
2133 p: [f64; 12],
2134 binning_x: u32,
2135 binning_y: u32,
2136 roi: RegionOfInterest,
2137 ) -> Result<Self, CdrError> {
2138 let mut sizer = CdrSizer::new();
2139 Time::size_cdr(&mut sizer);
2140 sizer.size_string(frame_id);
2141 let o0 = sizer.offset();
2142 sizer.size_u32(); sizer.size_u32(); sizer.size_string(distortion_model);
2145 let o1 = sizer.offset();
2146 sizer.size_u32();
2147 sizer.size_seq_8(d.len());
2148 let o2 = sizer.offset();
2149 size_f64_array9(&mut sizer);
2150 size_f64_array9(&mut sizer);
2151 size_f64_array12(&mut sizer);
2152 sizer.size_u32(); sizer.size_u32(); RegionOfInterest::size_cdr(&mut sizer);
2155
2156 let mut buf = vec![0u8; sizer.size()];
2157 let mut w = CdrWriter::new(&mut buf)?;
2158 stamp.write_cdr(&mut w);
2159 w.write_string(frame_id);
2160 w.write_u32(height);
2161 w.write_u32(width);
2162 w.write_string(distortion_model);
2163 w.write_u32(d.len() as u32);
2164 w.write_slice_f64(d);
2165 write_f64_array9(&mut w, &k);
2166 write_f64_array9(&mut w, &r);
2167 write_f64_array12(&mut w, &p);
2168 w.write_u32(binning_x);
2169 w.write_u32(binning_y);
2170 roi.write_cdr(&mut w);
2171 w.finish()?;
2172
2173 Ok(CameraInfo {
2174 offsets: [o0, o1, o2],
2175 buf,
2176 })
2177 }
2178
2179 pub fn into_cdr(self) -> Vec<u8> {
2180 self.buf
2181 }
2182
2183 pub fn builder<'a>() -> CameraInfoBuilder<'a> {
2185 CameraInfoBuilder::new()
2186 }
2187}
2188
2189pub struct CameraInfoBuilder<'a> {
2196 stamp: Time,
2197 frame_id: std::borrow::Cow<'a, str>,
2198 height: u32,
2199 width: u32,
2200 distortion_model: std::borrow::Cow<'a, str>,
2201 d: &'a [f64],
2202 k: [f64; 9],
2203 r: [f64; 9],
2204 p: [f64; 12],
2205 binning_x: u32,
2206 binning_y: u32,
2207 roi: RegionOfInterest,
2208}
2209
2210impl<'a> Default for CameraInfoBuilder<'a> {
2211 fn default() -> Self {
2212 Self {
2213 stamp: Time { sec: 0, nanosec: 0 },
2214 frame_id: std::borrow::Cow::Borrowed(""),
2215 height: 0,
2216 width: 0,
2217 distortion_model: std::borrow::Cow::Borrowed(""),
2218 d: &[],
2219 k: [0.0; 9],
2220 r: [0.0; 9],
2221 p: [0.0; 12],
2222 binning_x: 0,
2223 binning_y: 0,
2224 roi: RegionOfInterest {
2225 x_offset: 0,
2226 y_offset: 0,
2227 height: 0,
2228 width: 0,
2229 do_rectify: false,
2230 },
2231 }
2232 }
2233}
2234
2235impl<'a> CameraInfoBuilder<'a> {
2236 pub fn new() -> Self {
2237 Self::default()
2238 }
2239
2240 pub fn stamp(&mut self, t: Time) -> &mut Self {
2241 self.stamp = t;
2242 self
2243 }
2244 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2245 self.frame_id = s.into();
2246 self
2247 }
2248 pub fn height(&mut self, v: u32) -> &mut Self {
2249 self.height = v;
2250 self
2251 }
2252 pub fn width(&mut self, v: u32) -> &mut Self {
2253 self.width = v;
2254 self
2255 }
2256 pub fn distortion_model(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2257 self.distortion_model = s.into();
2258 self
2259 }
2260 pub fn d(&mut self, d: &'a [f64]) -> &mut Self {
2261 self.d = d;
2262 self
2263 }
2264 pub fn k(&mut self, k: [f64; 9]) -> &mut Self {
2265 self.k = k;
2266 self
2267 }
2268 pub fn r(&mut self, r: [f64; 9]) -> &mut Self {
2269 self.r = r;
2270 self
2271 }
2272 pub fn p(&mut self, p: [f64; 12]) -> &mut Self {
2273 self.p = p;
2274 self
2275 }
2276 pub fn binning_x(&mut self, v: u32) -> &mut Self {
2277 self.binning_x = v;
2278 self
2279 }
2280 pub fn binning_y(&mut self, v: u32) -> &mut Self {
2281 self.binning_y = v;
2282 self
2283 }
2284 pub fn roi(&mut self, r: RegionOfInterest) -> &mut Self {
2285 self.roi = r;
2286 self
2287 }
2288
2289 fn size(&self) -> usize {
2290 let mut s = CdrSizer::new();
2291 Time::size_cdr(&mut s);
2292 s.size_string(&self.frame_id);
2293 s.size_u32(); s.size_u32(); s.size_string(&self.distortion_model);
2296 s.size_u32();
2297 s.size_seq_8(self.d.len());
2298 size_f64_array9(&mut s);
2299 size_f64_array9(&mut s);
2300 size_f64_array12(&mut s);
2301 s.size_u32(); s.size_u32(); RegionOfInterest::size_cdr(&mut s);
2304 s.size()
2305 }
2306
2307 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
2308 let mut w = CdrWriter::new(buf)?;
2309 self.stamp.write_cdr(&mut w);
2310 w.write_string(&self.frame_id);
2311 w.write_u32(self.height);
2312 w.write_u32(self.width);
2313 w.write_string(&self.distortion_model);
2314 w.write_u32(self.d.len() as u32);
2315 w.write_slice_f64(self.d);
2316 write_f64_array9(&mut w, &self.k);
2317 write_f64_array9(&mut w, &self.r);
2318 write_f64_array12(&mut w, &self.p);
2319 w.write_u32(self.binning_x);
2320 w.write_u32(self.binning_y);
2321 self.roi.write_cdr(&mut w);
2322 w.finish()
2323 }
2324
2325 pub fn build(&self) -> Result<CameraInfo<Vec<u8>>, CdrError> {
2326 let mut buf = vec![0u8; self.size()];
2327 self.write_into(&mut buf)?;
2328 CameraInfo::from_cdr(buf)
2329 }
2330
2331 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
2332 buf.resize(self.size(), 0);
2333 self.write_into(buf)
2334 }
2335
2336 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
2337 let need = self.size();
2338 if buf.len() < need {
2339 return Err(CdrError::BufferTooShort {
2340 need,
2341 have: buf.len(),
2342 });
2343 }
2344 self.write_into(&mut buf[..need])?;
2345 Ok(need)
2346 }
2347}
2348
2349impl<B: AsRef<[u8]> + AsMut<[u8]>> CameraInfo<B> {
2350 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
2351 let b = self.buf.as_mut();
2352 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
2353 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
2354 }
2355
2356 pub fn set_height(&mut self, h: u32) -> Result<(), CdrError> {
2357 let p = align(self.offsets[0], 4);
2358 wr_u32(self.buf.as_mut(), p, h)
2359 }
2360
2361 pub fn set_width(&mut self, w: u32) -> Result<(), CdrError> {
2362 let p = align(self.offsets[0], 4) + 4;
2363 wr_u32(self.buf.as_mut(), p, w)
2364 }
2365
2366 pub fn set_k(&mut self, k: [f64; 9]) -> Result<(), CdrError> {
2367 let p = self.fixed_base();
2368 let b = self.buf.as_mut();
2369 for (i, v) in k.iter().enumerate() {
2370 wr_f64(b, p + i * 8, *v)?;
2371 }
2372 Ok(())
2373 }
2374
2375 pub fn set_r(&mut self, r: [f64; 9]) -> Result<(), CdrError> {
2376 let p = self.fixed_base() + 72;
2377 let b = self.buf.as_mut();
2378 for (i, v) in r.iter().enumerate() {
2379 wr_f64(b, p + i * 8, *v)?;
2380 }
2381 Ok(())
2382 }
2383
2384 pub fn set_p(&mut self, p_mat: [f64; 12]) -> Result<(), CdrError> {
2385 let p = self.fixed_base() + 144;
2386 let b = self.buf.as_mut();
2387 for (i, v) in p_mat.iter().enumerate() {
2388 wr_f64(b, p + i * 8, *v)?;
2389 }
2390 Ok(())
2391 }
2392
2393 pub fn set_binning_x(&mut self, v: u32) -> Result<(), CdrError> {
2394 let p = self.fixed_base() + 240;
2395 wr_u32(self.buf.as_mut(), p, v)
2396 }
2397
2398 pub fn set_binning_y(&mut self, v: u32) -> Result<(), CdrError> {
2399 let p = self.fixed_base() + 244;
2400 wr_u32(self.buf.as_mut(), p, v)
2401 }
2402
2403 pub fn set_roi(&mut self, r: RegionOfInterest) -> Result<(), CdrError> {
2404 let p = self.fixed_base() + 248;
2405 let b = self.buf.as_mut();
2406 wr_u32(b, p, r.x_offset)?;
2407 wr_u32(b, p + 4, r.y_offset)?;
2408 wr_u32(b, p + 8, r.height)?;
2409 wr_u32(b, p + 12, r.width)?;
2410 wr_bool(b, p + 16, r.do_rectify)
2411 }
2412}
2413
2414pub mod nav_sat_fix {
2417 pub const COVARIANCE_TYPE_UNKNOWN: u8 = 0;
2418 pub const COVARIANCE_TYPE_APPROXIMATED: u8 = 1;
2419 pub const COVARIANCE_TYPE_DIAGONAL_KNOWN: u8 = 2;
2420 pub const COVARIANCE_TYPE_KNOWN: u8 = 3;
2421}
2422
2423pub mod nav_sat_status {
2424 pub const STATUS_NO_FIX: i8 = -1;
2425 pub const STATUS_FIX: i8 = 0;
2426 pub const STATUS_SBAS_FIX: i8 = 1;
2427 pub const STATUS_GBAS_FIX: i8 = 2;
2428 pub const SERVICE_GPS: u8 = 1;
2429 pub const SERVICE_GLONASS: u8 = 2;
2430 pub const SERVICE_COMPASS: u8 = 4;
2431 pub const SERVICE_GALILEO: u8 = 8;
2432}
2433
2434pub mod point_field {
2435 pub const INT8: u8 = 1;
2436 pub const UINT8: u8 = 2;
2437 pub const INT16: u8 = 3;
2438 pub const UINT16: u8 = 4;
2439 pub const INT32: u8 = 5;
2440 pub const UINT32: u8 = 6;
2441 pub const FLOAT32: u8 = 7;
2442 pub const FLOAT64: u8 = 8;
2443}
2444
2445pub struct MagneticField<B> {
2453 buf: B,
2454 offsets: [usize; 1],
2455}
2456
2457impl<B> MagneticField<B> {
2458 #[inline]
2460 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> MagneticField<C> {
2461 MagneticField {
2462 buf: f(self.buf),
2463 offsets: self.offsets,
2464 }
2465 }
2466}
2467
2468impl<B: AsRef<[u8]>> MagneticField<B> {
2469 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
2470 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
2471 let pre = header.end_offset();
2472 let mut c = CdrCursor::resume(buf.as_ref(), pre);
2473 c.align(8);
2474 let o0 = c.offset();
2475 Vector3::read_cdr(&mut c)?;
2476 read_f64_array9(&mut c)?;
2477 Ok(MagneticField { offsets: [o0], buf })
2478 }
2479
2480 pub fn header(&self) -> Header<&[u8]> {
2482 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
2483 }
2484 pub fn stamp(&self) -> Time {
2485 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
2486 }
2487 pub fn frame_id(&self) -> &str {
2488 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
2489 }
2490 pub fn magnetic_field(&self) -> Vector3 {
2491 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0]);
2492 Vector3::read_cdr(&mut c).expect("magnetic_field validated during from_cdr")
2493 }
2494 pub fn magnetic_field_covariance(&self) -> [f64; 9] {
2495 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[0] + 24);
2496 read_f64_array9(&mut c).expect("covariance validated during from_cdr")
2497 }
2498 pub fn as_cdr(&self) -> &[u8] {
2499 self.buf.as_ref()
2500 }
2501 pub fn to_cdr(&self) -> Vec<u8> {
2502 self.buf.as_ref().to_vec()
2503 }
2504}
2505
2506impl MagneticField<Vec<u8>> {
2507 #[deprecated(
2508 since = "3.2.0",
2509 note = "use MagneticField::builder() for allocation-free buffer reuse; MagneticField::new will be removed in 4.0"
2510 )]
2511 pub fn new(
2512 stamp: Time,
2513 frame_id: &str,
2514 magnetic_field: Vector3,
2515 magnetic_field_covariance: [f64; 9],
2516 ) -> Result<Self, CdrError> {
2517 let mut sizer = CdrSizer::new();
2518 Time::size_cdr(&mut sizer);
2519 sizer.size_string(frame_id);
2520 sizer.align(8);
2521 let o0 = sizer.offset();
2522 Vector3::size_cdr(&mut sizer);
2523 size_f64_array9(&mut sizer);
2524
2525 let mut buf = vec![0u8; sizer.size()];
2526 let mut w = CdrWriter::new(&mut buf)?;
2527 stamp.write_cdr(&mut w);
2528 w.write_string(frame_id);
2529 magnetic_field.write_cdr(&mut w);
2530 write_f64_array9(&mut w, &magnetic_field_covariance);
2531 w.finish()?;
2532
2533 Ok(MagneticField { offsets: [o0], buf })
2534 }
2535
2536 pub fn into_cdr(self) -> Vec<u8> {
2537 self.buf
2538 }
2539
2540 pub fn builder<'a>() -> MagneticFieldBuilder<'a> {
2542 MagneticFieldBuilder::new()
2543 }
2544}
2545
2546pub struct MagneticFieldBuilder<'a> {
2550 stamp: Time,
2551 frame_id: std::borrow::Cow<'a, str>,
2552 magnetic_field: Vector3,
2553 magnetic_field_covariance: [f64; 9],
2554}
2555
2556impl<'a> Default for MagneticFieldBuilder<'a> {
2557 fn default() -> Self {
2558 Self {
2559 stamp: Time { sec: 0, nanosec: 0 },
2560 frame_id: std::borrow::Cow::Borrowed(""),
2561 magnetic_field: Vector3 {
2562 x: 0.0,
2563 y: 0.0,
2564 z: 0.0,
2565 },
2566 magnetic_field_covariance: [0.0; 9],
2567 }
2568 }
2569}
2570
2571impl<'a> MagneticFieldBuilder<'a> {
2572 pub fn new() -> Self {
2573 Self::default()
2574 }
2575
2576 pub fn stamp(&mut self, t: Time) -> &mut Self {
2577 self.stamp = t;
2578 self
2579 }
2580 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2581 self.frame_id = s.into();
2582 self
2583 }
2584 pub fn magnetic_field(&mut self, v: Vector3) -> &mut Self {
2585 self.magnetic_field = v;
2586 self
2587 }
2588 pub fn magnetic_field_covariance(&mut self, c: [f64; 9]) -> &mut Self {
2589 self.magnetic_field_covariance = c;
2590 self
2591 }
2592
2593 fn size(&self) -> usize {
2594 let mut s = CdrSizer::new();
2595 Time::size_cdr(&mut s);
2596 s.size_string(&self.frame_id);
2597 s.align(8);
2598 Vector3::size_cdr(&mut s);
2599 size_f64_array9(&mut s);
2600 s.size()
2601 }
2602
2603 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
2604 let mut w = CdrWriter::new(buf)?;
2605 self.stamp.write_cdr(&mut w);
2606 w.write_string(&self.frame_id);
2607 self.magnetic_field.write_cdr(&mut w);
2608 write_f64_array9(&mut w, &self.magnetic_field_covariance);
2609 w.finish()
2610 }
2611
2612 pub fn build(&self) -> Result<MagneticField<Vec<u8>>, CdrError> {
2613 let mut buf = vec![0u8; self.size()];
2614 self.write_into(&mut buf)?;
2615 MagneticField::from_cdr(buf)
2616 }
2617
2618 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
2619 buf.resize(self.size(), 0);
2620 self.write_into(buf)
2621 }
2622
2623 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
2624 let need = self.size();
2625 if buf.len() < need {
2626 return Err(CdrError::BufferTooShort {
2627 need,
2628 have: buf.len(),
2629 });
2630 }
2631 self.write_into(&mut buf[..need])?;
2632 Ok(need)
2633 }
2634}
2635
2636impl<B: AsRef<[u8]> + AsMut<[u8]>> MagneticField<B> {
2637 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
2638 let b = self.buf.as_mut();
2639 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
2640 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
2641 }
2642
2643 pub fn set_magnetic_field(&mut self, v: Vector3) -> Result<(), CdrError> {
2644 let p = self.offsets[0];
2645 let b = self.buf.as_mut();
2646 wr_f64(b, p, v.x)?;
2647 wr_f64(b, p + 8, v.y)?;
2648 wr_f64(b, p + 16, v.z)
2649 }
2650
2651 pub fn set_magnetic_field_covariance(&mut self, c: [f64; 9]) -> Result<(), CdrError> {
2652 let p = self.offsets[0] + 24;
2653 let b = self.buf.as_mut();
2654 for (i, v) in c.iter().enumerate() {
2655 wr_f64(b, p + i * 8, *v)?;
2656 }
2657 Ok(())
2658 }
2659}
2660
2661pub struct FluidPressure<B> {
2667 buf: B,
2668 offsets: [usize; 1],
2669}
2670
2671impl<B> FluidPressure<B> {
2672 #[inline]
2674 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> FluidPressure<C> {
2675 FluidPressure {
2676 buf: f(self.buf),
2677 offsets: self.offsets,
2678 }
2679 }
2680}
2681
2682impl<B: AsRef<[u8]>> FluidPressure<B> {
2683 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
2684 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
2685 let pre = header.end_offset();
2686 let mut c = CdrCursor::resume(buf.as_ref(), pre);
2687 c.align(8);
2688 let o0 = c.offset();
2689 c.read_f64()?; c.read_f64()?; Ok(FluidPressure { offsets: [o0], buf })
2692 }
2693
2694 pub fn header(&self) -> Header<&[u8]> {
2695 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
2696 }
2697 pub fn stamp(&self) -> Time {
2698 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
2699 }
2700 pub fn frame_id(&self) -> &str {
2701 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
2702 }
2703 pub fn fluid_pressure(&self) -> f64 {
2704 rd_f64(self.buf.as_ref(), self.offsets[0])
2705 }
2706 pub fn variance(&self) -> f64 {
2707 rd_f64(self.buf.as_ref(), self.offsets[0] + 8)
2708 }
2709 pub fn as_cdr(&self) -> &[u8] {
2710 self.buf.as_ref()
2711 }
2712 pub fn to_cdr(&self) -> Vec<u8> {
2713 self.buf.as_ref().to_vec()
2714 }
2715}
2716
2717impl FluidPressure<Vec<u8>> {
2718 #[deprecated(
2719 since = "3.2.0",
2720 note = "use FluidPressure::builder() for allocation-free buffer reuse; FluidPressure::new will be removed in 4.0"
2721 )]
2722 pub fn new(
2723 stamp: Time,
2724 frame_id: &str,
2725 fluid_pressure: f64,
2726 variance: f64,
2727 ) -> Result<Self, CdrError> {
2728 let mut sizer = CdrSizer::new();
2729 Time::size_cdr(&mut sizer);
2730 sizer.size_string(frame_id);
2731 sizer.align(8);
2732 let o0 = sizer.offset();
2733 sizer.size_f64();
2734 sizer.size_f64();
2735
2736 let mut buf = vec![0u8; sizer.size()];
2737 let mut w = CdrWriter::new(&mut buf)?;
2738 stamp.write_cdr(&mut w);
2739 w.write_string(frame_id);
2740 w.write_f64(fluid_pressure);
2741 w.write_f64(variance);
2742 w.finish()?;
2743
2744 Ok(FluidPressure { offsets: [o0], buf })
2745 }
2746
2747 pub fn into_cdr(self) -> Vec<u8> {
2748 self.buf
2749 }
2750
2751 pub fn builder<'a>() -> FluidPressureBuilder<'a> {
2753 FluidPressureBuilder::new()
2754 }
2755}
2756
2757pub struct FluidPressureBuilder<'a> {
2761 stamp: Time,
2762 frame_id: std::borrow::Cow<'a, str>,
2763 fluid_pressure: f64,
2764 variance: f64,
2765}
2766
2767impl<'a> Default for FluidPressureBuilder<'a> {
2768 fn default() -> Self {
2769 Self {
2770 stamp: Time { sec: 0, nanosec: 0 },
2771 frame_id: std::borrow::Cow::Borrowed(""),
2772 fluid_pressure: 0.0,
2773 variance: 0.0,
2774 }
2775 }
2776}
2777
2778impl<'a> FluidPressureBuilder<'a> {
2779 pub fn new() -> Self {
2780 Self::default()
2781 }
2782
2783 pub fn stamp(&mut self, t: Time) -> &mut Self {
2784 self.stamp = t;
2785 self
2786 }
2787 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2788 self.frame_id = s.into();
2789 self
2790 }
2791 pub fn fluid_pressure(&mut self, v: f64) -> &mut Self {
2792 self.fluid_pressure = v;
2793 self
2794 }
2795 pub fn variance(&mut self, v: f64) -> &mut Self {
2796 self.variance = v;
2797 self
2798 }
2799
2800 fn size(&self) -> usize {
2801 let mut s = CdrSizer::new();
2802 Time::size_cdr(&mut s);
2803 s.size_string(&self.frame_id);
2804 s.align(8);
2805 s.size_f64();
2806 s.size_f64();
2807 s.size()
2808 }
2809
2810 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
2811 let mut w = CdrWriter::new(buf)?;
2812 self.stamp.write_cdr(&mut w);
2813 w.write_string(&self.frame_id);
2814 w.write_f64(self.fluid_pressure);
2815 w.write_f64(self.variance);
2816 w.finish()
2817 }
2818
2819 pub fn build(&self) -> Result<FluidPressure<Vec<u8>>, CdrError> {
2820 let mut buf = vec![0u8; self.size()];
2821 self.write_into(&mut buf)?;
2822 FluidPressure::from_cdr(buf)
2823 }
2824
2825 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
2826 buf.resize(self.size(), 0);
2827 self.write_into(buf)
2828 }
2829
2830 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
2831 let need = self.size();
2832 if buf.len() < need {
2833 return Err(CdrError::BufferTooShort {
2834 need,
2835 have: buf.len(),
2836 });
2837 }
2838 self.write_into(&mut buf[..need])?;
2839 Ok(need)
2840 }
2841}
2842
2843impl<B: AsRef<[u8]> + AsMut<[u8]>> FluidPressure<B> {
2844 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
2845 let b = self.buf.as_mut();
2846 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
2847 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
2848 }
2849
2850 pub fn set_fluid_pressure(&mut self, v: f64) -> Result<(), CdrError> {
2851 wr_f64(self.buf.as_mut(), self.offsets[0], v)
2852 }
2853
2854 pub fn set_variance(&mut self, v: f64) -> Result<(), CdrError> {
2855 wr_f64(self.buf.as_mut(), self.offsets[0] + 8, v)
2856 }
2857}
2858
2859pub struct Temperature<B> {
2865 buf: B,
2866 offsets: [usize; 1],
2867}
2868
2869impl<B> Temperature<B> {
2870 #[inline]
2872 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> Temperature<C> {
2873 Temperature {
2874 buf: f(self.buf),
2875 offsets: self.offsets,
2876 }
2877 }
2878}
2879
2880impl<B: AsRef<[u8]>> Temperature<B> {
2881 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
2882 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
2883 let pre = header.end_offset();
2884 let mut c = CdrCursor::resume(buf.as_ref(), pre);
2885 c.align(8);
2886 let o0 = c.offset();
2887 c.read_f64()?; c.read_f64()?; Ok(Temperature { offsets: [o0], buf })
2890 }
2891
2892 pub fn header(&self) -> Header<&[u8]> {
2893 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
2894 }
2895 pub fn stamp(&self) -> Time {
2896 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
2897 }
2898 pub fn frame_id(&self) -> &str {
2899 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
2900 }
2901 pub fn temperature(&self) -> f64 {
2902 rd_f64(self.buf.as_ref(), self.offsets[0])
2903 }
2904 pub fn variance(&self) -> f64 {
2905 rd_f64(self.buf.as_ref(), self.offsets[0] + 8)
2906 }
2907 pub fn as_cdr(&self) -> &[u8] {
2908 self.buf.as_ref()
2909 }
2910 pub fn to_cdr(&self) -> Vec<u8> {
2911 self.buf.as_ref().to_vec()
2912 }
2913}
2914
2915impl Temperature<Vec<u8>> {
2916 #[deprecated(
2917 since = "3.2.0",
2918 note = "use Temperature::builder() for allocation-free buffer reuse; Temperature::new will be removed in 4.0"
2919 )]
2920 pub fn new(
2921 stamp: Time,
2922 frame_id: &str,
2923 temperature: f64,
2924 variance: f64,
2925 ) -> Result<Self, CdrError> {
2926 let mut sizer = CdrSizer::new();
2927 Time::size_cdr(&mut sizer);
2928 sizer.size_string(frame_id);
2929 sizer.align(8);
2930 let o0 = sizer.offset();
2931 sizer.size_f64();
2932 sizer.size_f64();
2933
2934 let mut buf = vec![0u8; sizer.size()];
2935 let mut w = CdrWriter::new(&mut buf)?;
2936 stamp.write_cdr(&mut w);
2937 w.write_string(frame_id);
2938 w.write_f64(temperature);
2939 w.write_f64(variance);
2940 w.finish()?;
2941
2942 Ok(Temperature { offsets: [o0], buf })
2943 }
2944
2945 pub fn into_cdr(self) -> Vec<u8> {
2946 self.buf
2947 }
2948
2949 pub fn builder<'a>() -> TemperatureBuilder<'a> {
2951 TemperatureBuilder::new()
2952 }
2953}
2954
2955pub struct TemperatureBuilder<'a> {
2959 stamp: Time,
2960 frame_id: std::borrow::Cow<'a, str>,
2961 temperature: f64,
2962 variance: f64,
2963}
2964
2965impl<'a> Default for TemperatureBuilder<'a> {
2966 fn default() -> Self {
2967 Self {
2968 stamp: Time { sec: 0, nanosec: 0 },
2969 frame_id: std::borrow::Cow::Borrowed(""),
2970 temperature: 0.0,
2971 variance: 0.0,
2972 }
2973 }
2974}
2975
2976impl<'a> TemperatureBuilder<'a> {
2977 pub fn new() -> Self {
2978 Self::default()
2979 }
2980
2981 pub fn stamp(&mut self, t: Time) -> &mut Self {
2982 self.stamp = t;
2983 self
2984 }
2985 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
2986 self.frame_id = s.into();
2987 self
2988 }
2989 pub fn temperature(&mut self, v: f64) -> &mut Self {
2990 self.temperature = v;
2991 self
2992 }
2993 pub fn variance(&mut self, v: f64) -> &mut Self {
2994 self.variance = v;
2995 self
2996 }
2997
2998 fn size(&self) -> usize {
2999 let mut s = CdrSizer::new();
3000 Time::size_cdr(&mut s);
3001 s.size_string(&self.frame_id);
3002 s.align(8);
3003 s.size_f64();
3004 s.size_f64();
3005 s.size()
3006 }
3007
3008 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
3009 let mut w = CdrWriter::new(buf)?;
3010 self.stamp.write_cdr(&mut w);
3011 w.write_string(&self.frame_id);
3012 w.write_f64(self.temperature);
3013 w.write_f64(self.variance);
3014 w.finish()
3015 }
3016
3017 pub fn build(&self) -> Result<Temperature<Vec<u8>>, CdrError> {
3018 let mut buf = vec![0u8; self.size()];
3019 self.write_into(&mut buf)?;
3020 Temperature::from_cdr(buf)
3021 }
3022
3023 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
3024 buf.resize(self.size(), 0);
3025 self.write_into(buf)
3026 }
3027
3028 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
3029 let need = self.size();
3030 if buf.len() < need {
3031 return Err(CdrError::BufferTooShort {
3032 need,
3033 have: buf.len(),
3034 });
3035 }
3036 self.write_into(&mut buf[..need])?;
3037 Ok(need)
3038 }
3039}
3040
3041impl<B: AsRef<[u8]> + AsMut<[u8]>> Temperature<B> {
3042 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
3043 let b = self.buf.as_mut();
3044 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
3045 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
3046 }
3047
3048 pub fn set_temperature(&mut self, v: f64) -> Result<(), CdrError> {
3049 wr_f64(self.buf.as_mut(), self.offsets[0], v)
3050 }
3051
3052 pub fn set_variance(&mut self, v: f64) -> Result<(), CdrError> {
3053 wr_f64(self.buf.as_mut(), self.offsets[0] + 8, v)
3054 }
3055}
3056
3057pub mod power_supply_status {
3073 pub const UNKNOWN: u8 = 0;
3074 pub const CHARGING: u8 = 1;
3075 pub const DISCHARGING: u8 = 2;
3076 pub const NOT_CHARGING: u8 = 3;
3077 pub const FULL: u8 = 4;
3078}
3079
3080pub mod power_supply_health {
3082 pub const UNKNOWN: u8 = 0;
3083 pub const GOOD: u8 = 1;
3084 pub const OVERHEAT: u8 = 2;
3085 pub const DEAD: u8 = 3;
3086 pub const OVERVOLTAGE: u8 = 4;
3087 pub const UNSPEC_FAILURE: u8 = 5;
3088 pub const COLD: u8 = 6;
3089 pub const WATCHDOG_TIMER_EXPIRE: u8 = 7;
3090 pub const SAFETY_TIMER_EXPIRE: u8 = 8;
3091}
3092
3093pub mod power_supply_technology {
3095 pub const UNKNOWN: u8 = 0;
3096 pub const NIMH: u8 = 1;
3097 pub const LION: u8 = 2;
3098 pub const LIPO: u8 = 3;
3099 pub const LIFE: u8 = 4;
3100 pub const NICD: u8 = 5;
3101 pub const LIMN: u8 = 6;
3102}
3103
3104pub struct BatteryState<B> {
3105 buf: B,
3106 offsets: [usize; 5],
3112}
3113
3114impl<B> BatteryState<B> {
3115 #[inline]
3117 pub fn map_buffer<C>(self, f: impl FnOnce(B) -> C) -> BatteryState<C> {
3118 BatteryState {
3119 buf: f(self.buf),
3120 offsets: self.offsets,
3121 }
3122 }
3123}
3124
3125impl<B: AsRef<[u8]>> BatteryState<B> {
3126 pub fn from_cdr(buf: B) -> Result<Self, CdrError> {
3127 let header = Header::<&[u8]>::from_cdr(buf.as_ref())?;
3128 let pre = header.end_offset();
3129 let mut c = CdrCursor::resume(buf.as_ref(), pre);
3130 c.align(4);
3131 let o0 = c.offset();
3132 for _ in 0..7 {
3134 c.read_f32()?;
3135 }
3136 c.read_u8()?; c.read_u8()?; c.read_u8()?; c.read_bool()?; let o1 = c.offset();
3141 let raw = c.read_u32()?;
3143 let cv_len = c.check_seq_count(raw, 4)?;
3144 for _ in 0..cv_len {
3145 c.read_f32()?;
3146 }
3147 let o2 = c.offset();
3148 let raw = c.read_u32()?;
3149 let ct_len = c.check_seq_count(raw, 4)?;
3150 for _ in 0..ct_len {
3151 c.read_f32()?;
3152 }
3153 let o3 = c.offset();
3154 c.read_string()?; let o4 = c.offset();
3156 c.read_string()?; Ok(BatteryState {
3158 offsets: [o0, o1, o2, o3, o4],
3159 buf,
3160 })
3161 }
3162
3163 pub fn header(&self) -> Header<&[u8]> {
3164 Header::from_cdr(self.buf.as_ref()).expect("header bytes validated during from_cdr")
3165 }
3166 pub fn stamp(&self) -> Time {
3167 rd_time(self.buf.as_ref(), CDR_HEADER_SIZE)
3168 }
3169 pub fn frame_id(&self) -> &str {
3170 rd_string(self.buf.as_ref(), CDR_HEADER_SIZE + 8).0
3171 }
3172 pub fn voltage(&self) -> f32 {
3173 rd_f32(self.buf.as_ref(), self.offsets[0])
3174 }
3175 pub fn temperature(&self) -> f32 {
3176 rd_f32(self.buf.as_ref(), self.offsets[0] + 4)
3177 }
3178 pub fn current(&self) -> f32 {
3179 rd_f32(self.buf.as_ref(), self.offsets[0] + 8)
3180 }
3181 pub fn charge(&self) -> f32 {
3182 rd_f32(self.buf.as_ref(), self.offsets[0] + 12)
3183 }
3184 pub fn capacity(&self) -> f32 {
3185 rd_f32(self.buf.as_ref(), self.offsets[0] + 16)
3186 }
3187 pub fn design_capacity(&self) -> f32 {
3188 rd_f32(self.buf.as_ref(), self.offsets[0] + 20)
3189 }
3190 pub fn percentage(&self) -> f32 {
3191 rd_f32(self.buf.as_ref(), self.offsets[0] + 24)
3192 }
3193 pub fn power_supply_status(&self) -> u8 {
3194 rd_u8(self.buf.as_ref(), self.offsets[0] + 28)
3195 }
3196 pub fn power_supply_health(&self) -> u8 {
3197 rd_u8(self.buf.as_ref(), self.offsets[0] + 29)
3198 }
3199 pub fn power_supply_technology(&self) -> u8 {
3200 rd_u8(self.buf.as_ref(), self.offsets[0] + 30)
3201 }
3202 pub fn present(&self) -> bool {
3203 rd_bool(self.buf.as_ref(), self.offsets[0] + 31)
3204 }
3205 pub fn cell_voltage_len(&self) -> u32 {
3206 rd_u32(self.buf.as_ref(), self.offsets[1])
3207 }
3208 pub fn cell_voltage_seq_offset(&self) -> usize {
3211 self.offsets[1]
3212 }
3213 pub fn cell_voltage(&self) -> Vec<f32> {
3214 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[1]);
3215 let n = c
3216 .read_u32()
3217 .expect("cell_voltage length validated during from_cdr") as usize;
3218 let mut out = Vec::with_capacity(n);
3219 for _ in 0..n {
3220 out.push(
3221 c.read_f32()
3222 .expect("cell_voltage element validated during from_cdr"),
3223 );
3224 }
3225 out
3226 }
3227 pub fn cell_temperature_len(&self) -> u32 {
3228 rd_u32(self.buf.as_ref(), self.offsets[2])
3229 }
3230 pub fn cell_temperature_seq_offset(&self) -> usize {
3233 self.offsets[2]
3234 }
3235 pub fn cell_temperature(&self) -> Vec<f32> {
3236 let mut c = CdrCursor::resume(self.buf.as_ref(), self.offsets[2]);
3237 let n = c
3238 .read_u32()
3239 .expect("cell_temperature length validated during from_cdr") as usize;
3240 let mut out = Vec::with_capacity(n);
3241 for _ in 0..n {
3242 out.push(
3243 c.read_f32()
3244 .expect("cell_temperature element validated during from_cdr"),
3245 );
3246 }
3247 out
3248 }
3249 pub fn location(&self) -> &str {
3250 rd_string(self.buf.as_ref(), self.offsets[3]).0
3251 }
3252 pub fn serial_number(&self) -> &str {
3253 rd_string(self.buf.as_ref(), self.offsets[4]).0
3254 }
3255 pub fn as_cdr(&self) -> &[u8] {
3256 self.buf.as_ref()
3257 }
3258 pub fn to_cdr(&self) -> Vec<u8> {
3259 self.buf.as_ref().to_vec()
3260 }
3261}
3262
3263impl BatteryState<Vec<u8>> {
3264 #[deprecated(
3265 since = "3.2.0",
3266 note = "use BatteryState::builder() for allocation-free buffer reuse; BatteryState::new will be removed in 4.0"
3267 )]
3268 #[allow(clippy::too_many_arguments)]
3269 pub fn new(
3270 stamp: Time,
3271 frame_id: &str,
3272 voltage: f32,
3273 temperature: f32,
3274 current: f32,
3275 charge: f32,
3276 capacity: f32,
3277 design_capacity: f32,
3278 percentage: f32,
3279 power_supply_status: u8,
3280 power_supply_health: u8,
3281 power_supply_technology: u8,
3282 present: bool,
3283 cell_voltage: &[f32],
3284 cell_temperature: &[f32],
3285 location: &str,
3286 serial_number: &str,
3287 ) -> Result<Self, CdrError> {
3288 let mut sizer = CdrSizer::new();
3289 Time::size_cdr(&mut sizer);
3290 sizer.size_string(frame_id);
3291 sizer.align(4);
3292 let o0 = sizer.offset();
3293 for _ in 0..7 {
3294 sizer.size_f32();
3295 }
3296 sizer.size_u8();
3297 sizer.size_u8();
3298 sizer.size_u8();
3299 sizer.size_bool();
3300 let o1 = sizer.offset();
3301 sizer.size_u32();
3302 for _ in cell_voltage {
3303 sizer.size_f32();
3304 }
3305 let o2 = sizer.offset();
3306 sizer.size_u32();
3307 for _ in cell_temperature {
3308 sizer.size_f32();
3309 }
3310 let o3 = sizer.offset();
3311 sizer.size_string(location);
3312 let o4 = sizer.offset();
3313 sizer.size_string(serial_number);
3314
3315 let mut buf = vec![0u8; sizer.size()];
3316 let mut w = CdrWriter::new(&mut buf)?;
3317 stamp.write_cdr(&mut w);
3318 w.write_string(frame_id);
3319 w.write_f32(voltage);
3320 w.write_f32(temperature);
3321 w.write_f32(current);
3322 w.write_f32(charge);
3323 w.write_f32(capacity);
3324 w.write_f32(design_capacity);
3325 w.write_f32(percentage);
3326 w.write_u8(power_supply_status);
3327 w.write_u8(power_supply_health);
3328 w.write_u8(power_supply_technology);
3329 w.write_bool(present);
3330 w.write_u32(cell_voltage.len() as u32);
3331 for v in cell_voltage {
3332 w.write_f32(*v);
3333 }
3334 w.write_u32(cell_temperature.len() as u32);
3335 for v in cell_temperature {
3336 w.write_f32(*v);
3337 }
3338 w.write_string(location);
3339 w.write_string(serial_number);
3340 w.finish()?;
3341
3342 Ok(BatteryState {
3343 offsets: [o0, o1, o2, o3, o4],
3344 buf,
3345 })
3346 }
3347
3348 pub fn into_cdr(self) -> Vec<u8> {
3349 self.buf
3350 }
3351
3352 pub fn builder<'a>() -> BatteryStateBuilder<'a> {
3354 BatteryStateBuilder::new()
3355 }
3356}
3357
3358pub struct BatteryStateBuilder<'a> {
3365 stamp: Time,
3366 frame_id: std::borrow::Cow<'a, str>,
3367 voltage: f32,
3368 temperature: f32,
3369 current: f32,
3370 charge: f32,
3371 capacity: f32,
3372 design_capacity: f32,
3373 percentage: f32,
3374 power_supply_status: u8,
3375 power_supply_health: u8,
3376 power_supply_technology: u8,
3377 present: bool,
3378 cell_voltage: &'a [f32],
3379 cell_temperature: &'a [f32],
3380 location: std::borrow::Cow<'a, str>,
3381 serial_number: std::borrow::Cow<'a, str>,
3382}
3383
3384impl<'a> Default for BatteryStateBuilder<'a> {
3385 fn default() -> Self {
3386 Self {
3387 stamp: Time { sec: 0, nanosec: 0 },
3388 frame_id: std::borrow::Cow::Borrowed(""),
3389 voltage: 0.0,
3390 temperature: 0.0,
3391 current: 0.0,
3392 charge: 0.0,
3393 capacity: 0.0,
3394 design_capacity: 0.0,
3395 percentage: 0.0,
3396 power_supply_status: 0,
3397 power_supply_health: 0,
3398 power_supply_technology: 0,
3399 present: false,
3400 cell_voltage: &[],
3401 cell_temperature: &[],
3402 location: std::borrow::Cow::Borrowed(""),
3403 serial_number: std::borrow::Cow::Borrowed(""),
3404 }
3405 }
3406}
3407
3408impl<'a> BatteryStateBuilder<'a> {
3409 pub fn new() -> Self {
3410 Self::default()
3411 }
3412
3413 pub fn stamp(&mut self, t: Time) -> &mut Self {
3414 self.stamp = t;
3415 self
3416 }
3417 pub fn frame_id(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3418 self.frame_id = s.into();
3419 self
3420 }
3421 pub fn voltage(&mut self, v: f32) -> &mut Self {
3422 self.voltage = v;
3423 self
3424 }
3425 pub fn temperature(&mut self, v: f32) -> &mut Self {
3426 self.temperature = v;
3427 self
3428 }
3429 pub fn current(&mut self, v: f32) -> &mut Self {
3430 self.current = v;
3431 self
3432 }
3433 pub fn charge(&mut self, v: f32) -> &mut Self {
3434 self.charge = v;
3435 self
3436 }
3437 pub fn capacity(&mut self, v: f32) -> &mut Self {
3438 self.capacity = v;
3439 self
3440 }
3441 pub fn design_capacity(&mut self, v: f32) -> &mut Self {
3442 self.design_capacity = v;
3443 self
3444 }
3445 pub fn percentage(&mut self, v: f32) -> &mut Self {
3446 self.percentage = v;
3447 self
3448 }
3449 pub fn power_supply_status(&mut self, v: u8) -> &mut Self {
3450 self.power_supply_status = v;
3451 self
3452 }
3453 pub fn power_supply_health(&mut self, v: u8) -> &mut Self {
3454 self.power_supply_health = v;
3455 self
3456 }
3457 pub fn power_supply_technology(&mut self, v: u8) -> &mut Self {
3458 self.power_supply_technology = v;
3459 self
3460 }
3461 pub fn present(&mut self, v: bool) -> &mut Self {
3462 self.present = v;
3463 self
3464 }
3465 pub fn cell_voltage(&mut self, v: &'a [f32]) -> &mut Self {
3466 self.cell_voltage = v;
3467 self
3468 }
3469 pub fn cell_temperature(&mut self, v: &'a [f32]) -> &mut Self {
3470 self.cell_temperature = v;
3471 self
3472 }
3473 pub fn location(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3474 self.location = s.into();
3475 self
3476 }
3477 pub fn serial_number(&mut self, s: impl Into<std::borrow::Cow<'a, str>>) -> &mut Self {
3478 self.serial_number = s.into();
3479 self
3480 }
3481
3482 fn size(&self) -> usize {
3483 let mut s = CdrSizer::new();
3484 Time::size_cdr(&mut s);
3485 s.size_string(&self.frame_id);
3486 s.align(4);
3487 for _ in 0..7 {
3488 s.size_f32();
3489 }
3490 s.size_u8();
3491 s.size_u8();
3492 s.size_u8();
3493 s.size_bool();
3494 s.size_u32();
3495 for _ in self.cell_voltage {
3496 s.size_f32();
3497 }
3498 s.size_u32();
3499 for _ in self.cell_temperature {
3500 s.size_f32();
3501 }
3502 s.size_string(&self.location);
3503 s.size_string(&self.serial_number);
3504 s.size()
3505 }
3506
3507 fn write_into(&self, buf: &mut [u8]) -> Result<(), CdrError> {
3508 let mut w = CdrWriter::new(buf)?;
3509 self.stamp.write_cdr(&mut w);
3510 w.write_string(&self.frame_id);
3511 w.write_f32(self.voltage);
3512 w.write_f32(self.temperature);
3513 w.write_f32(self.current);
3514 w.write_f32(self.charge);
3515 w.write_f32(self.capacity);
3516 w.write_f32(self.design_capacity);
3517 w.write_f32(self.percentage);
3518 w.write_u8(self.power_supply_status);
3519 w.write_u8(self.power_supply_health);
3520 w.write_u8(self.power_supply_technology);
3521 w.write_bool(self.present);
3522 w.write_u32(self.cell_voltage.len() as u32);
3523 for v in self.cell_voltage {
3524 w.write_f32(*v);
3525 }
3526 w.write_u32(self.cell_temperature.len() as u32);
3527 for v in self.cell_temperature {
3528 w.write_f32(*v);
3529 }
3530 w.write_string(&self.location);
3531 w.write_string(&self.serial_number);
3532 w.finish()
3533 }
3534
3535 pub fn build(&self) -> Result<BatteryState<Vec<u8>>, CdrError> {
3536 let mut buf = vec![0u8; self.size()];
3537 self.write_into(&mut buf)?;
3538 BatteryState::from_cdr(buf)
3539 }
3540
3541 pub fn encode_into_vec(&self, buf: &mut Vec<u8>) -> Result<(), CdrError> {
3542 buf.resize(self.size(), 0);
3543 self.write_into(buf)
3544 }
3545
3546 pub fn encode_into_slice(&self, buf: &mut [u8]) -> Result<usize, CdrError> {
3547 let need = self.size();
3548 if buf.len() < need {
3549 return Err(CdrError::BufferTooShort {
3550 need,
3551 have: buf.len(),
3552 });
3553 }
3554 self.write_into(&mut buf[..need])?;
3555 Ok(need)
3556 }
3557}
3558
3559impl<B: AsRef<[u8]> + AsMut<[u8]>> BatteryState<B> {
3560 pub fn set_stamp(&mut self, t: Time) -> Result<(), CdrError> {
3561 let b = self.buf.as_mut();
3562 wr_i32(b, CDR_HEADER_SIZE, t.sec)?;
3563 wr_u32(b, CDR_HEADER_SIZE + 4, t.nanosec)
3564 }
3565
3566 pub fn set_voltage(&mut self, v: f32) -> Result<(), CdrError> {
3567 wr_f32(self.buf.as_mut(), self.offsets[0], v)
3568 }
3569
3570 pub fn set_temperature(&mut self, v: f32) -> Result<(), CdrError> {
3571 wr_f32(self.buf.as_mut(), self.offsets[0] + 4, v)
3572 }
3573
3574 pub fn set_current(&mut self, v: f32) -> Result<(), CdrError> {
3575 wr_f32(self.buf.as_mut(), self.offsets[0] + 8, v)
3576 }
3577
3578 pub fn set_charge(&mut self, v: f32) -> Result<(), CdrError> {
3579 wr_f32(self.buf.as_mut(), self.offsets[0] + 12, v)
3580 }
3581
3582 pub fn set_capacity(&mut self, v: f32) -> Result<(), CdrError> {
3583 wr_f32(self.buf.as_mut(), self.offsets[0] + 16, v)
3584 }
3585
3586 pub fn set_design_capacity(&mut self, v: f32) -> Result<(), CdrError> {
3587 wr_f32(self.buf.as_mut(), self.offsets[0] + 20, v)
3588 }
3589
3590 pub fn set_percentage(&mut self, v: f32) -> Result<(), CdrError> {
3591 wr_f32(self.buf.as_mut(), self.offsets[0] + 24, v)
3592 }
3593
3594 pub fn set_power_supply_status(&mut self, v: u8) -> Result<(), CdrError> {
3595 wr_u8(self.buf.as_mut(), self.offsets[0] + 28, v)
3596 }
3597
3598 pub fn set_power_supply_health(&mut self, v: u8) -> Result<(), CdrError> {
3599 wr_u8(self.buf.as_mut(), self.offsets[0] + 29, v)
3600 }
3601
3602 pub fn set_power_supply_technology(&mut self, v: u8) -> Result<(), CdrError> {
3603 wr_u8(self.buf.as_mut(), self.offsets[0] + 30, v)
3604 }
3605
3606 pub fn set_present(&mut self, v: bool) -> Result<(), CdrError> {
3607 wr_bool(self.buf.as_mut(), self.offsets[0] + 31, v)
3608 }
3609}
3610
3611pub fn is_type_supported(type_name: &str) -> bool {
3615 matches!(
3616 type_name,
3617 "BatteryState"
3618 | "CameraInfo"
3619 | "CompressedImage"
3620 | "FluidPressure"
3621 | "Image"
3622 | "Imu"
3623 | "MagneticField"
3624 | "NavSatFix"
3625 | "NavSatStatus"
3626 | "PointCloud2"
3627 | "PointField"
3628 | "RegionOfInterest"
3629 | "Temperature"
3630 )
3631}
3632
3633pub fn list_types() -> &'static [&'static str] {
3635 &[
3636 "sensor_msgs/msg/BatteryState",
3637 "sensor_msgs/msg/CameraInfo",
3638 "sensor_msgs/msg/CompressedImage",
3639 "sensor_msgs/msg/FluidPressure",
3640 "sensor_msgs/msg/Image",
3641 "sensor_msgs/msg/Imu",
3642 "sensor_msgs/msg/MagneticField",
3643 "sensor_msgs/msg/NavSatFix",
3644 "sensor_msgs/msg/NavSatStatus",
3645 "sensor_msgs/msg/PointCloud2",
3646 "sensor_msgs/msg/PointField",
3647 "sensor_msgs/msg/RegionOfInterest",
3648 "sensor_msgs/msg/Temperature",
3649 ]
3650}
3651
3652use crate::schema_registry::SchemaType;
3654
3655impl SchemaType for NavSatStatus {
3656 const SCHEMA_NAME: &'static str = "sensor_msgs/msg/NavSatStatus";
3657}
3658
3659impl SchemaType for RegionOfInterest {
3660 const SCHEMA_NAME: &'static str = "sensor_msgs/msg/RegionOfInterest";
3661}
3662
3663#[cfg(test)]
3664#[allow(deprecated)] mod tests {
3666 use super::*;
3667 use crate::builtin_interfaces::Time;
3668 use crate::cdr::{decode_fixed, encode_fixed};
3669 use crate::geometry_msgs::{Quaternion, Vector3};
3670
3671 #[test]
3672 fn compressed_image_roundtrip() {
3673 let img = CompressedImage::new(
3674 Time::new(100, 500_000_000),
3675 "camera",
3676 "jpeg",
3677 &[0xFF, 0xD8, 0xFF],
3678 )
3679 .unwrap();
3680 assert_eq!(img.stamp(), Time::new(100, 500_000_000));
3681 assert_eq!(img.frame_id(), "camera");
3682 assert_eq!(img.format(), "jpeg");
3683 assert_eq!(img.data(), &[0xFF, 0xD8, 0xFF]);
3684
3685 let bytes = img.to_cdr();
3686 let decoded = CompressedImage::from_cdr(bytes).unwrap();
3687 assert_eq!(decoded.format(), "jpeg");
3688 assert_eq!(decoded.data(), &[0xFF, 0xD8, 0xFF]);
3689 }
3690
3691 #[test]
3692 fn image_roundtrip() {
3693 let data = vec![128u8; 1920 * 480];
3694 let img = Image::new(
3695 Time::new(100, 500_000_000),
3696 "camera_optical",
3697 480,
3698 640,
3699 "rgb8",
3700 0,
3701 1920,
3702 &data,
3703 )
3704 .unwrap();
3705 assert_eq!(img.height(), 480);
3706 assert_eq!(img.width(), 640);
3707 assert_eq!(img.encoding(), "rgb8");
3708 assert_eq!(img.is_bigendian(), 0);
3709 assert_eq!(img.step(), 1920);
3710 assert_eq!(img.data().len(), 1920 * 480);
3711
3712 let bytes = img.to_cdr();
3713 let decoded = Image::from_cdr(bytes).unwrap();
3714 assert_eq!(decoded.height(), 480);
3715 assert_eq!(decoded.width(), 640);
3716 }
3717
3718 #[test]
3719 fn imu_roundtrip() {
3720 let imu = Imu::new(
3721 Time::new(100, 0),
3722 "imu_link",
3723 Quaternion {
3724 x: 0.0,
3725 y: 0.0,
3726 z: 0.0,
3727 w: 1.0,
3728 },
3729 [0.0; 9],
3730 Vector3 {
3731 x: 0.1,
3732 y: 0.2,
3733 z: 9.8,
3734 },
3735 [0.0; 9],
3736 Vector3 {
3737 x: 0.0,
3738 y: 0.0,
3739 z: 0.0,
3740 },
3741 [0.0; 9],
3742 )
3743 .unwrap();
3744 assert_eq!(imu.stamp(), Time::new(100, 0));
3745 let bytes = imu.to_cdr();
3746 let decoded = Imu::from_cdr(bytes).unwrap();
3747 assert_eq!(decoded.orientation().w, 1.0);
3748 assert!((decoded.angular_velocity().z - 9.8).abs() < 1e-10);
3749 }
3750
3751 #[test]
3752 fn nav_sat_fix_roundtrip() {
3753 let fix = NavSatFix::new(
3754 Time::new(100, 0),
3755 "gps",
3756 NavSatStatus {
3757 status: 0,
3758 service: 1,
3759 },
3760 45.5017,
3761 -73.5673,
3762 100.0,
3763 [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
3764 2,
3765 )
3766 .unwrap();
3767 let bytes = fix.to_cdr();
3768 let decoded = NavSatFix::from_cdr(bytes).unwrap();
3769 assert!((decoded.latitude() - 45.5017).abs() < 1e-10);
3770 assert_eq!(decoded.position_covariance_type(), 2);
3771 }
3772
3773 #[test]
3774 fn nav_sat_status_roundtrip() {
3775 let status = NavSatStatus {
3776 status: 0,
3777 service: 1,
3778 };
3779 let bytes = encode_fixed(&status).unwrap();
3780 let decoded: NavSatStatus = decode_fixed(&bytes).unwrap();
3781 assert_eq!(status, decoded);
3782 }
3783
3784 #[test]
3785 fn region_of_interest_roundtrip() {
3786 let roi = RegionOfInterest {
3787 x_offset: 10,
3788 y_offset: 20,
3789 height: 100,
3790 width: 200,
3791 do_rectify: true,
3792 };
3793 let bytes = encode_fixed(&roi).unwrap();
3794 let decoded: RegionOfInterest = decode_fixed(&bytes).unwrap();
3795 assert_eq!(roi, decoded);
3796 }
3797
3798 #[test]
3799 fn point_cloud2_roundtrip() {
3800 let fields = [
3801 PointFieldView {
3802 name: "x",
3803 offset: 0,
3804 datatype: 7,
3805 count: 1,
3806 },
3807 PointFieldView {
3808 name: "y",
3809 offset: 4,
3810 datatype: 7,
3811 count: 1,
3812 },
3813 PointFieldView {
3814 name: "z",
3815 offset: 8,
3816 datatype: 7,
3817 count: 1,
3818 },
3819 ];
3820 let data = vec![0u8; 12288];
3821 let cloud = PointCloud2::new(
3822 Time::new(100, 0),
3823 "lidar",
3824 1,
3825 1024,
3826 &fields,
3827 false,
3828 12,
3829 12288,
3830 &data,
3831 true,
3832 )
3833 .unwrap();
3834 let bytes = cloud.to_cdr();
3835 let decoded = PointCloud2::from_cdr(bytes).unwrap();
3836 assert_eq!(decoded.height(), 1);
3837 assert_eq!(decoded.width(), 1024);
3838 assert_eq!(decoded.fields_len(), 3);
3839 assert!(decoded.is_dense());
3840 }
3841
3842 #[test]
3843 fn point_cloud2_fields_iter() {
3844 let fields = [
3845 PointFieldView {
3846 name: "x",
3847 offset: 0,
3848 datatype: 7,
3849 count: 1,
3850 },
3851 PointFieldView {
3852 name: "y",
3853 offset: 4,
3854 datatype: 7,
3855 count: 1,
3856 },
3857 PointFieldView {
3858 name: "z",
3859 offset: 8,
3860 datatype: 7,
3861 count: 1,
3862 },
3863 ];
3864 let data = vec![0u8; 36]; let cloud = PointCloud2::new(
3866 Time::new(100, 0),
3867 "lidar",
3868 1,
3869 3,
3870 &fields,
3871 false,
3872 12,
3873 36,
3874 &data,
3875 true,
3876 )
3877 .unwrap();
3878 let cdr = cloud.to_cdr();
3879 let decoded = PointCloud2::from_cdr(cdr).unwrap();
3880
3881 let iter_fields: Vec<_> = decoded.fields_iter().collect();
3882 assert_eq!(iter_fields.len(), 3);
3883 assert_eq!(iter_fields[0].name, "x");
3884 assert_eq!(iter_fields[1].name, "y");
3885 assert_eq!(iter_fields[2].name, "z");
3886 assert_eq!(iter_fields[0].offset, 0);
3887 assert_eq!(iter_fields[1].offset, 4);
3888 assert_eq!(iter_fields[2].offset, 8);
3889 assert_eq!(decoded.point_count(), 3);
3890 }
3891
3892 #[test]
3893 fn camera_info_roundtrip() {
3894 let roi = RegionOfInterest {
3895 x_offset: 0,
3896 y_offset: 0,
3897 height: 480,
3898 width: 640,
3899 do_rectify: false,
3900 };
3901 let cam = CameraInfo::new(
3902 Time::new(100, 0),
3903 "camera",
3904 480,
3905 640,
3906 "plumb_bob",
3907 &[0.1, -0.2, 0.0, 0.0, 0.0],
3908 [500.0, 0.0, 320.0, 0.0, 500.0, 240.0, 0.0, 0.0, 1.0],
3909 [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
3910 [
3911 500.0, 0.0, 320.0, 0.0, 0.0, 500.0, 240.0, 0.0, 0.0, 0.0, 1.0, 0.0,
3912 ],
3913 1,
3914 1,
3915 roi,
3916 )
3917 .unwrap();
3918 let bytes = cam.to_cdr();
3919 let decoded = CameraInfo::from_cdr(bytes).unwrap();
3920 assert_eq!(decoded.height(), 480);
3921 assert_eq!(decoded.width(), 640);
3922 assert_eq!(decoded.distortion_model(), "plumb_bob");
3923 assert_eq!(decoded.d_len(), 5);
3924 assert_eq!(decoded.binning_x(), 1);
3925 }
3926
3927 #[test]
3934 fn navsatfix_accessors_robust_across_frame_id_alignments() {
3935 let lat = 43.6532_f64;
3936 let lon = -79.3832_f64;
3937 let alt = 150.0_f64;
3938 let cov = [0.1, 0.0, 0.0, 0.0, 0.2, 0.0, 0.0, 0.0, 0.3_f64];
3939 let cov_type = 2_u8;
3940 let status = NavSatStatus {
3941 status: 0,
3942 service: 1,
3943 };
3944 for len in 0..=16_usize {
3945 let frame_id: String = "x".repeat(len);
3946 let fix = NavSatFix::new(
3947 Time::new(1, 0),
3948 &frame_id,
3949 status,
3950 lat,
3951 lon,
3952 alt,
3953 cov,
3954 cov_type,
3955 )
3956 .unwrap();
3957 let bytes = fix.to_cdr();
3958 let view = NavSatFix::from_cdr(&bytes[..]).unwrap();
3959 assert_eq!(view.frame_id(), frame_id, "frame_id at len={len}");
3960 let rx_status = view.status();
3961 assert_eq!(rx_status.status, 0, "status.status at len={len}");
3962 assert_eq!(rx_status.service, 1, "status.service at len={len}");
3963 assert_eq!(view.latitude(), lat, "latitude at len={len}");
3964 assert_eq!(view.longitude(), lon, "longitude at len={len}");
3965 assert_eq!(view.altitude(), alt, "altitude at len={len}");
3966 assert_eq!(
3967 view.position_covariance(),
3968 cov,
3969 "position_covariance at len={len}"
3970 );
3971 assert_eq!(
3972 view.position_covariance_type(),
3973 cov_type,
3974 "position_covariance_type at len={len}"
3975 );
3976 }
3977 }
3978
3979 #[test]
3984 fn navsatfix_gps_link_frame_id_regression() {
3985 let status = NavSatStatus {
3986 status: 0,
3987 service: 1,
3988 };
3989 let fix = NavSatFix::new(
3990 Time::new(0, 0),
3991 "gps_link",
3992 status,
3993 43.6532,
3994 -79.3832,
3995 150.0,
3996 [0.0; 9],
3997 0,
3998 )
3999 .unwrap();
4000 let bytes = fix.to_cdr();
4001 let rx = NavSatFix::from_cdr(&bytes[..]).unwrap();
4002 assert_eq!(rx.latitude(), 43.6532);
4003 assert_eq!(rx.longitude(), -79.3832);
4004 assert_eq!(rx.altitude(), 150.0);
4005 }
4006
4007 #[test]
4010 fn sensor_setter_byte_parity() {
4011 let imu_a = Imu::builder()
4013 .stamp(Time::new(100, 500))
4014 .frame_id("imu_link")
4015 .orientation(Quaternion {
4016 x: 0.1,
4017 y: 0.2,
4018 z: 0.3,
4019 w: 0.4,
4020 })
4021 .orientation_covariance([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
4022 .angular_velocity(Vector3 {
4023 x: 0.11,
4024 y: 0.22,
4025 z: 0.33,
4026 })
4027 .angular_velocity_covariance([10.0; 9])
4028 .linear_acceleration(Vector3 {
4029 x: 0.44,
4030 y: 0.55,
4031 z: 0.66,
4032 })
4033 .linear_acceleration_covariance([20.0; 9])
4034 .build()
4035 .unwrap();
4036 let mut imu_b = Imu::builder()
4037 .stamp(Time::new(0, 0))
4038 .frame_id("imu_link")
4039 .build()
4040 .unwrap();
4041 imu_b.set_stamp(Time::new(100, 500)).unwrap();
4042 imu_b
4043 .set_orientation(Quaternion {
4044 x: 0.1,
4045 y: 0.2,
4046 z: 0.3,
4047 w: 0.4,
4048 })
4049 .unwrap();
4050 imu_b
4051 .set_orientation_covariance([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
4052 .unwrap();
4053 imu_b
4054 .set_angular_velocity(Vector3 {
4055 x: 0.11,
4056 y: 0.22,
4057 z: 0.33,
4058 })
4059 .unwrap();
4060 imu_b.set_angular_velocity_covariance([10.0; 9]).unwrap();
4061 imu_b
4062 .set_linear_acceleration(Vector3 {
4063 x: 0.44,
4064 y: 0.55,
4065 z: 0.66,
4066 })
4067 .unwrap();
4068 imu_b.set_linear_acceleration_covariance([20.0; 9]).unwrap();
4069 assert_eq!(imu_a.as_cdr(), imu_b.as_cdr(), "Imu byte mismatch");
4070
4071 let nsf_a = NavSatFix::builder()
4073 .stamp(Time::new(5, 6))
4074 .frame_id("gps")
4075 .status(NavSatStatus {
4076 status: 1,
4077 service: 3,
4078 })
4079 .latitude(45.5)
4080 .longitude(-73.6)
4081 .altitude(100.0)
4082 .position_covariance([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
4083 .position_covariance_type(2)
4084 .build()
4085 .unwrap();
4086 let mut nsf_b = NavSatFix::builder()
4087 .stamp(Time::new(0, 0))
4088 .frame_id("gps")
4089 .build()
4090 .unwrap();
4091 nsf_b.set_stamp(Time::new(5, 6)).unwrap();
4092 nsf_b
4093 .set_status(NavSatStatus {
4094 status: 1,
4095 service: 3,
4096 })
4097 .unwrap();
4098 nsf_b.set_latitude(45.5).unwrap();
4099 nsf_b.set_longitude(-73.6).unwrap();
4100 nsf_b.set_altitude(100.0).unwrap();
4101 nsf_b
4102 .set_position_covariance([0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9])
4103 .unwrap();
4104 nsf_b.set_position_covariance_type(2).unwrap();
4105 assert_eq!(nsf_a.as_cdr(), nsf_b.as_cdr(), "NavSatFix byte mismatch");
4106
4107 let pf_a = PointField::builder()
4109 .name("x")
4110 .offset(16)
4111 .datatype(7)
4112 .count(3)
4113 .build()
4114 .unwrap();
4115 let mut pf_b = PointField::builder().name("x").build().unwrap();
4116 pf_b.set_offset(16).unwrap();
4117 pf_b.set_datatype(7).unwrap();
4118 pf_b.set_count(3).unwrap();
4119 assert_eq!(pf_a.as_cdr(), pf_b.as_cdr(), "PointField byte mismatch");
4120
4121 let pc_a = PointCloud2::builder()
4123 .stamp(Time::new(1, 2))
4124 .frame_id("base_link")
4125 .height(480)
4126 .width(640)
4127 .is_bigendian(true)
4128 .point_step(16)
4129 .row_step(16 * 640)
4130 .is_dense(true)
4131 .build()
4132 .unwrap();
4133 let mut pc_b = PointCloud2::builder()
4134 .stamp(Time::new(0, 0))
4135 .frame_id("base_link")
4136 .build()
4137 .unwrap();
4138 pc_b.set_stamp(Time::new(1, 2)).unwrap();
4139 pc_b.set_height(480).unwrap();
4140 pc_b.set_width(640).unwrap();
4141 pc_b.set_is_bigendian(true).unwrap();
4142 pc_b.set_point_step(16).unwrap();
4143 pc_b.set_row_step(16 * 640).unwrap();
4144 pc_b.set_is_dense(true).unwrap();
4145 assert_eq!(pc_a.as_cdr(), pc_b.as_cdr(), "PointCloud2 byte mismatch");
4146
4147 let k = [1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0];
4149 let r = [10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0, 17.0, 18.0];
4150 let p = [
4151 20.0, 21.0, 22.0, 23.0, 24.0, 25.0, 26.0, 27.0, 28.0, 29.0, 30.0, 31.0,
4152 ];
4153 let roi = RegionOfInterest {
4154 x_offset: 1,
4155 y_offset: 2,
4156 height: 3,
4157 width: 4,
4158 do_rectify: true,
4159 };
4160 let ci_a = CameraInfo::builder()
4161 .stamp(Time::new(7, 8))
4162 .frame_id("cam")
4163 .height(480)
4164 .width(640)
4165 .distortion_model("plumb_bob")
4166 .d(&[0.1, 0.2])
4167 .k(k)
4168 .r(r)
4169 .p(p)
4170 .binning_x(2)
4171 .binning_y(3)
4172 .roi(roi)
4173 .build()
4174 .unwrap();
4175 let mut ci_b = CameraInfo::builder()
4176 .stamp(Time::new(0, 0))
4177 .frame_id("cam")
4178 .distortion_model("plumb_bob")
4179 .d(&[0.1, 0.2])
4180 .build()
4181 .unwrap();
4182 ci_b.set_stamp(Time::new(7, 8)).unwrap();
4183 ci_b.set_height(480).unwrap();
4184 ci_b.set_width(640).unwrap();
4185 ci_b.set_k(k).unwrap();
4186 ci_b.set_r(r).unwrap();
4187 ci_b.set_p(p).unwrap();
4188 ci_b.set_binning_x(2).unwrap();
4189 ci_b.set_binning_y(3).unwrap();
4190 ci_b.set_roi(roi).unwrap();
4191 assert_eq!(ci_a.as_cdr(), ci_b.as_cdr(), "CameraInfo byte mismatch");
4192
4193 let mf_a = MagneticField::builder()
4195 .stamp(Time::new(9, 10))
4196 .frame_id("imu")
4197 .magnetic_field(Vector3 {
4198 x: 1.0,
4199 y: 2.0,
4200 z: 3.0,
4201 })
4202 .magnetic_field_covariance([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
4203 .build()
4204 .unwrap();
4205 let mut mf_b = MagneticField::builder()
4206 .stamp(Time::new(0, 0))
4207 .frame_id("imu")
4208 .build()
4209 .unwrap();
4210 mf_b.set_stamp(Time::new(9, 10)).unwrap();
4211 mf_b.set_magnetic_field(Vector3 {
4212 x: 1.0,
4213 y: 2.0,
4214 z: 3.0,
4215 })
4216 .unwrap();
4217 mf_b.set_magnetic_field_covariance([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0])
4218 .unwrap();
4219 assert_eq!(mf_a.as_cdr(), mf_b.as_cdr(), "MagneticField byte mismatch");
4220
4221 let fp_a = FluidPressure::builder()
4223 .stamp(Time::new(11, 12))
4224 .frame_id("barometer")
4225 .fluid_pressure(101_325.0)
4226 .variance(0.5)
4227 .build()
4228 .unwrap();
4229 let mut fp_b = FluidPressure::builder()
4230 .stamp(Time::new(0, 0))
4231 .frame_id("barometer")
4232 .build()
4233 .unwrap();
4234 fp_b.set_stamp(Time::new(11, 12)).unwrap();
4235 fp_b.set_fluid_pressure(101_325.0).unwrap();
4236 fp_b.set_variance(0.5).unwrap();
4237 assert_eq!(fp_a.as_cdr(), fp_b.as_cdr(), "FluidPressure byte mismatch");
4238
4239 let t_a = Temperature::builder()
4241 .stamp(Time::new(13, 14))
4242 .frame_id("temp")
4243 .temperature(25.5)
4244 .variance(0.1)
4245 .build()
4246 .unwrap();
4247 let mut t_b = Temperature::builder()
4248 .stamp(Time::new(0, 0))
4249 .frame_id("temp")
4250 .build()
4251 .unwrap();
4252 t_b.set_stamp(Time::new(13, 14)).unwrap();
4253 t_b.set_temperature(25.5).unwrap();
4254 t_b.set_variance(0.1).unwrap();
4255 assert_eq!(t_a.as_cdr(), t_b.as_cdr(), "Temperature byte mismatch");
4256
4257 let bs_a = BatteryState::builder()
4259 .stamp(Time::new(15, 16))
4260 .frame_id("batt")
4261 .voltage(12.1)
4262 .temperature(25.0)
4263 .current(-1.5)
4264 .charge(0.5)
4265 .capacity(2.0)
4266 .design_capacity(2.5)
4267 .percentage(0.75)
4268 .power_supply_status(1)
4269 .power_supply_health(2)
4270 .power_supply_technology(3)
4271 .present(true)
4272 .build()
4273 .unwrap();
4274 let mut bs_b = BatteryState::builder()
4275 .stamp(Time::new(0, 0))
4276 .frame_id("batt")
4277 .build()
4278 .unwrap();
4279 bs_b.set_stamp(Time::new(15, 16)).unwrap();
4280 bs_b.set_voltage(12.1).unwrap();
4281 bs_b.set_temperature(25.0).unwrap();
4282 bs_b.set_current(-1.5).unwrap();
4283 bs_b.set_charge(0.5).unwrap();
4284 bs_b.set_capacity(2.0).unwrap();
4285 bs_b.set_design_capacity(2.5).unwrap();
4286 bs_b.set_percentage(0.75).unwrap();
4287 bs_b.set_power_supply_status(1).unwrap();
4288 bs_b.set_power_supply_health(2).unwrap();
4289 bs_b.set_power_supply_technology(3).unwrap();
4290 bs_b.set_present(true).unwrap();
4291 assert_eq!(bs_a.as_cdr(), bs_b.as_cdr(), "BatteryState byte mismatch");
4292 }
4293}