cu_transform/
frames.rs

1//! Frame identification system for compile-time frame safety
2//! This module provides a way to identify coordinate frames at compile time
3//! to avoid dynamic string allocations and improve type safety.
4
5use std::fmt::Debug;
6
7/// Trait for compile-time frame identification
8/// Each frame type must implement this to provide a unique identifier
9pub trait FrameId: Debug + Clone + Copy + PartialEq + Eq + 'static {
10    /// Unique identifier for this frame
11    const ID: u32;
12
13    /// Human-readable name for debugging
14    const NAME: &'static str;
15}
16
17/// A transform relationship between two specific frame types
18#[derive(Debug, Clone, Copy, PartialEq, Eq)]
19pub struct FramePair<Parent: FrameId, Child: FrameId> {
20    /// Parent frame type
21    pub parent: std::marker::PhantomData<Parent>,
22    /// Child frame type  
23    pub child: std::marker::PhantomData<Child>,
24}
25
26impl<Parent: FrameId, Child: FrameId> FramePair<Parent, Child> {
27    pub fn new() -> Self {
28        Self {
29            parent: std::marker::PhantomData,
30            child: std::marker::PhantomData,
31        }
32    }
33
34    pub fn parent_id() -> u32 {
35        Parent::ID
36    }
37
38    pub fn child_id() -> u32 {
39        Child::ID
40    }
41
42    pub fn parent_name() -> &'static str {
43        Parent::NAME
44    }
45
46    pub fn child_name() -> &'static str {
47        Child::NAME
48    }
49}
50
51impl<Parent: FrameId, Child: FrameId> Default for FramePair<Parent, Child> {
52    fn default() -> Self {
53        Self::new()
54    }
55}
56
57/// Common frame definitions for robotics applications
58/// Users can extend this by defining their own frame types
59///
60/// Base/world coordinate frame
61#[derive(Debug, Clone, Copy, PartialEq, Eq)]
62pub struct WorldFrame;
63
64impl FrameId for WorldFrame {
65    const ID: u32 = 0;
66    const NAME: &'static str = "world";
67}
68
69/// Robot base frame  
70#[derive(Debug, Clone, Copy, PartialEq, Eq)]
71pub struct BaseFrame;
72
73impl FrameId for BaseFrame {
74    const ID: u32 = 1;
75    const NAME: &'static str = "base";
76}
77
78/// Robot frame
79#[derive(Debug, Clone, Copy, PartialEq, Eq)]
80pub struct RobotFrame;
81
82impl FrameId for RobotFrame {
83    const ID: u32 = 2;
84    const NAME: &'static str = "robot";
85}
86
87/// Camera frame
88#[derive(Debug, Clone, Copy, PartialEq, Eq)]
89pub struct CameraFrame;
90
91impl FrameId for CameraFrame {
92    const ID: u32 = 3;
93    const NAME: &'static str = "camera";
94}
95
96/// Lidar frame
97#[derive(Debug, Clone, Copy, PartialEq, Eq)]
98pub struct LidarFrame;
99
100impl FrameId for LidarFrame {
101    const ID: u32 = 4;
102    const NAME: &'static str = "lidar";
103}
104
105/// IMU frame
106#[derive(Debug, Clone, Copy, PartialEq, Eq)]
107pub struct ImuFrame;
108
109impl FrameId for ImuFrame {
110    const ID: u32 = 5;
111    const NAME: &'static str = "imu";
112}
113
114/// Convenience type aliases for common transform relationships
115pub type WorldToBase = FramePair<WorldFrame, BaseFrame>;
116pub type WorldToRobot = FramePair<WorldFrame, RobotFrame>;
117pub type BaseToRobot = FramePair<BaseFrame, RobotFrame>;
118pub type RobotToCamera = FramePair<RobotFrame, CameraFrame>;
119pub type RobotToLidar = FramePair<RobotFrame, LidarFrame>;
120pub type RobotToImu = FramePair<RobotFrame, ImuFrame>;
121
122#[cfg(test)]
123mod tests {
124    use super::*;
125
126    #[test]
127    fn test_frame_ids() {
128        assert_eq!(WorldFrame::ID, 0);
129        assert_eq!(WorldFrame::NAME, "world");
130
131        assert_eq!(RobotFrame::ID, 2);
132        assert_eq!(RobotFrame::NAME, "robot");
133    }
134
135    #[test]
136    fn test_frame_pair() {
137        let _pair = WorldToRobot::new();
138        assert_eq!(WorldToRobot::parent_id(), WorldFrame::ID);
139        assert_eq!(WorldToRobot::child_id(), RobotFrame::ID);
140        assert_eq!(WorldToRobot::parent_name(), "world");
141        assert_eq!(WorldToRobot::child_name(), "robot");
142    }
143
144    #[test]
145    fn test_frame_equality() {
146        let frame1 = WorldFrame;
147        let frame2 = WorldFrame;
148        assert_eq!(frame1, frame2);
149
150        // Test different frame types
151        assert_eq!(WorldFrame::ID, 0);
152        assert_eq!(RobotFrame::ID, 2);
153        assert_ne!(WorldFrame::ID, RobotFrame::ID);
154    }
155}