Subsystem used Asynchronously

We have an ActiveSubsystem and two buttons—one for activating a solenoid to grab the power cube and another button to pull the power cube in.

The problem is these two commands both require ActiveSubsystem (even though hardware used does not overlap). What is the best way to solve this?

Here are my ideas:

  1. Do not use require()
  2. Separate ActiveSubsystem into a multiple Subsytems

What do you recommend?

Additionally, this leads to the question: when should requires() be used and when should it not?

Or this:

  1. Do not use require()
  2. Separate ActiveSubsystem into a multiple Subsytems
  3. Make the subsystem control both in unison from a single command.

Option 1. is a very bad idea, it defies the principal of commands becoming inactive (automatically…) as other commands start (via OI-trigger code…).

Option 2. can work perfectly well, but then depending on how the driver/control is supposed to be used you might find that that you always need ‘parallel’ command groups or logic to provide other synchronization.

Option 3. means that you have the ability to very simply automate some type of synchronization - one command to one subsystem like you described - i.e. if motor is on then solenoid is off, if motor is off (0…) then solenoid is back on. (BTW this option still doesn’t limit you to a single command for the subsystem, it just means still only one command active at a time).

In this case, it probably makes more sense to separate into multiple subsystems. If you don’t use require(), you lose the functionality of having commands interrupt each other.

WaitCommand requires nothing because it controlls nothing.

When you use CommandGroup & ConditionalCommand (or subclass these. ) you don’t need to write requires statements, because the sequential & parallel & iftrue components get required by the these owner-commands.

Nearly everything else probably needs a requires statements.

The consensus I see is that multiple subsystems should be used. However, wouldn’t this create code clog?

For example: if there are 3 buttons which control either the left active wheel, right active wheel, or active rotation, this would require 3 subsystems (1 subsystem per talon). If this were done throughout the whole codebase, there would be quite a few subsystems.

That isn’t the consesus that I meant to imply.

‘chassis’ is typically going to be a single subsystem with 2, 3, or 4 motor-controllers. it will typically have public methods very similar Differential-drive or to Mechanum-drive. – and 2 or 3 commands will control based on tele-joystick mode vs auto-PID mode (perhaps 2 separate commands) vs perhaps vision-mode. (in this case the subsystem can just own/manage one ‘drive’ variable rather than 2 or 4 controllers…).

The other example I was thinking of …based on your ‘activating a solenoid’ & ‘pulling in cube’ comments (you didn’t describe how your solenoid/motors work together)… , is if a ‘system’ has for example has a motor and a pneumatic brake - where the brake needs to be on whenever the motor is stopped, and vic-a-versa.

I believe the intent of a subsystem is to represent a physical system that serves one core purpose (e.g. driving, holding something, intaking, etc.), and a physical system that can only do one task at once.

If you want two tasks done in parallel from one “subsystem”, there’s plenty of ways to change your code to make this happen, but from a semantics perspective I suggest you consider some things.

Are the two “parallel tasks” really one task? If you want to complete some action (say picking up a cube), do you need to use these two tasks in parallel/close to it for it to work properly? If you can’t have one without the other (most/all of the time you’re doing this task), then I suggest you make it one command that uses two actuators.

If you do the two tasks separately more often than together, than I suggest making them separate subsystems.

Motors are used to bring the cube into the active intake, while the pneumatics are used to hold onto the cube as it is brought up in an elevator. Also, I do not understand what you mean by “‘drive’ variable.”

“‘drive’ variable.” My mistake. I mistook active wheel comments and rotate as references to drive-wheels and chassis.

Still the same idea can apply - just as you can have one command control via Robot.chassis.tankDrive(…) you can use a single command for a similar control such as Robot.intake.activeDrive(leftspeed, rightspeed);

Keep in mind too, that just because buttons can start commands via whenpressed/whileheld this doesn’t mean that a command cannot be active and reading getRawButton status values within execute(){}.

Better, to avoid the word drive…
Robot.intake.cubecontrol(leftspeed, rightspeed);
Robot.intake.cubecontrol(leftspeed, rightspeed, bPistonExtend);
or similar. Such an action could be done entirely from a single default-command. Then alternative non-button-variations of this as an autonomous command.

I reread you intake design again…

I still wouldn’t call this a consensus. Yes one-talon-per-subsystem adds to a subsystems count, but it certainly isn’t too many for the RIO to handle if it makes sense for them to each operate independently. Your solenoid can still be kept separate or combined into this.

Still not clear to me what the ‘active-rotation’ controller does, and when… but IMHO a command with 3-button-states into-3-speed-parameters is better than avoidance of requires.

So what I’ve shown is how this can be controlled in unison, if that is as logical to you for your 3 talons within autonomous AND within teleOP, then it is feasible to keep this as a single subsystem.

First things first: You shouldn’t be doing anything to avoid requires, the whole point of requires is to protect your own flow control from breaking your stuff.

If you are having trouble doing multiple command actions without having requires step on each other and interrupt the other…this is a code smell indicator that things are not designed intuitively. So, the question then becomes “How do I fix this?”

We break our subsystems into chunks of sensors and actuators that can be operated both autonomously and in teleop. In your particular case stated above, you have two discrete actions with two sets of different sensors and actuators. If you split this code into an Intake Subsystem, and an Elevator Subsystem then you find that you will be able to bring in a cube as you wish, either manually or autonomously, and then once the sensors in your Intake Subsystem have indicated that you have successfully grabbed the cube, the Elevator Subsystem can fire and complete the task of lifting the cube. The first step of which would be fire the actuators to grab the cube.