franka/robot/target_control/
runner.rs1use std::sync::atomic::Ordering;
6use std::sync::mpsc::SyncSender;
7use std::sync::Arc;
8
9use super::{Settle, Shared, DEVIATION_MESSAGE, STOP_TIMEOUT_CYCLES};
10use crate::error::{ControlException, FrankaError, FrankaResult};
11use crate::otg::{MultiOtg, OtgLimits};
12use crate::rate_limiting::DELTA_T;
13use crate::robot_state::RobotState;
14
15pub const REST_VELOCITY: f64 = 1e-4;
22pub const REST_ACCELERATION: f64 = 0.05;
25pub const REST_JOINT_VELOCITY: f64 = 0.01;
28
29pub(super) type Chart<const N: usize, const S: usize> =
32 fn(target: &[f64; S], commanded: &[f64; S]) -> ([f64; N], [f64; N]);
33
34pub(super) struct Step<const N: usize, const S: usize> {
36 pub position: [f64; N],
37 pub velocity: [f64; N],
38 pub acceleration: [f64; N],
39 pub target: [f64; S],
41 pub hold: bool,
43 pub finished: bool,
44}
45
46struct Hold<const N: usize> {
48 position: [f64; N],
49 sent: u32,
50}
51
52pub(super) struct Runner<const N: usize, const S: usize> {
54 shared: Arc<Shared<S>>,
55 started: Option<SyncSender<()>>,
56 otg: MultiOtg<N>,
57 settle: Settle,
58 chart: Chart<N, S>,
59 target: [f64; S],
60 anchored: bool,
61 deviated: bool,
62 stop_cycles: u32,
63 hold: Option<Hold<N>>,
64}
65
66pub(super) fn identity<const N: usize>(
68 target: &[f64; N],
69 commanded: &[f64; N],
70) -> ([f64; N], [f64; N]) {
71 (*commanded, *target)
72}
73
74impl<const N: usize, const S: usize> Runner<N, S> {
75 pub(super) fn new(
76 shared: Arc<Shared<S>>,
77 started: SyncSender<()>,
78 limits: [OtgLimits; N],
79 settle: Settle,
80 chart: Chart<N, S>,
81 ) -> FrankaResult<Self> {
82 Ok(Runner {
83 shared,
84 started: Some(started),
85 otg: MultiOtg::with_limits([0.0; N], limits, true)?,
88 settle,
89 chart,
90 target: [0.0; S],
91 anchored: false,
92 deviated: false,
93 stop_cycles: 0,
94 hold: None,
95 })
96 }
97
98 pub(super) fn cycle(
101 &mut self,
102 state: &RobotState,
103 commanded: [f64; S],
104 strayed: bool,
105 ) -> Step<N, S> {
106 if let Ok(mut latest) = self.shared.state.try_lock() {
107 *latest = *state;
108 }
109 if let Some(hold) = &mut self.hold {
110 hold.sent += 1;
113 return Step {
114 position: hold.position,
115 velocity: [0.0; N],
116 acceleration: [0.0; N],
117 target: self.target,
118 hold: true,
119 finished: hold.sent > self.settle.cycles,
120 };
121 }
122 let stopping = self.deviated || self.shared.stop.load(Ordering::SeqCst);
124 if !self.anchored {
125 self.anchored = true;
126 self.target = commanded;
127 self.otg.reset((self.chart)(&commanded, &commanded).0);
128 self.shared.slot.publish(commanded);
129 if let Some(started) = self.started.take() {
130 let _ = started.try_send(());
131 }
132 } else if !self.deviated && strayed {
133 self.deviated = true;
134 self.target = commanded;
135 } else if !self.deviated {
136 while !self.shared.slot.load(&mut self.target) && stopping {}
139 }
140 let (anchor, goal) = (self.chart)(&self.target, &commanded);
142 let _ = self.otg.set_position(anchor);
143 let _ = self.otg.set_target(goal);
144 let position = self.otg.step(DELTA_T);
145 let axes = self.otg.axes();
146 let velocity = std::array::from_fn(|i| axes[i].velocity());
147 let acceleration = std::array::from_fn(|i| axes[i].acceleration());
148
149 if stopping || self.deviated {
150 self.stop_cycles = self.stop_cycles.saturating_add(1);
151 let landed = axes.iter().all(|a| {
152 (a.position() - a.target()).abs() < self.settle.tolerance
153 && a.velocity().abs() < REST_VELOCITY
154 && a.acceleration().abs() < REST_ACCELERATION
155 });
156 if landed || self.stop_cycles >= STOP_TIMEOUT_CYCLES {
161 let held = (self.chart)(&commanded, &commanded).0;
162 self.hold = Some(Hold {
163 position: held,
164 sent: 1,
165 });
166 return Step {
167 position: held,
168 velocity: [0.0; N],
169 acceleration: [0.0; N],
170 target: self.target,
171 hold: true,
172 finished: false,
173 };
174 }
175 }
176 Step {
177 position,
178 velocity,
179 acceleration,
180 target: self.target,
181 hold: false,
182 finished: false,
183 }
184 }
185
186 pub(super) fn finish(&self, result: FrankaResult<()>) -> FrankaResult<()> {
188 match result {
189 Ok(()) if self.deviated => Err(FrankaError::Control(ControlException::new(
190 DEVIATION_MESSAGE,
191 ))),
192 other => other,
193 }
194 }
195}