Schedule Command in End of Command

Scheduling a command in the End() method of the current command causes an endless loop calling End() of the same command repeatedly.

How should one command schedule another command following the current command. Note that a command group is not feasible as the first command has to be cancelled (by the driver) in order to stop. That is there is not an automatic IsFinished() on the first command.

The first command constructs the following command in it’s constructor. Then calls mCommand.Schedule() in the End() method of the first command.

Please share your code.

What action is the driver performing to cancel the first command? Can you make that action schedule the second command?

We are using ToggleWhenPressed on a Joystick button. So the first press starts the command and the second press cancels the command. Pretty convenient.

Other suggestions?

Still interested why scheduling a command is an endless loop.

I knew that would be the first response, because I would ask the same thing.

Unfortunately, there’s about 20 files involved. :slightly_frowning_face:

There’s combinations of parallel and sequential group commands.

The key element is calling Command::Schedule from End() of a different command causes the End() of the current command to be repeatedly called.

It sounds like you’re setting up a toggle switch so one command or the other is always running. This should work if you made the “second command” the default command for the subsystem. It will run whenever the other isn’t.

Added: I believe end() is being called repeatedly because starting the second command cancels whatever command is already using any of the subsystems needed, which is - your first.

Nailed it. Making the second command the default would also be a possible solution.

Cancelling is different than exiting normally.

Cancelling calls End() which schedules another command which calls End() … forever.

We can break the loop in End by flagging that we’ve already ended. I bit of a hack but not horrible.

None of these fit the bill for what you are trying to do?

Based on your short description whenFinished() is what you are trying to have happen.

Perhaps. However, WhenFinished() would have to schedule a new command to be run.

It seems that scheduling a new command might not be supported in this context.

Also, it’s not terribly clear how to use WhenFinished (in C++).

button.WhenPressed(command.WhenFinished([] { std::cout << "hello"; }));

What is command? Where is the actual command?

I’ll read more to try to decipher this example.

I spoke before testing. While the first command ends, the robot crashes before the second (end) command is run. There’s clearly a data structure out of sorts (invalid iterator).

We’re trying the default command solution as well as WhenFinished decorator.

Thank you for the suggestions.

With regard to the decorators (e.g. WhenFinished(), which is not actually implemented :frowning:),

The decorators are just returning a convenient SequentialCommand. Cancelling the command is still going to cancel the entire sequential list of commands. We want to cancel the current running command and then complete with some additional commands.

1 Like

Any reference to WhenFinished in the docs is in error; it has been renamed to AndThen.

You can also set a SelectCommand to be the default command, and then it is a bit more organized.