autocore_std/motion/axis_view.rs
1//! Generic hardware interface for CiA 402 servo drives.
2//!
3//! [`AxisView`] provides raw PDO field access. The [`Axis`](super::Axis)
4//! struct handles all CiA 402 protocol logic (state machine, PP handshake,
5//! homing) on top of this, so implementors only need to map PDO fields.
6
7/// Generic hardware interface for a CiA 402 servo drive.
8///
9/// Maps raw PDO fields. The [`Axis`](super::Axis) struct handles all CiA 402
10/// protocol logic (state machine, PP handshake, homing) on top of this.
11///
12/// # Implementing
13///
14/// Implementors just map their struct's PDO fields — no CiA 402 protocol
15/// knowledge is needed:
16///
17/// ```ignore
18/// impl AxisView for MyDriveView<'_> {
19/// fn control_word(&self) -> u16 { *self.control_word }
20/// fn set_control_word(&mut self, w: u16) { *self.control_word = w; }
21/// fn status_word(&self) -> u16 { *self.status_word }
22/// fn set_target_position(&mut self, pos: i32) { *self.target_position = pos; }
23/// // ... etc
24/// }
25/// ```
26pub trait AxisView {
27 // ── Control word (RxPDO) ──
28
29 /// Read the current control word.
30 fn control_word(&self) -> u16;
31 /// Write the control word.
32 fn set_control_word(&mut self, word: u16);
33
34 // ── Targets (RxPDO) ──
35
36 /// Set the target position in encoder counts.
37 fn set_target_position(&mut self, pos: i32);
38 /// Set the profile velocity in counts/s.
39 fn set_profile_velocity(&mut self, vel: u32);
40 /// Set the profile acceleration in counts/s².
41 fn set_profile_acceleration(&mut self, accel: u32);
42 /// Set the profile deceleration in counts/s².
43 fn set_profile_deceleration(&mut self, decel: u32);
44
45 // ── Mode (RxPDO / TxPDO) ──
46
47 /// Write the modes of operation register (0x6060).
48 fn set_modes_of_operation(&mut self, mode: i8);
49 /// Read the modes of operation display (0x6061).
50 fn modes_of_operation_display(&self) -> i8;
51
52 // ── Status (TxPDO) ──
53
54 /// Read the status word.
55 fn status_word(&self) -> u16;
56 /// Read the actual position in encoder counts.
57 fn position_actual(&self) -> i32;
58 /// Read the actual velocity in counts/s.
59 fn velocity_actual(&self) -> i32;
60
61 // ── Optional: error code from TxPDO (vendor-mapped) ──
62
63 /// Read the drive error code. Returns 0 if not mapped.
64 fn error_code(&self) -> u16 { 0 }
65
66 // ── Optional: limit switches and home sensor ──
67
68 /// True when the positive-direction hardware limit switch is active.
69 ///
70 /// Implement this to wire a physical limit switch input from your
71 /// global memory / PDO mapping. If not implemented, returns `false`
72 /// (no limit switch).
73 fn positive_limit_active(&self) -> bool { false }
74
75 /// True when the negative-direction hardware limit switch is active.
76 fn negative_limit_active(&self) -> bool { false }
77
78 /// True when the home reference sensor is active.
79 fn home_sensor_active(&self) -> bool { false }
80
81 // ── Optional: dynamic (GlobalMemory-linked) software position limits ──
82
83 /// Current maximum software position limit in user units, or `None`
84 /// if no dynamic limit is configured. When `Some`, the axis rejects
85 /// moves whose target exceeds this value, and quick-stops if the
86 /// actual position passes it while moving in the positive direction.
87 ///
88 /// This is combined with the static [`AxisConfig`](super::axis_config::AxisConfig)
89 /// max limit using the most-restrictive value.
90 fn dynamic_max_position_limit(&self) -> Option<f64> { None }
91
92 /// Current minimum software position limit in user units, or `None`
93 /// if no dynamic limit is configured. See [`dynamic_max_position_limit`](Self::dynamic_max_position_limit).
94 fn dynamic_min_position_limit(&self) -> Option<f64> { None }
95}
96
97/// High-level interface for a motion axis.
98///
99/// This trait provides a unified interface for both raw [`Axis`](super::Axis)
100/// objects and the higher-level generated `AxisHandle` structs used in the
101/// control program.
102pub trait AxisHandle {
103 /// Actual position in user units.
104 fn position(&self) -> f64;
105 /// Read-only access to the axis configuration.
106 fn config(&self) -> &super::axis_config::AxisConfig;
107 /// Issue a relative move command.
108 fn move_relative(&mut self, distance: f64, vel: f64, accel: f64, decel: f64);
109 /// Issue an absolute move command.
110 fn move_absolute(&mut self, position: f64, vel: f64, accel: f64, decel: f64);
111 /// Halt the axis immediately.
112 fn halt(&mut self);
113 /// True if the axis is currently executing an operation.
114 fn is_busy(&self) -> bool;
115 /// True if the axis is in an error state.
116 fn is_error(&self) -> bool;
117 /// True if the motor is enabled and holding torque.
118 fn motor_on(&self) -> bool;
119}