@@ -5,8 +5,14 @@ use cu_zed::{
55} ;
66use cu29:: clock:: Tov ;
77use cu29:: prelude:: * ;
8- use cu29_logviz:: { apply_tov, log_as_components, log_fallback_payload, log_imu, log_pointcloud} ;
9- use rerun:: { Arrows3D , DepthImage , Image , RecordingStream , RecordingStreamBuilder } ;
8+ use rerun:: components:: TransformMat3x3 ;
9+ use rerun:: datatypes:: Mat3x3 ;
10+ use rerun:: {
11+ Arrows3D , DepthImage , Image , Points3D , RecordingStream , RecordingStreamBuilder , Scalars ,
12+ TextDocument , Transform3D as RerunTransform3D ,
13+ } ;
14+ use serde:: Serialize ;
15+ use std:: collections:: BTreeMap ;
1016use std:: path:: PathBuf ;
1117
1218#[ copper_runtime( config = "examples/zed_rerun_demo.ron" ) ]
@@ -69,10 +75,10 @@ impl CuSinkTask for ZedRerunSink {
6975 self . update_calibration ( calibration_msg) ?;
7076 self . update_transforms ( transforms_msg) ?;
7177
72- if let Some ( ( left , right ) ) = stereo_msg. payload ( ) {
78+ if let Some ( stereo ) = stereo_msg. payload ( ) {
7379 apply_tov ( & self . rec , & stereo_msg. tov ) ;
74- log_rgba_image ( & self . rec , "zed/left_camera/image" , left) ?;
75- log_rgba_image ( & self . rec , "zed/right_camera/image" , right) ?;
80+ log_rgba_image ( & self . rec , "zed/left_camera/image" , & stereo . left ) ?;
81+ log_rgba_image ( & self . rec , "zed/right_camera/image" , & stereo . right ) ?;
7682 }
7783
7884 if let Some ( depth) = depth_msg. payload ( ) {
@@ -163,7 +169,7 @@ impl ZedRerunSink {
163169
164170 fn log_rig_transforms ( & self , transforms : & ZedRigTransforms , tov : & Tov ) -> CuResult < ( ) > {
165171 apply_tov ( & self . rec , tov) ;
166- log_as_components (
172+ log_transform (
167173 & self . rec ,
168174 "zed/right_camera" ,
169175 & transforms. left_to_right . to_transform3d ( ) ,
@@ -176,7 +182,7 @@ impl ZedRerunSink {
176182 log_axes ( & self . rec , "zed/right_camera" , 0.08 ) ?;
177183
178184 if transforms. has_camera_to_imu {
179- log_as_components (
185+ log_transform (
180186 & self . rec ,
181187 "zed/imu" ,
182188 & transforms. camera_to_imu . to_transform3d ( ) ,
@@ -193,6 +199,135 @@ impl ZedRerunSink {
193199 }
194200}
195201
202+ fn tov_to_secs ( tov : & Tov ) -> Option < f64 > {
203+ match tov {
204+ Tov :: Time ( t) => Some ( t. 0 as f64 / 1_000_000_000.0 ) ,
205+ Tov :: Range ( r) => Some ( r. start . 0 as f64 / 1_000_000_000.0 ) ,
206+ Tov :: None => None ,
207+ }
208+ }
209+
210+ fn apply_tov ( rec : & RecordingStream , tov : & Tov ) {
211+ if let Some ( secs) = tov_to_secs ( tov) {
212+ rec. set_duration_secs ( "tov" , secs) ;
213+ } else {
214+ rec. reset_time ( ) ;
215+ }
216+ }
217+
218+ fn log_scalar ( rec : & RecordingStream , path : & str , value : f64 ) -> CuResult < ( ) > {
219+ rec. log ( path, & Scalars :: new ( [ value] ) )
220+ . map_err ( |e| CuError :: new_with_cause ( "Failed to log scalar" , e) )
221+ }
222+
223+ fn log_pointcloud < const N : usize > (
224+ rec : & RecordingStream ,
225+ path : & str ,
226+ pointcloud : & cu_sensor_payloads:: PointCloudSoa < N > ,
227+ ) -> CuResult < ( ) > {
228+ let len = pointcloud. len . min ( N ) ;
229+ let points = ( 0 ..len)
230+ . map ( |i| {
231+ [
232+ pointcloud. x [ i] . value ,
233+ pointcloud. y [ i] . value ,
234+ pointcloud. z [ i] . value ,
235+ ]
236+ } )
237+ . collect :: < Vec < _ > > ( ) ;
238+
239+ rec. log ( path, & Points3D :: new ( points) )
240+ . map_err ( |e| CuError :: new_with_cause ( "Failed to log point cloud" , e) )
241+ }
242+
243+ fn log_imu ( rec : & RecordingStream , base : & str , imu : & ImuPayload ) -> CuResult < ( ) > {
244+ log_scalar ( rec, & format ! ( "{}/accel_x" , base) , imu. accel_x . value as f64 ) ?;
245+ log_scalar ( rec, & format ! ( "{}/accel_y" , base) , imu. accel_y . value as f64 ) ?;
246+ log_scalar ( rec, & format ! ( "{}/accel_z" , base) , imu. accel_z . value as f64 ) ?;
247+ log_scalar ( rec, & format ! ( "{}/gyro_x" , base) , imu. gyro_x . value as f64 ) ?;
248+ log_scalar ( rec, & format ! ( "{}/gyro_y" , base) , imu. gyro_y . value as f64 ) ?;
249+ log_scalar ( rec, & format ! ( "{}/gyro_z" , base) , imu. gyro_z . value as f64 ) ?;
250+ log_scalar (
251+ rec,
252+ & format ! ( "{}/temperature_c" , base) ,
253+ imu. temperature
254+ . get :: < cu29:: units:: si:: thermodynamic_temperature:: degree_celsius > ( ) as f64 ,
255+ ) ?;
256+ Ok ( ( ) )
257+ }
258+
259+ fn log_transform (
260+ rec : & RecordingStream ,
261+ path : & str ,
262+ transform : & cu_transform:: Transform3D < f32 > ,
263+ ) -> CuResult < ( ) > {
264+ let matrix = transform. to_matrix ( ) ;
265+ let translation = [ matrix[ 3 ] [ 0 ] , matrix[ 3 ] [ 1 ] , matrix[ 3 ] [ 2 ] ] ;
266+ let mat3 = [
267+ matrix[ 0 ] [ 0 ] ,
268+ matrix[ 0 ] [ 1 ] ,
269+ matrix[ 0 ] [ 2 ] ,
270+ matrix[ 1 ] [ 0 ] ,
271+ matrix[ 1 ] [ 1 ] ,
272+ matrix[ 1 ] [ 2 ] ,
273+ matrix[ 2 ] [ 0 ] ,
274+ matrix[ 2 ] [ 1 ] ,
275+ matrix[ 2 ] [ 2 ] ,
276+ ] ;
277+ let transform = RerunTransform3D :: new ( )
278+ . with_translation ( translation)
279+ . with_mat3x3 ( TransformMat3x3 :: from ( Mat3x3 ( mat3) ) ) ;
280+
281+ rec. log ( path, & transform)
282+ . map_err ( |e| CuError :: new_with_cause ( "Failed to log transform" , e) )
283+ }
284+
285+ fn flatten_json ( prefix : & str , value : & serde_json:: Value ) -> BTreeMap < String , serde_json:: Value > {
286+ let mut out = BTreeMap :: new ( ) ;
287+ match value {
288+ serde_json:: Value :: Object ( map) => {
289+ for ( key, value) in map {
290+ let path = format ! ( "{}/{}" , prefix, key) ;
291+ out. extend ( flatten_json ( & path, value) ) ;
292+ }
293+ }
294+ serde_json:: Value :: Array ( values) => {
295+ for ( idx, value) in values. iter ( ) . enumerate ( ) {
296+ let path = format ! ( "{}/{}" , prefix, idx) ;
297+ out. extend ( flatten_json ( & path, value) ) ;
298+ }
299+ }
300+ _ => {
301+ out. insert ( prefix. to_string ( ) , value. clone ( ) ) ;
302+ }
303+ }
304+ out
305+ }
306+
307+ fn log_fallback_payload < T : Serialize > (
308+ rec : & RecordingStream ,
309+ base : & str ,
310+ payload : & T ,
311+ ) -> CuResult < ( ) > {
312+ let value = serde_json:: to_value ( payload)
313+ . map_err ( |e| CuError :: new_with_cause ( "Failed to serialize payload" , e) ) ?;
314+ let flat = flatten_json ( base, & value) ;
315+ for ( path, value) in flat {
316+ if let Some ( num) = value. as_f64 ( ) {
317+ log_scalar ( rec, & path, num) ?;
318+ } else if let Some ( value_bool) = value. as_bool ( ) {
319+ log_scalar ( rec, & path, if value_bool { 1.0 } else { 0.0 } ) ?;
320+ } else if let Some ( text) = value. as_str ( ) {
321+ rec. log ( path. as_str ( ) , & TextDocument :: new ( text) )
322+ . map_err ( |e| CuError :: new_with_cause ( "Failed to log text" , e) ) ?;
323+ } else if !value. is_null ( ) {
324+ rec. log ( path. as_str ( ) , & TextDocument :: new ( value. to_string ( ) ) )
325+ . map_err ( |e| CuError :: new_with_cause ( "Failed to log text" , e) ) ?;
326+ }
327+ }
328+ Ok ( ( ) )
329+ }
330+
196331fn pinhole_from_intrinsics ( intrinsics : & cu_zed:: ZedCameraIntrinsics ) -> rerun:: Pinhole {
197332 let projection = rerun:: components:: PinholeProjection :: from_focal_length_and_principal_point (
198333 [ intrinsics. fx , intrinsics. fy ] ,
0 commit comments