moonbitstack/moonmcl/contract does not have a README file

    Controller

    pub(open) trait Controller {
    fn update(Self, reference :
    Vec
    , measurement :
    Vec
    , dt : Double) ->
    Vec

    fn reset(Self) -> Unit
    }

    A feedback law: the input to apply for a reference and a measurement.

    The combinators in control (cascade, saturation, rate limiting) take any &Controller, so a controller written outside this library composes the same way the ones here do.

    Estimator

    pub(open) trait Estimator {
    fn predict(Self, u :
    Vec
    , dt : Double) -> Unit
    fn correct(Self, z :
    Vec
    ) -> Unit raise
    Refused

    fn state(Self) ->
    Vec

    fn covariance(Self) ->
    Mat

    }

    A state estimator: propagate on the input, then fold in a measurement.

    The two steps are separate because a sensor does not always deliver on every control period; a caller that has no measurement that cycle calls predict alone.

    Kinematics

    A mechanism: joint values to a task-space pose, and back.

    Both spaces are plain Vecs so that one contract covers a two-wheel base and a six-axis arm; a model that has typed joint values offers them alongside.

    Model

    A plant: how the state moves under an input, and what a sensor sees.

    step and observe are the model. step_jacobian and observe_jacobian have default implementations built on them by central differences, so a plant that gives only the two functions works with the extended Kalman filter, the unscented Kalman filter and the particle filter as it is.

    Planner

    A planner: a start, a goal and a budget, out comes a path of states from the start to the goal.

    Space

    A state space a planner can search: where to draw random states, how far apart two are, and how to walk between them.

    A vehicle model implements this with its (x, y, heading) states and its own steering primitives, which is what lets a sampling planner plan a Dubins path without knowing what Dubins is.

    Trajectory

    pub(open) trait Trajectory {
    fn duration(Self) -> Double
    fn sample(Self, t : Double) -> Sample
    }

    A single-axis motion profile: a duration, and the state at any time in it.

    Sampling outside [0, duration] is defined rather than refused: before the start the motion is held at its first sample and after the end at its last, so a caller can run a clock past the end without a branch.

    Validity

    pub(open) trait Validity {
    fn valid(Self, x :
    Vec
    ) -> Bool
    fn motion(Self, space : &Space, a :
    Vec
    , b :
    Vec
    ) -> Bool = _
    }

    Which states and motions a motion planner may use.

    Collision checking lives here, so the planners stay free of geometry.

    Budget

    pub(all) struct Budget {
    iterations : Int
    seconds : Double?
    } derive(
    Debug
    )

    How long a planner may search.

    Budget::to_repr

    Discretize

    pub(all) enum Discretize {
    Zoh
    ForwardEuler
    Tustin
    } derive(
    Debug
    )

    Which rule turns a continuous state matrix into a discrete one.

    Dynamics

    A nonlinear plant given as a derivative and an output map, integrated with a named rule.

    The derivative is f(x, u, dt), taking the period as well because a plant may be defined for a fixed control period; the rule treats it as the vector field at x.
    impl Model for Dynamics

    Dynamics::new

    A nonlinear plant from its derivative and its output map, integrated with RK4 unless told otherwise.

    Dynamics::observe_jacobian

    Dynamics::to_repr

    Integrator

    pub(all) enum Integrator {
    Euler
    Midpoint
    Rk4
    } derive(
    Debug
    )

    How Dynamics integrates its derivative.

    Sample

    pub(all) struct Sample {
    position : Double
    velocity : Double
    acceleration : Double
    jerk : Double
    } derive(
    Debug
    )

    One instant of a single-axis motion, with every derivative a drive may need.

    The jerk is what separates a smooth profile from a trapezoid: a drive that bounds it never excites the resonance the way a step in acceleration does.

    Sample::new

    fn Sample::new(position~ : Double, velocity? : Double, acceleration? : Double, jerk? : Double) -> Sample

    A sample from its four derivatives.

    Sample::still

    fn Sample::still(position : Double) -> Sample

    A sample that is not moving.

    Sample::to_repr

    StateSpace

    A linear time-invariant plant, x' = a x + b u, y = c x + d u.

    With dt set the record is already discrete and step applies a x + b u once; without it the record is continuous and step integrates over the period it is given. A discrete record is what the Kalman filter and the model-predictive controller want; a continuous one is what a plant model in physical units looks like.
    impl Model for StateSpace

    StateSpace::discretize

    fn StateSpace::discretize(self : StateSpace, dt~ : Double, discretize? : Discretize) -> StateSpace raise
    Refused

    The same plant discretised at dt seconds.

    A record that is already discrete is returned unchanged when the periods agree and refused when they do not: resampling would need the original continuous plant, which the record no longer carries.

    StateSpace::is_discrete

    fn StateSpace::is_discrete(self : StateSpace) -> Bool

    Whether the record is already discrete.

    StateSpace::observe_jacobian

    budget

    let budget : Budget

    The default budget: iterations samples and no wall-clock limit, so a run is reproducible.

    jacobian_step

    let jacobian_step : Double

    The step the numerical Jacobians use, in the units of the state.

    A central difference with this step reaches about seven correct digits for a state of order one, which is the accuracy a filter or a planner needs and far cheaper than a symbolic derivative. An implementation that knows its Jacobian should override the default method instead.

    motion_samples

    let motion_samples : Int

    How many points the default Validity::motion checks between two states.