use std::{
cell::{BorrowMutError, RefCell},
rc::Rc,
};
use log::warn;
use snafu::Snafu;
use vexide::{
controller::{ControllerError, ControllerState},
math::Angle,
prelude::{Controller, Motor},
smart::{PortError, motor::BrakeMode},
};
use crate::utils::error::Report;
#[derive(Clone)]
#[allow(dead_code)]
pub struct Differential {
pub left: Rc<RefCell<dyn AsMut<[Motor]>>>,
pub right: Rc<RefCell<dyn AsMut<[Motor]>>>,
}
#[derive(Debug, Snafu)]
pub enum DrivetrainError {
#[snafu(display("Failed to access port: {port_error}"))]
PortError {
port_error: PortError,
},
#[snafu(display("Failed to access controller: {controller_error}"))]
ControllerError {
controller_error: ControllerError,
},
#[snafu(display("Failed to borrow RefCell mutably: {borrow_mut_error}"))]
BorrowMutError {
borrow_mut_error: BorrowMutError,
},
Unknown {
string: String,
},
}
#[allow(dead_code)]
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 tank(&self, controller: &Controller) -> Vec<DrivetrainError> {
let mut errors: Vec<DrivetrainError> = Vec::new();
let state = controller.state().unwrap_or_else(|e| {
let err = DrivetrainError::ControllerError {
controller_error: e,
};
warn!("{}", err);
errors.push(err);
ControllerState::default()
});
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;
match self.left.try_borrow_mut() {
Ok(mut left_motors) => {
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match self.right.try_borrow_mut() {
Ok(mut right_motors) => {
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub fn arcade(&self, controller: &Controller) -> Vec<DrivetrainError> {
let mut errors: Vec<DrivetrainError> = Vec::new();
let state = controller.state().unwrap_or_else(|e| {
let err = DrivetrainError::ControllerError {
controller_error: e,
};
warn!("{}", err);
errors.push(err);
ControllerState::default()
});
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;
match self.left.try_borrow_mut() {
Ok(mut left_motors) => {
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match self.right.try_borrow_mut() {
Ok(mut right_motors) => {
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub fn reverse_tank(&self, controller: &Controller) -> Vec<DrivetrainError> {
let mut errors: Vec<DrivetrainError> = Vec::new();
let state = controller.state().unwrap_or_else(|e| {
let err = DrivetrainError::ControllerError {
controller_error: e,
};
warn!("{}", err);
errors.push(err);
ControllerState::default()
});
let left_voltage = (-state.right_stick.y()) * 12.0;
let right_voltage = (-state.left_stick.y()) * 12.0;
match self.left.try_borrow_mut() {
Ok(mut left_motors) => {
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match self.right.try_borrow_mut() {
Ok(mut right_motors) => {
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub fn reverse_arcade(&self, controller: &Controller) -> Vec<DrivetrainError> {
let mut errors: Vec<DrivetrainError> = Vec::new();
let state = controller.state().unwrap_or_else(|e| {
let err = DrivetrainError::ControllerError {
controller_error: e,
};
warn!("{}", err);
errors.push(err);
ControllerState::default()
});
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;
match self.left.try_borrow_mut() {
Ok(mut left_motors) => {
for motor in left_motors.as_mut() {
motor.set_voltage(left_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match self.right.try_borrow_mut() {
Ok(mut right_motors) => {
for motor in right_motors.as_mut() {
motor.set_voltage(right_voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub fn set_brakemode(&self, brakemode: BrakeMode) -> Vec<DrivetrainError> {
let mut errors = Vec::new();
let left = self.left.try_borrow_mut();
let right = self.right.try_borrow_mut();
match left {
Ok(mut motors) => {
for motor in motors.as_mut() {
let _ = motor.brake(brakemode).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match right {
Ok(mut motors) => {
for motor in motors.as_mut() {
let _ = motor.brake(brakemode).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub 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 { port_error: e };
warn!("{}", err);
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
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 { port_error: e };
warn!("{}", err);
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match errors.is_empty() {
true => Report::new(angle / denom),
false => Report::from_parts(angle / denom, errors),
}
}
pub 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 { port_error: e };
warn!("{}", err);
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match errors.is_empty() {
true => Report::new(angle / denom),
false => Report::from_parts(angle / denom, errors),
}
}
pub 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 { port_error: e };
warn!("{}", err);
errors.push(err);
denom -= 1.0;
Angle::ZERO
});
denom += 1.0;
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match errors.is_empty() {
true => Report::new(angle / denom),
false => Report::from_parts(angle / denom, errors),
}
}
pub fn reset_position(&self) -> Result<(), PortError> {
let mut errors = Vec::new();
let left = self.left.try_borrow_mut();
let right = self.right.try_borrow_mut();
match left {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.reset_position().unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
})
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match right {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.reset_position().unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
})
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
Ok(())
}
pub fn set_position(&self, position: Angle) -> Result<(), PortError> {
let mut errors = Vec::new();
let left = self.left.try_borrow_mut();
let right = self.right.try_borrow_mut();
match left {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.set_position(position).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
})
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match right {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.set_position(position).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
})
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
Ok(())
}
pub fn set_voltage(&self, voltage: f64) -> Vec<DrivetrainError> {
let mut errors = Vec::new();
let left = self.left.try_borrow_mut();
let right = self.right.try_borrow_mut();
match left {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.set_voltage(voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
match right {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.set_voltage(voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub fn set_left_voltage(&self, voltage: f64) -> Vec<DrivetrainError> {
let mut errors = Vec::new();
let left = self.left.try_borrow_mut();
match left {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.set_voltage(voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub fn set_right_voltage(&self, voltage: f64) -> Vec<DrivetrainError> {
let mut errors = Vec::new();
let right = self.right.try_borrow_mut();
match right {
Ok(mut motors) => {
for motor in motors.as_mut() {
motor.set_voltage(voltage).unwrap_or_else(|e| {
let err = DrivetrainError::PortError { port_error: e };
warn!("{}", err);
errors.push(err);
});
}
}
Err(e) => {
let err = DrivetrainError::BorrowMutError {
borrow_mut_error: e,
};
warn!("{}", err);
errors.push(err);
}
}
errors
}
pub fn from_shared<L: AsMut<[Motor]> + 'static, R: AsMut<[Motor]> + 'static>(
left: Rc<RefCell<L>>,
right: Rc<RefCell<R>>,
) -> Self {
Self { left, right }
}
}