use std::ops::AddAssign;
use num_traits::{Float, FloatConst};
use crate::laplace_transform::DelayedRationalSum;
use crate::trajectory::{ReferenceTrajectory, Trajectory, TrajectoryProfile};
use crate::{Polynomial, TransferFunction};
#[derive(Clone, Copy, Debug)]
pub struct Sin;
impl<T: Float + FloatConst> Trajectory<T> for Sin {
fn profile(&self, distance: T, x: T) -> TrajectoryProfile<T> {
if x < T::zero() {
return TrajectoryProfile::rest(T::zero());
}
if x > T::one() {
return TrajectoryProfile::rest(distance);
}
let pi: T = FloatConst::PI();
let gain = distance * T::from(0.5).unwrap();
TrajectoryProfile {
s: gain * (T::one() - (pi * x).cos()),
v: gain * pi * (pi * x).sin(),
a: gain * pi * pi * (pi * x).cos(),
}
}
}
impl<T: Float + FloatConst + AddAssign> ReferenceTrajectory<T> for Sin {
type Reference = DelayedRationalSum<T>;
fn reference(&self, distance: T, duration: T, start: T) -> DelayedRationalSum<T> {
laplace_transform(distance, duration, start)
}
}
pub fn laplace_transform<T: Float + FloatConst + AddAssign>(distance: T, duration: T, start: T) -> DelayedRationalSum<T> {
let omega = T::PI() / duration;
let half = distance * T::from(0.5).unwrap();
let rational = TransferFunction::from_polynomials(
Polynomial(vec![half * omega * omega]),
Polynomial(vec![T::one(), T::zero(), omega * omega, T::zero()]),
);
let mut signal = DelayedRationalSum::new();
signal.push(start, rational.clone()).push(start + duration, rational);
signal
}