use cu_spatial_payloads::Transform3D;
use cu_transform::transform_payload::StampedFrameTransform;
use cu_transform::{FrameIdString, FrameTransform, TransformTree};
use cu29::clock::{CuDuration, RobotClock, Tov};
fn main() {
println!("Cu Transform - CuMsg Pattern Demo");
println!("=================================");
println!();
let mut tree = TransformTree::<f32>::new();
let clock = RobotClock::default();
println!("Creating transforms with CuMsg...");
let transform1 = Transform3D::from_matrix([
[1.0f32, 0.0, 0.0, 0.0], [0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[1.0, 0.0, 0.0, 1.0], ]);
let frame_transform = FrameTransform::new(
transform1,
FrameIdString::from("world").expect("Frame name too long"),
FrameIdString::from("base").expect("Frame name too long"),
);
let mut sft = StampedFrameTransform::new(Some(frame_transform));
sft.tov = Tov::Time(CuDuration(1_000_000_000));
tree.add_transform(&sft).expect("Failed to add transform");
println!(" Added world->base transform at t=1s");
let transform2 = Transform3D::from_matrix([
[0.0, 1.0, 0.0, 0.0], [-1.0, 0.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[0.5, 0.0, 0.0, 1.0], ]);
let msg2 = FrameTransform::new(
transform2,
FrameIdString::from("base").expect("Frame name too long"),
FrameIdString::from("arm").expect("Frame name too long"),
);
let mut sft = StampedFrameTransform::new(Some(msg2));
sft.tov = Tov::Time(CuDuration(1_000_000_000));
tree.add_transform(&sft).expect("Failed to add transform");
println!(" Added base->arm transform at t=1s");
println!("\nBroadcasting multiple transforms with time range...");
let times = [
CuDuration(2_000_000_000), CuDuration(2_100_000_000), CuDuration(2_200_000_000),
];
for (i, &time) in times.iter().enumerate() {
let x_translation = 1.0 + (i as f32) * 0.1;
let transform = Transform3D::from_matrix([
[1.0, 0.0, 0.0, 0.0],
[0.0, 1.0, 0.0, 0.0],
[0.0, 0.0, 1.0, 0.0],
[x_translation, 0.0, 0.0, 1.0],
]);
let msg = FrameTransform::new(
transform,
FrameIdString::from("world").expect("Frame name too long"),
FrameIdString::from("base").expect("Frame name too long"),
);
let mut sft = StampedFrameTransform::new(Some(msg));
if i == 0 {
sft.tov = Tov::Range(cu29::clock::CuTimeRange {
start: times[0],
end: *times.last().unwrap(),
});
} else {
sft.tov = Tov::Time(time);
}
tree.add_transform(&sft).expect("Failed to add transform");
}
println!(" Added 3 transforms with time range 2.0s - 2.2s");
println!("\nQuerying transforms...");
let result = tree.lookup_transform("world", "arm", CuDuration(1_000_000_000), &clock);
match result {
Ok(transform) => {
let mat = transform.to_matrix();
println!(
" World->arm at t=1s: translation=({:.2}, {:.2}, {:.2})",
mat[3][0], mat[3][1], mat[3][2]
);
}
Err(e) => println!(" Error: {e}"),
}
let velocity = tree.lookup_velocity("world", "base", CuDuration(2_100_000_000), &clock);
match velocity {
Ok(vel) => {
println!(
" World->base velocity at t=2.1s: linear=({:.2}, {:.2}, {:.2}) m/s",
vel.linear[0], vel.linear[1], vel.linear[2]
);
}
Err(e) => println!(" Error computing velocity: {e}"),
}
println!("\nKey advantages of CuMsg pattern:");
println!("- Integrates with Copper message system");
println!("- Timestamps handled by CuMsg metadata (Tov)");
println!("- Supports time ranges for broadcasts");
}