1#[cfg(feature = "visualization")]
45use apex_manifolds::{se2::SE2, se3::SE3};
46#[cfg(feature = "visualization")]
47use rerun::{Arrows2D, Arrows3D, Points2D, Points3D, Transform3D, Vec2D, Vec3D};
48
49#[cfg(feature = "visualization")]
57pub trait RerunConvert3D {
58 fn to_rerun_transform(&self) -> Transform3D;
60
61 fn to_rerun_vec3d(&self) -> Vec3D;
63
64 fn to_rerun_points3d(&self) -> Points3D;
66
67 fn to_rerun_arrows3d(&self) -> Arrows3D;
72}
73
74#[cfg(feature = "visualization")]
78pub trait RerunConvert2D {
79 fn to_rerun_vec2d(&self) -> Vec2D;
81
82 fn to_rerun_points2d(&self) -> Points2D;
84
85 fn to_rerun_arrows2d(&self) -> Arrows2D;
90
91 fn to_rerun_transform_3d(&self) -> Transform3D;
95}
96
97#[cfg(feature = "visualization")]
99pub trait CollectRerun3D<'a> {
100 fn collect_points3d(self) -> Points3D;
102
103 fn collect_arrows3d(self) -> Arrows3D;
107}
108
109#[cfg(feature = "visualization")]
111pub trait CollectRerun2D<'a> {
112 fn collect_points2d(self) -> Points2D;
114
115 fn collect_arrows2d(self) -> Arrows2D;
119}
120
121#[cfg(feature = "visualization")]
126impl RerunConvert3D for SE3 {
127 fn to_rerun_transform(&self) -> Transform3D {
128 let trans = self.translation();
129 let rot = self.rotation_quaternion();
130
131 let position =
132 rerun::external::glam::Vec3::new(trans.x as f32, trans.y as f32, trans.z as f32);
133
134 let rotation = rerun::external::glam::Quat::from_xyzw(
135 rot.as_ref().i as f32,
136 rot.as_ref().j as f32,
137 rot.as_ref().k as f32,
138 rot.as_ref().w as f32,
139 );
140
141 Transform3D::from_translation_rotation(position, rotation)
142 }
143
144 fn to_rerun_vec3d(&self) -> Vec3D {
145 let trans = self.translation();
146 Vec3D::new(trans.x as f32, trans.y as f32, trans.z as f32)
147 }
148
149 fn to_rerun_points3d(&self) -> Points3D {
150 let vec = self.to_rerun_vec3d();
151 Points3D::new([vec])
152 }
153
154 fn to_rerun_arrows3d(&self) -> Arrows3D {
155 let rot_quat = self.rotation_quaternion();
156 let rot_mat = rot_quat.to_rotation_matrix();
157 let trans = self.translation();
158
159 let x_axis = [
160 rot_mat[(0, 0)] as f32,
161 rot_mat[(1, 0)] as f32,
162 rot_mat[(2, 0)] as f32,
163 ];
164 let y_axis = [
165 rot_mat[(0, 1)] as f32,
166 rot_mat[(1, 1)] as f32,
167 rot_mat[(2, 1)] as f32,
168 ];
169 let z_axis = [
170 rot_mat[(0, 2)] as f32,
171 rot_mat[(1, 2)] as f32,
172 rot_mat[(2, 2)] as f32,
173 ];
174
175 let origin = [trans.x as f32, trans.y as f32, trans.z as f32];
176
177 Arrows3D::from_vectors([x_axis, y_axis, z_axis])
178 .with_origins([origin, origin, origin])
179 .with_colors([[255, 0, 0], [0, 255, 0], [0, 0, 255]]) }
181}
182
183#[cfg(feature = "visualization")]
188impl RerunConvert2D for SE2 {
189 fn to_rerun_vec2d(&self) -> Vec2D {
190 Vec2D::new(self.x() as f32, self.y() as f32)
191 }
192
193 fn to_rerun_points2d(&self) -> Points2D {
194 let vec = self.to_rerun_vec2d();
195 Points2D::new([vec])
196 }
197
198 fn to_rerun_arrows2d(&self) -> Arrows2D {
199 let rot_mat = self.rotation_matrix();
200
201 let x_axis = [rot_mat[(0, 0)] as f32, rot_mat[(1, 0)] as f32];
202 let y_axis = [rot_mat[(0, 1)] as f32, rot_mat[(1, 1)] as f32];
203
204 let origin = [self.x() as f32, self.y() as f32];
205
206 Arrows2D::from_vectors([x_axis, y_axis])
207 .with_origins([origin, origin])
208 .with_colors([[255, 0, 0], [0, 255, 0]]) }
210
211 fn to_rerun_transform_3d(&self) -> Transform3D {
212 let position = rerun::external::glam::Vec3::new(self.x() as f32, self.y() as f32, 0.0);
213
214 let angle = self.angle();
215 let half_angle = (angle / 2.0) as f32;
216 let rotation =
217 rerun::external::glam::Quat::from_xyzw(0.0, 0.0, half_angle.sin(), half_angle.cos());
218
219 Transform3D::from_translation_rotation(position, rotation)
220 }
221}
222
223#[cfg(feature = "visualization")]
228impl<'a, I> CollectRerun3D<'a> for I
229where
230 I: Iterator<Item = &'a SE3>,
231{
232 fn collect_points3d(self) -> Points3D {
233 let points: Vec<Vec3D> = self.map(|se3| se3.to_rerun_vec3d()).collect();
234 Points3D::new(points)
235 }
236
237 fn collect_arrows3d(self) -> Arrows3D {
238 let mut vectors = Vec::new();
239 let mut origins = Vec::new();
240 let mut colors = Vec::new();
241
242 for se3 in self {
243 let rot_quat = se3.rotation_quaternion();
244 let rot_mat = rot_quat.to_rotation_matrix();
245 let trans = se3.translation();
246
247 let x_axis = [
248 rot_mat[(0, 0)] as f32,
249 rot_mat[(1, 0)] as f32,
250 rot_mat[(2, 0)] as f32,
251 ];
252 let y_axis = [
253 rot_mat[(0, 1)] as f32,
254 rot_mat[(1, 1)] as f32,
255 rot_mat[(2, 1)] as f32,
256 ];
257 let z_axis = [
258 rot_mat[(0, 2)] as f32,
259 rot_mat[(1, 2)] as f32,
260 rot_mat[(2, 2)] as f32,
261 ];
262
263 let origin = [trans.x as f32, trans.y as f32, trans.z as f32];
264
265 vectors.push(x_axis);
266 vectors.push(y_axis);
267 vectors.push(z_axis);
268 origins.push(origin);
269 origins.push(origin);
270 origins.push(origin);
271 colors.push([255, 0, 0]); colors.push([0, 255, 0]); colors.push([0, 0, 255]); }
275
276 Arrows3D::from_vectors(vectors)
277 .with_origins(origins)
278 .with_colors(colors)
279 }
280}
281
282#[cfg(feature = "visualization")]
287impl<'a, I> CollectRerun2D<'a> for I
288where
289 I: Iterator<Item = &'a SE2>,
290{
291 fn collect_points2d(self) -> Points2D {
292 let points: Vec<Vec2D> = self.map(|se2| se2.to_rerun_vec2d()).collect();
293 Points2D::new(points)
294 }
295
296 fn collect_arrows2d(self) -> Arrows2D {
297 let mut vectors = Vec::new();
298 let mut origins = Vec::new();
299 let mut colors = Vec::new();
300
301 for se2 in self {
302 let rot_mat = se2.rotation_matrix();
303
304 let x_axis = [rot_mat[(0, 0)] as f32, rot_mat[(1, 0)] as f32];
305 let y_axis = [rot_mat[(0, 1)] as f32, rot_mat[(1, 1)] as f32];
306
307 let origin = [se2.x() as f32, se2.y() as f32];
308
309 vectors.push(x_axis);
310 vectors.push(y_axis);
311 origins.push(origin);
312 origins.push(origin);
313 colors.push([255, 0, 0]); colors.push([0, 255, 0]); }
316
317 Arrows2D::from_vectors(vectors)
318 .with_origins(origins)
319 .with_colors(colors)
320 }
321}
322
323#[cfg(test)]
324#[cfg(feature = "visualization")]
325mod tests {
326 use super::*;
327
328 #[test]
329 fn test_se3_to_vec3d() {
330 use apex_manifolds::se3::SE3;
331
332 let pose = SE3::identity();
333 let vec = pose.to_rerun_vec3d();
334
335 assert_eq!(vec.x(), 0.0);
336 assert_eq!(vec.y(), 0.0);
337 assert_eq!(vec.z(), 0.0);
338 }
339
340 #[test]
341 fn test_se2_to_vec2d() {
342 use apex_manifolds::se2::SE2;
343
344 let pose = SE2::identity();
345 let vec = pose.to_rerun_vec2d();
346
347 assert_eq!(vec.x(), 0.0);
348 assert_eq!(vec.y(), 0.0);
349 }
350
351 #[test]
352 fn test_se3_collection_to_points() {
353 use apex_manifolds::se3::SE3;
354
355 let poses = [SE3::identity(), SE3::identity(), SE3::identity()];
356 let points = poses.iter().collect_points3d();
357
358 let _ = points;
359 }
360
361 #[test]
362 fn test_se2_collection_to_arrows() {
363 use apex_manifolds::se2::SE2;
364
365 let poses = [SE2::identity(), SE2::identity()];
366 let arrows = poses.iter().collect_arrows2d();
367
368 let _ = arrows;
369 }
370}