Hey,
Requiring more than one subsystem in one command would work, as the code will compile and run without errors. However, that seems bad, as it would break the single responsibility principle because it would mean that one command changes the state of more than one subsystem.
There seems to be a solution for that, with making a few commands, each of them does one thing, then combining them inside a command group.
What do you think? Is using more than one subsystem for one command encouraged?
Using more than one subsystem in a command is not encouraged. Instead, as you mentioned, you should use a command group.
Ooh, I love programming philosophy.
First of all, (maybe this is the EE in me) I don’t think pursuing a single design philosophy to the nth degree is worthwhile. When you start making compromises in functionality and ease of coding to fit into a design philosophy, it stops being worth your time. For example, when you have to shoehorn something like this into OOP, sure you’re following the design philosophy, but it’s not as practical as cheating. Pure OO is incredibly and verbose and rigid IMO, which is why I think lots of languages that are ostensibly OO have functional elements (All of Python, recent Java lambdas, etc)
Second of all, in a way you are still controlling each functionality individually in that each subsystem can be owned be only one command at a time. It’s just different in that where this responsibility ends up changes based on where the program is at the operating point. You could argue that this isn’t truly single responsibility, at which point I would direct you back to my first point, “So what?”
It also depends on how much the two subsystems have to interact in order to achieve your ends. If the subsystems’ interaction is loose enough that it can be decomposed into parallel tracks of single-subsystem commands, then yes, command group is the way to go for the reasons stated. Most drive train + 1 manipulator combinations can be done this way.
However, if you were trying (for example) to lift a single large game piece using two independent lift devices (which operate independently for other tasks) and keep it level as you did, it would likely be cleaner to have one command which manipulates both subsystems through method calls than through constantly instantiating commands or using shared variables.
Yup.
Sometimes the right thing to do is one command with a state machine controlling multiple systems. There are times when an elevator should be fairly low while the drive train is scooting around the countryside, then raise when the robot is in a different motion profile.
This should be avoided as a general principle, but general principles should be abandoned as soon as they stop serving to make your job easier.
Sometimes, you want finer control over the interaction between two subsystems than is easily possible through a control group. In such a case, there is nothing wrong with a two-subsystem command.
^^ This. Note that commands should use always methods of the subsystem to control the subsystem, and not “reach in” and (for example) directly tell the motor controllers what to do. That is, use elevator.upslow() or elevator.up(0.5), not liftTalon.set(0.5). This helps reduce the amount of code which must change if (when) the hardware changes - you should only have to modify the subsystem.
This is ESPECIALLY important for commands which utilize multiple subsystems.