use super::{r2::Positioned, se2::MaybeOriented, timed, Interpolation};
use arrayvec::ArrayVec;
pub trait Waypoint:
timed::Timed + Interpolation<Self::Position, Self::Velocity> + Clone + std::fmt::Debug
{
type Position;
type Velocity;
fn position(&self) -> Self::Position;
fn zero_velocity() -> Self::Velocity;
}
pub trait IntegrateWaypoints<W> {
type WaypointIntegrationError;
type IntegratedWaypointIter<'a>: IntoIterator<Item = Result<W, Self::WaypointIntegrationError>>
+ 'a
where
Self: 'a,
Self::WaypointIntegrationError: 'a,
W: 'a;
fn integrated_waypoints<'a>(
&'a self,
initial_waypoint: Option<W>,
) -> Self::IntegratedWaypointIter<'a>
where
Self: 'a,
Self::WaypointIntegrationError: 'a,
W: 'a;
}
pub trait Measurable<State> {
fn arclength(&self, from_state: &State, to_state: &State) -> Arclength;
}
pub struct Arclength {
pub translational: f64,
pub rotational: f64,
}
impl<S, W, const N: usize> Measurable<S> for ArrayVec<W, N>
where
S: Positioned + MaybeOriented,
W: Positioned + MaybeOriented,
{
fn arclength(&self, from_state: &S, to_state: &S) -> Arclength {
let mut translational = 0.0;
let mut rotational = 0.0;
let mut last_p = from_state.point();
let mut last_yaw = from_state.maybe_oriented();
for wp in self {
let p = wp.point();
translational += (p - last_p).norm();
last_p = p;
let yaw = wp.maybe_oriented();
if let (Some(yaw), Some(last_yaw)) = (yaw, last_yaw) {
rotational += (yaw / last_yaw).angle().abs();
}
if let Some(yaw) = yaw {
last_yaw = Some(yaw);
}
}
assert!((to_state.point() - last_p).norm_squared() < 1e-6);
Arclength {
translational,
rotational,
}
}
}