Introduce TimeInvariantSystem trait.
This trait simplifies writing dynamics equations that do not depend on time. In the future, implementations may specialize on this trait to simulate large timestamps. Gracefully ignores time parameter if called as System.
This commit is contained in:
parent
c8b15c949f
commit
ea326d4a55
6 changed files with 70 additions and 16 deletions
|
|
@ -2,7 +2,7 @@ use crate::units::*;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
integrators::traits::Accumulate,
|
integrators::traits::Accumulate,
|
||||||
traits::{Integrator, System, TimeDerivative},
|
traits::{Integrator, System, TimeDerivative, TimeInvariantSystem},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub struct Rk4;
|
pub struct Rk4;
|
||||||
|
|
@ -32,3 +32,35 @@ where
|
||||||
.add_scaled(dt / 6.0, &k4)
|
.add_scaled(dt / 6.0, &k4)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Rk4 {
|
||||||
|
pub fn step_ti<S, const N: usize, const M: usize>(
|
||||||
|
&self,
|
||||||
|
system: &S,
|
||||||
|
x: &S::State,
|
||||||
|
u: &S::Input,
|
||||||
|
dt: Time,
|
||||||
|
) -> S::State
|
||||||
|
where
|
||||||
|
S: TimeInvariantSystem<N, M>,
|
||||||
|
S::State: Clone + TimeDerivative + Accumulate<<S::State as TimeDerivative>::Derivative>,
|
||||||
|
{
|
||||||
|
let half_dt = dt * 0.5;
|
||||||
|
|
||||||
|
let k1 = system.derivatives(x, u);
|
||||||
|
|
||||||
|
let x2 = x.add_scaled(half_dt, &k1);
|
||||||
|
let k2 = system.derivatives(&x2, u);
|
||||||
|
|
||||||
|
let x3 = x.add_scaled(half_dt, &k2);
|
||||||
|
let k3 = system.derivatives(&x3, u);
|
||||||
|
|
||||||
|
let x4 = x.add_scaled(dt, &k3);
|
||||||
|
let k4 = system.derivatives(&x4, u);
|
||||||
|
|
||||||
|
x.add_scaled(dt / 6.0, &k1)
|
||||||
|
.add_scaled(dt / 3.0, &k2)
|
||||||
|
.add_scaled(dt / 3.0, &k3)
|
||||||
|
.add_scaled(dt / 6.0, &k4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -18,4 +18,4 @@ pub use units::{BackEmfConstant, CurrentRate, FrictionCoefficient, TorqueConstan
|
||||||
pub use controllers::linear_feedback::LinearFeedback;
|
pub use controllers::linear_feedback::LinearFeedback;
|
||||||
pub use integrators::rk4::Rk4;
|
pub use integrators::rk4::Rk4;
|
||||||
pub use systems::linear_system::LinearSystem;
|
pub use systems::linear_system::LinearSystem;
|
||||||
pub use traits::{Controller, Integrator, System, TimeDerivative};
|
pub use traits::{Controller, Integrator, System, TimeDerivative, TimeInvariantSystem};
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ use crate::units::*;
|
||||||
|
|
||||||
use crate::inputs::{CurrentInput, VoltageInput};
|
use crate::inputs::{CurrentInput, VoltageInput};
|
||||||
use crate::states::{CurrentRateState, CurrentState, OmegaAlphaState, ThetaOmegaState};
|
use crate::states::{CurrentRateState, CurrentState, OmegaAlphaState, ThetaOmegaState};
|
||||||
use crate::traits::{Saturate, System, TimeDerivative};
|
use crate::traits::{Saturate, TimeDerivative, TimeInvariantSystem};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
pub struct DCMotor {
|
pub struct DCMotor {
|
||||||
|
|
@ -110,13 +110,12 @@ impl DCMotor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl System<1, 1> for DCMotor {
|
impl TimeInvariantSystem<1, 1> for DCMotor {
|
||||||
type State = CurrentState;
|
type State = CurrentState;
|
||||||
type Input = VoltageInput;
|
type Input = VoltageInput;
|
||||||
|
|
||||||
fn derivatives(
|
fn derivatives(
|
||||||
&self,
|
&self,
|
||||||
_t: Time,
|
|
||||||
x: &Self::State,
|
x: &Self::State,
|
||||||
u: &Self::Input,
|
u: &Self::Input,
|
||||||
) -> <Self::State as TimeDerivative>::Derivative {
|
) -> <Self::State as TimeDerivative>::Derivative {
|
||||||
|
|
@ -160,13 +159,12 @@ impl DCMotorPosition {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl System<2, 1> for DCMotorPosition {
|
impl TimeInvariantSystem<2, 1> for DCMotorPosition {
|
||||||
type State = ThetaOmegaState;
|
type State = ThetaOmegaState;
|
||||||
type Input = VoltageInput;
|
type Input = VoltageInput;
|
||||||
|
|
||||||
fn derivatives(
|
fn derivatives(
|
||||||
&self,
|
&self,
|
||||||
_t: Time,
|
|
||||||
x: &Self::State,
|
x: &Self::State,
|
||||||
u: &Self::Input,
|
u: &Self::Input,
|
||||||
) -> <Self::State as TimeDerivative>::Derivative {
|
) -> <Self::State as TimeDerivative>::Derivative {
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
use crate::inputs::AccelerationInput;
|
use crate::inputs::AccelerationInput;
|
||||||
use crate::states::{PositionVelocityState, VelocityAccelerationState};
|
use crate::states::{PositionVelocityState, VelocityAccelerationState};
|
||||||
use crate::traits::{System, TimeDerivative, VectorValue};
|
use crate::traits::{TimeDerivative, TimeInvariantSystem, VectorValue};
|
||||||
use crate::units::*;
|
use crate::units::*;
|
||||||
use nalgebra::{DMatrix, DVector, SMatrix, SVector};
|
use nalgebra::{DMatrix, DVector, SMatrix, SVector};
|
||||||
|
|
||||||
|
|
@ -28,13 +28,12 @@ impl<const N: usize, const M: usize> LinearSystem<N, M> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<const N: usize, const M: usize> System<N, M> for LinearSystem<N, M> {
|
impl<const N: usize, const M: usize> TimeInvariantSystem<N, M> for LinearSystem<N, M> {
|
||||||
type State = SVector<f64, N>;
|
type State = SVector<f64, N>;
|
||||||
type Input = SVector<f64, M>;
|
type Input = SVector<f64, M>;
|
||||||
|
|
||||||
fn derivatives(
|
fn derivatives(
|
||||||
&self,
|
&self,
|
||||||
_t: Time,
|
|
||||||
x: &Self::State,
|
x: &Self::State,
|
||||||
u: &Self::Input,
|
u: &Self::Input,
|
||||||
) -> <Self::State as TimeDerivative>::Derivative {
|
) -> <Self::State as TimeDerivative>::Derivative {
|
||||||
|
|
@ -85,13 +84,12 @@ impl DoubleIntegrator {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl System<2, 1> for DoubleIntegrator {
|
impl TimeInvariantSystem<2, 1> for DoubleIntegrator {
|
||||||
type State = PositionVelocityState;
|
type State = PositionVelocityState;
|
||||||
type Input = AccelerationInput;
|
type Input = AccelerationInput;
|
||||||
|
|
||||||
fn derivatives(
|
fn derivatives(
|
||||||
&self,
|
&self,
|
||||||
_t: Time,
|
|
||||||
x: &Self::State,
|
x: &Self::State,
|
||||||
u: &Self::Input,
|
u: &Self::Input,
|
||||||
) -> <Self::State as TimeDerivative>::Derivative {
|
) -> <Self::State as TimeDerivative>::Derivative {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@ use crate::inputs::CurrentInput;
|
||||||
use crate::states::{OmegaAlphaState, ThetaOmegaState};
|
use crate::states::{OmegaAlphaState, ThetaOmegaState};
|
||||||
use crate::systems::LinearSystem;
|
use crate::systems::LinearSystem;
|
||||||
use crate::systems::dc_motor::DCMotor;
|
use crate::systems::dc_motor::DCMotor;
|
||||||
use crate::traits::{Saturate, System, TimeDerivative};
|
use crate::traits::{Saturate, TimeDerivative, TimeInvariantSystem};
|
||||||
use nalgebra::{SMatrix, SVector};
|
use nalgebra::{SMatrix, SVector};
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug)]
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
|
@ -63,13 +63,12 @@ impl Pendulum {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl System<2, 1> for Pendulum {
|
impl TimeInvariantSystem<2, 1> for Pendulum {
|
||||||
type State = ThetaOmegaState;
|
type State = ThetaOmegaState;
|
||||||
type Input = CurrentInput;
|
type Input = CurrentInput;
|
||||||
|
|
||||||
fn derivatives(
|
fn derivatives(
|
||||||
&self,
|
&self,
|
||||||
_t: Time,
|
|
||||||
x: &Self::State,
|
x: &Self::State,
|
||||||
u: &Self::Input,
|
u: &Self::Input,
|
||||||
) -> <Self::State as TimeDerivative>::Derivative {
|
) -> <Self::State as TimeDerivative>::Derivative {
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,6 @@ pub trait System<const N: usize, const M: usize> {
|
||||||
type Input;
|
type Input;
|
||||||
|
|
||||||
// Evaluate the derivative vector x_dot at (t, x, u)
|
// Evaluate the derivative vector x_dot at (t, x, u)
|
||||||
// TODO Create time-invariant system trait?
|
|
||||||
fn derivatives(
|
fn derivatives(
|
||||||
&self,
|
&self,
|
||||||
t: Time,
|
t: Time,
|
||||||
|
|
@ -26,6 +25,34 @@ pub trait System<const N: usize, const M: usize> {
|
||||||
) -> <Self::State as TimeDerivative>::Derivative;
|
) -> <Self::State as TimeDerivative>::Derivative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub trait TimeInvariantSystem<const N: usize, const M: usize> {
|
||||||
|
type State: TimeDerivative;
|
||||||
|
type Input;
|
||||||
|
|
||||||
|
fn derivatives(
|
||||||
|
&self,
|
||||||
|
x: &Self::State,
|
||||||
|
u: &Self::Input,
|
||||||
|
) -> <Self::State as TimeDerivative>::Derivative;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T, const N: usize, const M: usize> System<N, M> for T
|
||||||
|
where
|
||||||
|
T: TimeInvariantSystem<N, M>,
|
||||||
|
{
|
||||||
|
type State = T::State;
|
||||||
|
type Input = T::Input;
|
||||||
|
|
||||||
|
fn derivatives(
|
||||||
|
&self,
|
||||||
|
_t: Time,
|
||||||
|
x: &Self::State,
|
||||||
|
u: &Self::Input,
|
||||||
|
) -> <Self::State as TimeDerivative>::Derivative {
|
||||||
|
self.derivatives(x, u)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Computes the evolution of a system over (t, x, u)
|
// Computes the evolution of a system over (t, x, u)
|
||||||
pub trait Integrator<S, const N: usize, const M: usize>
|
pub trait Integrator<S, const N: usize, const M: usize>
|
||||||
where
|
where
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue