kernelvex 0.2.2

VEX Controls library
Documentation
use kernelvex::motion::trajectory::{Bezier, Trajectory, TrajectoryPoint};
use kernelvex::odom::pose::Pose;
use kernelvex::util::si::Vector2;
use kernelvex::util::si::{QAngle, QTime};

#[test]
fn test_trajectory_sample_endpoints() {
    let mut traj = Trajectory::new();
    traj.push(TrajectoryPoint::new(
        Pose::new(Default::default(), QAngle::from_degrees(0.0)),
        0.0,
        0.0,
        QTime::from_sec(0.0),
    ));
    traj.push(TrajectoryPoint::new(
        Pose::new(Vector2::<f64>::new(1., 0.), QAngle::from_degrees(0.0)),
        1.0,
        0.0,
        QTime::from_sec(1.0),
    ));

    let start = traj.sample(QTime::from_sec(0.0)).unwrap();
    let end = traj.sample(QTime::from_sec(1.0)).unwrap();

    let (sx, sy) = (start.pose.position().x, start.pose.position().y);
    let (ex, ey) = (end.pose.position().x, end.pose.position().y);

    assert!((sx - 0.0).abs() < 1e-6);
    assert!((sy - 0.0).abs() < 1e-6);
    assert!((ex - 1.0).abs() < 1e-6);
    assert!((ey - 0.0).abs() < 1e-6);
}

#[test]
fn test_trajectory_sample_intermediate() {
    let mut traj = Trajectory::new();
    traj.push(TrajectoryPoint::new(
        Pose::new(Default::default(), QAngle::from_degrees(0.0)),
        0.0,
        0.0,
        QTime::from_sec(0.0),
    ));
    traj.push(TrajectoryPoint::new(
        Pose::new(Vector2::<f64>::new(2., 0.), QAngle::from_degrees(0.0)),
        2.0,
        0.0,
        QTime::from_sec(2.0),
    ));

    let mid = traj.sample(QTime::from_sec(1.0)).unwrap();
    let m = mid.pose.position();

    assert!((m.x - 1.0).abs() < 1e-6);
    assert!((m.y - 0.0).abs() < 1e-6);
    assert!((mid.linear_velocity - 1.0).abs() < 1e-6);
}

#[test]
fn test_trajectory_sample_out_of_bounds() {
    let mut traj = Trajectory::new();
    traj.push(TrajectoryPoint::new(
        Pose::new(Default::default(), QAngle::from_degrees(0.0)),
        0.0,
        0.0,
        QTime::from_sec(0.0),
    ));
    traj.push(TrajectoryPoint::new(
        Pose::new(Vector2::<f64>::new(1., 0.), QAngle::from_degrees(0.0)),
        1.0,
        0.0,
        QTime::from_sec(1.0),
    ));

    let before = traj.sample(QTime::from_sec(-1.0)).unwrap();
    let after = traj.sample(QTime::from_sec(2.0)).unwrap();

    let b = before.pose.position();
    let a = after.pose.position();

    assert!((b.x - 0.0).abs() < 1e-6);
    assert!((b.y - 0.0).abs() < 1e-6);
    assert!((a.x - 1.0).abs() < 1e-6);
    assert!((a.y - 0.0).abs() < 1e-6);
}

#[test]
fn test_trajectory_heading_interpolation_shortest_arc() {
    let mut traj = Trajectory::new();
    traj.push(TrajectoryPoint::new(
        Pose::new(Default::default(), QAngle::from_degrees(350.0)),
        0.0,
        0.0,
        QTime::from_sec(0.0),
    ));
    traj.push(TrajectoryPoint::new(
        Pose::new(Default::default(), QAngle::from_degrees(10.0)),
        0.0,
        0.0,
        QTime::from_sec(1.0),
    ));

    let mid = traj.sample(QTime::from_sec(0.5)).unwrap();
    let heading = mid.pose.heading().remainder(QAngle::TAU).as_degrees();
    let heading_abs = heading.abs();

    assert!(heading_abs < 1e-6 || (360.0 - heading_abs).abs() < 1e-6);
}

#[test]
fn test_trajectory_total_time() {
    let traj = Trajectory::from_points(vec![
        TrajectoryPoint::new(
            Pose::new(Default::default(), QAngle::from_degrees(0.0)),
            0.0,
            0.0,
            QTime::from_sec(0.0),
        ),
        TrajectoryPoint::new(
            Pose::new(Vector2::<f64>::new(1., 0.), QAngle::from_degrees(0.0)),
            1.0,
            0.0,
            QTime::from_sec(3.0),
        ),
    ]);

    let total = traj.total_time().unwrap();
    assert!((total.as_sec() - 3.0).abs() < 1e-6);
}

#[test]
fn test_trajectory_sample_empty() {
    let traj = Trajectory::new();
    assert!(traj.sample(QTime::from_sec(0.0)).is_none());
}

#[test]
fn test_bezier_to_trajectory_endpoints() {
    let bezier = Bezier::new(
        Vector2::<f64>::new(0.0, 0.0),
        Vector2::<f64>::new(1.0, 0.0),
        Vector2::<f64>::new(1.0, 1.0),
        Vector2::<f64>::new(2.0, 1.0),
    );

    let traj = bezier.to_trajectory(QTime::from_sec(2.0), 5, 1.0);
    let start = traj.sample(QTime::from_sec(0.0)).unwrap();
    let end = traj.sample(QTime::from_sec(2.0)).unwrap();

    let s = start.pose.position();
    let e = end.pose.position();

    assert!((s.x - 0.0).abs() < 1e-9);
    assert!((s.y - 0.0).abs() < 1e-9);
    assert!((e.x - 2.0).abs() < 1e-9);
    assert!((e.y - 1.0).abs() < 1e-9);
}

#[test]
fn test_bezier_point() {
    let bezier = Bezier::new(Vector2::<f64>::new(1., 0.),
                                    Vector2::<f64>::new(2., 3.),
                                    Vector2::<f64>::new(3., 4.),
                                    Vector2::<f64>::new(5., 6.));

    println!("{:?}", bezier.point(0.7));
}