1use deke_types::DekeError;
2
3#[derive(Debug, thiserror::Error)]
5pub enum LinearError {
6 #[error("need at least 2 poses to define a path, got {0}")]
7 TooFewPoses(usize),
8 #[error("run {run}: every vertex coincides — nothing to follow")]
9 DegenerateRun { run: usize },
10 #[error("run {run}: Cartesian pose at arc length {s:.4} m has no reachable IK solution")]
11 Unreachable { run: usize, s: f64 },
12 #[error(
13 "run {run}: every reachable configuration at arc length {s:.4} m is rejected by the validator (obstructed)"
14 )]
15 Obstructed { run: usize, s: f64 },
16 #[error("run {run}: could not route a continuous joint track through the IK candidates")]
17 NoContinuousTrack { run: usize },
18 #[error(
19 "retimer stalled on run {run} near arc length {s:.4} m (path likely passes through a singularity)"
20 )]
21 Stalled { run: usize, s: f64 },
22 #[error(
23 "run {run}: holding constant TCP speed forbids the interior dip at arc length {s:.4} m (max feasible {feasible_speed:.4} m/s < commanded {commanded:.4} m/s)"
24 )]
25 SpeedDipRequired {
26 run: usize,
27 s: f64,
28 feasible_speed: f64,
29 commanded: f64,
30 },
31 #[error(transparent)]
32 Deke(#[from] DekeError),
33}
34
35impl From<LinearError> for DekeError {
36 fn from(e: LinearError) -> Self {
37 match e {
38 LinearError::Deke(d) => d,
39 other => DekeError::RetimerFailed(other.to_string()),
40 }
41 }
42}