use super::*;
pub mod constants;
pub use constants::*;
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct Time(pub i64);
impl Time {
pub const fn new(value: i64) -> Self {
Self(value)
}
}
impl From<i64> for Time {
fn from(was: i64) -> Self {
Self(was)
}
}
impl From<Time> for i64 {
fn from(was: Time) -> i64 {
was.0
}
}
impl TryFrom<Quantity> for Time {
type Error = ();
fn try_from(was: Quantity) -> Result<Self, ()> {
if was.unit.eq_assume_true(&SECOND) {
Ok(Self((was.value * 1_000_000_000.0) as i64))
} else {
Err(())
}
}
}
impl From<Time> for Quantity {
fn from(was: Time) -> Quantity {
Quantity::new(was.0 as f32 / 1_000_000_000.0, SECOND)
}
}
impl Add for Time {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0)
}
}
impl AddAssign for Time {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Sub for Time {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self(self.0 - rhs.0)
}
}
impl SubAssign for Time {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
}
}
impl Mul for Time {
type Output = Quantity;
fn mul(self, rhs: Self) -> Quantity {
Quantity::from(self) * Quantity::from(rhs)
}
}
impl Div for Time {
type Output = Quantity;
fn div(self, rhs: Self) -> Quantity {
Quantity::from(self) / Quantity::from(rhs)
}
}
impl Neg for Time {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl Mul<DimensionlessInteger> for Time {
type Output = Self;
fn mul(self, rhs: DimensionlessInteger) -> Self {
Self(self.0 * rhs.0)
}
}
impl MulAssign<DimensionlessInteger> for Time {
fn mul_assign(&mut self, rhs: DimensionlessInteger) {
self.0 *= rhs.0;
}
}
impl Div<DimensionlessInteger> for Time {
type Output = Self;
fn div(self, rhs: DimensionlessInteger) -> Self {
Self(self.0 / rhs.0)
}
}
impl DivAssign<DimensionlessInteger> for Time {
fn div_assign(&mut self, rhs: DimensionlessInteger) {
self.0 /= rhs.0;
}
}
impl Add<Quantity> for Time {
type Output = Quantity;
fn add(self, rhs: Quantity) -> Quantity {
Quantity::from(self) + rhs
}
}
impl Sub<Quantity> for Time {
type Output = Quantity;
fn sub(self, rhs: Quantity) -> Quantity {
Quantity::from(self) - rhs
}
}
impl Mul<Quantity> for Time {
type Output = Quantity;
fn mul(self, rhs: Quantity) -> Quantity {
rhs * self
}
}
impl Div<Quantity> for Time {
type Output = Quantity;
fn div(self, rhs: Quantity) -> Quantity {
Quantity::from(self) / rhs
}
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, PartialOrd, Ord)]
#[repr(transparent)]
pub struct DimensionlessInteger(pub i64);
impl DimensionlessInteger {
pub const fn new(value: i64) -> Self {
Self(value)
}
}
impl From<i64> for DimensionlessInteger {
fn from(was: i64) -> Self {
Self(was)
}
}
impl From<DimensionlessInteger> for i64 {
fn from(was: DimensionlessInteger) -> Self {
was.0
}
}
impl TryFrom<Quantity> for DimensionlessInteger {
type Error = ();
fn try_from(was: Quantity) -> Result<Self, ()> {
if was.unit.eq_assume_true(&DIMENSIONLESS) {
Ok(Self(was.value as i64))
} else {
Err(())
}
}
}
impl From<DimensionlessInteger> for Quantity {
fn from(was: DimensionlessInteger) -> Self {
Quantity::new(was.0 as f32, DIMENSIONLESS)
}
}
impl Add for DimensionlessInteger {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self(self.0 + rhs.0)
}
}
impl AddAssign for DimensionlessInteger {
fn add_assign(&mut self, rhs: Self) {
self.0 += rhs.0;
}
}
impl Sub for DimensionlessInteger {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self(self.0 - rhs.0)
}
}
impl SubAssign for DimensionlessInteger {
fn sub_assign(&mut self, rhs: Self) {
self.0 -= rhs.0;
}
}
impl Mul for DimensionlessInteger {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
Self(self.0 * rhs.0)
}
}
impl MulAssign for DimensionlessInteger {
fn mul_assign(&mut self, rhs: Self) {
self.0 *= rhs.0;
}
}
impl Div for DimensionlessInteger {
type Output = Self;
fn div(self, rhs: Self) -> Self {
Self(self.0 / rhs.0)
}
}
impl DivAssign for DimensionlessInteger {
fn div_assign(&mut self, rhs: Self) {
self.0 /= rhs.0;
}
}
impl Neg for DimensionlessInteger {
type Output = Self;
fn neg(self) -> Self {
Self(-self.0)
}
}
impl Mul<Time> for DimensionlessInteger {
type Output = Time;
fn mul(self, rhs: Time) -> Time {
Time(self.0 * rhs.0)
}
}
impl Div<Time> for DimensionlessInteger {
type Output = Quantity;
fn div(self, rhs: Time) -> Quantity {
Quantity::from(self) / Quantity::from(rhs)
}
}
impl Add<Quantity> for DimensionlessInteger {
type Output = Quantity;
fn add(self, rhs: Quantity) -> Quantity {
Quantity::from(self) + rhs
}
}
impl Sub<Quantity> for DimensionlessInteger {
type Output = Quantity;
fn sub(self, rhs: Quantity) -> Quantity {
Quantity::from(self) - rhs
}
}
impl Mul<Quantity> for DimensionlessInteger {
type Output = Quantity;
fn mul(self, rhs: Quantity) -> Quantity {
rhs * self
}
}
impl Div<Quantity> for DimensionlessInteger {
type Output = Quantity;
fn div(self, rhs: Quantity) -> Quantity {
Quantity::from(self) / Quantity::from(rhs)
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(
any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
),
derive(PartialEq, Eq)
)]
pub struct Unit {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
millimeter_exp: i8,
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
second_exp: i8,
}
impl Unit {
#[allow(unused)]
pub const fn new(millimeter_exp: i8, second_exp: i8) -> Self {
Self {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
millimeter_exp: millimeter_exp,
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
second_exp: second_exp,
}
}
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
#[allow(unused)]
pub const fn const_eq(&self, rhs: &Self) -> bool {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
return self.millimeter_exp == rhs.millimeter_exp && self.second_exp == rhs.second_exp;
#[cfg(not(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
)))]
true
}
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
pub const fn const_assert_eq(&self, rhs: &Self) {
assert!(self.const_eq(rhs));
}
#[allow(unused)]
pub const fn eq_assume_true(&self, rhs: &Self) -> bool {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
return self.const_eq(rhs);
#[cfg(not(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
)))]
true
}
#[allow(unused)]
pub const fn eq_assume_false(&self, rhs: &Self) -> bool {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
return self.const_eq(rhs);
#[cfg(not(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
)))]
false
}
pub const fn assert_eq_assume_ok(&self, rhs: &Self) {
assert!(self.eq_assume_true(rhs))
}
pub const fn assert_eq_assume_not_ok(&self, rhs: &Self) {
assert!(self.eq_assume_false(rhs))
}
}
impl From<PositionDerivative> for Unit {
#[allow(unused)]
fn from(was: PositionDerivative) -> Self {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
return Self {
millimeter_exp: 1,
second_exp: match was {
PositionDerivative::Position => 0,
PositionDerivative::Velocity => -1,
PositionDerivative::Acceleration => -2,
},
};
#[cfg(not(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
)))]
Self {}
}
}
impl TryFrom<MotionProfilePiece> for Unit {
type Error = ();
fn try_from(was: MotionProfilePiece) -> Result<Self, ()> {
let pos_der: PositionDerivative = was.try_into()?;
let unit: Self = pos_der.into();
Ok(unit)
}
}
impl Add for Unit {
type Output = Self;
fn add(self, rhs: Self) -> Self {
self.assert_eq_assume_ok(&rhs);
self
}
}
impl AddAssign for Unit {
fn add_assign(&mut self, rhs: Self) {
self.assert_eq_assume_ok(&rhs);
}
}
impl Sub for Unit {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
self.assert_eq_assume_ok(&rhs);
self
}
}
impl SubAssign for Unit {
fn sub_assign(&mut self, rhs: Self) {
self.assert_eq_assume_ok(&rhs);
}
}
impl Mul for Unit {
type Output = Self;
#[allow(unused)]
fn mul(self, rhs: Self) -> Self {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
return Self {
millimeter_exp: self.millimeter_exp + rhs.millimeter_exp,
second_exp: self.second_exp + rhs.second_exp,
};
#[cfg(not(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
)))]
Self {}
}
}
impl MulAssign for Unit {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl Div for Unit {
type Output = Self;
#[allow(unused)]
fn div(self, rhs: Self) -> Self {
#[cfg(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
))]
return Self {
millimeter_exp: self.millimeter_exp - rhs.millimeter_exp,
second_exp: self.second_exp - rhs.second_exp,
};
#[cfg(not(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
)))]
Self {}
}
}
impl DivAssign for Unit {
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
}
impl Neg for Unit {
type Output = Self;
fn neg(self) -> Self {
self
}
}
#[derive(Clone, Copy, Debug)]
#[cfg_attr(
any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
),
derive(PartialEq)
)]
pub struct Quantity {
pub value: f32,
pub unit: Unit,
}
impl Quantity {
pub const fn new(value: f32, unit: Unit) -> Self {
Self {
value: value,
unit: unit,
}
}
pub const fn dimensionless(value: f32) -> Self {
Self::new(value, DIMENSIONLESS)
}
#[inline]
pub fn abs(self) -> Self {
Self::new(
#[cfg(feature = "std")]
self.value.abs(),
#[cfg(not(feature = "std"))]
if self.value >= 0.0 {
self.value
} else {
-self.value
},
self.unit,
)
}
}
impl From<Command> for Quantity {
fn from(was: Command) -> Self {
match was {
Command::Position(pos) => Self::new(pos, MILLIMETER),
Command::Velocity(vel) => Self::new(vel, MILLIMETER_PER_SECOND),
Command::Acceleration(acc) => Self::new(acc, MILLIMETER_PER_SECOND_SQUARED),
}
}
}
impl From<Quantity> for f32 {
fn from(was: Quantity) -> f32 {
was.value
}
}
impl Add for Quantity {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self {
value: self.value + rhs.value,
unit: self.unit + rhs.unit,
}
}
}
impl AddAssign for Quantity {
fn add_assign(&mut self, rhs: Self) {
*self = *self + rhs;
}
}
impl Sub for Quantity {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self {
value: self.value - rhs.value,
unit: self.unit - rhs.unit,
}
}
}
impl SubAssign for Quantity {
fn sub_assign(&mut self, rhs: Self) {
*self = *self - rhs;
}
}
impl Mul for Quantity {
type Output = Self;
fn mul(self, rhs: Self) -> Self {
Self {
value: self.value * rhs.value,
unit: self.unit * rhs.unit,
}
}
}
impl MulAssign for Quantity {
fn mul_assign(&mut self, rhs: Self) {
*self = *self * rhs;
}
}
impl Div for Quantity {
type Output = Self;
fn div(self, rhs: Self) -> Self {
Self {
value: self.value / rhs.value,
unit: self.unit / rhs.unit,
}
}
}
impl DivAssign for Quantity {
fn div_assign(&mut self, rhs: Self) {
*self = *self / rhs;
}
}
impl Neg for Quantity {
type Output = Self;
fn neg(self) -> Self {
Self {
value: -self.value,
unit: self.unit,
}
}
}
impl Add<Time> for Quantity {
type Output = Self;
fn add(self, rhs: Time) -> Self {
self + Self::from(rhs)
}
}
impl AddAssign<Time> for Quantity {
fn add_assign(&mut self, rhs: Time) {
*self = *self + rhs;
}
}
impl Sub<Time> for Quantity {
type Output = Self;
fn sub(self, rhs: Time) -> Self {
self - Self::from(rhs)
}
}
impl SubAssign<Time> for Quantity {
fn sub_assign(&mut self, rhs: Time) {
*self = *self - rhs;
}
}
impl Add<DimensionlessInteger> for Quantity {
type Output = Self;
fn add(self, rhs: DimensionlessInteger) -> Self {
self + Self::from(rhs)
}
}
impl AddAssign<DimensionlessInteger> for Quantity {
fn add_assign(&mut self, rhs: DimensionlessInteger) {
*self = *self + rhs;
}
}
impl Sub<DimensionlessInteger> for Quantity {
type Output = Self;
fn sub(self, rhs: DimensionlessInteger) -> Self {
self - Self::from(rhs)
}
}
impl SubAssign<DimensionlessInteger> for Quantity {
fn sub_assign(&mut self, rhs: DimensionlessInteger) {
*self = *self - rhs;
}
}
impl Mul<Time> for Quantity {
type Output = Self;
fn mul(self, rhs: Time) -> Self {
self * Quantity::from(rhs)
}
}
impl MulAssign<Time> for Quantity {
fn mul_assign(&mut self, rhs: Time) {
*self = *self * rhs;
}
}
impl Div<Time> for Quantity {
type Output = Self;
fn div(self, rhs: Time) -> Self {
self / Quantity::from(rhs)
}
}
impl DivAssign<Time> for Quantity {
fn div_assign(&mut self, rhs: Time) {
*self = *self / rhs;
}
}
impl Mul<DimensionlessInteger> for Quantity {
type Output = Self;
fn mul(self, rhs: DimensionlessInteger) -> Self {
self * Quantity::from(rhs)
}
}
impl MulAssign<DimensionlessInteger> for Quantity {
fn mul_assign(&mut self, rhs: DimensionlessInteger) {
*self = *self * rhs
}
}
impl Div<DimensionlessInteger> for Quantity {
type Output = Self;
fn div(self, rhs: DimensionlessInteger) -> Self {
self / Quantity::from(rhs)
}
}
impl DivAssign<DimensionlessInteger> for Quantity {
fn div_assign(&mut self, rhs: DimensionlessInteger) {
*self = *self / rhs
}
}
#[cfg(not(any(
feature = "dim_check_release",
all(debug_assertions, feature = "dim_check_debug")
)))]
impl PartialEq for Quantity {
fn eq(&self, rhs: &Self) -> bool {
if self.unit.eq_assume_true(&rhs.unit) {
self.value == rhs.value
} else {
false
}
}
}
impl PartialOrd for Quantity {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.unit.assert_eq_assume_ok(&other.unit);
self.value.partial_cmp(&other.value)
}
}