Skip to content
This repository has been archived by the owner on Jun 19, 2024. It is now read-only.

refactor(breaking): Motor API #66

Merged
merged 38 commits into from
Mar 13, 2024
Merged
Changes from 1 commit
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
c706b04
refactor: Motor API
Tropix126 Jan 19, 2024
87bfbea
docs: update changelog
Tropix126 Jan 19, 2024
86654f0
Merge remote-tracking branch 'upstream/main' into refactor/motor
Tropix126 Jan 19, 2024
2d60528
docs: fix examples
Tropix126 Jan 19, 2024
6a3714b
Merge branch 'main' into refactor/motor
Tropix126 Feb 26, 2024
5f2c100
feat: (hopefully) full coverage of the PROS motor api
Tropix126 Mar 1, 2024
97f1f12
chore: fmt
Tropix126 Mar 1, 2024
c45a047
docs: reword warning
Tropix126 Mar 1, 2024
12ec99d
docs: add comments for missing functions
Tropix126 Mar 1, 2024
42caf61
feat: set_profiled_velocity
Tropix126 Mar 1, 2024
1625a58
refactor/docs: clean up MotorTuningConstants
Tropix126 Mar 1, 2024
5f4f173
refactor: various subjective API tweaks
Tropix126 Mar 2, 2024
d522bca
docs: document `voltage_limit` unit uncertainty
Tropix126 Mar 2, 2024
391ed9c
Merge remote-tracking branch 'upstream/main' into refactor/motor
Tropix126 Mar 2, 2024
68a7404
fix: `dangerous_motor_tuning` feature flag
Tropix126 Mar 2, 2024
42d1614
refactor: rename `MotorTarget` to `MotorControl`
Tropix126 Mar 6, 2024
427ba08
Merge branch 'main' into refactor/motor
Tropix126 Mar 6, 2024
c2f96c1
refactor: make `voltage_limit` non-optional
Tropix126 Mar 6, 2024
9a0aedd
Merge branch 'refactor/motor' of https://github.com/Tropix126/pros-rs…
Tropix126 Mar 6, 2024
b6924b2
refactor: use `bitflags` crate for status structs, deprecate MotorSta…
Tropix126 Mar 6, 2024
a88c9c4
refactor: `InertialStatus` bitflags
Tropix126 Mar 6, 2024
a70fa58
refactor: `Direction` enum
Tropix126 Mar 6, 2024
cf9899a
refactor: switch to i8 port indexes in `pros_sys`
Tropix126 Mar 7, 2024
cb7c6d0
refactor: use coast braking on velocity/position control
Tropix126 Mar 7, 2024
b25cd5f
docs: update description
Tropix126 Mar 7, 2024
eda3dd2
fix: remove `voltage_limit` until kernel fix
Tropix126 Mar 8, 2024
5ad9b43
refactor: rename `rotate_to_position` to `set_position_target`
Tropix126 Mar 8, 2024
86125ae
feat: add max RPM getter for `Gearset`
Tropix126 Mar 8, 2024
0555f6f
docs: fix example
Tropix126 Mar 8, 2024
f71cfea
docs: update changelog
Tropix126 Mar 8, 2024
a7f7dd3
refactor: make `efficiency` return 0.0-1.0
Tropix126 Mar 8, 2024
127f7e2
feat: add TPR getter
Tropix126 Mar 8, 2024
460c982
refactor: raw_position timestamp outvalue
Tropix126 Mar 8, 2024
d34a4f3
chore: fmt :]
Tropix126 Mar 8, 2024
1d7cdf7
refactor: `SmartDeviceTimestamp`
Tropix126 Mar 8, 2024
10d8eaf
chore: fmt 🪈
Tropix126 Mar 8, 2024
ad92aa9
chore: remove extraneous dlmalloc dep
Tropix126 Mar 11, 2024
8fa3eaf
fix: typo in changelog
Tropix126 Mar 13, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
187 changes: 94 additions & 93 deletions packages/pros/src/devices/smart/motor.rs
Tropix126 marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -39,55 +39,44 @@ pub struct Motor {
//TODO: Implement good set_velocity and get_velocity functions.
//TODO: Measure the number of counts per rotation. Fow now we assume it is 4096
impl Motor {
pub fn new(port: SmartPort, brake_mode: BrakeMode) -> Result<Self, MotorError> {
unsafe {
bail_on!(
PROS_ERR,
pros_sys::motor_set_encoder_units(port.index(), pros_sys::E_MOTOR_ENCODER_DEGREES)
);
bail_on!(
PROS_ERR,
pros_sys::motor_set_brake_mode(port.index(), brake_mode.into())
);
}
pub fn new(port: SmartPort, gearset: Gearset, reversed: bool) -> Result<Self, MotorError> {
Tropix126 marked this conversation as resolved.
Show resolved Hide resolved
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_set_encoder_units(port.index(), pros_sys::E_MOTOR_ENCODER_DEGREES)
});

let mut motor = Self { port };

Ok(Self { port })
motor.set_gearset(gearset)?;
motor.set_reversed(reversed)?;

Ok(motor)
}

pub fn set_gearset(&mut self, gearset: Gearset) -> Result<(), MotorError> {
unsafe {
bail_on!(
PROS_ERR,
pros_sys::motor_set_gearing(self.port.index(), gearset as i32)
);
}
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_set_gearing(self.port.index(), gearset as i32)
});
Ok(())
}

pub fn gearset(&self) -> Result<Gearset, MotorError> {
Ok(unsafe { bail_on!(PROS_ERR, pros_sys::motor_get_gearing(self.port.index())) }.into())
unsafe { pros_sys::motor_get_gearing(self.port.index()).try_into() }
}

/// Takes in a f32 from -1 to 1 that is scaled to -12 to 12 volts.
/// Useful for driving motors with controllers.
pub fn set_output(&mut self, output: f32) -> Result<(), MotorError> {
unsafe {
bail_on!(
PROS_ERR,
pros_sys::motor_move(self.port.index(), (output * 127.0) as i32)
);
}
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_move(self.port.index(), (output * 127.0) as i32)
});
Ok(())
}

/// Takes in and i8 between -127 and 127 which is scaled to -12 to 12 Volts.
pub fn set_raw_output(&mut self, raw_output: i8) -> Result<(), MotorError> {
unsafe {
bail_on!(
PROS_ERR,
pros_sys::motor_move(self.port.index(), raw_output as i32)
);
}
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_move(self.port.index(), raw_output as i32)
});
Ok(())
}

Expand All @@ -96,12 +85,9 @@ impl Motor {
if !(-12.0..=12.0).contains(&voltage) || voltage.is_nan() {
return Err(MotorError::VoltageOutOfRange);
}
unsafe {
bail_on!(
PROS_ERR,
pros_sys::motor_move_voltage(self.port.index(), (voltage * 1000.0) as i32)
);
}
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_move_voltage(self.port.index(), (voltage * 1000.0) as i32)
});

Ok(())
}
Expand All @@ -113,12 +99,9 @@ impl Motor {
position: Position,
velocity: i32,
) -> Result<(), MotorError> {
unsafe {
bail_on!(
PROS_ERR,
pros_sys::motor_move_absolute(self.port.index(), position.into_degrees(), velocity)
);
};
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_move_absolute(self.port.index(), position.into_degrees(), velocity)
});
Ok(())
}

Expand All @@ -129,51 +112,41 @@ impl Motor {
position: Position,
velocity: i32,
) -> Result<(), MotorError> {
unsafe {
bail_on!(
PROS_ERR,
pros_sys::motor_move_relative(self.port.index(), position.into_degrees(), velocity)
);
}
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_move_relative(self.port.index(), position.into_degrees(), velocity)
});

Ok(())
}

/// Returns the power drawn by the motor in Watts.
pub fn power(&self) -> Result<f64, MotorError> {
unsafe {
Ok(bail_on!(
PROS_ERR_F,
pros_sys::motor_get_power(self.port.index())
))
}
Ok(bail_on!(PROS_ERR_F, unsafe {
pros_sys::motor_get_power(self.port.index())
}))
}

/// Returns the torque output of the motor in Nm.
pub fn torque(&self) -> Result<f64, MotorError> {
unsafe {
Ok(bail_on!(
PROS_ERR_F,
pros_sys::motor_get_torque(self.port.index())
))
}
Ok(bail_on!(PROS_ERR_F, unsafe {
pros_sys::motor_get_torque(self.port.index())
}))
}

/// Returns the voltage the motor is drawing in volts.
pub fn voltage(&self) -> Result<f64, MotorError> {
// docs say this function returns PROS_ERR_F but it actually returns PROS_ERR
let millivolts =
unsafe { bail_on!(PROS_ERR, pros_sys::motor_get_voltage(self.port.index())) };
let millivolts = bail_on!(PROS_ERR, unsafe {
pros_sys::motor_get_voltage(self.port.index())
});
Ok(millivolts as f64 / 1000.0)
}

/// Returns the current position of the motor.
pub fn position(&self) -> Result<Position, MotorError> {
unsafe {
Ok(Position::from_degrees(bail_on!(
PROS_ERR_F,
pros_sys::motor_get_position(self.port.index())
)))
}
Ok(Position::from_degrees(bail_on!(PROS_ERR_F, unsafe {
pros_sys::motor_get_position(self.port.index())
})))
}

/// Returns the current draw of the motor.
Expand All @@ -186,9 +159,9 @@ impl Motor {
/// Sets the current encoder position to zero without moving the motor.
/// Analogous to taring or resetting the encoder to the current position.
pub fn zero(&mut self) -> Result<(), MotorError> {
unsafe {
bail_on!(PROS_ERR, pros_sys::motor_tare_position(self.port.index()));
}
bail_on!(PROS_ERR, unsafe {
pros_sys::motor_tare_position(self.port.index())
});
Ok(())
}

Expand Down Expand Up @@ -217,9 +190,13 @@ impl Motor {
Ok(())
}

//TODO: Test this, as im not entirely sure of the actual implementation
pub fn brake_mode(&self) -> Result<BrakeMode, MotorError> {
Tropix126 marked this conversation as resolved.
Show resolved Hide resolved
unsafe { pros_sys::motor_get_brake_mode(self.port.index()).try_into() }
}

// TODO: Test this, as im not entirely sure of the actual implementation
/// Get the current state of the motor.
pub fn get_state(&self) -> Result<MotorState, MotorError> {
pub fn state(&self) -> Result<MotorState, MotorError> {
Tropix126 marked this conversation as resolved.
Show resolved Hide resolved
let bit_flags = bail_on!(PROS_ERR as _, unsafe {
pros_sys::motor_get_flags(self.port.index())
});
Expand All @@ -235,8 +212,10 @@ impl Motor {
}

/// Check if this motor has been reversed.
pub fn reversed(&self) -> bool {
unsafe { pros_sys::motor_is_reversed(self.port.index()) == 1 }
pub fn reversed(&self) -> Result<bool, MotorError> {
Ok(bail_on!(PROS_ERR, unsafe {
pros_sys::motor_is_reversed(self.port.index())
}) == 1)
}

/// Returns a future that completes when the motor reports that it has stopped.
Expand All @@ -257,22 +236,34 @@ impl SmartDevice for Motor {

/// Determines how a motor should act when braking.
#[derive(Debug, Clone, Copy)]
#[repr(i32)]
pub enum BrakeMode {
/// Motor never brakes.
None,
None = pros_sys::E_MOTOR_BRAKE_COAST,
/// Motor uses regenerative braking to slow down faster.
Brake,
Brake = pros_sys::E_MOTOR_BRAKE_BRAKE,
/// Motor exerts force to hold the same position.
Hold,
Hold = pros_sys::E_MOTOR_BRAKE_HOLD,
}

impl TryFrom<pros_sys::motor_brake_mode_e_t> for BrakeMode {
type Error = MotorError;

fn try_from(value: pros_sys::motor_brake_mode_e_t) -> Result<Self, MotorError> {
bail_on!(PROS_ERR, value);

Ok(match value {
pros_sys::E_MOTOR_BRAKE_COAST => Self::None,
pros_sys::E_MOTOR_BRAKE_BRAKE => Self::Brake,
pros_sys::E_MOTOR_BRAKE_HOLD => Self::Hold,
_ => unreachable!(),
})
}
}

impl From<BrakeMode> for pros_sys::motor_brake_mode_e_t {
fn from(other: BrakeMode) -> pros_sys::motor_brake_mode_e_t {
match other {
BrakeMode::Brake => pros_sys::E_MOTOR_BRAKE_BRAKE,
BrakeMode::Hold => pros_sys::E_MOTOR_BRAKE_HOLD,
BrakeMode::None => pros_sys::E_MOTOR_BRAKE_COAST,
}
fn from(value: BrakeMode) -> pros_sys::motor_brake_mode_e_t {
value as _
}
}

Expand Down Expand Up @@ -321,14 +312,24 @@ impl Gearset {
pub const RPM_600: Gearset = Gearset::Blue;
}

impl From<i32> for Gearset {
fn from(value: i32) -> Self {
match value {
pros_sys::E_MOTOR_GEAR_RED => Gearset::Red,
pros_sys::E_MOTOR_GEAR_GREEN => Gearset::Green,
pros_sys::E_MOTOR_GEAR_BLUE => Gearset::Blue,
impl From<Gearset> for pros_sys::motor_gearset_e_t {
fn from(value: Gearset) -> Self {
value as _
}
}

impl TryFrom<pros_sys::motor_gearset_e_t> for Gearset {
type Error = MotorError;

fn try_from(value: pros_sys::motor_gearset_e_t) -> Result<Self, MotorError> {
bail_on!(PROS_ERR, value);

Ok(match value {
pros_sys::E_MOTOR_GEAR_RED => Self::Red,
pros_sys::E_MOTOR_GEAR_GREEN => Self::Green,
pros_sys::E_MOTOR_GEAR_BLUE => Self::Blue,
_ => unreachable!(),
}
})
}
}

Expand All @@ -342,7 +343,7 @@ impl<'a> core::future::Future for MotorStoppedFuture<'a> {
self: core::pin::Pin<&mut Self>,
cx: &mut core::task::Context<'_>,
) -> core::task::Poll<Self::Output> {
match self.motor.get_state()?.stopped {
match self.motor.state()?.stopped {
true => core::task::Poll::Ready(Ok(())),
false => {
cx.waker().wake_by_ref();
Expand Down
Loading