use core::cell::RefCell;
use alloc::rc::Rc;
use vexide::{devices::smart::motor::MotorError, prelude::Motor};
pub struct Differential {
pub left: Rc<RefCell<dyn AsMut<[Motor]>>>,
pub right: Rc<RefCell<dyn AsMut<[Motor]>>>,
}
impl Differential {
pub fn new<L: AsMut<[Motor]> + 'static, R: AsMut<[Motor]> + 'static>(
left: L,
right: R,
) -> Self {
Self {
left: Rc::new(RefCell::new(left)),
right: Rc::new(RefCell::new(right)),
}
}
pub fn from_shared<L: AsMut<[Motor]> + 'static, R: AsMut<[Motor]> + 'static>(
left: Rc<RefCell<L>>,
right: Rc<RefCell<R>>,
) -> Self {
Self { left, right }
}
pub fn set_voltages(&mut self, voltages: impl Into<Voltages>) -> Result<(), MotorError> {
let voltages = voltages.into();
let mut rtn = Ok(());
for motor in self.left.borrow_mut().as_mut() {
let result = motor.set_voltage(voltages.left());
if result.is_err() {
rtn = result;
}
}
for motor in self.right.borrow_mut().as_mut() {
let result = motor.set_voltage(voltages.right());
if result.is_err() {
rtn = result;
}
}
rtn
}
}
#[derive(Default, Debug, Clone, Copy, PartialEq)]
pub struct Voltages(pub f64, pub f64);
impl Voltages {
#[must_use]
pub const fn from_arcade(linear: f64, angular: f64) -> Self {
Self(linear + angular, linear - angular)
}
#[must_use]
pub fn normalized(&self, max: f64) -> Self {
let larger_magnitude = self.0.abs().max(self.1.abs()) / max;
let mut voltages = *self;
if larger_magnitude > 1.0 {
voltages.0 /= larger_magnitude;
voltages.1 /= larger_magnitude;
}
voltages
}
#[must_use]
pub const fn left(&self) -> f64 {
self.0
}
#[must_use]
pub const fn right(&self) -> f64 {
self.1
}
}
impl From<(f64, f64)> for Voltages {
fn from(value: (f64, f64)) -> Self {
Self(value.0, value.1)
}
}