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.
- 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
- Install PathPlanner from the Microsoft Store or the GitHub releases page.
- Click Open Robot Project and pick the project root, the folder with
build.gradlein it. The app createssrc/main/deploy/pathplanner. - In VS Code, open the WPILib Vendor Dependencies view from the activity bar. Expand INSTALL FROM URL, paste the URL below, and press Install.
- Build the project. It should compile with nothing else added.
https://raw.githubusercontent.com/JosephTLockwood/pathplanner/vendordep/PathplannerLib.jsonThen 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.
| Setting | Where it comes from |
|---|---|
| Robot Mass | A scale, with battery and bumpers on, in kilograms. 68 kg is the usual stand-in until you weigh it. |
| Robot MOI | Mass × (length² + width²) ÷ 12, in meters. A 68 kg robot, 0.84 m square, comes to about 8.0. |
| Bumper Width, Length | The tape measure, outside edge to outside edge. |
| Wheel Radius, Drive Gearing | kWheelRadius and kDriveGearRatio in TunerConstants.java. The radius there is in inches. Multiply by 0.0254. |
| True Max Drive Speed | The plateau you measured for kSpeedAt12Volts. |
| Drive Motor, Current Limit | Kraken X60, and kSlipCurrent. Leave Wheel COF at 1.2 unless your wheel vendor lists one. |
| Module Offsets | kFrontLeftXPos 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.
- Click + in the Paths section and name the path
Leave Start. - Drag the first waypoint onto the tape mark. Set Ideal Starting State rotation to the way the front bumper points.
- 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.
- 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:
- Path, action, path
Start to Shoot, then theShootnamed command, thenShoot to Neutral Zone.- Path, path, action
Start to Neutral Zone, with anIntakezone along it, thenNeutral Zone to ShootandShoot.
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.
// 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 mechanismImport 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.
@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
- 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.
- 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.
- 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
- Run WPILib: Simulate Robot Code. Pick Auto from the autonomous list. In the sim GUI, open NetworkTables and check that
Tunables/Auto/optionslists all three autos andNone. - Enable with
Leave Startselected. WatchDrivetrain/Poseon the 2D field in AdvantageScope. - Select
Neutral Zone Run, enable again, and watch the scheduler forIntakeandShoot. - Deploy, put the robot on the tape mark, and run
Leave Startthree times with one person on disable.
You should see
- In sim, the robot ending within a few centimeters of the last waypoint, turned to 45 degrees, and staying stopped.
Intakerunning only through the marked zone, andShoottaking one second at the end.- Three floor runs that land closer together than the three timed runs of Leave Start did.
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?