PathPlanner: Visual Autonomous Routines
What is PathPlanner?
PathPlanner is a motion profile generator and autonomous path planning tool for FRC robots. It allows you to draw paths on a field map, configure robot constraints (max velocity, acceleration), and automatically generate smooth trajectories. It integrates seamlessly with WPILib via PathPlannerLib to follow these paths in code.
The modern workflow uses AutoBuilder, which automatically generates commands to follow paths and trigger event markers (like “Intake” or “Shoot”) defined in the GUI.
Learn more: PathPlanner Documentation | PathPlannerLib API
Key Concepts
Path: A single trajectory from point A to point B, with waypoints and rotation targets. (PathPlannerPath API)
Auto: A full autonomous routine consisting of multiple paths and commands (e.g., “Score -> Taxi -> Balance”).
Event Markers: Triggers placed along a path that execute commands (like running an intake) when the robot reaches that point. (NamedCommands API)
Holonomic Mode: For swerve/mecanum drives, allows the robot to rotate independently of its movement direction.
AutoBuilder: A utility that builds a full “Command” from a PathPlanner file, handling path following, event markers, and telemetry automatically. (AutoBuilder API)
Configuring AutoBuilder
To use PathPlanner, you must configure AutoBuilder in your “RobotContainer” or “Drivetrain” subsystem. This tells PathPlanner how to control your robot and where it is. See AutoBuilder Configuration Documentation.
AutoBuilder Configuration (Swerve)
Current PathPlannerLib uses AutoBuilder.configure() with a PPHolonomicDriveController and a RobotConfig describing the drivetrain’s physical properties. Older guides show configureHolonomic() with HolonomicPathFollowerConfig and ReplanningConfig — those types no longer exist.
import com.pathplanner.lib.auto.AutoBuilder;
import com.pathplanner.lib.config.ModuleConfig;
import com.pathplanner.lib.config.PIDConstants;
import com.pathplanner.lib.config.RobotConfig;
import com.pathplanner.lib.controllers.PPHolonomicDriveController;
import com.pathplanner.lib.pathfinding.Pathfinding;
public class Drive extends SubsystemBase {
// Physical description of the robot, used for PathPlanner's feedforward
private static final RobotConfig PP_CONFIG = new RobotConfig(
PathPlannerConstants.ROBOT_MASS_KG, // total robot mass, kg
PathPlannerConstants.ROBOT_MOI, // moment of inertia, kg*m^2
new ModuleConfig(
TunerConstants.FrontLeft.WheelRadius,
TunerConstants.kSpeedAt12Volts.in(MetersPerSecond),
PathPlannerConstants.WHEEL_COF, // wheel coefficient of friction
DCMotor.getKrakenX60(1)
.withReduction(TunerConstants.FrontLeft.DriveMotorGearRatio),
TunerConstants.FrontLeft.SlipCurrent,
1), // motors per module
getModuleTranslations());
public Drive(/* ... */) {
// ... hardware init ...
// API: AutoBuilder.configure() - https://pathplanner.dev/api/java/com/pathplanner/lib/auto/AutoBuilder.html
AutoBuilder.configure(
this::getPose, // Supplier<Pose2d> current robot pose
this::setPose, // Consumer<Pose2d> reset the pose
this::getChassisSpeeds, // Supplier<ChassisSpeeds> robot-relative speeds
this::runVelocity, // Consumer<ChassisSpeeds> output for driving
new PPHolonomicDriveController(
new PIDConstants(5.0, 0.0, 0.0), // Translation PID
new PIDConstants(5.0, 0.0, 0.0)), // Rotation PID
PP_CONFIG,
// Flip the path for the red alliance. The origin stays on the blue side.
() -> DriverStation.getAlliance().orElse(Alliance.Blue) == Alliance.Red,
this // Reference to this subsystem to set requirements
);
}
}
Keep RobotConfig honest
RobotConfig is how PathPlanner predicts what the robot will do. Mass, moment of inertia, and wheel coefficient of friction all feed its feedforward.
A mass left over from last season’s robot produces consistent tracking error on every path — and it looks exactly like badly tuned PID, so teams often spend a practice session tuning gains to compensate for a wrong number. Update it when the robot’s weight changes.
Warmup and Pathfinding
Two additions worth making once the basics work.
Warmup. The first path of autonomous otherwise pays a one-time class-loading cost while the match clock is running. Schedule the warmup commands at startup to pay it before the match instead:
// In the Robot constructor
FollowPathCommand.warmupCommand().schedule();
PathfindingCommand.warmupCommand().schedule();
Pathfinding with AdvantageKit. PathPlanner’s default pathfinder runs on a background thread, which makes log replay non-deterministic. Teams using AdvantageKit swap in a logged wrapper:
Pathfinding.setPathfinder(new LocalADStarAK());
LocalADStarAK routes the pathfinder’s results through the logger so a replay follows the same path the robot did. It is a single file, published by PathPlanner’s author — see the gist.
You can also log the active path and target pose so they appear in AdvantageScope:
PathPlannerLogging.setLogActivePathCallback(
(activePath) -> Logger.recordOutput("Odometry/Trajectory", activePath.toArray(new Pose2d[0])));
PathPlannerLogging.setLogTargetPoseCallback(
(targetPose) -> Logger.recordOutput("Odometry/TrajectorySetpoint", targetPose));
Creating and Running Paths
Once configured, you can load paths or full autos by name. PathPlanner files are deployed to the robot’s “deploy/pathplanner” directory.
Loading Paths
// In RobotContainer.java
// API: AutoBuilder.buildAuto() - https://pathplanner.dev/api/java/com/pathplanner/lib/auto/AutoBuilder.html#buildAuto(java.lang.String)
// Build an auto command from a named "Auto" file in the GUI
Command myAuto = AutoBuilder.buildAuto("My Two Piece Auto");
// API: AutoBuilder.followPath() - https://pathplanner.dev/api/java/com/pathplanner/lib/auto/AutoBuilder.html#followPath(com.pathplanner.lib.path.PathPlannerPath)
// API: PathPlannerPath.fromPathFile() - https://pathplanner.dev/api/java/com/pathplanner/lib/path/PathPlannerPath.html#fromPathFile(java.lang.String)
// Or, follow a single path
Command followPath = AutoBuilder.followPath(PathPlannerPath.fromPathFile("Taxi Path"));
// API: AutoBuilder.buildAutoChooser() - https://pathplanner.dev/api/java/com/pathplanner/lib/auto/AutoBuilder.html#buildAutoChooser()
// Add to SmartDashboard chooser
SendableChooser<Command> autoChooser = AutoBuilder.buildAutoChooser();
SmartDashboard.putData("Auto Chooser", autoChooser);
Event Markers and Named Commands
To use Event Markers, you must register your commands with NamedCommands before building the auto. This maps the string names in the PathPlanner GUI to actual Java commands. See Event Markers Documentation.
Registering Named Commands
import com.pathplanner.lib.auto.NamedCommands;
import edu.wpi.first.wpilibj2.command.InstantCommand;
public class RobotContainer {
public RobotContainer() {
// API: NamedCommands.registerCommand() - https://pathplanner.dev/api/java/com/pathplanner/lib/auto/NamedCommands.html#registerCommand(java.lang.String,edu.wpi.first.wpilibj2.command.Command)
// Register Named Commands
NamedCommands.registerCommand("intake", new IntakeCommand(m_intake));
NamedCommands.registerCommand("shoot", new ShootCommand(m_shooter));
NamedCommands.registerCommand("stop", new InstantCommand(m_intake::stop, m_intake));
// Now build the auto
autoChooser = AutoBuilder.buildAutoChooser();
}
}
PathPlanner Tips
Best practices for success:
- Always measure your robot’s max velocity and acceleration accurately.
- Use ‘On-the-fly’ generation for dynamic pathing if needed, but pre-generated paths are safer.
- Visualize path following in AdvantageScope or Field2d to debug tracking errors.
- Remember to register NamedCommands before building the auto chooser.
- Schedule the warmup commands at startup so the first path does not stutter.
- Keep the robot mass in
RobotConfigcurrent.