mirror of
https://github.com/wpilibsuite/allwpilib
synced 2026-06-22 01:11:42 +00:00
[wpilib] Add EventLoop (#4104)
This is a generic expansion of the command-based Trigger framework.
This commit is contained in:
@@ -4,6 +4,8 @@
|
||||
|
||||
package edu.wpi.first.wpilibj2.command;
|
||||
|
||||
import static edu.wpi.first.util.ErrorMessages.requireNonNullParam;
|
||||
|
||||
import edu.wpi.first.hal.FRCNetComm.tInstances;
|
||||
import edu.wpi.first.hal.FRCNetComm.tResourceType;
|
||||
import edu.wpi.first.hal.HAL;
|
||||
@@ -15,13 +17,13 @@ import edu.wpi.first.wpilibj.RobotBase;
|
||||
import edu.wpi.first.wpilibj.RobotState;
|
||||
import edu.wpi.first.wpilibj.TimedRobot;
|
||||
import edu.wpi.first.wpilibj.Watchdog;
|
||||
import edu.wpi.first.wpilibj.event.EventLoop;
|
||||
import edu.wpi.first.wpilibj.livewindow.LiveWindow;
|
||||
import edu.wpi.first.wpilibj2.command.button.Trigger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
@@ -64,8 +66,9 @@ public final class CommandScheduler implements NTSendable, AutoCloseable {
|
||||
// as a list of currently-registered subsystems.
|
||||
private final Map<Subsystem, Command> m_subsystems = new LinkedHashMap<>();
|
||||
|
||||
private final EventLoop m_defaultButtonLoop = new EventLoop();
|
||||
// The set of currently-registered buttons that will be polled every iteration.
|
||||
private final Collection<Runnable> m_buttons = new LinkedHashSet<>();
|
||||
private EventLoop m_activeButtonLoop = m_defaultButtonLoop;
|
||||
|
||||
private boolean m_disabled;
|
||||
|
||||
@@ -114,18 +117,53 @@ public final class CommandScheduler implements NTSendable, AutoCloseable {
|
||||
LiveWindow.setDisabledListener(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the default button poll.
|
||||
*
|
||||
* @return a reference to the default {@link EventLoop} object polling buttons.
|
||||
*/
|
||||
public EventLoop getDefaultButtonLoop() {
|
||||
return m_defaultButtonLoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the active button poll.
|
||||
*
|
||||
* @return a reference to the current {@link EventLoop} object polling buttons.
|
||||
*/
|
||||
public EventLoop getActiveButtonLoop() {
|
||||
return m_activeButtonLoop;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace the button poll with another one.
|
||||
*
|
||||
* @param loop the new button polling loop object.
|
||||
*/
|
||||
public void setActiveButtonLoop(EventLoop loop) {
|
||||
m_activeButtonLoop =
|
||||
requireNonNullParam(loop, "loop", "CommandScheduler" + ".replaceButtonEventLoop");
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a button binding to the scheduler, which will be polled to schedule commands.
|
||||
*
|
||||
* @param button The button to add
|
||||
* @deprecated Use {@link Trigger}
|
||||
*/
|
||||
@Deprecated(since = "2023")
|
||||
public void addButton(Runnable button) {
|
||||
m_buttons.add(button);
|
||||
m_activeButtonLoop.bind(() -> true, button);
|
||||
}
|
||||
|
||||
/** Removes all button bindings from the scheduler. */
|
||||
/**
|
||||
* Removes all button bindings from the scheduler.
|
||||
*
|
||||
* @deprecated call {@link EventLoop#clear()} on {@link #getActiveButtonLoop()} directly instead.
|
||||
*/
|
||||
@Deprecated(since = "2023")
|
||||
public void clearButtons() {
|
||||
m_buttons.clear();
|
||||
m_activeButtonLoop.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,10 +292,11 @@ public final class CommandScheduler implements NTSendable, AutoCloseable {
|
||||
m_watchdog.addEpoch(subsystem.getClass().getSimpleName() + ".periodic()");
|
||||
}
|
||||
|
||||
// Cache the active instance to avoid concurrency problems if setActiveLoop() is called from
|
||||
// inside the button bindings.
|
||||
EventLoop loopCache = m_activeButtonLoop;
|
||||
// Poll buttons for new commands to add.
|
||||
for (Runnable button : m_buttons) {
|
||||
button.run();
|
||||
}
|
||||
loopCache.poll();
|
||||
m_watchdog.addEpoch("buttons.run()");
|
||||
|
||||
m_inRunLoop = true;
|
||||
|
||||
@@ -20,9 +20,11 @@ import java.util.function.BooleanSupplier;
|
||||
*/
|
||||
public class Button extends Trigger {
|
||||
/**
|
||||
* Default constructor; creates a button that is never pressed (unless {@link Button#get()} is
|
||||
* overridden).
|
||||
* Default constructor; creates a button that is never pressed.
|
||||
*
|
||||
* @deprecated Replace with {@code new Button(() -> false) }.
|
||||
*/
|
||||
@Deprecated(since = "2023")
|
||||
public Button() {}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
package edu.wpi.first.wpilibj2.command.button;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
/**
|
||||
* This class is intended to be used within a program. The programmer can manually set its value.
|
||||
* Also includes a setting for whether or not it should invert its value.
|
||||
@@ -11,8 +13,9 @@ package edu.wpi.first.wpilibj2.command.button;
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
public class InternalButton extends Button {
|
||||
private boolean m_pressed;
|
||||
private boolean m_inverted;
|
||||
// need to be references, so they can be mutated after being captured in the constructor.
|
||||
private final AtomicBoolean m_pressed;
|
||||
private final AtomicBoolean m_inverted;
|
||||
|
||||
/** Creates an InternalButton that is not inverted. */
|
||||
public InternalButton() {
|
||||
@@ -26,19 +29,24 @@ public class InternalButton extends Button {
|
||||
* when set to false.
|
||||
*/
|
||||
public InternalButton(boolean inverted) {
|
||||
m_pressed = m_inverted = inverted;
|
||||
this(new AtomicBoolean(), new AtomicBoolean(inverted));
|
||||
}
|
||||
|
||||
/*
|
||||
* Mock constructor so the AtomicBoolean objects can be constructed before the super
|
||||
* constructor invocation.
|
||||
*/
|
||||
private InternalButton(AtomicBoolean state, AtomicBoolean inverted) {
|
||||
super(() -> state.get() != inverted.get());
|
||||
this.m_pressed = state;
|
||||
this.m_inverted = inverted;
|
||||
}
|
||||
|
||||
public void setInverted(boolean inverted) {
|
||||
m_inverted = inverted;
|
||||
m_inverted.set(inverted);
|
||||
}
|
||||
|
||||
public void setPressed(boolean pressed) {
|
||||
m_pressed = pressed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get() {
|
||||
return m_pressed ^ m_inverted;
|
||||
m_pressed.set(pressed);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,9 +14,6 @@ import edu.wpi.first.wpilibj.GenericHID;
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
public class JoystickButton extends Button {
|
||||
private final GenericHID m_joystick;
|
||||
private final int m_buttonNumber;
|
||||
|
||||
/**
|
||||
* Creates a joystick button for triggering commands.
|
||||
*
|
||||
@@ -24,19 +21,7 @@ public class JoystickButton extends Button {
|
||||
* @param buttonNumber The button number (see {@link GenericHID#getRawButton(int) }
|
||||
*/
|
||||
public JoystickButton(GenericHID joystick, int buttonNumber) {
|
||||
super(() -> joystick.getRawButton(buttonNumber));
|
||||
requireNonNullParam(joystick, "joystick", "JoystickButton");
|
||||
|
||||
m_joystick = joystick;
|
||||
m_buttonNumber = buttonNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the value of the joystick button.
|
||||
*
|
||||
* @return The value of the joystick button
|
||||
*/
|
||||
@Override
|
||||
public boolean get() {
|
||||
return m_joystick.getRawButton(m_buttonNumber);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@
|
||||
|
||||
package edu.wpi.first.wpilibj2.command.button;
|
||||
|
||||
import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam;
|
||||
|
||||
import edu.wpi.first.networktables.NetworkTable;
|
||||
import edu.wpi.first.networktables.NetworkTableEntry;
|
||||
import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
@@ -14,15 +16,14 @@ import edu.wpi.first.networktables.NetworkTableInstance;
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
public class NetworkButton extends Button {
|
||||
private final NetworkTableEntry m_entry;
|
||||
|
||||
/**
|
||||
* Creates a NetworkButton that commands can be bound to.
|
||||
*
|
||||
* @param entry The entry that is the value.
|
||||
*/
|
||||
public NetworkButton(NetworkTableEntry entry) {
|
||||
m_entry = entry;
|
||||
super(() -> entry.getInstance().isConnected() && entry.getBoolean(false));
|
||||
requireNonNullParam(entry, "entry", "NetworkButton");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -44,9 +45,4 @@ public class NetworkButton extends Button {
|
||||
public NetworkButton(String table, String field) {
|
||||
this(NetworkTableInstance.getDefault().getTable(table), field);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean get() {
|
||||
return m_entry.getInstance().isConnected() && m_entry.getBoolean(false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,10 +14,6 @@ import edu.wpi.first.wpilibj.GenericHID;
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
public class POVButton extends Button {
|
||||
private final GenericHID m_joystick;
|
||||
private final int m_angle;
|
||||
private final int m_povNumber;
|
||||
|
||||
/**
|
||||
* Creates a POV button for triggering commands.
|
||||
*
|
||||
@@ -26,11 +22,8 @@ public class POVButton extends Button {
|
||||
* @param povNumber The POV number (see {@link GenericHID#getPOV(int)})
|
||||
*/
|
||||
public POVButton(GenericHID joystick, int angle, int povNumber) {
|
||||
super(() -> joystick.getPOV(povNumber) == angle);
|
||||
requireNonNullParam(joystick, "joystick", "POVButton");
|
||||
|
||||
m_joystick = joystick;
|
||||
m_angle = angle;
|
||||
m_povNumber = povNumber;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,14 +35,4 @@ public class POVButton extends Button {
|
||||
public POVButton(GenericHID joystick, int angle) {
|
||||
this(joystick, angle, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the current value of the POV is the target angle.
|
||||
*
|
||||
* @return Whether the value of the POV matches the target angle
|
||||
*/
|
||||
@Override
|
||||
public boolean get() {
|
||||
return m_joystick.getPOV(m_povNumber) == m_angle;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,43 +7,58 @@ package edu.wpi.first.wpilibj2.command.button;
|
||||
import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam;
|
||||
|
||||
import edu.wpi.first.math.filter.Debouncer;
|
||||
import edu.wpi.first.wpilibj.event.BooleanEvent;
|
||||
import edu.wpi.first.wpilibj.event.EventLoop;
|
||||
import edu.wpi.first.wpilibj2.command.Command;
|
||||
import edu.wpi.first.wpilibj2.command.CommandScheduler;
|
||||
import edu.wpi.first.wpilibj2.command.InstantCommand;
|
||||
import edu.wpi.first.wpilibj2.command.Subsystem;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.BooleanSupplier;
|
||||
|
||||
/**
|
||||
* This class provides an easy way to link commands to inputs.
|
||||
*
|
||||
* <p>It is very easy to link a button to a command. For instance, you could link the trigger button
|
||||
* of a joystick to a "score" command.
|
||||
*
|
||||
* <p>It is encouraged that teams write a subclass of Trigger if they want to have something unusual
|
||||
* (for instance, if they want to react to the user holding a button while the robot is reading a
|
||||
* certain sensor input). For this, they only have to write the {@link Trigger#get()} method to get
|
||||
* the full functionality of the Trigger class.
|
||||
* This class is a wrapper around {@link BooleanEvent}, providing an easy way to link commands to
|
||||
* digital inputs.
|
||||
*
|
||||
* <p>This class is provided by the NewCommands VendorDep
|
||||
*/
|
||||
public class Trigger implements BooleanSupplier {
|
||||
private final BooleanSupplier m_isActive;
|
||||
|
||||
public class Trigger extends BooleanEvent {
|
||||
/**
|
||||
* Creates a new trigger with the given condition determining whether it is active.
|
||||
* Creates a new trigger with the given condition/digital signal.
|
||||
*
|
||||
* @param isActive returns whether or not the trigger should be active
|
||||
* @param loop the loop that polls this trigger
|
||||
* @param signal the digital signal represented.
|
||||
*/
|
||||
public Trigger(BooleanSupplier isActive) {
|
||||
m_isActive = isActive;
|
||||
public Trigger(EventLoop loop, BooleanSupplier signal) {
|
||||
super(loop, signal);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new trigger that is always inactive. Useful only as a no-arg constructor for
|
||||
* subclasses that will be overriding {@link Trigger#get()} anyway.
|
||||
* Copies the BooleanEvent into a Trigger object.
|
||||
*
|
||||
* @param toCast the BooleanEvent
|
||||
* @return a Trigger wrapping the given BooleanEvent
|
||||
* @see BooleanEvent#castTo(BiFunction)
|
||||
*/
|
||||
public static Trigger cast(BooleanEvent toCast) {
|
||||
return toCast.castTo(Trigger::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new trigger with the given condition/digital signal.
|
||||
*
|
||||
* <p>Polled by the {@link CommandScheduler#getDefaultButtonLoop() default scheduler button loop}.
|
||||
*
|
||||
* @param signal the digital signal represented.
|
||||
*/
|
||||
public Trigger(BooleanSupplier signal) {
|
||||
this(CommandScheduler.getInstance().getDefaultButtonLoop(), signal);
|
||||
}
|
||||
|
||||
/** Creates a new trigger that is always inactive. */
|
||||
@Deprecated
|
||||
public Trigger() {
|
||||
m_isActive = () -> false;
|
||||
this(() -> false);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -54,23 +69,11 @@ public class Trigger implements BooleanSupplier {
|
||||
* <p>Functionally identical to {@link Trigger#getAsBoolean()}.
|
||||
*
|
||||
* @return whether or not the trigger condition is active.
|
||||
* @deprecated use {@link #getAsBoolean()}
|
||||
*/
|
||||
public boolean get() {
|
||||
return m_isActive.getAsBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the trigger is active.
|
||||
*
|
||||
* <p>This method will be called repeatedly a command is linked to the Trigger.
|
||||
*
|
||||
* <p>Functionally identical to {@link Trigger#get()}.
|
||||
*
|
||||
* @return whether or not the trigger condition is active.
|
||||
*/
|
||||
@Override
|
||||
public final boolean getAsBoolean() {
|
||||
return this.get();
|
||||
@Deprecated
|
||||
public final boolean get() {
|
||||
return getAsBoolean();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,23 +86,7 @@ public class Trigger implements BooleanSupplier {
|
||||
public Trigger whenActive(final Command command, boolean interruptible) {
|
||||
requireNonNullParam(command, "command", "whenActive");
|
||||
|
||||
CommandScheduler.getInstance()
|
||||
.addButton(
|
||||
new Runnable() {
|
||||
private boolean m_pressedLast = get();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean pressed = get();
|
||||
|
||||
if (!m_pressedLast && pressed) {
|
||||
command.schedule(interruptible);
|
||||
}
|
||||
|
||||
m_pressedLast = pressed;
|
||||
}
|
||||
});
|
||||
|
||||
this.rising().ifHigh(() -> command.schedule(interruptible));
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -138,24 +125,9 @@ public class Trigger implements BooleanSupplier {
|
||||
public Trigger whileActiveContinuous(final Command command, boolean interruptible) {
|
||||
requireNonNullParam(command, "command", "whileActiveContinuous");
|
||||
|
||||
CommandScheduler.getInstance()
|
||||
.addButton(
|
||||
new Runnable() {
|
||||
private boolean m_pressedLast = get();
|
||||
this.ifHigh(() -> command.schedule(interruptible));
|
||||
this.falling().ifHigh(command::cancel);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean pressed = get();
|
||||
|
||||
if (pressed) {
|
||||
command.schedule(interruptible);
|
||||
} else if (m_pressedLast) {
|
||||
command.cancel();
|
||||
}
|
||||
|
||||
m_pressedLast = pressed;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -163,7 +135,7 @@ public class Trigger implements BooleanSupplier {
|
||||
* Constantly starts the given command while the button is held.
|
||||
*
|
||||
* <p>{@link Command#schedule(boolean)} will be called repeatedly while the trigger is active, and
|
||||
* will be canceled when the trigger becomes inactive. The command is set to be interruptible.
|
||||
* will be canceled when the trigger becomes inactive.
|
||||
*
|
||||
* @param command the command to start
|
||||
* @return this trigger, so calls can be chained
|
||||
@@ -194,24 +166,9 @@ public class Trigger implements BooleanSupplier {
|
||||
public Trigger whileActiveOnce(final Command command, boolean interruptible) {
|
||||
requireNonNullParam(command, "command", "whileActiveOnce");
|
||||
|
||||
CommandScheduler.getInstance()
|
||||
.addButton(
|
||||
new Runnable() {
|
||||
private boolean m_pressedLast = get();
|
||||
this.rising().ifHigh(() -> command.schedule(interruptible));
|
||||
this.falling().ifHigh(command::cancel);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean pressed = get();
|
||||
|
||||
if (!m_pressedLast && pressed) {
|
||||
command.schedule(interruptible);
|
||||
} else if (m_pressedLast && !pressed) {
|
||||
command.cancel();
|
||||
}
|
||||
|
||||
m_pressedLast = pressed;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -236,22 +193,8 @@ public class Trigger implements BooleanSupplier {
|
||||
public Trigger whenInactive(final Command command, boolean interruptible) {
|
||||
requireNonNullParam(command, "command", "whenInactive");
|
||||
|
||||
CommandScheduler.getInstance()
|
||||
.addButton(
|
||||
new Runnable() {
|
||||
private boolean m_pressedLast = get();
|
||||
this.falling().ifHigh(() -> command.schedule(interruptible));
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean pressed = get();
|
||||
|
||||
if (m_pressedLast && !pressed) {
|
||||
command.schedule(interruptible);
|
||||
}
|
||||
|
||||
m_pressedLast = pressed;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -286,26 +229,16 @@ public class Trigger implements BooleanSupplier {
|
||||
public Trigger toggleWhenActive(final Command command, boolean interruptible) {
|
||||
requireNonNullParam(command, "command", "toggleWhenActive");
|
||||
|
||||
CommandScheduler.getInstance()
|
||||
.addButton(
|
||||
new Runnable() {
|
||||
private boolean m_pressedLast = get();
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean pressed = get();
|
||||
|
||||
if (!m_pressedLast && pressed) {
|
||||
if (command.isScheduled()) {
|
||||
command.cancel();
|
||||
} else {
|
||||
command.schedule(interruptible);
|
||||
}
|
||||
}
|
||||
|
||||
m_pressedLast = pressed;
|
||||
this.rising()
|
||||
.ifHigh(
|
||||
() -> {
|
||||
if (command.isScheduled()) {
|
||||
command.cancel();
|
||||
} else {
|
||||
command.schedule(interruptible);
|
||||
}
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -328,85 +261,45 @@ public class Trigger implements BooleanSupplier {
|
||||
public Trigger cancelWhenActive(final Command command) {
|
||||
requireNonNullParam(command, "command", "cancelWhenActive");
|
||||
|
||||
CommandScheduler.getInstance()
|
||||
.addButton(
|
||||
new Runnable() {
|
||||
private boolean m_pressedLast = get();
|
||||
this.rising().ifHigh(command::cancel);
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
boolean pressed = get();
|
||||
|
||||
if (!m_pressedLast && pressed) {
|
||||
command.cancel();
|
||||
}
|
||||
|
||||
m_pressedLast = pressed;
|
||||
}
|
||||
});
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes this trigger with a boolean supplier, returning a new trigger that is active when both
|
||||
* triggers are active.
|
||||
*
|
||||
* @param booleanSupplier the boolean supplier to compose with
|
||||
* @return the trigger that is active when both triggers are active
|
||||
*/
|
||||
public Trigger and(BooleanSupplier booleanSupplier) {
|
||||
return new Trigger(() -> get() && booleanSupplier.getAsBoolean());
|
||||
/* ----------- Super method type redeclarations ----------------- */
|
||||
|
||||
@Override
|
||||
public Trigger and(BooleanSupplier trigger) {
|
||||
return cast(super.and(trigger));
|
||||
}
|
||||
|
||||
/**
|
||||
* Composes this trigger with a boolean supplier, returning a new trigger that is active when
|
||||
* either trigger is active.
|
||||
*
|
||||
* @param booleanSupplier the boolean supplier to compose with
|
||||
* @return the trigger that is active when either trigger is active
|
||||
*/
|
||||
public Trigger or(BooleanSupplier booleanSupplier) {
|
||||
return new Trigger(() -> get() || booleanSupplier.getAsBoolean());
|
||||
@Override
|
||||
public Trigger or(BooleanSupplier trigger) {
|
||||
return cast(super.or(trigger));
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new trigger that is active when this trigger is inactive, i.e. that acts as the
|
||||
* negation of this trigger.
|
||||
*
|
||||
* @return the negated trigger
|
||||
*/
|
||||
@Override
|
||||
public Trigger negate() {
|
||||
return new Trigger(() -> !get());
|
||||
return cast(super.negate());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new debounced trigger from this trigger - it will become active when this trigger has
|
||||
* been active for longer than the specified period.
|
||||
*
|
||||
* @param seconds The debounce period.
|
||||
* @return The debounced trigger (rising edges debounced only)
|
||||
*/
|
||||
@Override
|
||||
public Trigger debounce(double seconds) {
|
||||
return debounce(seconds, Debouncer.DebounceType.kRising);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new debounced trigger from this trigger - it will become active when this trigger has
|
||||
* been active for longer than the specified period.
|
||||
*
|
||||
* @param seconds The debounce period.
|
||||
* @param type The debounce type.
|
||||
* @return The debounced trigger.
|
||||
*/
|
||||
@Override
|
||||
public Trigger debounce(double seconds, Debouncer.DebounceType type) {
|
||||
return new Trigger(
|
||||
new BooleanSupplier() {
|
||||
Debouncer m_debouncer = new Debouncer(seconds, type);
|
||||
return cast(super.debounce(seconds, type));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
return m_debouncer.calculate(get());
|
||||
}
|
||||
});
|
||||
@Override
|
||||
public Trigger rising() {
|
||||
return cast(super.rising());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger falling() {
|
||||
return cast(super.falling());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user