Command binded to whileHeld gets ran and then immediately, even while holding it

I’m trying to make it so when you hold a button it extends pneumatics then it retracts when you let go. This is my code and it doesn’t work, after testing I found that it is immediately running isFinished().

package frc.robot.commands;

import com.ctre.phoenix.motorcontrol.ControlMode;
import edu.wpi.first.wpilibj.DoubleSolenoid.Value;
//import static edu.wpi.first.wpilibj.DoubleSolenoid.Value.*;
//import edu.wpi.first.wpilibj.PneumaticsModuleType;
//import edu.wpi.first.wpilibj.Compressor;
import edu.wpi.first.wpilibj.command.Command;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
import frc.robot.Robot;
import frc.robot.RobotMap;

public class StartIntake extends Command {
  public StartIntake() {
    // Use requires() here to declare subsystem dependencies
    requires(Robot.intake);
  }

  // Called just before this Command runs the first time
  @Override
  protected void initialize() {
    SmartDashboard.putBoolean("reversed", false);
    RobotMap.pneumaticDoubleSolenoid.set(Value.kForward);
    RobotMap.timeSinceStartedBeingReleasedForSolenoids = System.currentTimeMillis();
    RobotMap.IntakeMotor1.set(ControlMode.PercentOutput, .8);
  }

  // Called repeatedly when this Command is scheduled to run
  @Override
  protected void execute() {

  }

  // Make this return true when this Command no longer needs to run execute()
  @Override
  protected boolean isFinished() {
    return true;
  }

  // Called once after isFinished returns true
  @Override
  protected void end() {
    SmartDashboard.putBoolean("reversed", true);
    RobotMap.IntakeMotor1.set(ControlMode.PercentOutput, 0.0);
    RobotMap.timeSinceStartedBeingReleasedForSolenoids = -1;
    RobotMap.pneumaticDoubleSolenoid.set(Value.kReverse);
  }

  // Called when another command which requires one or more of the same
  // subsystems is scheduled to run
  @Override
  protected void interrupted() {
  }

}// class

I don’t think you want it to immediately finish based on what you describe, but your isFinished returns true.

1 Like

I thought isFinished gets called repeatedly after execute finishes?

It does. The execution path for what you have there should be:

  1. initialize
  2. execute
  3. isFinished
  4. end

So the end result is that your solenoid is commanded out then back in the same program loop.

What you’re likely looking for is 2 separate commands tied to whenPressed and whenReleased (I think those are the names… going from memory)

2 Likes

Is finished is a method used by the scheduler every time it runs to determine when the command should be unscheduled. When the method returns true, the command ends. WhileHeld ends the command when the button is released. So leave isFinished as return true, and it should work.

I believe WhileHeld will actually reschedule a command after it ends, which is why return true works that way. WhenPressed will schedule a command exactly once on button press and whenever it ends, it ends. WhenReleased using a command that requires the same subsystem will interrupt the other one if it hasn’t already ended.

We have had good success running shooters only when a button is pressed by making it a whileheld command and isFinished being false. If it reschedules on release, that is a bug and should be reported to WPILib.

There are a few way to approach this.

#1 you should Set the isFinnished to return False in the extend command.

Then use your whileHeld. Whit this the initialize() will execute once then the execute() will run every 20ms. Finnaly when you release the button the end() method will run.

OR

Use whenPressed to call the Extend command then whenReleased to call the Retract command. The Retract command could be an instant command (That is what you had programed above)

4 Likes

Correct. The downside of option 1 is that your intake can no longer run any other commands (think running rollers/wheels) due to the requires(…). This is why I generally recommend the pressed/released approach

Fully agree, I suspect the best approach here would be to create a few simple commands for each actuator or subsystem, then group them up in a paralleCommanGroup

1 Like

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.