You are using while loops in some of the methods in your DriveTrain subsystem that run for an unknown amount of time. While those loops are running, nothing else will respond.
For a command based robot, you don’t really want to be doing any while loops or sleeps. Try to keep your subsystems very simple, move the smarts to your commands and avoid loops and sleeps/delays. I would suggest the following as a starting point on refactoring:
- After constructing your Encoders, use the setDistancePerPulse() method so you can use the getDistance() method to retrieve a value in inches.
- Add methods to your drive system so you can read the distance in inches on each encoder.
- Refactor your DriveEncoders command so that it: reads the current encoder starting position in the initialize() method, applies power to the motors in the execute() method and checks to see if the robot has gone far enough in the isFinished() method.
This won’t be an ideal way to drive autonomously (it won’t stop on a dime and will likely veer some), but it should be enough that you should be able to cross a line.
Example of setting distance per pulse on encoders (in your RobotMap.java):
// This looks like the value you provided that converts inches to counts
// on your encoder, use it in the setDistancePerPulse() invocation
int tinch = 76;
encoderRight = new Encoder(0, 1, true, Encoder.EncodingType.k4X);
encoderRight.setPIDSourceType(PIDSourceType.kDisplacement);
encoderRight.setDistancePerPulse(1.0 / tinch);
// encoderRight.reset();
encoderLeft = new Encoder(2, 3, false, Encoder.EncodingType.k4X);
encoderLeft.setPIDSourceType(PIDSourceType.kDisplacement);
encoderLeft.setDistancePerPulse(1.0 / tinch);
Here is an example of two methods to add to your DriveTrain subsystem that return the distance values from the encoders:
/**
* Returns distance traveled by left side of drive train since reset.
*
* @return Distance traveled in inches.
*/
public double getLeftDistance() {
// NOTE: Assumes that when you constructed your encoder, you
// used the setDistancePerPulse() so that it returns the distance
// in inches.
return RobotMap.encoderLeft.getDistance();
}
/**
* Returns distance traveled by right side of drive train since reset.
*
* @return Distance traveled in inches.
*/
public double getRightDistance() {
// NOTE: Assumes that when you constructed your encoder, you
// used the setDistancePerPulse() so that it returns the distance
// in inches.
return RobotMap.encoderRight.getDistance();
}
Here is a refactored version of your DriveEncoders class that applies power to both motors until the distance driven by the left side exceeds a specified amount (NOTE: This is a fairly crude way to do it, but it will probably do what you want and can at least serve as a starting point).
public class DriveEncoders extends Command {
private int driveDistance;
private double botSpeed;
private double endDistance;
public DriveEncoders(double speed, int userFeet, int userInches) {
// Use requires() here to declare subsystem dependencies
// eg. requires(chassis);
requires(Robot.driveTrain);
driveDistance = userInches + (12 * userFeet);
botSpeed = speed;
}
// Called just before this Command runs the first time
protected void initialize() {
// When this command is started, determine how far we want to drive
endDistance = Robot.driveTrain.getLeftDistance() + driveDistance;
}
// Called repeatedly when this Command is scheduled to run
protected void execute() {
// Apply power to drive straight
Robot.driveTrain.arcadeDrive(botSpeed, 0);
}
// Make this return true when this Command no longer needs to run execute()
protected boolean isFinished() {
// Stop once we've moved to or past the end distance
return (Robot.driveTrain.getLeftDistance() >= endDistance);
}
// Called once after isFinished returns true
protected void end() {
Robot.driveTrain.stop();
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
protected void interrupted() {
// We will be paranoid and do the same clean up if we are interrupted
end();
}
}