mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-22 01:11:42 +00:00
[command] Rename trigger methods (#4210)
Motivation Feedback from 2022 showed that the Trigger API is rather confusing, mostly due to the following: - duplicate Trigger and Button APIs were available; users were confused searching for a nonexistent difference between them. - the when terminology was ambiguous and unclear whether it refers to the high state or specifically the rising edge. - the Active terminology didn't unambiguously refer to the high state; it wasn't unintuitive to understand it as "when the binding is active/polled". - whileHeld vs whenHeld was very confusing, and the difference between them wasn't obvious. The parallel Trigger verbs, whileActiveContinuously and whileActiveOnce are much less confusing. Solution Deprecating Button and its binding methods. The rationale for deprecating Button (and not Trigger) is because Button uses terminology that is needlessly more specific and restricting to the button use case, making the use case of arbitrary trigger conditions unintuitive. After consideration, deprecation of Button's subclasses was decided against: - NetworkButton (a trigger condition based on a boolean NT entry/topic) is a use case that is not necessarily intuitive for teams to implement themselves, so it is an abstraction that should be provided in the library. A parallel class for the BooleanEvent level, NetworkBooleanEvent, was also added as part of NT4. NT listeners were considered as a alternative solution, but they require attention to thread safety, and aren't interoperable with the EventLoop API. - JoystickButton/POVButton provide abstractions around HID buttons. The new Trigger-returning factories on the HID classes are an equal (if not more concise) alternative, but there is no reason not to keep them for those who find their use preferable. At a later date in the deprecation cycle (perhaps for 2024), when Button is removed, these subclasses should be changed to inherit directly from Trigger. Trigger's bindings are changed to use True/False terminology, as it should be unambiguous. Each binding type has both True and False variants; for brevity, only the True variants are listed here: - onTrue (replaces whenActive): schedule on rising edge. - whileTrue (replaces whileActiveOnce): schedule on rising edge, cancel on falling edge. - toggleOnTrue (replaces toggleWhenActive): on rising edge, schedule if unscheduled and cancel if scheduled. Two binding types are completely deprecated: - cancelWhenActive: this is a fairly niche use case which is better described as having the trigger's rising edge (Trigger.rising()) as an end condition for the command (using Command.until()). - whileActiveContinuously: however common, this relied on the no-op behavior of scheduling an already-scheduled command. The more correct way to repeat the command if it ends before the falling edge is using Command.repeatedly/RepeatCommand or a RunCommand -- the only difference is if the command is interrupted, but that is more likely to result in two commands perpetually canceling each other than achieve the desired behavior. Manually implementing a blindly-scheduling binding like whileActiveContinuously is still possible, though might not be intuitive. Notes It was considered to share BooleanEvent's digital signal terminology; however, once it was decided that Trigger should not inherit from BooleanEvent (due to overload incompatibility) the common terminology was not worth the unintuitiveness stemming from users' unfamiliarity with the signal processing terms.
This commit is contained in:
@@ -17,7 +17,10 @@ import java.util.function.BooleanSupplier;
|
||||
* <p>This class represents a subclass of Trigger that is specifically aimed at buttons on an
|
||||
* operator interface as a common use case of the more generalized Trigger objects. This is a simple
|
||||
* wrapper around Trigger with the method names renamed to fit the Button object use.
|
||||
*
|
||||
* @deprecated Replace with {@link Trigger}.
|
||||
*/
|
||||
@Deprecated
|
||||
public class Button extends Trigger {
|
||||
/**
|
||||
* Default constructor; creates a button that is never pressed.
|
||||
@@ -31,7 +34,9 @@ public class Button extends Trigger {
|
||||
* Creates a new button with the given condition determining whether it is pressed.
|
||||
*
|
||||
* @param isPressed returns whether or not the trigger should be active
|
||||
* @deprecated Replace with Trigger.
|
||||
*/
|
||||
@Deprecated
|
||||
public Button(BooleanSupplier isPressed) {
|
||||
super(isPressed);
|
||||
}
|
||||
@@ -41,7 +46,9 @@ public class Button extends Trigger {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Replace with {@link Trigger#onTrue(Command)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Button whenPressed(final Command command) {
|
||||
whenActive(command);
|
||||
return this;
|
||||
@@ -53,7 +60,9 @@ public class Button extends Trigger {
|
||||
* @param toRun the runnable to run
|
||||
* @param requirements the required subsystems
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Replace with {@link #onTrue(Command)}, creating the InstantCommand manually
|
||||
*/
|
||||
@Deprecated
|
||||
public Button whenPressed(final Runnable toRun, Subsystem... requirements) {
|
||||
whenActive(toRun, requirements);
|
||||
return this;
|
||||
@@ -67,7 +76,10 @@ public class Button extends Trigger {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Use {@link #whileTrue(Command)} with {@link
|
||||
* edu.wpi.first.wpilibj2.command.RepeatCommand RepeatCommand}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Button whileHeld(final Command command) {
|
||||
whileActiveContinuous(command);
|
||||
return this;
|
||||
@@ -79,7 +91,9 @@ public class Button extends Trigger {
|
||||
* @param toRun the runnable to run
|
||||
* @param requirements the required subsystems
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Use {@link #whileTrue(Command)} and construct a RunCommand manually
|
||||
*/
|
||||
@Deprecated
|
||||
public Button whileHeld(final Runnable toRun, Subsystem... requirements) {
|
||||
whileActiveContinuous(toRun, requirements);
|
||||
return this;
|
||||
@@ -91,7 +105,9 @@ public class Button extends Trigger {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Replace with {@link Trigger#whileTrue(Command)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Button whenHeld(final Command command) {
|
||||
whileActiveOnce(command);
|
||||
return this;
|
||||
@@ -102,7 +118,9 @@ public class Button extends Trigger {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Replace with {@link Trigger#onFalse(Command)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Button whenReleased(final Command command) {
|
||||
whenInactive(command);
|
||||
return this;
|
||||
@@ -114,7 +132,9 @@ public class Button extends Trigger {
|
||||
* @param toRun the runnable to run
|
||||
* @param requirements the required subsystems
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Replace with {@link Trigger#onFalse(Command)}, creating the InstantCommand manually
|
||||
*/
|
||||
@Deprecated
|
||||
public Button whenReleased(final Runnable toRun, Subsystem... requirements) {
|
||||
whenInactive(toRun, requirements);
|
||||
return this;
|
||||
@@ -126,7 +146,9 @@ public class Button extends Trigger {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Replace with {@link Trigger#toggleOnTrue(Command)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Button toggleWhenPressed(final Command command) {
|
||||
toggleWhenActive(command);
|
||||
return this;
|
||||
@@ -137,7 +159,10 @@ public class Button extends Trigger {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this button, so calls can be chained
|
||||
* @deprecated Instead, pass {@link #rising()} as an end condition to {@link
|
||||
* Command#until(BooleanSupplier)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Button cancelWhenPressed(final Command command) {
|
||||
cancelWhenActive(command);
|
||||
return this;
|
||||
|
||||
@@ -12,6 +12,7 @@ import java.util.concurrent.atomic.AtomicBoolean;
|
||||
*
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class InternalButton extends Button {
|
||||
// need to be references, so they can be mutated after being captured in the constructor.
|
||||
private final AtomicBoolean m_pressed;
|
||||
|
||||
@@ -13,6 +13,7 @@ import edu.wpi.first.wpilibj.GenericHID;
|
||||
*
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class JoystickButton extends Button {
|
||||
/**
|
||||
* Creates a joystick button for triggering commands.
|
||||
|
||||
@@ -16,6 +16,7 @@ import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
*
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class NetworkButton extends Button {
|
||||
/**
|
||||
* Creates a NetworkButton that commands can be bound to.
|
||||
|
||||
@@ -13,6 +13,7 @@ import edu.wpi.first.wpilibj.GenericHID;
|
||||
*
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public class POVButton extends Button {
|
||||
/**
|
||||
* Creates a POV button for triggering commands.
|
||||
|
||||
@@ -22,7 +22,9 @@ import java.util.function.BooleanSupplier;
|
||||
*
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
public class Trigger extends BooleanEvent {
|
||||
public class Trigger implements BooleanSupplier {
|
||||
private final BooleanEvent m_event;
|
||||
|
||||
/**
|
||||
* Creates a new trigger with the given condition/digital signal.
|
||||
*
|
||||
@@ -30,7 +32,7 @@ public class Trigger extends BooleanEvent {
|
||||
* @param signal the digital signal represented.
|
||||
*/
|
||||
public Trigger(EventLoop loop, BooleanSupplier signal) {
|
||||
super(loop, signal);
|
||||
m_event = new BooleanEvent(loop, signal);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -62,18 +64,103 @@ public class Trigger extends BooleanEvent {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the trigger is active.
|
||||
* Starts the given command whenever the signal rises from the low state to the high state.
|
||||
*
|
||||
* <p>This method will be called repeatedly a command is linked to the Trigger.
|
||||
*
|
||||
* <p>Functionally identical to {@link Trigger#getAsBoolean()}.
|
||||
*
|
||||
* @return whether or not the trigger condition is active.
|
||||
* @deprecated use {@link #getAsBoolean()}
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
* @see #rising()
|
||||
*/
|
||||
@Deprecated
|
||||
public final boolean get() {
|
||||
return getAsBoolean();
|
||||
public Trigger onTrue(Command command) {
|
||||
requireNonNullParam(command, "command", "onRising");
|
||||
m_event.rising().ifHigh(command::schedule);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the given command whenever the signal falls from the high state to the low state.
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
* @see #falling()
|
||||
*/
|
||||
public Trigger onFalse(Command command) {
|
||||
requireNonNullParam(command, "command", "onFalling");
|
||||
m_event.falling().ifHigh(command::schedule);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the given command when the signal rises to the high state and cancels it when the signal
|
||||
* falls.
|
||||
*
|
||||
* <p>Doesn't re-start the command in-between.
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
*/
|
||||
public Trigger whileTrue(Command command) {
|
||||
requireNonNullParam(command, "command", "whileHigh");
|
||||
m_event.rising().ifHigh(command::schedule);
|
||||
m_event.falling().ifHigh(command::cancel);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Starts the given command when the signal falls to the low state and cancels it when the signal
|
||||
* rises.
|
||||
*
|
||||
* <p>Does not re-start the command in-between.
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
*/
|
||||
public Trigger whileFalse(Command command) {
|
||||
requireNonNullParam(command, "command", "whileLow");
|
||||
m_event.falling().ifHigh(command::schedule);
|
||||
m_event.rising().ifHigh(command::cancel);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a command when the signal rises from the low state to the high state.
|
||||
*
|
||||
* @param command the command to toggle
|
||||
* @return this trigger, so calls can be chained
|
||||
*/
|
||||
public Trigger toggleOnTrue(Command command) {
|
||||
requireNonNullParam(command, "command", "toggleOnRising");
|
||||
m_event
|
||||
.rising()
|
||||
.ifHigh(
|
||||
() -> {
|
||||
if (!command.isScheduled()) {
|
||||
command.schedule();
|
||||
} else {
|
||||
command.cancel();
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles a command when the signal rises from the low state to the high state.
|
||||
*
|
||||
* @param command the command to toggle
|
||||
* @return this trigger, so calls can be chained
|
||||
*/
|
||||
public Trigger toggleOnFalse(Command command) {
|
||||
requireNonNullParam(command, "command", "toggleOnFalling");
|
||||
m_event
|
||||
.falling()
|
||||
.ifHigh(
|
||||
() -> {
|
||||
if (!command.isScheduled()) {
|
||||
command.schedule();
|
||||
} else {
|
||||
command.cancel();
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -81,11 +168,13 @@ public class Trigger extends BooleanEvent {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Use {@link #onTrue(Command)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger whenActive(final Command command) {
|
||||
requireNonNullParam(command, "command", "whenActive");
|
||||
|
||||
this.rising().ifHigh(command::schedule);
|
||||
m_event.rising().ifHigh(command::schedule);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -95,7 +184,9 @@ public class Trigger extends BooleanEvent {
|
||||
* @param toRun the runnable to run
|
||||
* @param requirements the required subsystems
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Replace with {@link #onTrue(Command)}, creating the InstantCommand manually
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger whenActive(final Runnable toRun, Subsystem... requirements) {
|
||||
return whenActive(new InstantCommand(toRun, requirements));
|
||||
}
|
||||
@@ -108,12 +199,17 @@ public class Trigger extends BooleanEvent {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Use {@link #whileTrue(Command)} with {@link
|
||||
* edu.wpi.first.wpilibj2.command.RepeatCommand RepeatCommand}, or bind {@link
|
||||
* Command#schedule() command::schedule} to {@link BooleanEvent#ifHigh(Runnable)} (passing no
|
||||
* requirements).
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger whileActiveContinuous(final Command command) {
|
||||
requireNonNullParam(command, "command", "whileActiveContinuous");
|
||||
|
||||
this.ifHigh(command::schedule);
|
||||
this.falling().ifHigh(command::cancel);
|
||||
m_event.ifHigh(command::schedule);
|
||||
m_event.falling().ifHigh(command::cancel);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -124,7 +220,9 @@ public class Trigger extends BooleanEvent {
|
||||
* @param toRun the runnable to run
|
||||
* @param requirements the required subsystems
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Use {@link #whileTrue(Command)} and construct a RunCommand manually
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger whileActiveContinuous(final Runnable toRun, Subsystem... requirements) {
|
||||
return whileActiveContinuous(new InstantCommand(toRun, requirements));
|
||||
}
|
||||
@@ -135,12 +233,14 @@ public class Trigger extends BooleanEvent {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Use {@link #whileTrue(Command)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger whileActiveOnce(final Command command) {
|
||||
requireNonNullParam(command, "command", "whileActiveOnce");
|
||||
|
||||
this.rising().ifHigh(command::schedule);
|
||||
this.falling().ifHigh(command::cancel);
|
||||
m_event.rising().ifHigh(command::schedule);
|
||||
m_event.falling().ifHigh(command::cancel);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -150,11 +250,13 @@ public class Trigger extends BooleanEvent {
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Use {@link #onFalse(Command)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger whenInactive(final Command command) {
|
||||
requireNonNullParam(command, "command", "whenInactive");
|
||||
|
||||
this.falling().ifHigh(command::schedule);
|
||||
m_event.falling().ifHigh(command::schedule);
|
||||
|
||||
return this;
|
||||
}
|
||||
@@ -165,7 +267,9 @@ public class Trigger extends BooleanEvent {
|
||||
* @param toRun the runnable to run
|
||||
* @param requirements the required subsystems
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Construct the InstantCommand manually and replace with {@link #onFalse(Command)}
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger whenInactive(final Runnable toRun, Subsystem... requirements) {
|
||||
return whenInactive(new InstantCommand(toRun, requirements));
|
||||
}
|
||||
@@ -175,11 +279,14 @@ public class Trigger extends BooleanEvent {
|
||||
*
|
||||
* @param command the command to toggle
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Use {@link #toggleOnTrue(Command)} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger toggleWhenActive(final Command command) {
|
||||
requireNonNullParam(command, "command", "toggleWhenActive");
|
||||
|
||||
this.rising()
|
||||
m_event
|
||||
.rising()
|
||||
.ifHigh(
|
||||
() -> {
|
||||
if (command.isScheduled()) {
|
||||
@@ -197,49 +304,57 @@ public class Trigger extends BooleanEvent {
|
||||
*
|
||||
* @param command the command to cancel
|
||||
* @return this trigger, so calls can be chained
|
||||
* @deprecated Instead, pass {@link #rising()} as an end condition to {@link
|
||||
* Command#until(BooleanSupplier)}.
|
||||
*/
|
||||
@Deprecated
|
||||
public Trigger cancelWhenActive(final Command command) {
|
||||
requireNonNullParam(command, "command", "cancelWhenActive");
|
||||
|
||||
this.rising().ifHigh(command::cancel);
|
||||
m_event.rising().ifHigh(command::cancel);
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/* ----------- Super method type redeclarations ----------------- */
|
||||
/**
|
||||
* Get the wrapped BooleanEvent.
|
||||
*
|
||||
* @return the wrapped BooleanEvent instance.
|
||||
*/
|
||||
public BooleanEvent getEvent() {
|
||||
return m_event;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
return m_event.getAsBoolean();
|
||||
}
|
||||
|
||||
public Trigger and(BooleanSupplier trigger) {
|
||||
return cast(super.and(trigger));
|
||||
return cast(m_event.and(trigger));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger or(BooleanSupplier trigger) {
|
||||
return cast(super.or(trigger));
|
||||
return cast(m_event.or(trigger));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger negate() {
|
||||
return cast(super.negate());
|
||||
return cast(m_event.negate());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger debounce(double seconds) {
|
||||
return debounce(seconds, Debouncer.DebounceType.kRising);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger debounce(double seconds, Debouncer.DebounceType type) {
|
||||
return cast(super.debounce(seconds, type));
|
||||
return cast(m_event.debounce(seconds, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger rising() {
|
||||
return cast(super.rising());
|
||||
return cast(m_event.rising());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger falling() {
|
||||
return cast(super.falling());
|
||||
return cast(m_event.falling());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user