Updating gyro angle in autonomous using Timer.delay()

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.

(Disclaimer, we are using iterative robot code)

Our autonomous program resets and starts the timer during autoInit. This should always reset the timer to read 0.00 whenever autonomous runs.

In auto, we just create a variable that is equal to the value of timer.get(), and have an if structure to move the program forward as time progresses.

So you use java’s timer class instead of WPILib’s, and it’s that simple?

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
}

etc

If you use Zuelu562’s code, be sure to start the timer:

autoTimer.Start()

For a 4 second auto routine split into two 2 second intervals in Iterative robot, it’ll look something like this:


...
...
...

Timer timer = new Timer();

autonomousInit() {
    timer.start();
}

autonomousPeriodic () {
    double time = timer.get();
    if(time <= 2.0) {
        Do something
    else if(time <= 4.0) {
        Do something else
    } else {
        Stop stuff
    }
}

disabledInit() {
    timer.stop():
    timer.reset();
}

...
...
...