Turns routes driven by drivers into Java code for a Pedro Pathing 3 autonomous with Ivy commands.
Add JitPack to TeamCode/build.gradle (or to build.dependencies.gradle in the Quickstart):
repositories {
maven { url 'https://jitpack.io' }
}
dependencies {
implementation 'com.pedropathing:revhub:3.0.2'
implementation 'com.pedropathing.ivy:pedro:1.1.1'
implementation 'org.westwoodrobots:pathrecorder-ftc:0.1.0'
implementation 'org.westwoodrobots:pathrecorder-ivy:0.1.0'
implementation 'org.westwoodrobots:pathrecorder-panels:0.1.0'
}panels module is optional. Add only if your team uses Panels.
The library uses compileOnly for Pedro, Ivy, Panels and the FTC SDK. Your project supplies these at runtime.
| Dependency | Version | Source |
|---|---|---|
| Pedro Pathing | 3.0.2 | v3.0.2 (cf4be31) |
| Ivy | 1.1.1 | v1.1.1 (d35242a) |
| Panels field plugin | 1.0.10 | mymaven.bylazar.com (a68ed55) |
| FTC SDK | 12.0.0 | v3.0.2 |
| Android Gradle Plugin | 8.13.2 | same as Quickstart |
| Java | source and target 1.8 | same as Quickstart |
Use Pedro 3.0.2 or later. The Quickstart v3.0.2 still uses revhub:3.0.1. In Pedro 3.0.1, linear heading moves with the
curve parameter t. In 3.0.2 it moves with arc length, and the heading classifier uses arc length.
See RecordAuto in sample/.
recorder = new PathRecorder<>(follower, new Pose(8, 72, 0), config, IvyRuntime.owned())
.action("claw.open()", () -> gamepad1.aWasPressed(), claw::open)
.action("claw.close()", () -> gamepad1.bWasPressed(), claw::close)
.waypoint(() -> gamepad1.xWasPressed())
.finish(() -> gamepad1.backWasPressed())
.overlay(new PanelsOverlay());
// in loop()
recorder.update(gamepad1, telemetry);
telemetry.update();- The first arg of
actionis the Java expr that the generator writes into the output, must be valid. - The last arg supplies a new
Commandfor each push, scheduled by the recorder. - Trigger is fired on the rising edge.
- The constructor calls
follower.setPose(start).updatecallsfollower.manual(...)andfollower.update(). Do not call them again in the same loop. IvyRuntime.owned()callsScheduler.execute()inupdate. If your code already callsScheduler.execute(), useIvyRuntime.external().Scheduleris static, so callScheduler.reset()ininit().- The default stick mapping is the mapping of the Pedro localization test. For field-centric drive, use
.drive(DriveInput.fieldCentric(0)), or give your ownDriveInput.
When the driver pushes the finish button (or the OpMode stops and calls finish()):
- Code goes to
/sdcard/FIRST/pathrecorder/<timestamp>.javaon the Control Hub. Useadb pull /sdcard/FIRST/pathrecorder. http://192.168.43.1:8080/pathrecorderwill display the newest file
The output format should be imports first, statements in a method in scope of follower/subsystem, and command is scheduled, and setPose() is called.
With config.style = OutputStyle.CLASS you get a class with start() and create(Follower, ...) instead.
All settings are public fields of RecorderConfig.
| Field | Default | Meaning |
|---|---|---|
positionTolerance |
1.0 |
Maximum distance (in) from a recorded point to the fitted curve |
headingTolerance |
3.0 |
RMS heading error (deg) for a heading mode, and the turn tolerance |
stopSpeed |
1.5 |
Speed (in/s) below which the robot is stopped |
minStopTime |
150 |
Minimum stop time (ms) that splits a path |
sampleInterval |
0 |
Minimum time (ms) between samples, 0 records every loop |
degrees |
true |
Degrees through PoseFactory.degrees(), or radians through new Pose(...) |
mirrorAxis |
NaN |
Mirror the output with PoseFactory.mirrorX(axis), for example 72 for the other alliance |
style |
SNIPPET |
SNIPPET or CLASS |
followerName, commandName, startName, poseName, pathName |
follower, auto, start, p, path |
Names in the output |
packageName, className, parameters, imports |
Settings for CLASS output, for example parameters.add("Claw claw") |
|
outputDirectory |
/sdcard/FIRST/pathrecorder |
Directory for the files |
livePreview |
true |
Fit the route again at each stop for the overlay |
- A short pause (less than
minStopTime) with no turn does not split a path. - A stop with a heading change becomes
PedroCommands.holdand a wait for the heading, with a timeout of two times the recorded turn time (500 ms minimum). - A waypoint during motion splits the path into two paths. Pedro can slow the robot at the end of each path.
- The robot waits at each stop until the actions of the stop are done. The recorded wait time is not in the output.
- A path with an action during motion is a
Groups.parallel. The next step starts only when all actions of that path are done. - One path can contain more than one Bézier curve as
Paths.path(...). In Pedro 3.0.2,follower.completion()is not correct for such a path. For these paths the output usesfollower.pathIndex()andfollower.parametricCompletion()instead. - The output depends on
follower.update()in each loop.follower.completion()is1.0until the first update afterfollow(), the same asPedroCommands.follow. - A path that crosses itself can place an action at the wrong crossing.
- If no heading mode is inside the tolerance, the output uses
linearand a// heading errornote with the measured RMS error. - Odometry drift goes into the output. The output is only as good as your localizer.
During a match, the Competition Manual (R704) does not permit live data streams other than Driver Station telemetry. Do not put any recorders in a competition OpMode.
BSD 3-Clause. See LICENSE.