Skip to content

Command that can interrupt itself #7896

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
DJ-Laser opened this issue Apr 10, 2025 · 3 comments
Open

Command that can interrupt itself #7896

DJ-Laser opened this issue Apr 10, 2025 · 3 comments
Labels
type: feature Brand new functionality, features, pages, workflows, endpoints, etc.

Comments

@DJ-Laser
Copy link

DJ-Laser commented Apr 10, 2025

Is your feature request related to a problem? Please describe.
This season my team and I decided to implement complex sequences, such as aligning and scoring and bind them to button on the driver's controller. There work great until a part of the robot gets unintentionally stuck on the reef. The driver suggested that pressing the button again would rerun the sequence, but since it never finished due to waiting for the robot to reach a position, pressing the button again simply does nothing as the command is already running.

Describe the solution you'd like
A new enum option in InterruptionBehavior or separate enum that can be set to make the CommandScheduler restart the command if it is scheduled while already active.

Describe alternatives you've considered
I've taken to using this ugly pattern to schedule a new instance of the same command logic, but it seems like code smell to me, and is not the best in terms of gc.

public Command scoreCancelSelf() {
    return Commands.defer(
        () -> new ScheduleCommand(score()),
        Set.of());
  }

Additional context
Another fun snippet:

mainController
        .povLeft()
        .onTrue(Commands.defer(() -> new ScheduleCommand(s.intake.toggleDeploy()), Set.of()));

This one allows the driver to interrupt the command that moves and homes the intake

@DJ-Laser DJ-Laser added the type: feature Brand new functionality, features, pages, workflows, endpoints, etc. label Apr 10, 2025
@KangarooKoala
Copy link
Contributor

KangarooKoala commented Apr 10, 2025

A slightly more performant and cleaner way to do this is the following:

mainController
        .povLeft()
        .onTrue(
                Commands
                        .runOnce(() -> CommandScheduler.getInstance().schedule(s.intake.toggleDeploy()))
                        .withName("Schedule toggle deploy"));

It does the same thing (create and schedule the command every time the button is pressed and finish instantly), but does the scheduling directly instead of via another command.

That said, this button is unlikely to be pressed more than once a second, so worrying about a few more allocations per button press is almost certainly a premature optimization.

Your code instincts are spot on though! This is definitely a code smell, and I 100% agree that it'd be nice to be able to specify if a command can interrupt itself. (My team ran into the same issue)

@WispySparks
Copy link
Contributor

My team also ran into the same issue, implementing something similar to choosing which command to do on the same button press depending on current state and then manually scheduling it

@HarryXChen3
Copy link
Contributor

HarryXChen3 commented Apr 11, 2025

Also hit this one today, after thinking about it some more and with some input from @KangarooKoala (thanks!) I settled with this:

final Command command = doSomething();
trigger
        .onTrue(Commands.runOnce(() -> {
            command.cancel();
            command.schedule();
        }));

It avoids recreation and will always re-schedule the command, so I think its a decent workaround for now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type: feature Brand new functionality, features, pages, workflows, endpoints, etc.
Projects
None yet
Development

No branches or pull requests

4 participants