cu_sensor_payloads/
pointcloud.rs1use bincode::{Decode, Encode};
2use cu29::prelude::*;
3use cu29::units::si::f32::{Length, Ratio};
4use cu29::units::si::length::meter;
5use cu29::units::si::ratio::percent;
6use cu29_clock::CuTime;
7use cu29_soa_derive::Soa;
8use serde::{Deserialize, Serialize};
9
10pub type Distance = Length;
11pub type Reflectivity = Ratio;
12
13#[derive(
18 Default, Clone, PartialEq, Debug, Soa, Serialize, Deserialize, Encode, Decode, Reflect,
19)]
20#[reflect(from_reflect = false)]
21pub struct PointCloud {
22 pub tov: CuTime, pub x: Distance,
24 pub y: Distance,
25 pub z: Distance,
26 pub i: Reflectivity,
27 pub return_order: u8, }
29
30impl PointCloud {
31 pub fn new(tov: CuTime, x: f32, y: f32, z: f32, i: f32, return_order: Option<u8>) -> Self {
32 Self {
33 tov,
34 x: Distance::new::<meter>(x),
35 y: Distance::new::<meter>(y),
36 z: Distance::new::<meter>(z),
37 i: Reflectivity::new::<percent>(i),
38 return_order: return_order.unwrap_or(0),
39 }
40 }
41
42 pub fn new_units(
43 tov: CuTime,
44 x: Length,
45 y: Length,
46 z: Length,
47 i: Ratio,
48 return_order: Option<u8>,
49 ) -> Self {
50 Self {
51 tov,
52 x,
53 y,
54 z,
55 i,
56 return_order: return_order.unwrap_or(0),
57 }
58 }
59}
60
61impl<const N: usize> PointCloudSoa<N> {
62 pub fn sort(&mut self) {
64 self.quicksort(0, N - 1);
65 }
66
67 fn quicksort(&mut self, low: usize, high: usize) {
69 if low < high {
70 let pivot_index = self.partition(low, high);
71 if pivot_index > 0 {
72 self.quicksort(low, pivot_index - 1);
73 }
74 self.quicksort(pivot_index + 1, high);
75 }
76 }
77
78 fn partition(&mut self, low: usize, high: usize) -> usize {
80 let pivot = self.tov[high];
81 let mut i = low;
82 for j in low..high {
83 if self.tov[j] <= pivot {
84 self.swap(i, j);
85 i += 1;
86 }
87 }
88 self.swap(i, high);
89 i
90 }
91
92 pub fn swap(&mut self, a: usize, b: usize) {
94 self.tov.swap(a, b);
95 self.x.swap(a, b);
96 self.y.swap(a, b);
97 self.z.swap(a, b);
98 self.i.swap(a, b);
99 }
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105 use cu29_clock::CuDuration;
106
107 #[test]
108 fn test_point_payload() {
109 let payload = PointCloud::new(CuDuration(1), 1.0, 2.0, 3.0, 0.0, None);
110 assert_eq!(payload.x.value, 1.0);
111 assert_eq!(payload.y.value, 2.0);
112 assert_eq!(payload.z.value, 3.0);
113 }
114
115 #[test]
116 fn test_length_add_sub() {
117 let a = Distance::new::<meter>(1.0);
118 let b = Distance::new::<meter>(2.0);
119 let c = a + b;
120 assert_eq!(c.value, 3.0);
121 let d = c - a;
122 assert_eq!(d.value, 2.0);
123 }
124
125 #[test]
126 fn test_encoding_length() {
127 let a = Distance::new::<meter>(1.0);
128 let mut encoded = vec![0u8; 1024]; let length =
131 bincode::encode_into_slice(a, &mut encoded, bincode::config::standard()).unwrap();
132 assert_eq!(length, 4);
133 }
134}