use crate::*;
pub trait GenericState:
Copy
+ Debug
+ Default
+ PartialEq
+ Neg<Output = Self>
+ Add<Output = Self>
+ Sub<Output = Self>
+ Mul<Dimensionless<f32>, Output = Self>
+ Div<Dimensionless<f32>, Output = Self>
+ AddAssign
+ SubAssign
+ MulAssign<Dimensionless<f32>>
+ DivAssign<Dimensionless<f32>>
{
type Position: Copy
+ Debug
+ Default
+ fmt::Display
+ PartialOrd
+ Add<Output = Self::Position>
+ Sub<Output = Self::Position>
+ Mul<Dimensionless<f32>, Output = Self::Position>
+ Div<Dimensionless<f32>, Output = Self::Position>
+ Div<Time, Output = Self::Velocity>
+ stulta::AbsoluteValue;
type Velocity: Copy
+ Debug
+ Default
+ fmt::Display
+ PartialOrd
+ Add<Output = Self::Velocity>
+ Sub<Output = Self::Velocity>
+ Mul<Dimensionless<f32>, Output = Self::Velocity>
+ Div<Dimensionless<f32>, Output = Self::Velocity>
+ Mul<Time, Output = Self::Position>
+ Div<Time, Output = Self::Acceleration>
+ stulta::AbsoluteValue;
type Acceleration: Copy
+ Debug
+ Default
+ fmt::Display
+ PartialOrd
+ Add<Output = Self::Acceleration>
+ Sub<Output = Self::Acceleration>
+ Mul<Dimensionless<f32>, Output = Self::Acceleration>
+ Div<Dimensionless<f32>, Output = Self::Acceleration>
+ Mul<Time, Output = Self::Velocity>
+ stulta::AbsoluteValue;
fn generic_new(
position: Self::Position,
velocity: Self::Velocity,
acceleration: Self::Acceleration,
) -> Self;
fn generic_update(&mut self, delta_time: Time);
fn generic_set_constant_position(&mut self, position: Self::Position);
fn generic_set_constant_velocity(&mut self, velocity: Self::Velocity);
fn generic_set_constant_acceleration(&mut self, acceleration: Self::Acceleration);
fn generic_get_value(&self, position_derivative: PositionDerivative) -> f32;
fn generic_position(&self) -> Self::Position;
fn generic_velocity(&self) -> Self::Velocity;
fn generic_acceleration(&self) -> Self::Acceleration;
fn generic_position_mut(&mut self) -> &mut Self::Position;
fn generic_velocity_mut(&mut self) -> &mut Self::Velocity;
fn generic_acceleration_mut(&mut self) -> &mut Self::Acceleration;
}
macro_rules! build_state_struct {
($name: ident, $pos: ty, $vel: ty, $acc: ty) => {
#[derive(Clone, Copy, Debug, Default, PartialEq)]
pub struct $name {
///Where you are.
pub position: $pos,
pub velocity: $vel,
pub acceleration: $acc,
}
impl $name {
pub const ZERO: Self = Self::new(<$pos>::new(0.0), <$vel>::new(0.0), <$acc>::new(0.0));
pub const fn new(position: $pos, velocity: $vel, acceleration: $acc) -> Self {
$name {
position,
velocity,
acceleration,
}
}
pub fn update(&mut self, delta_time: Time) {
let old_acceleration = self.acceleration;
let old_velocity = self.velocity;
let old_position = self.position;
let new_velocity = old_velocity + delta_time * old_acceleration;
let new_position = old_position
+ delta_time * (old_velocity + new_velocity) / Dimensionless::new(2.0);
self.position = new_position;
self.velocity = new_velocity;
}
#[inline]
pub const fn set_constant_acceleration(&mut self, acceleration: $acc) {
self.acceleration = acceleration;
}
#[inline]
pub const fn set_constant_velocity(&mut self, velocity: $vel) {
self.acceleration = <$acc>::new(0.0);
self.velocity = velocity;
}
#[inline]
pub const fn set_constant_position(&mut self, position: $pos) {
self.acceleration = <$acc>::new(0.0);
self.velocity = <$vel>::new(0.0);
self.position = position;
}
pub fn get_value(&self, position_derivative: PositionDerivative) -> f32 {
match position_derivative {
PositionDerivative::Position => self.position.into_inner(),
PositionDerivative::Velocity => self.velocity.into_inner(),
PositionDerivative::Acceleration => self.acceleration.into_inner(),
}
}
pub const fn add_const(self, rhs: Self) -> Self {
Self::new(
self.position.add_const(rhs.position),
self.velocity.add_const(rhs.velocity),
self.acceleration.add_const(rhs.acceleration),
)
}
pub const fn sub_const(self, rhs: Self) -> Self {
Self::new(
self.position.sub_const(rhs.position),
self.velocity.sub_const(rhs.velocity),
self.acceleration.sub_const(rhs.acceleration),
)
}
}
impl Neg for $name {
type Output = Self;
fn neg(self) -> Self {
$name::new(-self.position, -self.velocity, -self.acceleration)
}
}
impl Add for $name {
type Output = Self;
fn add(self, other: $name) -> Self {
$name::new(
self.position + other.position,
self.velocity + other.velocity,
self.acceleration + other.acceleration,
)
}
}
impl Sub for $name {
type Output = Self;
fn sub(self, other: $name) -> Self {
$name::new(
self.position - other.position,
self.velocity - other.velocity,
self.acceleration - other.acceleration,
)
}
}
impl Mul<Dimensionless<f32>> for $name {
type Output = Self;
fn mul(self, coef: Dimensionless<f32>) -> Self {
$name::new(
self.position * coef,
self.velocity * coef,
self.acceleration * coef,
)
}
}
impl Div<Dimensionless<f32>> for $name {
type Output = Self;
fn div(self, dvsr: Dimensionless<f32>) -> Self {
$name::new(
self.position / dvsr,
self.velocity / dvsr,
self.acceleration / dvsr,
)
}
}
impl AddAssign for $name {
fn add_assign(&mut self, other: $name) {
*self = *self + other;
}
}
impl SubAssign for $name {
fn sub_assign(&mut self, other: $name) {
*self = *self - other;
}
}
impl MulAssign<Dimensionless<f32>> for $name {
fn mul_assign(&mut self, coef: Dimensionless<f32>) {
*self = *self * coef;
}
}
impl DivAssign<Dimensionless<f32>> for $name {
fn div_assign(&mut self, dvsr: Dimensionless<f32>) {
*self = *self / dvsr;
}
}
impl GenericState for $name {
type Position = $pos;
type Velocity = $vel;
type Acceleration = $acc;
#[inline]
fn generic_new(position: $pos, velocity: $vel, acceleration: $acc) -> Self {
Self::new(position, velocity, acceleration)
}
#[inline]
fn generic_update(&mut self, delta_time: Time) {
self.update(delta_time);
}
#[inline]
fn generic_set_constant_position(&mut self, position: $pos) {
self.set_constant_position(position);
}
#[inline]
fn generic_set_constant_velocity(&mut self, velocity: $vel) {
self.set_constant_velocity(velocity);
}
#[inline]
fn generic_set_constant_acceleration(&mut self, acceleration: $acc) {
self.set_constant_acceleration(acceleration);
}
#[inline]
fn generic_get_value(&self, position_derivative: PositionDerivative) -> f32 {
self.get_value(position_derivative)
}
#[inline]
fn generic_position(&self) -> $pos {
self.position
}
#[inline]
fn generic_velocity(&self) -> $vel {
self.velocity
}
#[inline]
fn generic_acceleration(&self) -> $acc {
self.acceleration
}
#[inline]
fn generic_position_mut(&mut self) -> &mut $pos {
&mut self.position
}
#[inline]
fn generic_velocity_mut(&mut self) -> &mut $vel {
&mut self.velocity
}
#[inline]
fn generic_acceleration_mut(&mut self) -> &mut $acc {
&mut self.acceleration
}
}
};
}
build_state_struct!(
LinearState,
Millimeter<f32>,
MillimeterPerSecond<f32>,
MillimeterPerSecondSquared<f32>
);
build_state_struct!(
AngularState,
Dimensionless<f32>,
InverseSecond<f32>,
InverseSecondSquared<f32>
);
impl Mul<Millimeter<f32>> for AngularState {
type Output = LinearState;
fn mul(self, rhs: Millimeter<f32>) -> LinearState {
LinearState {
position: self.position * rhs,
velocity: self.velocity * rhs,
acceleration: self.acceleration * rhs,
}
}
}
impl Div<Millimeter<f32>> for LinearState {
type Output = AngularState;
fn div(self, rhs: Millimeter<f32>) -> AngularState {
AngularState {
position: self.position / rhs,
velocity: self.velocity / rhs,
acceleration: self.acceleration / rhs,
}
}
}