After our first event, Gaylord FIM District, I found a mistake that I completely over looked going into the event. I completely forgot that Timer.delay() will pause the thread, therefore my variable at the top of the method (angle = gyro.getAngle() * RobotMap.KP (or 0.05), only updates once before autonomous, and the robot will not drive straight. Or robot drove very lopsided during autonomous. After realizing that gears in autonomous are extremely important (lost our 1st semi-final match because we didn’t get the first rotor turning in auto), I’m now going to write autons to place gears on any peg. I have vision working for high goals, and I planned on trying this using only a gyro and without vision since there’s a large margin of error for placing the gear, and we don’t have much time, but I digress.
I’m wondering how I could use time based control to maneuver the robot, without using Timer.delay()'s pausing the thread. I’ve looked into Timer.getMatchTime(), but it says it returns an approximate value, which does not seem reliable to me.
If you are using a Command Based framework you can use a TimedCommand. I would personally recommend encoders and a regular command.
For example, this is our command for moving a (straight*) distance in auto:
*The straightness is implemented in the driveBase subsystem because we use it in teleop as well
public class AutoMove extends Command {
private int target;
private double absolute_target;
private DriveBase driveBase = Robot.driveBase;
public AutoMove( int encoderCounts ) {
// Use requires() here to declare subsystem dependencies
// eg. requires(chassis);
target = encoderCounts;
}
// Called just before this Command runs the first time
protected void initialize() {
absolute_target = driveBase.getAverageEncoderCount() + target;
}
// Called repeatedly when this Command is scheduled to run
protected void execute() {
LVDash.setString( 7, String.valueOf( driveBase.getAverageEncoderCount() ) );
if( target > 0 ){
driveBase.driveArcade( -0.5, 0 );
}else{
driveBase.driveArcade( 0.5, 0 );
}
}
// Make this return true when this Command no longer needs to run execute()
protected boolean isFinished() {
return Math.abs( driveBase.getAverageEncoderCount() - this.absolute_target ) < 10;
}
// Called once after isFinished returns true
protected void end() {
driveBase.driveArcade(0, 0);
}
// Called when another command which requires one or more of the same
// subsystems is scheduled to run
protected void interrupted() {
}
}
The WPILib Timer has .get(), it returns a double. We’re storing the value of the .get() each iteration and then our if structure compares the variable to a specific time;
Timer autoTimer;
autoTimer = new Timer();
autoTime = autoTimer.get();
if (autoTime < 2.0){
// run first two seconds
}