Parameters in Command

Is it possible to pass in subsystems as parameters, instead of requiring them?

This is an example of what I want to do that did not work:

package org.usfirst.frc.team3997.robot.auto.actions;

import org.usfirst.frc.team3997.robot.MasterController;
import org.usfirst.frc.team3997.robot.controllers.ArmController;

import edu.wpi.first.wpilibj.command.Command;

public class ScaleAction extends Command {
	private ArmController arm;
	private Boolean setpointReached;
	public ScaleAction(MasterController controllers) {
		arm = controllers.getArmController();
		this.setpointReached = false;
	}

	protected boolean isFinished() {
		// TODO Auto-generated method stub
		return setpointReached;
	}

	protected void execute() {
		if(arm.armPIDController.onTarget()) {
			setpointReached = true;
		} else {
			setpointReached = false;
		}
		
	}

	protected void end() {
		arm.armPIDController.disable();
		
	}

	protected void intialize() {
		arm.goToScalePosition();
	}
	
	protected void interrupt() {
		end();
	}

}

The point of requiring is to prevent multiple commands from using the same subsystem at the same time. In what way did this not work, i.e. did the code crash, did the arm not move?

By the way, Master Controller is just a container class for all the other subsystems.

Here is github link: https://github.com/codeNinjaDev/FRC-2018/tree/feat/commandbasedprototype

I am trying to integrate existing architecture with command, but I am not sure if it is possible.

Sorry, I meant this file:

package org.usfirst.frc.team3997.robot.auto.actions;

import org.usfirst.frc.team3997.robot.MasterController;
import org.usfirst.frc.team3997.robot.controllers.ArmController;

import edu.wpi.first.wpilibj.command.Command;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;

public class SwitchAction extends Command {
	private ArmController arm;
	private Boolean setpointReached;
	public SwitchAction(MasterController controllers) {
		arm = controllers.getArmController();
		this.setpointReached = false;
	}
	@Override
	protected boolean isFinished() {
		// TODO Auto-generated method stub
		return setpointReached;
	}

	@Override
	protected void execute() {
		if(arm.armPIDController.onTarget()) {
			setpointReached = true;
		} else {
			setpointReached = false;
		}
		
	}

	protected void end() {
		arm.armPIDController.disable();
	}

	protected void intialize() {
		arm.goToSwitchPosition();
		SmartDashboard.putString("PID Switch", "RUnning");
	}
	
	protected void interrupt() {
		end();
	}

}
\CODE}

But, yeah nothing moved. 


I used this command in this file: https://github.com/codeNinjaDev/FRC-2018/blob/feat/commandbasedprototype/src/org/usfirst/frc/team3997/robot/auto/routines/OneCubeCenterAutoRoutine.java

And then I set the autonomous in AutoSelector and robotInit.

Thanks for the quick response

Sorry, here is the correct formatting:

package org.usfirst.frc.team3997.robot.auto.actions;

import org.usfirst.frc.team3997.robot.MasterController;
import org.usfirst.frc.team3997.robot.controllers.ArmController;

import edu.wpi.first.wpilibj.command.Command;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;

public class SwitchAction extends Command {
	private ArmController arm;
	private Boolean setpointReached;
	public SwitchAction(MasterController controllers) {
		arm = controllers.getArmController();
		this.setpointReached = false;
	}
	@Override
	protected boolean isFinished() {
		// TODO Auto-generated method stub
		return setpointReached;
	}

	@Override
	protected void execute() {
		if(arm.armPIDController.onTarget()) {
			setpointReached = true;
		} else {
			setpointReached = false;
		}
		
	}

	protected void end() {
		arm.armPIDController.disable();
	}

	protected void intialize() {
		arm.goToSwitchPosition();
		SmartDashboard.putString("PID Switch", "RUnning");
	}
	
	protected void interrupt() {
		end();
	}

}

Could you please expand on that? We really don’t have any way to help you unless we know where the error is coming from. Is the DriverStation printing out any stacktraces? How about the RIOLog inside of Eclipse? Is everything ported correctly? Are your Talons addressed correctly? Does the system work with other code? In order to help you properly we need more information.

Sorry for the confusion,

There were no errors, but the robot did not physically move.

And Teleop works (not using command)

Basically, autonomous is not working, but everything else is

Do other commands work? In Robot.java, the scheduler isn’t called, so I wouldn’t expect any commands to work.

I’m struggling with why you want to structure your code like this. Passing in a subsystem doesn’t seem to add any abstraction or increase the flexibility of your code.

No, other commands don’t work.

I think I call Scheduler on line 153. I’m not very experience with command based.

I just have an irrational dislike of static objects, but I do use them sometimes. A lot like camel case vs underscores. I just want to know if we can pass them in, it is not a deal breaker.

Yes, it is possible to do this. What you are describing is a design pattern called dependency injection, and it is by far the best way (in my opinion) to add flexibility and reusability to the Command-Based paradigm.

It is still good practice to require the subsystem, and you can easily do this by just calling requires() on the passed-in subsystem.

Note that your example code seems to be passing in a much bigger object than what you’re actually using. This is okay in some cases, but is generally inadvisable. You should pass in (or “inject”) only what you need, unless you have a very good reason to do otherwise.

It most certainly does - you simply have to take advantage of some sort of polymorphism in your subsystems (I recommend interfaces, but inheritance can work too). One can use the same “open claw” command on many different types of claws, for example, rather than tediously and messily writing a bunch of nearly-identical commands.

It also, as the OP noted, removes the need for global state, which is basically always a good idea.

But the OPs code doesn’t do this, which is what prompted the question.

Yeah, the reason I used Master controller was to simplify the competition code. Before master controller, I had to pass in 7 params per command plus our architecture was redundant. I just changed the structure to command as an offseason project. But I might individualize the params, now that it is much less redundant.

Thanks your advice