piper_sdk/robot/
command.rs

1//! 命令类型定义模块
2//!
3//! 提供命令优先级和类型区分机制,优化丢弃策略。
4
5use crate::can::PiperFrame;
6
7/// 命令优先级
8///
9/// 用于区分不同类型的命令,优化发送策略。
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum CommandPriority {
12    /// 实时控制命令(可丢弃)
13    ///
14    /// 用于高频控制命令(500Hz-1kHz),如关节位置控制。
15    /// 如果队列满,新命令会覆盖旧命令(Overwrite 策略)。
16    /// 这确保了最新的控制命令总是被发送,即使意味着丢弃旧命令。
17    RealtimeControl,
18
19    /// 可靠命令(不可丢弃)
20    ///
21    /// 用于配置帧、状态机切换帧等关键命令。
22    /// 使用 FIFO 队列,按顺序发送,不会覆盖。
23    /// 如果队列满,会阻塞或返回错误(取决于 API)。
24    ReliableCommand,
25}
26
27/// 带优先级的命令
28///
29/// 封装 CAN 帧和优先级信息,用于类型安全的命令发送。
30#[derive(Debug, Clone, Copy)]
31pub struct PiperCommand {
32    /// CAN 帧
33    pub frame: PiperFrame,
34    /// 命令优先级
35    pub priority: CommandPriority,
36}
37
38impl PiperCommand {
39    /// 创建实时控制命令
40    pub fn realtime(frame: PiperFrame) -> Self {
41        Self {
42            frame,
43            priority: CommandPriority::RealtimeControl,
44        }
45    }
46
47    /// 创建可靠命令
48    pub fn reliable(frame: PiperFrame) -> Self {
49        Self {
50            frame,
51            priority: CommandPriority::ReliableCommand,
52        }
53    }
54
55    /// 获取命令帧
56    pub fn frame(&self) -> PiperFrame {
57        self.frame
58    }
59
60    /// 获取命令优先级
61    pub fn priority(&self) -> CommandPriority {
62        self.priority
63    }
64}
65
66impl From<PiperFrame> for PiperCommand {
67    /// 默认转换为可靠命令(向后兼容)
68    fn from(frame: PiperFrame) -> Self {
69        Self::reliable(frame)
70    }
71}
72
73impl From<PiperCommand> for PiperFrame {
74    fn from(cmd: PiperCommand) -> Self {
75        cmd.frame
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82
83    #[test]
84    fn test_command_priority() {
85        let frame = PiperFrame::new_standard(0x123, &[1, 2, 3]);
86
87        let realtime_cmd = PiperCommand::realtime(frame);
88        assert_eq!(realtime_cmd.priority(), CommandPriority::RealtimeControl);
89
90        let reliable_cmd = PiperCommand::reliable(frame);
91        assert_eq!(reliable_cmd.priority(), CommandPriority::ReliableCommand);
92    }
93
94    #[test]
95    fn test_command_from_frame() {
96        let frame = PiperFrame::new_standard(0x123, &[1, 2, 3]);
97        let cmd: PiperCommand = frame.into();
98
99        // 默认转换为可靠命令
100        assert_eq!(cmd.priority(), CommandPriority::ReliableCommand);
101        assert_eq!(cmd.frame().id, 0x123);
102    }
103
104    #[test]
105    fn test_command_to_frame() {
106        let frame = PiperFrame::new_standard(0x123, &[1, 2, 3]);
107        let cmd = PiperCommand::realtime(frame);
108
109        let converted_frame: PiperFrame = cmd.into();
110        assert_eq!(converted_frame.id, 0x123);
111    }
112}