article / 12 min
Compare Choreo and PathPlanner for FRC autonomous trajectories: how Choreo's time-optimal solver differs from PathPlanner's GUI paths, and when to use each.
/ 2,529 words / 8 sections
Every FRC match starts with fifteen seconds where nobody touches a controller. Those autonomous seconds decide a shocking number of matches, and almost all of that scoring comes down to one thing: can your robot drive a planned route accurately and repeatably without a human in the loop? That is the job of a trajectory — a time-parameterized plan of where the robot should be, how fast it should be moving, and which way it should be facing at every instant.
Two tools dominate how modern FRC teams build those trajectories: PathPlanner and Choreo. They solve the same end problem — get a swerve (or tank) drive to follow a smooth, physically achievable route — but they get there from opposite directions. PathPlanner hands you a GUI where you draw waypoints and tune constraints. Choreo asks for your robot's physical limits and a few guide points, then mathematically solves for the fastest trajectory that respects them. This guide breaks down how each works, how they plug into WPILib command-based code and swerve odometry, and how to decide which one (or both) belongs in your codebase.
A trajectory is not just a line on the field. It is a schedule. At t = 0.42 s the robot should be at (3.1 m, 5.4 m), traveling 2.8 m/s at heading 120°, and so on for the whole path. Following it well requires three things working together:
The trajectory tells the robot where it should be; odometry tells it where it is; the controller drives the difference to zero. Weakness in any of the three shows up as a robot that misses its mark. A great trajectory cannot rescue bad odometry.
Both tools generate the file. Both lean on WPILib for the controller. The interesting differences are in how the file gets made and how much of the following logic each tool wraps for you.
PathPlanner, created by Michael Jansen of FRC team 3015, is a standalone GUI plus a vendor library (PathPlannerLib). You place Bezier waypoints on a field image, drag control handles to shape the curve, and set per-path or per-waypoint constraints — max velocity, max acceleration, max angular velocity, and (for swerve) an independent target heading at each point. It supports both holonomic (swerve) and differential (tank) drivetrains.
Three features make it the default choice for many teams:
You configure AutoBuilder once, typically in RobotContainer after subsystems exist, and register any named commands before any auto or path is loaded. This snippet is current for PathPlannerLib 2026:
public RobotContainer() {
// Register named commands BEFORE building any autos/paths.
NamedCommands.registerCommand("shoot", shooter.shootCommand());
NamedCommands.registerCommand("intake", intake.deployCommand());
AutoBuilder.configure(
drivetrain::getPose, // Supplier<Pose2d> from odometry
drivetrain::resetPose, // Consumer<Pose2d> to seed odometry
drivetrain::getRobotRelativeSpeeds, // Supplier<ChassisSpeeds>
(speeds, feedforwards) -> drivetrain.driveRobotRelative(speeds),
new PPHolonomicDriveController( // holonomic controller for swerve
new PIDConstants(5.0, 0.0, 0.0), // translation PID
new PIDConstants(5.0, 0.0, 0.0)), // rotation PID
RobotConfig.fromGUISettings(), // mass, MOI, module config from GUI
() -> DriverStation.getAlliance() // mirror path for red alliance
.orElse(Alliance.Blue) == Alliance.Red,
drivetrain);
// Build a chooser populated with every auto in the project.
autoChooser = AutoBuilder.buildAutoChooser();
SmartDashboard.putData("Auto", autoChooser);
}
From there, new PathPlannerAuto("My Auto") returns a ready-to-schedule command built from a .auto file you assembled in the GUI, and autoChooser.getSelected() gives you the dashboard-selected routine to return from getAutonomousCommand(). Note that RobotConfig.fromGUISettings() pulls your robot's mass, moment of inertia, and module geometry straight from the GUI's settings, so PathPlannerLib can respect swerve dynamics at follow time.
Load paths and autos at startup, not inside
getAutonomousCommand(). Reading and deserializing trajectory files is a blocking operation, and doing it as the match begins can cost you real time on the field.
PathPlanner's standout runtime feature is pathfinding: AutoBuilder.pathfindToPose(...) generates a path to an arbitrary target pose during the match, routing around a set of navigation obstacles using an implementation of the AD* (LocalADStar) search algorithm. This is what powers "drive to the nearest scoring location" style commands where you cannot pre-plan the exact start. Choreo cannot do this — its solver runs offline only.
PathPlanner also ships a version of FRC team 254's SwerveSetpointGenerator, which constrains commanded module setpoints to what the motors can physically deliver given available torque — useful whether or not you use PathPlanner's trajectories.
For a deeper walk-through of the PathPlanner GUI and autos, see the PathPlanner autonomous guide.
Choreo, from the SleipnirGroup, takes a fundamentally different stance. Instead of you drawing a path and hoping the robot can follow it, you specify the robot's physical characteristics — mass, moment of inertia, wheel radius, max motor speed and torque, track dimensions — plus a handful of waypoints and constraints (be at this pose, keep velocity under this value here, stop at the end). Choreo then runs a numerical trajectory optimization (built on the Sleipnir solver) to compute the time-optimal trajectory: the mathematically fastest route that never asks a module to exceed its real limits.
The practical payoff: because the output already respects your drivetrain's dynamics, the robot can usually follow a fresh Choreo trajectory accurately on the first try, with far less of the "generate, test, tweak, repeat" loop that hand-drawn paths often require. Choreo is bundled with the WPILib installer (look for the "Choreo" app in your WPILib Tools folder), so you likely already have it.
The runtime side is ChoreoLib, added as a vendor dependency. For the current season that JSON URL is https://choreo.autos/lib/ChoreoLib2026.json. Choreo deliberately leaves the how you follow a sample step to you — it hands you SwerveSample (or DifferentialSample) objects describing the desired state at each timestep, and you apply them with your own controller. That openness lets you add telemetry hooks or vendor features like CTRE's wheel-force feedforwards.
ChoreoLib's higher-level Java API is the AutoFactory / AutoRoutine system, which layers triggers and command composition on top of trajectory following. You build an AutoFactory once (giving it your pose supplier, an odometry-reset consumer, your follow function, an alliance-mirror flag, and the drive subsystem), then compose routines:
AutoRoutine routine = factory.newRoutine("FourPiece");
AutoTrajectory startToNote = routine.trajectory("StartToNote");
// Reset odometry to the trajectory's start, then drive it.
routine.active().onTrue(
Commands.sequence(startToNote.resetOdometry(), startToNote.cmd()));
// Trigger a command at a named event marker inside the trajectory.
startToNote.atTime("intake").onTrue(intake.deployCommand());
// Chain the next trajectory when this one finishes.
startToNote.done().onTrue(routine.trajectory("NoteToShoot").cmd());
Key AutoTrajectory triggers are active() (while running), done() (one cycle after it finishes), and atTime("marker") / atTime(seconds) for event markers — Choreo's equivalent of PathPlanner's markers. The exact AutoFactory constructor and a couple of helper names have shifted across seasons, so check the ChoreoLib docs for the version you have installed before copying a constructor call.
Load every trajectory at robot startup, not when auto begins. On a roboRIO, deserializing a large trajectory can take multiple seconds — enough to eat much of your autonomous window if you defer it.
Because you write the follow function yourself, Choreo integrates cleanly with whatever command-based structure and pose estimator you already run. Your followTrajectory(SwerveSample sample) typically reads the sample's target pose and field-relative speeds, adds a WPILib PIDController correction per axis against your live pose, and hands the resulting ChassisSpeeds to the drivetrain.
| Dimension | PathPlanner | Choreo |
|---|---|---|
| Core approach | You draw the path; the tool profiles it | You give constraints; the solver computes the path |
| Editing model | Bezier waypoints, drag handles, per-point headings | Guide waypoints + explicit physical/kinematic constraints |
| Optimization | Respects swerve dynamics, but not guaranteed time-optimal | True time-optimal solve for the given constraints |
| Runtime generation | Yes — on-the-fly pathfinding (AD*) to any pose | No — offline generation only |
| Event handling | Event markers + registered named commands | atTime triggers + bind on the AutoFactory |
| WPILib integration | AutoBuilder wraps most follow logic for you | You implement the follow step (more control) |
| Drivetrains | Holonomic (swerve) and differential | Holonomic (swerve) and differential |
| Learning curve | Gentle; very visual; great for newer teams | Steeper; requires accurate robot characterization |
The single sharpest distinction: PathPlanner gives you control, Choreo gives you optimality. With PathPlanner you can draw a path your robot physically cannot follow, then spend practice time discovering that. With Choreo you cannot draw an impossible path — the solver simply won't produce one — but you also give up the fine-grained "make it go exactly here in exactly this shape" control, and you must feed it an honest model of your robot.
A telling data point from the community: FRC 3015, the team that created PathPlanner, has publicly said they run Choreo for their own trajectories. That is not a knock on PathPlanner — it reflects that once you trust your robot model, time-optimal paths are hard to beat.
Reach for PathPlanner when:
Reach for Choreo when:
For many teams the honest answer early in the season is PathPlanner (to move fast), then Choreo once the robot is characterized and you're squeezing out cycle time.
You do not have to pick one forever. PathPlanner explicitly supports Choreo interop: you can generate a time-optimal trajectory in Choreo and load it into PathPlannerLib as a path, then follow it with all of AutoBuilder's plumbing and markers. The API is PathPlannerPath.fromChoreoTrajectory("Trajectory Name"), with an overload that takes a split index for Choreo trajectories broken into segments:
PathPlannerPath choreoPath =
PathPlannerPath.fromChoreoTrajectory("SprintToStage");
PathPlannerPath choreoSegment =
PathPlannerPath.fromChoreoTrajectory("SprintToStage", 1); // split index
This is a genuinely nice hybrid: Choreo does the hard optimization for the long, speed-critical drives, while PathPlanner handles auto assembly, event markers, the dashboard chooser, and runtime pathfinding for the align-and-score moments. A common pattern is Choreo for the pre-planned scoring runs and PathPlanner pathfindToPose for the reactive endgame.
Whichever tool you pick, the following loop is only as good as your pose estimate. Both PathPlanner and Choreo assume you feed them a trustworthy pose each cycle and expect to reset odometry to the trajectory's starting pose at the beginning of a routine (resetPose / resetOdometry above). Practical must-dos:
You can validate almost all of this before the robot exists on the field by running it in WPILib simulation — watch the commanded trajectory and the simulated pose track together in the sim GUI, and you'll catch reset, mirroring, and unit bugs on your laptop instead of on the practice field.
Neither is universally better — they optimize for different things. Choreo produces time-optimal trajectories that follow well on the first try, while PathPlanner offers visual editing, runtime pathfinding, and a fuller library that wraps the follow loop for you. Many strong teams use both.
Yes. PathPlannerLib provides PathPlannerPath.fromChoreoTrajectory("name") (with a split-index overload) to load a Choreo-generated trajectory as a PathPlanner path, so you get Choreo's optimization plus PathPlanner's AutoBuilder, event markers, and chooser.
Both support differential (tank) drivetrains as well as holonomic swerve. ChoreoLib exposes DifferentialSample and PathPlanner supports differential path following, though the ecosystem's momentum and most examples center on swerve.
Almost always odometry, not the trajectory. If your pose estimate drifts or starts at the wrong place, the follower chases a bad reference. Verify you reset odometry to the start pose, that your gyro and encoder conversions are correct, and that vision measurements aren't destabilizing the estimate.
Yes — that's the point. Choreo's solver needs accurate mass, moment of inertia, wheel radius, and motor limits to compute a trajectory your robot can actually execute. Garbage in, garbage out: a wrong model yields a trajectory that looks optimal but the robot can't follow.
PathPlanner is usually the gentler on-ramp: it's visual, forgiving, and its AutoBuilder writes most of the following code for you. Once your drivetrain is dialed in and characterized, adding Choreo for your speed-critical paths is a natural next step.
Both tools are free, actively maintained, and bundled with or installable alongside WPILib, so there's little cost to trying each on your own robot. Start with whichever matches your team's current strengths — visual control or optimized speed — get one clean autonomous working end to end, and expand from there. For more on the pieces that make autonomous work, browse the rest of the LearnFRC guides.
where this came from
This article is AI-assisted: drafted from primary sources, then reviewed and edited by hand. Errors still get through. When one is reported we fix it and write down what changed, in public, in the corrections log.
dept / programming-software
You came for one answer. These teach the same subject properly, in the order a team actually learns it. All 51 are free, and none of them need an account to read.
if you want to keep the ticks
LearnFRC has 394 free FRC lessons across every department. Create a free account to save your place, track your progress, and earn a certificate.
Create a free accountReading never needs one. This is only for saving where you got to.
these are the closest, not the newest
20 min read
A practical guide to programming FRC swerve drive with WPILib: kinematics, SwerveModuleState, field-relative control, odometry, and where PathPlanner fits.
read it8 min read
Learn how FRC teams build autonomous routines with PathPlanner (PPLib): paths vs autos, AutoBuilder, named commands, odometry, tuning, and Choreo.
read it4 min read
A beginner-friendly guide to FRC drivetrains: how tank, swerve, and mecanum drives work, their tradeoffs, and how to pick one for your robot.
read itend of sheet
Keep going with the other 102 articles, or work through all 394 lessons across 11 departments.