use approx::{assert_relative_eq, relative_eq};
use polynomen::Poly;
use automatica::{
plots::{bode::Bode, polar::Polar},
units::ToDecibel,
RadiansPerSecond, Tf,
};
#[test]
fn bode_plot() {
let xi = 0.1_f32;
let omega = 1.;
let tf = Tf::new([1.], [1., 2. * xi / omega, (omega * omega).recip()]);
let bode = Bode::new(tf, RadiansPerSecond(0.1), RadiansPerSecond(10.), 0.1);
let data: Vec<_> = bode.into_iter().into_db_deg().collect();
let peak = (1. / 2. / xi.abs()).to_db();
assert_relative_eq!(peak, data[10].magnitude(), max_relative = 1e-6);
assert_relative_eq!(-90., data[10].phase());
}
#[test]
fn polar_plot() {
let tf = Tf::new([5.], Poly::new_from_roots(&[-1., -10.]));
let p = Polar::new(tf, RadiansPerSecond(0.1), RadiansPerSecond(10.0), 0.1);
let points = p.into_iter();
assert!(points.clone().all(|x| x.magnitude() < 1.));
assert!(
points
.fold((true, 1.0), |acc, x| (
acc.0 && x.magnitude() < acc.1,
x.magnitude()
))
.0
);
}
#[test]
fn root_locus_plot() {
let tf = Tf::new([1.0_f64], Poly::new_from_roots(&[0., -3., -5.]));
let loci = tf.root_locus_plot(1., 130., 1.);
for locus in loci {
let out = locus.output();
if locus.k() < 120. {
assert!(out[0].re < 0.);
assert!(out[1].re < 0.);
assert!(out[2].re < 0.);
} else {
assert!(out[0].re > 0.);
assert!(out[1].re > 0.);
assert!(relative_eq!(out[2].re, -8.) || out[2].re <= -8.);
}
assert_relative_eq!(out[0].im.abs(), out[1].im.abs());
assert_relative_eq!(out[2].im, 0.);
}
}