I created a Drive1 command class as follows:
public class Drive1 extends Command {
public Drive1() {
// Use requires() here to declare subsystem dependencies
// eg. requires(chassis);
requires(Robot.driveTrain);
// BEGIN AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=REQUIRES
// END AUTOGENERATED CODE, SOURCE=ROBOTBUILDER ID=REQUIRES
}
private Timer timer;
private boolean running;
// Called just before this Command runs the first time
protected void initialize() {
timer.start();
timer.reset();
}
// Called repeatedly when this Command is scheduled to run
protected void execute() {
if (running != true) {
running = true;
timer.reset() ;
}
Robot.driveTrain.runMotor1( 0.5 );
}
// Make this return true when this Command no longer needs to run execute()
protected boolean isFinished() {
return timer.get() > 3.0e6;
}
// Called once after isFinished returns true
protected void end() {
Robot.driveTrain.runMotor1( 0 );
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
protected void interrupted() {
end();
}
I would expect this command to run the motor connected to jaguar1 for 3 seconds at half speed. It’s not doing anything.
I put numerous System.out.println calls throughout my code to try to see what’s happening. Maybe some of this is my lack of java proficiency, but I’m having trouble understanding how this is behaving.
In my Oi constructor, I have the following:
joystickButton2 = new JoystickButton(joystick1, 2);
joystickButton2.whenPressed(new Drive1());
I expected this to construct a new Drive1() command when button2 on joystick1 is pressed. My printlns indicate that the constructor of Drive1 is being called in Disabled mode. I would not have expected this constructor to be called until the button was pressed.
Any thoughts?
The next thing I did was to construct a Drive1() command in the disabledInit() method. I expected this to construct a Drive1 command. In any case, how does this newly constructed command become runnable? Do I have to do anything else to make it’s execute() method get called on every iteration?
I noticed that you never initialize the running variable in your code, that might cause some problems. Commands have a built-in timeout mechanism for doing tasks like the one you’re trying to do. So you can run a motor for half speed for 3 seconds like this:
public class Drive1 extends Command {
public Drive1() {
requires(Robot.driveTrain);
setTimeout(3); // 3 second timeout for the command
}
protected void initialize() {
Robot.driveTrain.runMotor(0.5); // start the motor running 1/2 speed
}
protected void execute() { // motor is already running, so nothing here
}
protected boolean isFinished() {
return isTimedOut(); // wait for 3 seconds to run out
}
protected void end() {
Robot.driveTrain.runMotor1(0.0); // stop the motor on the timeout
}
protected void interrupted() {
end(); // this is here in case the command is interrupted
}
}
All the RobotBuilder comments are removed for clarity - keep them in if you intend to keep using RobotBuilder.
This code:
joystickButton2 = new JoystickButton(joystick1, 2);
joystickButton2.whenPressed(new Drive1());
will create the Drive1 command when THIS code is executed, but it won’t be SCHEDULED until the button is pressed. And this is the correct way of doing it. Otherwise, the command would be created every time the button is pressed and that would be not make the memory allocator happy.
Brad
Thanks for the response. I apologize, but I guess I’m still missing something. I put a println in the initialize() method, but it’s not getting called. I was expecting initialize() to be called when a command is constructed. It appears that this is not the case.
What do I have to do to get the initialize() method to be called?
The initialize() method is called when the command is scheduled. So in your case, when the button is pressed, the command should be scheduled and the initialize() method will be called once. Then the command will loop between the isFinished() and exectute().
To get the scheduler to run it needs to be called repeatedly. The idea is to put a Scheduler.run() into the AutonomousPeriodic() and TeleopPeriodic() methods. This causes it to run every 20ms (once for each driver station data update). Each call to run() will do these things:
- look for buttons that are pressed or released and schedule commands dependent on them
- for each of the newly scheduled commands: call the initialize() method
- for each of the running commands: call the execute() method, then the isFinished() method. These are just run one after another for each command.
So it’s important to not do any delays or long loops in any of the commands methods or it will cause the other commands to not run or have an unpredictable schedule.
So, the bottom line, make sure you have something like this:
public void autonomousPeriodic() {
Scheduler.getInstance().run();
}
public void teleopPeriodic() {
Scheduler.getInstance().run();
}
If you use RobotBuilder to generate the program code, it will automatically insert this code for you. Otherwise you need to be sure to do it yourself.
Brad