Idea on coding Multi Button Commands

Hi all,

I was currently looking for the most efficient was to code a duel button command. Essentially we only want the command to run when both A and Left Bumper is pressed.

As far as i understand, buttons need to have a command to run when pressed so a simple if a and lbumper pressed wouldn’t work, so my solution was to create a command that checks if L Bumper is pressed and runs the desired action, and this command is ran when triangle is pressed. However I feel that this is probably incredibly inefficient.

I have yet to even test if the code works due to time constraints, but I was hoping someone could provide some insight into a possibly more efficient way to do this. (Maybe a way to have a button press return a true input)

Thanks!

Code (look in robot file and within right and left climbing mechanisms):

If it works it works, efficiency isn’t nearly as important as functionality and readability when it comes to FRC code.

The way I would personally implement this is by checking one of the buttons in the command itself. It doesn’t seem very elegant but just wrapping each method in the command like:

public void execute() {
  if (controller.btn_a.get() {
    thing.do();
  }
}
2 Likes

See if this helps at all: https://github.com/frc-862/lightning/blob/develop/src/main/java/com/lightningrobotics/common/util/operator/trigger/TwoButtonTrigger.java

3 Likes

This is a far more elegant solution

aButton.and(leftBumper).whenActive(new FooCommand());
15 Likes

And this is even more elegant (ours was old school)

2 Likes

Second this solution from Oblarg. We used this extensively in 2020 to combine JoystickButtons and Triggers from our Subsystem’s Sensors. We had three digital output IR Reflection Sensors along our intake/shooter assembly and used those along with button inputs to automatically control our intake and conveyor motors to ensure we had a gap between balls when indexing.

ie.

// Intake
intakeButton.and(finalConveyorDetector.or(launcherConveyorDetector).negate())
    .whileActiveContinuous(new IntakeBallIntake(ballIntake));

// Conveyor
intakeButton.and(initialConveyorDetector.or(finalConveyorDetector).and(launcherConveyorDetector.negate()))
    .whileActiveContinuous(new AdvanceConveyor(conveyor));
1 Like

Can you provide any detail on the implementation of the triggers (initialConveyorDetector)?

Exactly as shown on the inline+lambda “Creating Your Own Custom Trigger” example in the documentation Oblarg linked:

// Internal Robot Triggers
Trigger initialConveyorDetector = new Trigger(() -> conveyor.getInitialConveyorSensor());
Trigger finalConveyorDetector = new Trigger(() -> conveyor.getFinalConveyorSensor());
Trigger launcherConveyorDetector = new Trigger(() -> conveyor.getLauncherConveyorSensor());
Trigger launcherOnTarget = new Trigger(() -> launcher.isOnTargetAverage(7));
3 Likes

Cool that helps me. For some reason I thought that would cause some sort of issue because that doesn’t require the subsystem. But since it is just checking sensors maybe it is fine.

They’re programmed as read-only operation so its perfectly safe. If you were gonna have the subsystem actually “do” something when you checked the sensor that may be another matter.

1 Like

Oh, similarly I used this to bind commands to the POV Hat Buttons on an XBox Controller. And you could do similar for using the Analog Triggers.

Button povButton = new Button(()->m_operatorController.getPOV() == 90);
1 Like

Not applicable to analog devices, but for POV. WPILib has a POVButton (Javadoc) class that makes this a bit easier

Ah cool. I’d missed that one.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.