1use serde::{Deserialize, Serialize};
10
11#[serde_with::skip_serializing_none]
12#[derive(Default, Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
13pub struct PerceivedObject {
14 pub object_id: u8,
15 pub time_of_measurement: i16,
16 pub confidence: ObjectConfidence,
17 pub x_distance: i32,
18 pub y_distance: i32,
19 pub z_distance: Option<i32>,
20 pub x_speed: i16,
21 pub y_speed: i16,
22 pub z_speed: Option<i16>,
23 pub object_age: u16,
24 pub object_ref_point: Option<u8>,
25 pub x_acceleration: Option<i16>,
26 pub y_acceleration: Option<i16>,
27 pub z_acceleration: Option<i16>,
28 pub roll_angle: Option<u16>,
29 pub pitch_angle: Option<u16>,
30 pub yaw_angle: Option<u16>,
31 pub roll_rate: Option<i16>,
32 pub pitch_rate: Option<i16>,
33 pub yaw_rate: Option<i16>,
34 pub roll_acceleration: Option<i16>,
35 pub pitch_acceleration: Option<i16>,
36 pub yaw_acceleration: Option<i16>,
37 #[serde(skip_serializing_if = "Vec::is_empty", default)]
38 pub lower_triangular_correlation_matrix_columns: Vec<Vec<i8>>,
39 pub planar_object_dimension_1: Option<u16>,
40 pub planar_object_dimension_2: Option<u16>,
41 pub vertical_object_dimension: Option<u16>,
42 #[serde(skip_serializing_if = "Vec::is_empty", default)]
43 pub sensor_id_list: Vec<u8>,
44 pub dynamic_status: Option<u8>,
45 #[serde(skip_serializing_if = "Vec::is_empty", default)]
46 pub classification: Vec<ObjectClassification>,
47 pub matched_position: Option<MatchedPosition>,
48}
49
50#[serde_with::skip_serializing_none]
51#[derive(Default, Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
52pub struct ObjectConfidence {
53 pub x_distance: u16,
54 pub y_distance: u16,
55 pub x_speed: u8,
56 pub y_speed: u8,
57 pub object: Option<u8>,
58}
59
60#[serde_with::skip_serializing_none]
61#[derive(Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
62pub struct ObjectClassification {
63 pub object_class: ObjectClass,
64 pub confidence: u8,
65}
66
67#[serde_with::skip_serializing_none]
68#[derive(Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
69#[serde(rename_all = "snake_case")]
70pub enum ObjectClass {
71 Vehicle(u8),
72 SingleVru(SingleVruClass),
73 VruGroup(VruGroupClass),
74 Other(u8),
75}
76
77#[serde_with::skip_serializing_none]
78#[derive(Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
79#[serde(rename_all = "snake_case")]
80pub enum SingleVruClass {
81 Pedestrian(u8),
82 Bicyclist(u8),
83 Motorcyclist(u8),
84 Animal(u8),
85}
86
87#[serde_with::skip_serializing_none]
88#[derive(Default, Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
89pub struct VruGroupClass {
90 pub group_size: u8,
91 pub group_type: VruGroupType,
92 pub cluster_id: Option<u8>,
93}
94
95#[serde_with::skip_serializing_none]
96#[derive(Default, Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
97pub struct VruGroupType {
98 pub pedestrian: bool,
99 pub bicyclist: bool,
100 pub motorcyclist: bool,
101 pub animal: bool,
102}
103
104#[serde_with::skip_serializing_none]
105#[derive(Default, Debug, Clone, Hash, PartialEq, Serialize, Deserialize)]
106pub struct MatchedPosition {
107 pub lane_id: u8,
108 pub longitudinal_lane_position: u16,
109}
110
111#[cfg(test)]
112mod test {
113 use crate::reception::exchange::perceived_object::PerceivedObject;
114
115 #[test]
116 fn test_deserialize() {
117 let data = r#"{
118 "object_id": 5,
119 "time_of_measurement": 2,
120 "x_distance": 804,
121 "y_distance": 400,
122 "x_speed": 401,
123 "y_speed": 401,
124 "object_age": 1500,
125 "object_ref_point": 0,
126 "dynamic_status": 0,
127 "classification": [
128 {
129 "object_class": {
130 "single_vru": {
131 "pedestrian": 1
132 }
133 },
134 "confidence": 40
135 }
136 ],
137 "confidence": {
138 "x_distance": 4095,
139 "y_distance": 4095,
140 "x_speed": 0,
141 "y_speed": 0,
142 "object": 10
143 }
144 }"#;
145
146 match serde_json::from_str::<PerceivedObject>(data) {
147 Ok(po) => {
148 assert_eq!(5, po.object_id);
149 }
150 Err(e) => {
151 panic!("Failed to deserialize PO: '{}'", e);
152 }
153 }
154 }
155
156 #[test]
157 fn test_deserialize_full_po() {
158 let data = r#"{
159 "object_id": 0,
160 "time_of_measurement": 50,
161 "x_distance": 400,
162 "y_distance": 100,
163 "z_distance": 50,
164 "x_speed": 1400,
165 "y_speed": 500,
166 "z_speed": 0,
167 "x_acceleration": -160,
168 "y_acceleration": 0,
169 "z_acceleration": 161,
170 "roll_angle": 0,
171 "pitch_angle": 3600,
172 "yaw_angle": 3601,
173 "roll_rate": -32766,
174 "pitch_rate": 0,
175 "yaw_rate": 32767,
176 "roll_acceleration": -32766,
177 "pitch_acceleration": 0,
178 "yaw_acceleration": 32767,
179 "lower_triangular_correlation_matrix_columns": [
180 [-100, -99, -98],
181 [0, 1, 2],
182 [98, 99, 100]
183 ],
184 "planar_object_dimension_1": 1023,
185 "planar_object_dimension_2": 1023,
186 "vertical_object_dimension": 1023,
187 "object_ref_point": 8,
188 "confidence": {
189 "x_distance": 102,
190 "y_distance": 102,
191 "z_distance": 102,
192 "x_speed": 7,
193 "y_speed": 7,
194 "z_speed": 7,
195 "x_acceleration": 102,
196 "y_acceleration": 102,
197 "z_acceleration": 102,
198 "roll_angle": 127,
199 "pitch_angle": 127,
200 "yaw_angle": 127,
201 "roll_rate": 8,
202 "pitch_rate": 8,
203 "yaw_rate": 8,
204 "roll_acceleration": 8,
205 "pitch_acceleration": 8,
206 "yaw_acceleration": 8,
207 "planar_object_dimension_1": 102,
208 "planar_object_dimension_2": 102,
209 "vertical_object_dimension": 102,
210 "longitudinal_lane_position": 102,
211 "object": 10
212 },
213 "object_age": 1500,
214 "sensor_id_list": [1, 2, 10, 100, 255],
215 "dynamic_status": 2,
216 "classification": [{
217 "object_class": {
218 "vehicle": 10
219 },
220 "confidence": 101
221 },
222 {
223 "object_class": {
224 "single_vru": {
225 "pedestrian": 2
226 }
227 },
228 "confidence": 25
229 },
230 {
231 "object_class": {
232 "vru_group": {
233 "group_type": {
234 "pedestrian": true,
235 "bicyclist": false,
236 "motorcyclist": false,
237 "animal": true
238 },
239 "group_size": 12,
240 "cluster_id": 255
241 }
242 },
243 "confidence": 64
244 },
245 {
246 "object_class": {
247 "other": 1
248 },
249 "confidence": 0
250 }
251 ],
252 "matched_position": {
253 "lane_id": 255,
254 "longitudinal_lane_position": 32767
255 }
256 }"#;
257
258 match serde_json::from_str::<PerceivedObject>(data) {
259 Ok(po) => {
260 assert_eq!(0, po.object_id);
261 }
262 Err(e) => {
263 panic!("Failed to deserialize PO: '{}'", e);
264 }
265 }
266 }
267}