use core::{marker::PhantomData, ops};
use num_traits::{Inv as _, One as _};
use crate::MotionProfile;
pub struct Delays<'r, Profile>(pub &'r mut Profile);
impl<'r, Profile> Iterator for Delays<'r, Profile>
where
Profile: MotionProfile,
{
type Item = Profile::Delay;
fn next(&mut self) -> Option<Self::Item> {
self.0.next_delay()
}
}
pub struct Velocities<'r, Profile>(pub &'r mut Profile);
impl<'r, Profile> Iterator for Velocities<'r, Profile>
where
Profile: MotionProfile,
Profile::Delay: num_traits::Inv<Output = Profile::Velocity>,
{
type Item = Profile::Velocity;
fn next(&mut self) -> Option<Self::Item> {
self.0.next_delay().map(|delay| delay.inv())
}
}
pub struct Accelerations<'r, Profile: MotionProfile, Accel> {
pub profile: &'r mut Profile,
pub delay_prev: Option<Profile::Delay>,
_accel: PhantomData<Accel>,
}
impl<'r, Profile, Accel> Accelerations<'r, Profile, Accel>
where
Profile: MotionProfile,
{
pub fn new(profile: &'r mut Profile) -> Self {
let delay_prev = profile.next_delay();
Self {
profile,
delay_prev,
_accel: PhantomData,
}
}
}
impl<'r, Profile, Accel> Iterator for Accelerations<'r, Profile, Accel>
where
Profile: MotionProfile,
Profile::Delay: Copy
+ num_traits::One
+ num_traits::Inv<Output = Profile::Velocity>
+ ops::Add<Output = Profile::Delay>
+ ops::Div<Output = Profile::Delay>,
Profile::Velocity: ops::Sub<Output = Profile::Velocity>
+ ops::Div<Profile::Delay, Output = Accel>,
{
type Item = Accel;
fn next(&mut self) -> Option<Self::Item> {
let delay_next = self.profile.next_delay()?;
let mut accel = None;
if let Some(delay_prev) = self.delay_prev {
let velocity_prev = delay_prev.inv();
let velocity_next = delay_next.inv();
let velocity_diff = velocity_next - velocity_prev;
let two = Profile::Delay::one() + Profile::Delay::one();
let time_diff = delay_prev / two + delay_next / two;
accel = Some(velocity_diff / time_diff);
}
self.delay_prev = Some(delay_next);
accel
}
}