use std::{cell::RefCell, rc::Rc};
use vexide::{
math::Angle,
prelude::{Controller, Motor},
smart::motor::BrakeMode,
};
use super::DrivetrainError;
use crate::{
motion::localization::tracker::devices::{Trackable, TrackingSensorError},
peripherals::drivetrain::{Differential, Drivable},
utils::error::Report,
};
#[derive(Clone)]
#[allow(dead_code)]
pub struct StandardDifferential {
pub left: Rc<RefCell<dyn AsMut<[Motor]>>>,
pub right: Rc<RefCell<dyn AsMut<[Motor]>>>,
}
impl StandardDifferential {
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 Drivable for StandardDifferential {
fn tank(&mut self, controller: &Controller) -> Result<(), DrivetrainError> {
let state = controller.state()?;
let left_power = state.left_stick.y();
let right_power = state.right_stick.y();
let left_voltage = left_power * 12.0;
let right_voltage = right_power * 12.0;
let mut left_motors = self.left.try_borrow_mut()?;
let mut right_motors = self.right.try_borrow_mut()?;
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage)?;
}
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage)?;
}
Ok(())
}
fn arcade(&mut self, controller: &Controller) -> Result<(), DrivetrainError> {
let state = controller.state()?;
let fwd = state.left_stick.y();
let turn = state.right_stick.x();
let left_voltage = (fwd + turn) * 12.0;
let right_voltage = (fwd - turn) * 12.0;
let mut left_motors = self.left.try_borrow_mut()?;
let mut right_motors = self.right.try_borrow_mut()?;
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage)?;
}
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage)?;
}
Ok(())
}
fn reverse_tank(&mut self, controller: &Controller) -> Result<(), DrivetrainError> {
let state = controller.state()?;
let left_voltage = (-state.right_stick.y()) * 12.0;
let right_voltage = (-state.left_stick.y()) * 12.0;
let mut left_motors = self.left.try_borrow_mut()?;
let mut right_motors = self.right.try_borrow_mut()?;
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage)?;
}
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage)?;
}
Ok(())
}
fn reverse_arcade(&mut self, controller: &Controller) -> Result<(), DrivetrainError> {
let state = controller.state()?;
let fwd = -state.left_stick.y();
let turn = -state.right_stick.x();
let left_voltage = (fwd + turn) * 12.0;
let right_voltage = (fwd - turn) * 12.0;
let mut left_motors = self.left.try_borrow_mut()?;
let mut right_motors = self.right.try_borrow_mut()?;
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage)?;
}
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage)?;
}
Ok(())
}
}
impl Differential for StandardDifferential {
fn set_brakemode(&self, brakemode: BrakeMode) -> Result<(), DrivetrainError> {
let mut left = self.left.try_borrow_mut()?;
let mut right = self.right.try_borrow_mut()?;
for motor in left.as_mut() {
let _ = motor.brake(brakemode)?;
}
for motor in right.as_mut() {
let _ = motor.brake(brakemode)?;
}
Ok(())
}
fn position(&self) -> Report<Angle, Vec<DrivetrainError>> {
let mut errors = Vec::new();
let left = self.left.try_borrow_mut();
let right = self.right.try_borrow_mut();
let mut angle: Angle = Angle::from_degrees(0.0);
let mut denom: f64 = 0.0;
match left {
Ok(mut motors) => {
for motor in motors.as_mut() {
angle += motor.position().unwrap_or_else(|e| {
let err = DrivetrainError::PortError { source: e };
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError { source: e };
errors.push(err);
}
}
match right {
Ok(mut motors) => {
for motor in motors.as_mut() {
angle += motor.position().unwrap_or_else(|e| {
let err = DrivetrainError::PortError { source: e };
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError { source: e };
errors.push(err);
}
}
match errors.is_empty() {
true => Report::new(angle / denom),
false => Report::from_parts(angle / denom, errors),
}
}
fn left_position(&self) -> Report<Angle, Vec<DrivetrainError>> {
let mut errors = Vec::new();
let left = self.left.try_borrow_mut();
let mut angle: Angle = Angle::from_degrees(0.0);
let mut denom: f64 = 0.0;
match left {
Ok(mut motors) => {
for motor in motors.as_mut() {
angle += motor.position().unwrap_or_else(|e| {
let err = DrivetrainError::PortError { source: e };
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError { source: e };
errors.push(err);
}
}
match errors.is_empty() {
true => Report::new(angle / denom),
false => Report::from_parts(angle / denom, errors),
}
}
fn right_position(&self) -> Report<Angle, Vec<DrivetrainError>> {
let mut errors = Vec::new();
let right = self.right.try_borrow_mut();
let mut angle: Angle = Angle::from_degrees(0.0);
let mut denom: f64 = 0.0;
match right {
Ok(mut motors) => {
for motor in motors.as_mut() {
angle += motor.position().unwrap_or_else(|e| {
let err = DrivetrainError::PortError { source: e };
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError { source: e };
errors.push(err);
}
}
match errors.is_empty() {
true => Report::new(angle / denom),
false => Report::from_parts(angle / denom, errors),
}
}
fn reset_position(&self) -> Result<(), DrivetrainError> {
let mut left = self.left.try_borrow_mut()?;
let mut right = self.right.try_borrow_mut()?;
for motor in left.as_mut() {
motor.reset_position()?;
}
for motor in right.as_mut() {
motor.reset_position()?;
}
Ok(())
}
fn set_position(&self, position: Angle) -> Result<(), DrivetrainError> {
let mut left = self.left.try_borrow_mut()?;
let mut right = self.right.try_borrow_mut()?;
for motor in left.as_mut() {
motor.set_position(position)?
}
for motor in right.as_mut() {
motor.set_position(position)?
}
Ok(())
}
fn set_voltage(&self, voltage: f64) -> Result<(), DrivetrainError> {
let mut left_motors = self.left.try_borrow_mut()?;
let mut right_motors = self.right.try_borrow_mut()?;
for motor in left_motors.as_mut() {
motor.set_voltage(voltage)?;
}
for motor in right_motors.as_mut() {
motor.set_voltage(voltage)?;
}
Ok(())
}
fn set_left_voltage(&self, voltage: f64) -> Result<(), DrivetrainError> {
let mut left = self.left.try_borrow_mut()?;
for motor in left.as_mut() {
motor.set_voltage(voltage)?;
}
Ok(())
}
fn set_right_voltage(&self, voltage: f64) -> Result<(), DrivetrainError> {
let mut right = self.right.try_borrow_mut()?;
for motor in right.as_mut() {
motor.set_voltage(voltage)?;
}
Ok(())
}
}
impl Trackable for StandardDifferential {
fn track_position(
&mut self,
) -> Result<Angle, crate::motion::localization::tracker::devices::TrackingSensorError> {
let res = Self::position(&self);
if res.has_errors() {
let (_, e) = res.into_parts();
let source_err = e.unwrap_or_default().remove(0);
let err = TrackingSensorError::DrivetrainError { source: source_err };
Err(err)
} else {
Ok(res.value())
}
}
fn reset_track_position(
&mut self,
) -> Result<(), crate::motion::localization::tracker::devices::TrackingSensorError> {
match Self::reset_position(&self) {
Ok(_) => Ok(()),
Err(e) => Err(TrackingSensorError::DrivetrainError { source: e }),
}
}
fn set_track_position(
&mut self,
position: Angle,
) -> Result<(), crate::motion::localization::tracker::devices::TrackingSensorError> {
match Self::set_position(&self, position) {
Ok(_) => Ok(()),
Err(e) => Err(TrackingSensorError::DrivetrainError { source: e }),
}
}
}