Problem: Encoder Controlled Movement Not Working.

Hi,
I’ve been wrestling with this issue for an entire day now. When I try to run a method that just moves the robot forward a given number of feet based off of encoder values, the robot moves the same (roughly 6 inch) distance, regardless of what is passed to it. and then stops. What’s more, the command doesn’t end, and regular controls are only restored after canceling the command via SmartDashboard. We are using CAN Talon SRX’s, Talon Magnetic Encoders, and Java (Command Based). On our system, the Magnetic Encoders return values in full rotations. Originally, the command used PID, but the issue persisted even since I’ve simplified to just compare encoder values to a target while in motion. If anyone has any solution to this, or can spot my mistake, I’d really appreciate it.

Code:

public class DriveForDis extends Command {
double rots;
double feet;

public DriveForDis(double feet) {
    // Use requires() here to declare subsystem dependencies
    requires(Robot.driveTrain);
    this.feet = feet;
    
}
// Called just before this Command runs the first time
protected void initialize() {
	Robot.driveTrain.reset();
	rots = feet*.64;
	Robot.driveTrain.driveSet(-1, 1);
	
	 
}

// Called repeatedly when this Command is scheduled to run
protected void execute() {
	SmartDashboard.putNumber("rots", Robot.driveTrain.motorL1.getPosition());
	
}

// Make this return true when this Command no longer needs to run execute()
protected boolean isFinished() {
	if(Math.abs(Robot.driveTrain.motorL1.getPosition())<rots){
		return false;
	} else {
		return true;
	}
	
}

// Called once after isFinished returns true
protected void end() {
	Robot.driveTrain.driveSet(0);
	
}

// Called when another command which requires one or more of the same
// subsystems is scheduled to run
protected void interrupted() {
	Robot.driveTrain.driveSet(0);
}

}

We had the same problems. It was working fine until we updated WPIlib and the encoders stopped working. I am thinking it is a problem with the update.

The readings from the encoders are actually fine, it’s just that both them and the motors stop driving after half a rotation. Thanks for the reply, though!

Without all of your code I might be wrong, but I would guess that you are not setting your motors to a speed often enough. They are timing out, which is why they stop, but your command is still running. I would change execute to read:


protected void execute() {
SmartDashboard.putNumber("rots", Robot.driveTrain.motorL1.getPosition());
Robot.driveTrain.driveSet(-1, 1);
}

On a separate note, you might also want to slow down your robot.

What Rob Heslin said. The drive train class has motor safety enabled by default. MotorSafety is a background watchdog for your motor controllers. It expects that you’ll be sending a .Set command to the motors once every 100ms (by default). If you don’t send a Set command that often, it assumes something’s gone wrong and disables the motor controller.

Your two options are to do as Rob says and put a .Set call in your execute function for the command, or disable motor safety on the drivetrain by calling .setSafetyEnabled(false) on the drivetrain.

Secondarily, you may want to add timeouts to your Commands. In your constructor, call SetTimeout(seconds) to set a timeout. The timer starts automatically with the Command. Then call isTimedOut() as part of your isFinished. In your case you could change “return false” to “return isTimedOut()” and that’d take care of it.

Thank you VERY much! Not sure how I didn’t see it before! My team will be glad to know we’ll be able to have an Autonomous program this year! :slight_smile:

So my team is having the same problem, but my team is using Iterative Robot base. So I was wondering how we could fix the issue in the iterative setup, because the solutions I have seen so far only fix command based code. Thank You

ItsTheAce, iterative is the same thing. If you have the Safety enabled, just ensure that the Drive.set() command is invoked at least once every 100ms (or more specifically, with less than a 100ms gap between invocations) while the robot is enabled.

Specifically, for the SampleRobot base class, you should have a loop with a delay in it inside your Autonomous and OperatorControl methods; inside that loop, set the output for the drive motors at least once, and you should be fine.