use std::borrow::Borrow;
use nalgebra::{ComplexField, DMatrix, DVector, RealField};
use num_traits::Float;
use crate::{Continuous, Discrete, StateSpace, StateSpaceError, TransferFunction};
pub fn discretize_ssr<T: Float + ComplexField + RealField, S: Borrow<StateSpace<T, Continuous>>>(ssr: S, ts: T) -> Result<StateSpace<T, Discrete>, StateSpaceError> {
let system = ssr.borrow();
let (a, b) = {
let n = system.order.system;
let m = system.order.input;
let mut aug = DMatrix::<T>::zeros(n + m, n + m);
aug.view_mut((0, 0), (n, n)).copy_from(&system.a);
aug.view_mut((0, n), (n, m)).copy_from(&system.b);
let aug_exp = aug.scale(ts).exp();
let a = aug_exp.view((0, 0), (n, n)).into_owned();
let b = aug_exp.view((0, n), (n, m)).into_owned();
(a, b)
};
let c = system.c.clone();
let d = system.d.clone();
StateSpace::new(a, b, c, d)
}
pub fn discretize<T, S>(tf: S, ts: T) -> Result<TransferFunction<T, Discrete>, StateSpaceError>
where
T: Float + ComplexField + RealField,
S: Borrow<TransferFunction<T, Continuous>>,
{
let tf = tf.borrow();
match StateSpace::controllable_canonical(tf) {
Ok(ssr) => discretize_ssr(&ssr, ts)?.transfer_function(),
Err(StateSpaceError::EmptySystem) => {
Ok(TransferFunction::from_polynomials(tf.numerator.clone(), tf.denominator.clone()))
}
Err(e) => Err(e),
}
}
#[derive(Clone)]
pub struct DiscretizedSystem<T> {
pub continuous: StateSpace<T, Continuous>,
pub ssr: StateSpace<T, Discrete>,
pub state: DVector<T>,
pub output: DVector<T>,
pub ts: T,
}
impl<T: Float + ComplexField + RealField> DiscretizedSystem<T> {
pub fn from_ssr<S: Borrow<StateSpace<T, Continuous>>>(ssr: S, ts: T) -> Result<Self, StateSpaceError> {
let continuous = ssr.borrow().clone();
let ssr = discretize_ssr(&continuous, ts)?;
let state = DVector::zeros(ssr.order.system);
let output = DVector::zeros(ssr.order.output);
Ok(Self { continuous, ssr, state, output, ts})
}
pub fn from_tf<S: Borrow<TransferFunction<T, Continuous>>>(tf_c: S, ts: T) -> Result<Self, StateSpaceError> {
Self::from_ssr(StateSpace::controllable_canonical(tf_c.borrow())?, ts)
}
pub fn from_tf_normalized<S: Borrow<TransferFunction<T, Continuous>>>(tf_c: S, ts: T) -> Result<Self, StateSpaceError> {
Self::from_ssr(StateSpace::normalized_controllable_canonical(tf_c.borrow())?, ts)
}
pub fn update(&mut self, u: &[T]) -> Result<Vec<T>, StateSpaceError> {
if u.len() != self.ssr.order.input {
return Err(StateSpaceError::InputVector {
expected_row: self.ssr.order.input,
actual_rows: u.len()
})
}
let u: DVector<T> = DVector::from_row_slice(u);
self.output = (&self.ssr.c * &self.state) + (&self.ssr.d * &u);
self.state = (&self.ssr.a * &self.state) + (&self.ssr.b * &u);
Ok(self.output.as_slice().to_vec())
}
}