#![no_std]
#![no_main]
extern crate alloc;
use alloc::sync::Arc;
use core::time::Duration;
use num_traits::float::FloatCore;
use vex_rt::{prelude::*, state_machine};
struct DriveTrain {
left: Motor,
right: Motor,
}
impl DriveTrain {
fn drive(&mut self, x: i8, y: i8) -> Result<(), MotorError> {
let left = (y as i16 + x as i16).clamp(-127, 127) as i8;
let right = (y as i16 - x as i16).clamp(-127, 127) as i8;
self.left.move_i8(left)?;
self.right.move_i8(right)?;
Ok(())
}
fn drive_distance(&mut self, distance: f64, ctx: Context) -> Result<bool, MotorError> {
self.left.move_relative(distance, 100)?;
self.right.move_relative(distance, 100)?;
let mut pause = Loop::new(Duration::from_millis(10));
while (self.left.get_position()? - self.left.get_target_position()?).abs() >= 1.0
|| (self.right.get_position()? - self.right.get_target_position()?).abs() >= 1.0
{
select! {
_ = ctx.done() => return Ok(false),
_ = pause.select() => continue,
};
}
Ok(true)
}
}
state_machine! {
Drive(drive: DriveTrain) {
drive: DriveTrain = drive,
} = idle;
idle(_ctx) [drive] {
drive.drive(0, 0).unwrap_or_else(|err| {
eprintln!("idle drive error: {:?}", err);
});
}
manual(ctx, mut controller: BroadcastListener<ControllerData>) [drive] {
loop {
select! {
_ = ctx.done() => break,
data = controller.select() => drive.drive(data.left_x, data.left_y).unwrap_or_else(|err| {
eprintln!("manual drive error: {:?}", err);
}),
};
}
}
auto_drive(ctx, distance: f64) [drive] -> bool {
let result = drive.drive_distance(distance, ctx).unwrap_or_else(|err| {
eprintln!("auto drive error: {:?}", err);
false
});
return StateResult::Transition(result, DriveState::Idle);
}
}
struct Bot {
controller: Arc<BroadcastWrapper<Controller>>,
drive: Drive,
}
impl Robot for Bot {
fn new(p: Peripherals) -> Self {
Bot {
controller: Arc::new(p.master_controller.into_broadcast().unwrap()),
drive: Drive::new(DriveTrain {
left: p
.port01
.into_motor(Gearset::EighteenToOne, EncoderUnits::Degrees, false)
.unwrap(),
right: p
.port10
.into_motor(Gearset::EighteenToOne, EncoderUnits::Degrees, true)
.unwrap(),
}),
}
}
fn autonomous(&mut self, ctx: Context) {
let auto = self
.drive
.auto_drive_ext(ctx.fork_with_timeout(Duration::from_secs(1)), 100.0);
select! {
success = auto.done() => if *success {
println!("success");
} else {
println!("failed");
},
_ = ctx.done() => {},
}
}
fn opcontrol(&mut self, ctx: Context) {
let mut pause = Loop::new(Duration::from_millis(100));
self.drive.manual(self.controller.listen());
loop {
select! {
_ = ctx.done() => break,
_ = pause.select() => self.controller.update().unwrap(),
};
}
}
fn disabled(&mut self, _ctx: Context) {
self.drive.idle();
}
}
entry!(Bot);