Gray Matter
WorkshopPathPlanner Paths
Rough draft: nobody has reviewed this lesson yet, and it may not be how things are done this season.
LESSON 28

PathPlanner Paths

PathPlanner is a field editor. You draw paths on the field, string them into autos with the actions between them, and PathPlannerLib turns each auto into one command. This lesson replaces the Leave Start timer with a drawn auto.

Branchswerve-pathplanner30 minutes
You’ll need
  • The Leave Start routine from Autonomous, and the three numbers it measured.
  • Wheel radius, top speed and slip current from Swerve Drive Tuning.
  • The robot's weight with battery and bumpers, and a tape measure.

A path is one drive from a start pose to an end pose. Waypoints shape the curve. The rotation is set apart from them, so a swerve robot can travel one way while it faces another.

An auto is a list: drive this path, run this action, drive the next path. The app saves both as files in the robot project, and the robot builds each auto into a single command at boot.

Install and configure

  1. Install PathPlanner from the Microsoft Store or the GitHub releases page.
  2. Click Open Robot Project and pick the project root, the folder with build.gradle in it. The app creates src/main/deploy/pathplanner.
  3. In VS Code, open the WPILib Vendor Dependencies view from the activity bar. Expand INSTALL FROM URL, paste the URL below, and press Install.
  4. Build the project. It should compile with nothing else added.
PathPlannerLib for Commands v3, WPILib 2027 alpha-7
https://raw.githubusercontent.com/JosephTLockwood/pathplanner/vendordep/PathplannerLib.json

Then open Settings and the Robot Config tab. PathPlannerLib reads these numbers back on the robot and uses them to decide how hard each wheel can push. A guessed number shapes every path the robot drives.

SettingWhere it comes from
Robot MassA scale, with battery and bumpers on, in kilograms. 68 kg is the usual stand-in until you weigh it.
Robot MOIMass × (length² + width²) ÷ 12, in meters. A 68 kg robot, 0.84 m square, comes to about 8.0.
Bumper Width, LengthThe tape measure, outside edge to outside edge.
Wheel Radius, Drive GearingkWheelRadius and kDriveGearRatio in TunerConstants.java. The radius there is in inches. Multiply by 0.0254.
True Max Drive SpeedThe plateau you measured for kSpeedAt12Volts.
Drive Motor, Current LimitKraken X60, and kSlipCurrent. Leave Wheel COF at 1.2 unless your wheel vendor lists one.
Module OffsetskFrontLeftXPos and the other seven, converted to meters. The shipped 10 inches is 0.254.

Draw a path and auto

Draw the trip Leave Start made, from the same tape mark. The field in the app has its origin at the blue alliance corner, the same as Drivetrain/Pose.

  1. Click + in the Paths section and name the path Leave Start.
  2. Drag the first waypoint onto the tape mark. Set Ideal Starting State rotation to the way the front bumper points.
  3. Drag the last waypoint about two meters out, in open floor. Set Goal End State rotation to 45 degrees and leave its velocity at 0.
  4. Set Global Constraints to 2 m/s and 2 m/s². Watch the bumper outline through the preview, not just the line.

The app saves as you go, to deploy/pathplanner/paths/Leave Start.path. That file ships to the robot with every deploy.

A path on its own does nothing. The robot runs autos, so wrap the path in one. Click + in the Autos section, name it Leave Start, and drag the Leave Start path into its command list. Leave Reset Odometry on. At enable it tells odometry the robot is sitting on the first path's start pose.

The branch ships two longer autos built the same way. Each box in the list runs after the one above it finishes:

Shoot and Leave
Path, action, path
Start to Shoot, then the Shoot named command, then Shoot to Neutral Zone.
Neutral Zone Run
Path, path, action
Start to Neutral Zone, with an Intake zone along it, then Neutral Zone to Shoot and Shoot.

Teach AutoBuilder the robot

AutoBuilder is what turns a file into a command. It has to know how to read this robot and how to drive it, once, before any auto loads. That goes in the DriveMechanism constructor.

In the constructor, after registerTelemetry
// Teaches PathPlanner how to drive this robot. After this, AutoBuilder can turn any path or
// auto drawn in the PathPlanner app into a command.
AutoBuilder.configure(
() -> getPose(), // where the robot is
pose -> resetPose(pose), // used when an auto says where the robot starts
() -> getRobotVelocity(), // how fast it is moving, in its own directions
speeds -> drivetrain.setControl(pathRequest.withVelocity(speeds)), // drive like this
// Pulls the robot back onto the path when it drifts. The first gain is for position (m/s
// of correction per meter of error), the second for heading. TODO: tune on your robot.
new PPHolonomicDriveController(
new PIDConstants(5.0, 0.0, 0.0), new PIDConstants(5.0, 0.0, 0.0)),
loadPathConfig(),
// Paths are drawn from the blue side. On red, PathPlanner mirrors them across the field.
() -> MatchState.getAlliance().orElse(Alliance.BLUE) == Alliance.RED,
this); // path commands require this mechanism

Import AutoBuilder from com.pathplanner.lib.command3. The one in com.pathplanner.lib.auto makes commands for the other framework, and they will not compile against org.wpilib.command3.Command.

pathRequest is a SwerveRequest.ApplyRobotVelocity field, because PathPlannerLib hands back speeds relative to the robot. loadPathConfig() wraps RobotConfig.fromGUISettings(), which reads the Robot Config tab out of deploy/pathplanner/settings.json.

One Auto OpMode

Delete LeaveStartAuto.java. The drawn auto replaces it, and one @Autonomous class now runs every auto in the project. It registers the named commands, asks AutoBuilder for a drop-down of autos, and runs the selected one at enable.

AutoOpMode: register, list, run
@Autonomous(name = "Auto")
public class AutoOpMode extends PeriodicOpMode {
private final Selectable<Command> autoChooser;
private Command routine;
 
public AutoOpMode(Robot robot) {
// The name in quotes must match the name in the PathPlanner app exactly.
NamedCommands.registerCommand(
"Shoot",
Command.noRequirements(coroutine -> coroutine.wait(Seconds.of(1.0))).named("Shoot"));
NamedCommands.registerCommand(
"Intake", Command.noRequirements(coroutine -> coroutine.park()).named("Intake"));
 
// PathPlanner fills this with one choice per auto drawn in the app, plus "None". It loads
// every auto, so the named commands above have to be registered first.
autoChooser = AutoBuilder.buildAutoChooser("Leave Start");
Tunables.publish("Auto", autoChooser);
}
 
@Override
public void start() {
routine = autoChooser.getSelected();
Scheduler.getDefault().schedule(routine);
}
 
@Override
public void end() {
Scheduler.getDefault().cancel(routine);
}
 
/** Takes the drop-down off the dashboard when another OpMode is picked. */
@Override
public void close() {
Tunables.remove("Auto");
}
}

Shoot and Intake are stand-ins that only take time. A robot with a shooter registers its real command under the same name. Every auto that uses Shoot picks it up with no change in the app.

Intake parks, so it never finishes on its own. It runs inside the event marker zone on Start to Neutral Zone. The path starts it when the robot enters the zone and cancels it when the robot leaves.

The selected auto is read in start(), because someone can still change the drop-down after picking the mode. On the dashboard it appears under Tunables/Auto.

Three failure shapes

Does nothing
A missing name
The driver station reports a missing file, or the auto skips an action. A name in the app does not match a path file or a registered command, letter for letter.
Wrong place
Pose and plan disagree
The robot drives the right shape, offset or rotated. The starting rotation in the app does not match the way the robot sat on the tape.
Lags or overshoots
Config or gains
The robot falls behind the path or swings past its end. A guessed top speed or mass asks for more than the robot has. Fix the config before the gains.

Check your work

  1. Run WPILib: Simulate Robot Code. Pick Auto from the autonomous list. In the sim GUI, open NetworkTables and check that Tunables/Auto/options lists all three autos and None.
  2. Enable with Leave Start selected. Watch Drivetrain/Pose on the 2D field in AdvantageScope.
  3. Select Neutral Zone Run, enable again, and watch the scheduler for Intake and Shoot.
  4. Deploy, put the robot on the tape mark, and run Leave Start three times with one person on disable.
Check

You should see

  • In sim, the robot ending within a few centimeters of the last waypoint, turned to 45 degrees, and staying stopped.
  • Intake running only through the marked zone, and Shoot taking one second at the end.
  • Three floor runs that land closer together than the three timed runs of Leave Start did.
PathPlanner: Editing paths and autos

Check yourself

On a swerve path, what sets the direction the robot faces?

Where do wheel radius and True Max Drive Speed in Robot Config come from?

The drawn line clears the hub. What can still hit it?

Why does AutoOpMode register its named commands before it calls buildAutoChooser?

Intake parks forever. Why does it stop in Neutral Zone Run?

You rename the Shoot and Leave auto in the app and deploy. What changes on the robot?

Pick an answer for each.