motor_codec/motor.rs
1//! Vendor-tagged motor identifiers and value types.
2
3/// Vendor-tagged motor type identifier.
4///
5/// Each variant carries an opaque `u16` discriminant that the owning vendor's
6/// codec interprets internally — no two vendors need to coordinate their
7/// discriminant spaces.
8#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
9#[non_exhaustive]
10pub enum MotorTypeId {
11 /// Damiao motor SKU (DM4310, DM4340, ...). The `u16` is the SKU discriminant
12 /// defined in `can-motor-damiao-codec`.
13 Damiao(u16),
14 /// Robostride motor SKU. Reserved for a future vendor codec crate.
15 Robostride(u16),
16}
17
18/// Borrowed view of a motor's identity, suitable for passing into codec encode
19/// methods without taking ownership of the motor's mutable state.
20#[derive(Copy, Clone, Debug)]
21pub struct MotorRef<'a> {
22 /// The motor's vendor type identifier.
23 pub motor_type: MotorTypeId,
24 /// CAN ID this motor accepts commands on.
25 pub send_id: u32,
26 /// CAN ID this motor emits state and replies from.
27 pub recv_id: u32,
28 /// Human-readable motor name from the robot config.
29 pub name: &'a str,
30}
31
32/// Per-motor-type physical limits used to scale MIT commands and unscale
33/// state replies.
34#[derive(Copy, Clone, Debug, PartialEq)]
35pub struct Limits {
36 /// Position magnitude limit (radians).
37 pub p_max: f64,
38 /// Velocity magnitude limit (rad/s).
39 pub v_max: f64,
40 /// Torque magnitude limit (Nm).
41 pub t_max: f64,
42}
43
44#[cfg(test)]
45mod tests {
46 use super::*;
47
48 #[test]
49 fn damiao_variant_round_trips() {
50 let id = MotorTypeId::Damiao(7);
51 match id {
52 MotorTypeId::Damiao(d) => assert_eq!(d, 7),
53 _ => panic!("wrong variant"),
54 }
55 }
56
57 #[test]
58 fn non_exhaustive_match_falls_through() {
59 // Simulate the consumer pattern in design.md Decision 11.
60 fn classify(t: MotorTypeId) -> &'static str {
61 match t {
62 MotorTypeId::Damiao(_) => "damiao",
63 _ => "other",
64 }
65 }
66 assert_eq!(classify(MotorTypeId::Damiao(0)), "damiao");
67 assert_eq!(classify(MotorTypeId::Robostride(0)), "other");
68 }
69
70 #[test]
71 fn motor_ref_construction() {
72 let r = MotorRef {
73 motor_type: MotorTypeId::Damiao(0),
74 send_id: 0x01,
75 recv_id: 0x11,
76 name: "j0",
77 };
78 assert_eq!(r.name, "j0");
79 assert_eq!(r.send_id, 0x01);
80 }
81}