1use std::{
2 convert::Infallible,
3 fmt::{Debug, Display},
4 time::Duration,
5};
6
7pub use glam;
8
9pub mod rexports {
10 pub use glam;
11 pub use glam_traits_ext;
12 pub use ndarray;
13 pub use num_traits;
14 pub use smallvec;
15}
16
17mod fk;
18mod path;
19mod q;
20mod traj;
21mod validator;
22mod validator_dynamic;
23
24pub use fk::{
25 BoxFK, ContinuousFKChain, FKChain, IkOutcome, IkSolutions, IkSolver, JointSpec, KinScalar,
26 KinSpec, check_finite,
27};
28pub use path::{RobotPath, SRobotPath};
29pub use q::{RobotQ, SRobotQ, SRobotQLike, robotq};
30pub use traj::{RobotTraj, SRobotTraj};
31#[doc(hidden)]
32pub use validator::BatchLimits;
33pub use validator::{
34 FromFlattened, JointValidator, Leaf, MaybeValidator, Validator, ValidatorAnd, ValidatorContext,
35 ValidatorNot, ValidatorOr,
36};
37pub use validator_dynamic::DynamicJointValidator;
38
39use crate::validator::ValidatorRet;
40
41#[derive(Debug, Clone, thiserror::Error)]
42pub enum DekeError {
43 #[error("Expected {expected} joints, but found {found}")]
44 ShapeMismatch { expected: usize, found: usize },
45 #[error("Path has {0} waypoints, needs at least 2")]
46 PathTooShort(usize),
47 #[error("Joints contain non-finite values")]
48 JointsNonFinite,
49 #[error("Self-collision detected between joints {0} and {1}")]
50 SelfCollision(i16, i16),
51 #[error("Environment collision detected between joint {0} and object {1}")]
52 EnvironmentCollision(i16, i16),
53 #[error("Joints exceed their limits")]
54 ExceedJointLimits,
55 #[error("Out of iterations")]
56 OutOfIterations,
57 #[error("Locked-prefix constraint violated at waypoint {waypoint} joint {joint}")]
58 LockedPrefixViolation { waypoint: u32, joint: u8 },
59 #[error("Boundary conditions not parallel to path tangent (residual {0})")]
60 BoundaryInfeasible(f32),
61 #[error("Path has consecutive zero-length segments")]
62 DuplicateWaypoints,
63 #[error("Retimer failed: {0}")]
64 RetimerFailed(String),
65 #[error(
66 "Retimer output exceeds {limit_type} limit on dof {dof}: observed {observed_value}, limit {limit_value} (dt_in={dt_in:?})"
67 )]
68 ExceedsDynamicsLimits {
69 dt_in: Duration,
70 limit_type: &'static str,
71 dof: u8,
72 limit_value: f64,
73 observed_value: f64,
74 },
75 #[error(
76 "URDF joint at index {index} has an unexpected type: expected {expected}, found {found}"
77 )]
78 URDFJointTypeMismatch {
79 index: usize,
80 expected: &'static str,
81 found: &'static str,
82 },
83 #[error("URDFChain<{expected}> requires {expected} revolute joints, found {found}")]
84 URDFRevoluteCountMismatch { expected: usize, found: usize },
85 #[error("IkSolver failed to converge: {0}")]
86 IkSolverFailed(f64),
87 #[error("inverse kinematics is not viable for this chain: {0}")]
88 IkNotViable(String),
89 #[error("Super error")]
90 SuperError,
91}
92
93impl From<Infallible> for DekeError {
94 fn from(_: Infallible) -> Self {
95 unreachable!()
96 }
97}
98
99pub type DekeResult<T> = Result<T, DekeError>;
100
101pub trait Planner<const N: usize, F: KinScalar = f32, R: ValidatorRet = ()>: Sized {
102 type Diagnostic: Display + Debug;
103 type Config;
104 type Waypoints;
105
106 fn plan<E: Into<DekeError>, V: Validator<N, R, F>>(
107 &self,
108 config: &Self::Config,
109 waypoints: &Self::Waypoints,
110 validator: &V,
111 ctx: &V::Context<'_>,
112 ) -> (DekeResult<SRobotPath<N, F>>, Self::Diagnostic);
113}
114
115pub trait Retimer<const N: usize, F: KinScalar = f32, R: ValidatorRet = ()>: Sized {
116 type Diagnostic: Display + Debug;
117 type Constraints;
118
119 fn retime<V: Validator<N, R, F>>(
120 &self,
121 constraints: &Self::Constraints,
122 path: &SRobotPath<N, F>,
123 validator: &V,
124 ctx: &V::Context<'_>,
125 ) -> (DekeResult<SRobotTraj<N, F>>, Self::Diagnostic);
126}