Skip to main content

deke_linear/
lib.rs

1//! Constant-TCP-speed Cartesian polyline following for serial manipulators.
2//!
3//! Where the `deke-topp*` retimers are time-optimal (maximise speed under caps),
4//! `deke-linear` holds a *constant* TCP travel speed — the requirement for
5//! welding and similar process motions — and degrades gracefully near
6//! singularities. It is a CNC-style constant-feedrate interpolator in three
7//! stages:
8//!
9//! - **Stage A** ([`path`]) conditions the raw polyline into smooth, arc-length
10//!   parameterised [`CartesianRun`]s, splitting at sharp corners.
11//! - **Stage B** ([`planner`]) resolves each run to a continuous joint path by
12//!   analytic-IK branch tracking, steering away from singularities
13//!   ([`CartesianLinearPlanner`], implements [`deke_types::Planner`]).
14//! - **Stage C** ([`retimer`]) holds the commanded speed wherever the joint
15//!   v/a/j limits allow and dips smoothly where they don't
16//!   ([`ConstantSpeedRetimer`], implements [`deke_types::Retimer`]).
17//!
18//! Each stage is a standalone, trait-conforming component; the caller drives
19//! them. [`condition`] splits the polyline into runs, then for each run the
20//! [`CartesianLinearPlanner`] resolves a joint path and the
21//! [`ConstantSpeedRetimer`] times it:
22//!
23//! ```no_run
24//! # use deke_linear::*;
25//! # use deke_types::{Planner, Retimer};
26//! # use deke_types::glam::DAffine3;
27//! # fn run<FK: deke_types::ContinuousFKChain<6, f64> + deke_types::IkSolver<6, f64>>(
28//! #     fk: &FK, poses: &[DAffine3], cond: &PathConditioning,
29//! #     opts: &PlannerOptions<6>, cons: &LinearConstraints<6>) {
30//! let planner = CartesianLinearPlanner::new(fk);
31//! let retimer = ConstantSpeedRetimer::new(fk);
32//! // `NoopValidator` plans without obstacle checks; pass a real `Validator`
33//! // (and its context) to route the arm around obstacles inside the planner.
34//! for run in condition(poses, cond).unwrap() {
35//!     let (path, _) = planner.plan::<deke_types::DekeError, _>(opts, &run, &NoopValidator::<6>, &());
36//!     let (traj, _) = retimer.retime(cons, &path.unwrap(), &NoopValidator::<6>, &());
37//!     let _ = traj;
38//! }
39//! # }
40//! ```
41//!
42//! For a symmetric welding torch, the [`RedundantLinearPlanner`] treats the free
43//! tool-axis yaw as a DOF and resolves it globally to dodge singularities — and,
44//! with a real `Validator`, obstacles.
45
46pub mod constraints;
47pub mod diagnostic;
48pub mod error;
49pub mod path;
50pub mod planner;
51pub mod redundant;
52pub mod retimer;
53mod util;
54mod validator;
55
56pub use constraints::{JointLimits, LinearConstraints, PathConditioning, PlannerOptions};
57pub use diagnostic::{LinearPlannerDiagnostic, LinearRetimerDiagnostic, RedundantDiagnostic};
58pub use error::LinearError;
59pub use path::{CartesianRun, condition};
60pub use planner::CartesianLinearPlanner;
61pub use redundant::{RedundantAxis, RedundantConfig, RedundantLinearPlanner, RedundantOptions};
62pub use retimer::ConstantSpeedRetimer;
63pub use validator::NoopValidator;