[wpimath] Replace Speeds with Velocities (#8479)

I left "free speed" alone since that's the technical term for it. In
general, velocity is a vector quantity, and speed is a magnitude (i.e.,
a strictly positive value).

This PR also replaces the speed verbiage in MotorController with duty
cycle.

Fixes #8423.
This commit is contained in:
Tyler Veness
2026-03-06 14:19:15 -08:00
committed by GitHub
parent 1e39f39128
commit 9bd9656871
594 changed files with 8073 additions and 7875 deletions

View File

@@ -153,14 +153,14 @@ public class ExpansionHubMotor implements AutoCloseable {
}
/**
* Sets the percentage power to run the motor at, between -1 and 1.
* Sets the duty cycle.
*
* @param power The power to drive the motor at
* @param dutyCycle The duty cycle between -1 and 1 (sign indicates direction).
*/
public void setPercentagePower(double power) {
public void setDutyCycle(double dutyCycle) {
setEnabled(true);
m_modePublisher.set(kPercentageMode);
m_setpointPublisher.set(power);
m_setpointPublisher.set(dutyCycle);
}
/**

View File

@@ -114,7 +114,7 @@ public interface LEDPattern {
*
* <p>This method is intentionally designed to use separate objects for reading and writing data.
* By splitting them up, we can easily modify the behavior of some base pattern to make it {@link
* #scrollAtRelativeSpeed(Frequency) scroll}, {@link #blink(Time, Time) blink}, or {@link
* #scrollAtRelativeVelocity(Frequency) scroll}, {@link #blink(Time, Time) blink}, or {@link
* #breathe(Time) breathe} by intercepting the data writes to transform their behavior to whatever
* we like.
*
@@ -182,13 +182,13 @@ public interface LEDPattern {
/**
* Creates a pattern that displays this one in reverse. Scrolling patterns will scroll in the
* opposite direction (but at the same speed). It will treat the end of an LED strip as the start,
* and the start of the strip as the end. This can be useful for making ping-pong patterns that
* travel from one end of an LED strip to the other, then reverse direction and move back to the
* start. This can also be useful when working with LED strips connected in a serpentine pattern
* (where the start of one strip is connected to the end of the previous one); however, consider
* using a {@link AddressableLEDBufferView#reversed() reversed view} of the overall buffer for
* that segment rather than reversing patterns.
* opposite direction (but at the same velocity). It will treat the end of an LED strip as the
* start, and the start of the strip as the end. This can be useful for making ping-pong patterns
* that travel from one end of an LED strip to the other, then reverse direction and move back to
* the start. This can also be useful when working with LED strips connected in a serpentine
* pattern (where the start of one strip is connected to the end of the previous one); however,
* consider using a {@link AddressableLEDBufferView#reversed() reversed view} of the overall
* buffer for that segment rather than reversing patterns.
*
* @return the reverse pattern
* @see AddressableLEDBufferView#reversed()
@@ -219,14 +219,14 @@ public interface LEDPattern {
*
* <pre>
* LEDPattern rainbow = LEDPattern.rainbow(255, 255);
* LEDPattern scrollingRainbow = rainbow.scrollAtRelativeSpeed(Percent.per(Second).of(25));
* LEDPattern scrollingRainbow = rainbow.scrollAtRelativeVelocity(Percent.per(Second).of(25));
* </pre>
*
* @param velocity how fast the pattern should move, in terms of how long it takes to do a full
* scroll along the length of LEDs and return back to the starting position
* @return the scrolling pattern
*/
default LEDPattern scrollAtRelativeSpeed(Frequency velocity) {
default LEDPattern scrollAtRelativeVelocity(Frequency velocity) {
final double periodMicros = velocity.asPeriod().in(Microseconds);
return mapIndex(
@@ -254,7 +254,7 @@ public interface LEDPattern {
*
* LEDPattern rainbow = LEDPattern.rainbow();
* LEDPattern scrollingRainbow =
* rainbow.scrollAtAbsoluteSpeed(InchesPerSecond.of(4), LED_SPACING);
* rainbow.scrollAtAbsoluteVelocity(InchesPerSecond.of(4), LED_SPACING);
* </pre>
*
* <p>Note that this pattern will scroll <i>faster</i> if applied to a less dense LED strip (such
@@ -265,7 +265,7 @@ public interface LEDPattern {
* @param ledSpacing the distance between adjacent LEDs on the physical LED strip
* @return the scrolling pattern
*/
default LEDPattern scrollAtAbsoluteSpeed(LinearVelocity velocity, Distance ledSpacing) {
default LEDPattern scrollAtAbsoluteVelocity(LinearVelocity velocity, Distance ledSpacing) {
// eg velocity = 10 m/s, spacing = 0.01m
// meters per micro = 1e-5 m/us
// micros per LED = 1e-2 m / (1e-5 m/us) = 1e-3 us

View File

@@ -12,63 +12,65 @@ import org.wpilib.units.measure.Voltage;
/** Interface for motor controlling devices. */
public interface MotorController {
/**
* Common interface for setting the speed of a motor controller.
* Sets the duty cycle of the motor controller.
*
* @param speed The speed to set. Value should be between -1.0 and 1.0.
* @param dutyCycle The duty cycle between -1 and 1 (sign indicates direction).
*/
void set(double speed);
void setDutyCycle(double dutyCycle);
/**
* Sets the voltage output of the MotorController. Compensates for the current bus voltage to
* ensure that the desired voltage is output even if the battery voltage is below 12V - highly
* useful when the voltage outputs are "meaningful" (e.g. they come from a feedforward
* calculation).
* Sets the voltage output of the motor controller.
*
* <p>Compensates for the current bus voltage to ensure that the desired voltage is output even if
* the battery voltage is below 12V - highly useful when the voltage outputs are "meaningful"
* (e.g. they come from a feedforward calculation).
*
* <p>NOTE: This function *must* be called regularly in order for voltage compensation to work
* properly - unlike the ordinary set function, it is not "set it and forget it."
*
* @param outputVolts The voltage to output, in Volts.
* @param voltage The voltage.
*/
default void setVoltage(double outputVolts) {
set(outputVolts / RobotController.getBatteryVoltage());
default void setVoltage(double voltage) {
setDutyCycle(voltage / RobotController.getBatteryVoltage());
}
/**
* Sets the voltage output of the MotorController. Compensates for the current bus voltage to
* ensure that the desired voltage is output even if the battery voltage is below 12V - highly
* useful when the voltage outputs are "meaningful" (e.g. they come from a feedforward
* calculation).
* Sets the voltage output of the motor controller.
*
* <p>Compensates for the current bus voltage to ensure that the desired voltage is output even if
* the battery voltage is below 12V - highly useful when the voltage outputs are "meaningful"
* (e.g. they come from a feedforward calculation).
*
* <p>NOTE: This function *must* be called regularly in order for voltage compensation to work
* properly - unlike the ordinary set function, it is not "set it and forget it."
*
* @param outputVoltage The voltage to output.
* @param voltage The voltage.
*/
default void setVoltage(Voltage outputVoltage) {
setVoltage(outputVoltage.in(Volts));
default void setVoltage(Voltage voltage) {
setVoltage(voltage.in(Volts));
}
/**
* Common interface for getting the current set speed of a motor controller.
* Gets the duty cycle of the motor controller.
*
* @return The current set speed. Value is between -1.0 and 1.0.
* @return The duty cycle between -1 and 1 (sign indicates direction).
*/
double get();
double getDutyCycle();
/**
* Common interface for inverting direction of a motor controller.
* Sets the inversion state of the motor controller.
*
* @param isInverted The state of inversion true is inverted.
* @param isInverted The inversion state.
*/
void setInverted(boolean isInverted);
/**
* Common interface for returning if a motor controller is in the inverted state or not.
* Gets the inversion state of the motor controller.
*
* @return isInverted The state of the inversion true is inverted.
* @return The inversion state.
*/
boolean getInverted();
/** Disable the motor controller. */
/** Disables the motor controller. */
void disable();
}

View File

@@ -25,7 +25,7 @@ public abstract class PWMMotorController extends MotorSafety
protected PWM m_pwm;
private SimDevice m_simDevice;
private SimDouble m_simSpeed;
private SimDouble m_simDutyCycle;
private boolean m_eliminateDeadband;
private int m_minPwm;
@@ -48,7 +48,7 @@ public abstract class PWMMotorController extends MotorSafety
m_simDevice = SimDevice.create("PWMMotorController", channel);
if (m_simDevice != null) {
m_simSpeed = m_simDevice.createDouble("Speed", Direction.kOutput, 0.0);
m_simDutyCycle = m_simDevice.createDouble("DutyCycle", Direction.kOutput, 0.0);
m_pwm.setSimDevice(m_simDevice);
}
}
@@ -62,7 +62,7 @@ public abstract class PWMMotorController extends MotorSafety
if (m_simDevice != null) {
m_simDevice.close();
m_simDevice = null;
m_simSpeed = null;
m_simDutyCycle = null;
}
}
@@ -91,39 +91,41 @@ public abstract class PWMMotorController extends MotorSafety
}
/**
* Takes a speed from -1 to 1, and outputs it in the microsecond format.
* Takes a duty cycle from -1 to 1 (the sign indicates direction), and outputs it in the
* microsecond format.
*
* @param speed the speed to output
* @param dutyCycle The duty cycle between -1 and 1 (sign indicates direction).
*/
protected final void setSpeed(double speed) {
if (Double.isFinite(speed)) {
speed = Math.clamp(speed, -1.0, 1.0);
protected final void setDutyCycleInternal(double dutyCycle) {
if (Double.isFinite(dutyCycle)) {
dutyCycle = Math.clamp(dutyCycle, -1.0, 1.0);
} else {
speed = 0.0;
dutyCycle = 0.0;
}
if (m_simSpeed != null) {
m_simSpeed.set(speed);
if (m_simDutyCycle != null) {
m_simDutyCycle.set(dutyCycle);
}
int rawValue;
if (speed == 0.0) {
if (dutyCycle == 0.0) {
rawValue = m_centerPwm;
} else if (speed > 0.0) {
rawValue = (int) Math.round(speed * getPositiveScaleFactor()) + getMinPositivePwm();
} else if (dutyCycle > 0.0) {
rawValue = (int) Math.round(dutyCycle * getPositiveScaleFactor()) + getMinPositivePwm();
} else {
rawValue = (int) Math.round(speed * getNegativeScaleFactor()) + getMaxNegativePwm();
rawValue = (int) Math.round(dutyCycle * getNegativeScaleFactor()) + getMaxNegativePwm();
}
m_pwm.setPulseTimeMicroseconds(rawValue);
}
/**
* Gets the speed from -1 to 1, from the currently set pulse time.
* Gets the duty cycle from -1 to 1 (the sign indicates direction), from the currently set pulse
* time.
*
* @return motor controller speed
* @return motor controller duty cycle
*/
protected final double getSpeed() {
protected final double getDutyCycleInternal() {
int rawValue = m_pwm.getPulseTimeMicroseconds();
if (rawValue == 0) {
@@ -159,36 +161,23 @@ public abstract class PWMMotorController extends MotorSafety
m_minPwm = minPwm;
}
/**
* Set the PWM value.
*
* <p>The PWM value is set using a range of -1.0 to 1.0, appropriately scaling the value for the
* FPGA.
*
* @param speed The speed value between -1.0 and 1.0 to set.
*/
@Override
public void set(double speed) {
public void setDutyCycle(double dutyCycle) {
if (m_isInverted) {
speed = -speed;
dutyCycle = -dutyCycle;
}
setSpeed(speed);
setDutyCycleInternal(dutyCycle);
for (var follower : m_followers) {
follower.set(speed);
follower.setDutyCycle(dutyCycle);
}
feed();
}
/**
* Get the recently set value of the PWM. This value is affected by the inversion property.
*
* @return The most recently set value for the PWM between -1.0 and 1.0.
*/
@Override
public double get() {
return getSpeed() * (m_isInverted ? -1.0 : 1.0);
public double getDutyCycle() {
return getDutyCycleInternal() * (m_isInverted ? -1.0 : 1.0);
}
/**
@@ -197,7 +186,7 @@ public abstract class PWMMotorController extends MotorSafety
* @return The voltage of the motor controller, nominally between -12 V and 12 V.
*/
public double getVoltage() {
return get() * RobotController.getBatteryVoltage();
return getDutyCycle() * RobotController.getBatteryVoltage();
}
@Override
@@ -214,8 +203,8 @@ public abstract class PWMMotorController extends MotorSafety
public void disable() {
m_pwm.setDisabled();
if (m_simSpeed != null) {
m_simSpeed.set(0.0);
if (m_simDutyCycle != null) {
m_simDutyCycle.set(0.0);
}
for (var follower : m_followers) {
@@ -275,6 +264,6 @@ public abstract class PWMMotorController extends MotorSafety
public void initSendable(SendableBuilder builder) {
builder.setSmartDashboardType("Motor Controller");
builder.setActuator(true);
builder.addDoubleProperty("Value", this::get, this::set);
builder.addDoubleProperty("Value", this::getDutyCycle, this::setDutyCycle);
}
}

View File

@@ -351,7 +351,7 @@ public class Encoder implements CounterBase, Sendable, AutoCloseable {
builder.setSmartDashboardType("Encoder");
}
builder.addDoubleProperty("Speed", this::getRate, null);
builder.addDoubleProperty("Velocity", this::getRate, null);
builder.addDoubleProperty("Distance", this::getDistance, null);
builder.addDoubleProperty("Distance per Tick", this::getDistancePerPulse, null);
}