Skip to content

ProgressTracker

The ProgressTracker is a utility class in TurtleTracerLib that tracks the completion percentage of a path or a turning operation. Its primary purpose is to simplify triggering mechanism events (such as moving an arm or spinning an intake) based on how far the robot has traveled along its trajectory.

The tracker monitors robot traversal and evaluates registered events against progress, time, or field position thresholds.

Key features include:

  • Path Progress: Tracks parametric progress along the current curve segment (getPathProgress(), 0.0 to 1.0).
  • Total Progress: Tracks overall completion across the path (getTotalProgress() / getCompletion(), 0.0 to 1.0).
  • Turn Progress: Tracks angular progress during in-place turns.
  • Fluent Events: Register parametric, temporal, and spatial events directly on the tracker.
  • Loop Execution: tracker.update() evaluates and executes events safely during your OpMode loop.

To use ProgressTracker, instantiate it, register events or actions, and call tracker.update() in your OpMode loop.

Create an instance of ProgressTracker, passing it your Follower and the OpMode’s Telemetry.

import com.turtletracerlib.pathing.ProgressTracker;
// ...
public class MyAuto extends OpMode {
private Follower follower;
private ProgressTracker progressTracker;
@Override
public void init() {
follower = new Follower(hardwareMap);
// ...
progressTracker = new ProgressTracker(follower, telemetry);
}
}

Before starting a path or turn, register the events you want to trigger.

// Set the path to follow (Pedro Pathing 3.0 Path)
progressTracker.setCurrentPath(myPath);
// Register an event named "DeployIntake" to trigger halfway through the path (0.5)
progressTracker.registerEvent("DeployIntake", 0.5);
// Start following
follower.follow(myPath);

In your loop(), you can call tracker.update() to evaluate and execute events automatically:

@Override
public void loop() {
follower.update();
progressTracker.update(); // Evaluates and executes registered events safely
}

Or you can manually poll shouldTriggerEvent() for specific events:

@Override
public void loop() {
follower.update();
if (progressTracker.shouldTriggerEvent("DeployIntake")) {
// Option A: Execute code directly here
intake.deploy();
// Option B: If "DeployIntake" is registered in NamedCommands,
// you can use executeEvent() to schedule it automatically
progressTracker.executeEvent("DeployIntake");
}
}

You can attach actions directly to the tracker using fluent event methods:

// Parametric: triggers at 75% along the current curve
progressTracker.onParametric(0.75, () -> intake.start());
// Parametric range: triggers between 30% and 60%
progressTracker.onParametric(0.3, 0.6, () -> lights.blink());
// Path completion: triggers at 80% of total path
progressTracker.onCompletion(0.8, () -> arm.prepareScore());
// Temporal: triggers 500 ms after the path begins
progressTracker.onTemporal(500, () -> arm.lift());
// Spatial: triggers within 2 inches of a target field pose
progressTracker.onSpatial(new Pose(24.0, 48.0, Math.toRadians(90)), 2.0, () -> claw.open());
// Named: maps to markers placed in the Turtle Tracer visualizer
progressTracker.onEvent("IntakeMarker", () -> intake.start());

Event callbacks executed by progressTracker.update() run inside safe exception handling, logging any error to System.err without disrupting the follower.

If you have registered a command with NamedCommands that matches the name of a registered event, calling progressTracker.executeEvent(eventName) will automatically retrieve and run that command.

// Somewhere in your init()
NamedCommands.registerCommand("ScoreSample", () -> scoreSample());
// ... later, setting up a path ...
progressTracker.setCurrentPath(scoringPath);
progressTracker.registerEvent("ScoreSample", 0.9); // Trigger near the end
// ... in your loop() ...
if (progressTracker.shouldTriggerEvent("ScoreSample")) {
progressTracker.executeEvent("ScoreSample");
}

The ProgressTracker also simplifies event triggering during in-place turns.

Use the turn() method on the tracker to start a turn and register an event based on the turn’s completion percentage.

// Turn to 90 degrees (PI/2 radians) and trigger "RaiseLift" when 75% complete
progressTracker.turn(Math.PI / 2, "RaiseLift", 0.75);
// In your loop:
while (opModeIsActive() && progressTracker.isBusy()) {
follower.update();
progressTracker.update();
}

You can read raw progress values directly from the tracker:

// Returns 0.0 to 1.0 for the current individual path segment
double currentSegmentPercent = progressTracker.getPathProgress();
// Returns 0.0 to 1.0 for the entire path
double totalProgress = progressTracker.getTotalProgress();
double completion = progressTracker.getCompletion();

To stop path following or turning:

progressTracker.stop();
// breakFollowing() is supported as an alias
progressTracker.breakFollowing();