Timed Movements Approach Lesson

The Timed Movements Approach

The simplest way to create an autonomous routine is by using timed movements. This approach involves telling a mechanism to perform an action for a specific duration, serving as an excellent introduction to commands and command groups.

The Concept: Actions Based on a Clock

The core idea of a timed movement is straightforward: instead of relying on sensor feedback, we use the internal clock on the roboRIO to control how long an action lasts.

  • Instead of "drive forward 36 inches," we say "drive forward at 50% speed for 1.5 seconds."
  • Instead of "turn 90 degrees," we say "turn at 30% speed for 0.8 seconds."

Why This Approach is Unreliable for Competition

While simple, a timed autonomous is susceptible to real-world variations that make it inconsistent:

  • Battery Voltage: A fresh battery delivers more power, meaning "50% speed" will cover more distance than a depleted battery.
  • Field Friction: Variations in the carpet can change how the robot moves.
  • Defense: If another robot bumps us, our robot has no way of knowing it has been pushed off course.

Because of these factors, we almost exclusively use sensor-based control for our competition robots.

Building a Timed Command

Let's create a command that drives the robot forward at a specific speed for a set duration. To do this, we'll use WPILib's built-in `Timer` class.

public class DriveForTime extends Command {
    private final DriveSubsystem m_drive;
    private final double m_speed;
    private final double m_duration;
    private final Timer m_timer = new Timer();

    public DriveForTime(DriveSubsystem drive, double speed, double duration) {
        m_drive = drive;
        m_speed = speed;
        m_duration = duration;
        addRequirements(m_drive);
    }

    @Override
    public void initialize() {
        // Reset and start the timer when the command begins
        m_timer.reset();
        m_timer.start();
        m_drive.setSpeed(m_speed);
    }

    // This is the key: the command is finished when the timer's elapsed
    // time is greater than or equal to the desired duration.
    @Override
    public boolean isFinished() {
        return m_timer.hasElapsed(m_duration);
    }

    @Override
    public void end(boolean interrupted) {
        // Stop the motors when the command ends
        m_drive.stop();
        m_timer.stop();
    }
}
    

Assembling a Timed Autonomous Routine

Now, we can use this reusable `DriveForTime` command to build a simple autonomous routine in `RobotContainer.java` using a `SequentialCommandGroup`.

// In RobotContainer.java
public Command getTimedAuto() {
    // This routine will drive forward for 2 seconds, then turn for 1 second.
    return new SequentialCommandGroup(
        new DriveForTime(m_drivetrain, 0.5, 2.0), // Drive at 50% speed for 2s
        new DriveForTime(m_drivetrain, 0.3, 1.0)  // "Turn" by running one side
    );
}
    

Test Your Knowledge

Question: What is the main reason that timed movements are considered unreliable for high-level FRC competition?