Multi Command Auton

So we want to setup a different auton thats decently more advanced than our last. We need to set PID Position, forward while intake, rotate, forward, eject, reverse. I have a command for all of the above I just don’t really know how to compile so many commands into a single auton

So I’m having an error

Your Command’s Constructor wants:
Manipulator, double, double, Indexer, double, Manipulator, double, double, driveTrain, double, double, double

You are passing it:
Manipulator, double, Indexer…

So right there its already different.

Sorry i changed things before sending and didnt fix the second but despite that it still has the issue


image

Same issue… verify that your constructor variables are in the same order and type as what you’re calling.

yea its in the right order its just calling my DoubleSuppliers int

Maybe you could use Singletons for your subsystems? That way you don’t need to pass them in every time. A bit more work but a permanent fix.

A singleton??

Haven’t worked too much with command groups but when I create my commands I always hardcode the values within the command itself so when I call a command it is just like - ShooterOn(); That way it won’t really require any parameters for the command group, but I am not sure how tedious or feasible that is for your setup. Plus I am also curious about what a singleton is so this gets me following the topic

Well, in your screenshot you are using Ints, so if they are DoubleSuppliers in your Command’s Constructor then your types don’t match up.

So might be a dumb question but what exactly is a DoubleSupplier

Honestly not an easy question to answer to someone who isn’t more familiar with some programming concepts.

A DoubleSupplier is a type of lambda function in Java. A Lambda function, also called an “anonymous function” in java is usually used to pass primative type data (int, double, boolean, ect.) that can change dynamically, because the function will be called and thus computed later.

The most common and obvious case for doing this is the Drivetrain. You could just pass in your whole joystick to your Drive command and hard code the command to specific axes, but you really only need a couple of doubles that change over time, and the philosophy is that your command shouldn’t actually care where it comes from. SO instead of passing the WHOLE joystick, you pass a DouleSupplier that will give the Drive Command the values from the appropriate joysticks, or some other source.

ie

m_drivetrain.setDefaultCommand(new ArcadeDrive(m_drivetrain, ()->m_controller.getRawAxis(1), ()->m_controller.getRawAxis(2)));

where the ()-><something that returns a double> bit is functionally a DoubleSupplier. Then when you call the getAsDouble() method of that DoubleSupplier inside the Command it will call the getRawAxis(int) method of your controller and use the value, without having to pass the whole joystick and without the command caring where the value is actually coming from. The Command just knows it has SOMETHING that will give it doubles when it asks.

This is DIFFERENT than just putting

m_drivetrain.setDefaultCommand(new ArcadeDrive(m_drivetrain, m_controller.getRawAxis(1), m_controller.getRawAxis(2)));

because here the getRawAxis methods will get called once when you create the Command object and passed in, and thus won’t change over time.

Now if you want to pass a static value to something asking for a supplier you can do that pretty easily like so:

()->0.5

This is a DoubleSupplier, but it will ALWAYS return 0.5.

2 Likes

Ok yea i see now, so what would i have to put to fix it?

It’s in the WPIlib docs, but the basic idea is that you put a static instance if a class inside of itself to guarantee that there’s only 1 instance of it ever, and that the instance can be accessed using Subsystem.getInstance(). There’s an example in 6619s code here:

And the command that uses it here:

See the WPIlib docs on it for more information. In this example you can see how we don’t need to pass the subsystem into the command - we get it using getInstance().

I just added a little bit to the bottom of my post on the Lambda/DoubleSupplier stuff that may answer that for you

Ok yea that fixed it the () → int. Thanks i wont be able to test the auton till the morning though.

On the note of DoubleSuppliers, may I ask a question. I am trying to pass a distance value between different commands so it can do a bunch of different calculations. I have the varible in my constants as a double. Since it will be changing constantly, should I swap it to a DoubleSupplier? here

Personally I wouldn’t put “Variables” in the “Constants” file at all, but yes, if you have something that is going to change that you want to pass into Commands, and you want the commands to react to it as it changes, you’d want to use Lambdas like so. (fair warning I haven’t tried lambdas using direct variables, but I presume it would work fine)

m_button.whenPressed(new ShooterRPMbyDistance(m_shooter, ()->Constants.distance));

The way I’d do this is I’d put the Limelight in its own Subsystem and put getter methods in it to get the various values you want to pass around and use lambdas/suppliers to send the values to your commands.

ie, something like this in your RobotContainer

Camera m_limelight = new Camera();
Shooter m_shooter = new Shooter();

m_button.whenPressed(new ShooterRPMbyDistance(m_shooter, ()->m_limelight.getDistanceToGoal()));

It might be better to store the distance variable in something like NetworkTables that is meant to be freely accessed?