can_motor_control/
motor.rs1use motor_codec::{Event, MotorTypeId};
4
5#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
7pub struct FaultCode(pub u16);
8
9#[derive(Debug, Clone)]
15pub struct Motor {
16 name: String,
17 motor_type: MotorTypeId,
18 send_id: u32,
19 recv_id: u32,
20 position: f64,
21 velocity: f64,
22 torque: f64,
23 t_mos: i16,
24 t_rotor: i16,
25 is_enabled: bool,
26 fault: Option<FaultCode>,
27 state_sequence: u64,
28}
29
30impl Motor {
31 pub(crate) fn new(name: String, motor_type: MotorTypeId, send_id: u32, recv_id: u32) -> Self {
32 Self {
33 name,
34 motor_type,
35 send_id,
36 recv_id,
37 position: 0.0,
38 velocity: 0.0,
39 torque: 0.0,
40 t_mos: 0,
41 t_rotor: 0,
42 is_enabled: false,
43 fault: None,
44 state_sequence: 0,
45 }
46 }
47
48 pub fn name(&self) -> &str {
50 &self.name
51 }
52
53 pub fn motor_type(&self) -> MotorTypeId {
55 self.motor_type
56 }
57
58 pub fn send_id(&self) -> u32 {
60 self.send_id
61 }
62
63 pub fn recv_id(&self) -> u32 {
65 self.recv_id
66 }
67
68 pub fn position(&self) -> f64 {
70 self.position
71 }
72
73 pub fn velocity(&self) -> f64 {
75 self.velocity
76 }
77
78 pub fn torque(&self) -> f64 {
80 self.torque
81 }
82
83 pub fn temperature_mos(&self) -> i16 {
85 self.t_mos
86 }
87
88 pub fn temperature_rotor(&self) -> i16 {
90 self.t_rotor
91 }
92
93 pub fn is_enabled(&self) -> bool {
95 self.is_enabled
96 }
97
98 pub fn fault(&self) -> Option<FaultCode> {
100 self.fault
101 }
102
103 pub(crate) fn state_sequence(&self) -> u64 {
104 self.state_sequence
105 }
106
107 pub(crate) fn apply_event(&mut self, ev: &Event) {
108 match *ev {
109 Event::State {
110 q,
111 dq,
112 tau,
113 t_mos,
114 t_rotor,
115 ..
116 } => {
117 self.position = q;
118 self.velocity = dq;
119 self.torque = tau;
120 self.t_mos = t_mos;
121 self.t_rotor = t_rotor;
122 self.fault = None;
123 self.state_sequence = self.state_sequence.wrapping_add(1);
124 }
126 Event::Fault { code, .. } => {
127 self.fault = Some(FaultCode(code));
128 }
129 Event::ParamReply { .. } => {
130 }
133 _ => {
134 }
136 }
137 }
138
139 pub(crate) fn set_enabled(&mut self, on: bool) {
140 self.is_enabled = on;
141 }
142}
143
144#[cfg(test)]
145mod tests {
146 use super::*;
147
148 #[test]
149 fn newly_constructed_has_zero_state() {
150 let m = Motor::new("j0".into(), MotorTypeId::Damiao(3), 0x01, 0x11);
151 assert_eq!(m.name(), "j0");
152 assert_eq!(m.send_id(), 0x01);
153 assert_eq!(m.recv_id(), 0x11);
154 assert_eq!(m.position(), 0.0);
155 assert!(!m.is_enabled());
156 assert!(m.fault().is_none());
157 }
158
159 #[test]
160 fn apply_state_updates_cache() {
161 let mut m = Motor::new("j0".into(), MotorTypeId::Damiao(3), 0x01, 0x11);
162 m.apply_event(&Event::State {
163 motor_id: 0x11,
164 q: 0.5,
165 dq: 0.1,
166 tau: 0.2,
167 t_mos: 30,
168 t_rotor: 35,
169 });
170 assert_eq!(m.position(), 0.5);
171 assert_eq!(m.velocity(), 0.1);
172 assert_eq!(m.torque(), 0.2);
173 assert_eq!(m.temperature_mos(), 30);
174 assert_eq!(m.temperature_rotor(), 35);
175 }
176
177 #[test]
178 fn apply_fault_latches_code() {
179 let mut m = Motor::new("j0".into(), MotorTypeId::Damiao(3), 0x01, 0x11);
180 m.apply_event(&Event::Fault {
181 motor_id: 0x11,
182 code: 7,
183 });
184 assert_eq!(m.fault(), Some(FaultCode(7)));
185 }
186
187 #[test]
188 fn set_enabled_flips_flag() {
189 let mut m = Motor::new("j0".into(), MotorTypeId::Damiao(3), 0x01, 0x11);
190 assert!(!m.is_enabled());
191 m.set_enabled(true);
192 assert!(m.is_enabled());
193 m.set_enabled(false);
194 assert!(!m.is_enabled());
195 }
196}