Path Completion
Understanding when paths end and how to control completion behavior
How Path Completion Works
A path is considered "complete" when the robot reaches the endpoint within specified tolerances. Understanding completion criteria is crucial for reliable autonomous routines.
Completion Tolerances
// In RobotConfig - set how close is "close enough"
public static FollowerConstants followerConstants = new FollowerConstants()
.completionTolerances(
2.0, // X tolerance: within 2 inches
2.0, // Y tolerance: within 2 inches
Math.toRadians(5) // Heading tolerance: within 5°
);
// Path completes when robot is within ALL three tolerancesChoosing Tolerances:
- Tight tolerances (0.5-1 inch): Precise scoring, takes longer to complete
- Medium tolerances (2-3 inches): Balanced, good for most use cases
- Loose tolerances (4-6 inches): Fast transitions, less accurate
- Heading tolerance: Usually 2-10° depending on task requirements
Checking Path Status
// Standard path following loop
while (!follower.isPathComplete() && opModeIsActive()) {
robot.update();
follower.update();
robot.setDrivePowers(follower.getMotorPowers());
// Optional: monitor progress
telemetry.addData("Path Progress", "%.1f%%", follower.getPathProgress() * 100);
telemetry.addData("Distance to End", follower.getDistanceToEnd());
telemetry.update();
}
// When loop exits, path is complete!
telemetry.addLine("✓ Path Complete");Path End Callbacks
Execute Code on Path Completion:
Path pathWithEndAction = new BezierLine(new Point(48, 0, Point.CARTESIAN))
.setConstantHeadingInterpolation(0)
.setPathEndCallback(() -> {
// Automatically called when path completes
telemetry.addLine("Arrived at destination!");
intake.setPower(0);
arm.setTargetPosition(SCORE_POSITION);
});
// No need to manually check completion for callbacksCallback vs. Manual Actions:
- Callbacks: Execute automatically, cleaner code, no manual checking
- Manual (after loop): More control, easier to debug, explicit flow
- Both work - choose based on preference and complexity
Timeout Handling
Preventing Infinite Loops:
// Add timeout safety to prevent getting stuck
ElapsedTime timer = new ElapsedTime();
double timeoutSeconds = 5.0;
follower.followPath(/* ... */);
while (!follower.isPathComplete() && opModeIsActive() && timer.seconds() < timeoutSeconds) {
robot.update();
follower.update();
robot.setDrivePowers(follower.getMotorPowers());
}
if (timer.seconds() >= timeoutSeconds) {
telemetry.addLine("⚠ Path timeout - continuing anyway");
// Continue with autonomous (degraded but functional)
} else {
telemetry.addLine("✓ Path completed successfully");
}Multi-Path Completion
Chained Paths Complete Sequentially:
follower.followPath(
path1, // Completes when within tolerances
path2, // Then automatically starts
path3 // Then this one
);
// Single loop waits for ALL paths to complete
while (!follower.isPathComplete() && opModeIsActive()) {
robot.update();
follower.update();
robot.setDrivePowers(follower.getMotorPowers());
// Check which segment is running
int currentSegment = follower.getCurrentPathIndex();
telemetry.addData("Path Segment", "%d / 3", currentSegment + 1);
}
// All three paths are now completeEarly Termination
Stopping Paths Before Completion:
// Stop path if condition met
while (!follower.isPathComplete() && opModeIsActive()) {
robot.update();
follower.update();
// Emergency stop condition
if (gamepad1.b || visionDetectsObstacle()) {
follower.stopPath(); // Immediately halt
break;
}
robot.setDrivePowers(follower.getMotorPowers());
}
// Resume with new path or handle abort
if (follower.isPathComplete()) {
// Normal completion
} else {
// Early termination - recovery logic
telemetry.addLine("Path aborted - taking evasive action");
}Practical Example
RobustAutonomous.java
@Autonomous
public class RobustAutonomous extends LinearOpMode {
Robot robot;
Follower follower;
ElapsedTime timer = new ElapsedTime();
@Override
public void runOpMode() {
robot = new Robot(hardwareMap, RobotConfig.class);
robot.initializeLocalizer(hardwareMap);
follower = new Follower(hardwareMap);
waitForStart();
// Path with completion callback
follower.followPath(
new BezierLine(new Point(30, 0, Point.CARTESIAN))
.setConstantHeadingInterpolation(0)
.setPathEndCallback(() -> {
telemetry.addLine("✓ Reached spike mark");
releasePixel();
})
);
// Execute with timeout safety
timer.reset();
while (!follower.isPathComplete() && opModeIsActive() && timer.seconds() < 3.0) {
robot.update();
follower.update();
robot.setDrivePowers(follower.getMotorPowers());
// Real-time monitoring
telemetry.addData("Progress", "%.0f%%", follower.getPathProgress() * 100);
telemetry.addData("Distance Remaining", "%.1f in", follower.getDistanceToEnd());
telemetry.addData("Time Elapsed", "%.1f s", timer.seconds());
telemetry.update();
}
// Verify completion
if (follower.isPathComplete()) {
telemetry.addLine("✓ Path 1 Complete");
} else {
telemetry.addLine("⚠ Path 1 Timeout");
}
// Continue with autonomous...
}
}Completion Tips
💡 Tune Tolerances for Your Robot
Well-tuned PID allows tighter tolerances. If robot can't consistently reach 1-inch tolerance, either improve PID or use 2-3 inch tolerance.
💡 Always Use Timeouts
A robot stuck trying to complete an impossible path wastes the entire autonomous period. Timeouts ensure the routine continues even if one path fails.
💡 Log Completion Status
Add telemetry showing which paths completed vs. timed out. Helps identify problem paths during testing.