Newbie to Java: Subsystems and Sensors

First year java team, so be kind.

So this is what I understand about subsystems. You put methods in subsystems that you can call from robotcontainer. For instance, you can create an ‘intakeDown’ method, a ‘runIntakeForward’ method, and a ‘homeIntake’ command. Then, in Robot Container, you would bind these three methods to a button press, like:

IntakeDown - lowers the intake to a set position
runIntakeFoward - runs the intake forward
homeIntake - a runonce method that homes the intake and stops the rollers when the button is released

Pseudocode in Robot Container
whileTrue runIntakeForward and intakeDown else homeIntake

So, first I’d like to know - are we structuring this in a standard, or best practice manner?

Next, we have a question about sensors. We have various sensors. Let’s consider an encoder that gives us shooter position. We need to use this sensor in both the shooter subsystem to verify the shooter is in the right position, AND in the intake subsystem to make sure the shoot and the intake never occupy the same physical space.

I assume best practice is to create a class that contains all my sensors, then somehow pull their values from the class into a subsystem. But I’m at a bit of a loss what the best way is to do that.

Can someone point the way? Thanks!

2 Likes

A couple good resources:

We use the subsystems as hardware abstraction and commands as orchestration. So, the subsystems provide access to the sensors, motors, etc. with simple methods like “deployIntake()”. However, we use commands to actually “command” the subsystem to do something or inquiry the state of a subsystem (such as sensor value, current shooter speed, etc.) and then do something.

In the robotcontainer you map the commands to joysticks, etc.

So, you are real close! :slight_smile:

1 Like

Thanks! That first link had some very helpful info written at the level we’re at right now.

What I’m still a little confused on is how to pass the sensor values around to be used in my different subsystems.

For intance, my ‘lowerIntake’ command needs to check that the shooter is in a clear position.

How does the lowerIntake subsystem communicate with the shooter subsystem, and how do both get the necessary sensor info?

1 Like

Another question.

If I need to perform sequential operations like a state machine, do I create that state machine in robot container?

Write your commands as factory methods in the subsystem and you can capture them from the enclosing scope.

If you need sensor input from multiple subsystems, then the command should be defined at a scope where both subsystems are visible (eg RobotContainer) or else the sensor state needs to be plumbed some other way.

Only if it requires access to multiple subsystems. Otherwise, keep it in the scope of a single subsystem.

2 Likes

So… some people will hate this but…

What we do is have all of the subsystems be public on the RobotContainer class so all commands will be able to check the sensors, etc. on all subsystems. IMHO this just makes everything a lot simpler for students learning programming.

This would look somthing like:
RobotContainer.m_shooter.isClear();

Example from last year… Our grabber would grab cone when the sensor triggered.

But depending on what you are doing would probably want to compose a command group something like…
Command deployIntake = new WaitShooterToClear().andThen(new DeployIntake());

and you would create your WaitShooterToClear() command to not finish until the sensor said it was clear… once that command ends it does the next command which would deploy the intake.

(My syntax is probably off some, but should be close!)

Whut? pseudocode example maybe?

In the body of any sort of command like this, we can “capture” state from the enclosing subsystem.

class MySubsystem {
  CANSparkMax mySparkMax = ...;

  public Command getDoSomething(double speed) {
    return run(() -> {
      mySparkMax.set(speed);
    });
  }
}

SUUUUPER contrived, but this shows the capturing that I believe @Oblarg was referring to. In essence, you return your “command” inline instead of a separate class, and it will allow it to directly use objects scoped to the subsystem class

Edit: sniped…

1 Like

This only works if you make all your subsystems static. An alternative is just passing the robot into every subsystem/command. That’s what we did.

1 Like

Commands can require multiple subsystems. I would make a command to control the entire gamepiece handling pathway, which takes the intake, shooter, and presumably loader/indexer subsystems. Then, the command can provide the interlock of only allowing lowerIntake to be called when the encoder is at the right place.

1 Like