extern crate alloc;
use alloc::rc::Rc;
use core::cell::RefCell;
use vexide::smart::{PortError, motor::Motor};
use super::{DrivetrainModel, Tank};
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 }
}
}
impl DrivetrainModel for Differential {
type Error = PortError;
}
impl Tank for Differential {
fn drive_tank(&mut self, left: f64, right: f64) -> Result<(), Self::Error> {
let mut rtn = Ok(());
for motor in self.left.borrow_mut().as_mut() {
let result = motor.set_voltage(left * motor.max_voltage());
if result.is_err() {
rtn = result;
}
}
for motor in self.right.borrow_mut().as_mut() {
let result = motor.set_voltage(right * motor.max_voltage());
if result.is_err() {
rtn = result;
}
}
rtn
}
}