SharpAI
/

Draw the route. Take the Java.

How this works

Drag the waypoints, or click anywhere on the field to add one. Arrow keys nudge the selection, shift for 5″, delete removes it, space plays and ⌘Z steps back.

x runs right, y runs up the field, heading 0 faces +x and turns counter-clockwise — Pedro’s convention, not the SDK’s. Squares are 24″ tiles.

The clock is an estimate from distance and your speed limit alone. It does not know your motors, your weight or how much traction you have, so a real robot will be slower.

0.0s / 3.9s(116 in)
0.0s / 3.9s · 116 in · x 9.0 · y 60.0 · 0°

Current robot position

X 9.00Y 60.00Heading

Starting point

Robot

A mecanum robot strafes slower than it drives, so the two speeds are separate. The 3.9s estimate is geometry and these limits only — no traction, weight or heading cost — so a real robot will be slower. Over a 144″ field most legs never reach top speed at all; acceleration is usually what binds.

Click the field to add a point · arrows nudge, shift for 5″ · delete removes · space plays · Z undoes

Path chains (1)

Each chain becomes its own PathChain, followed in order.

Waypoints (3)

namexyheading°

Leg 12

Obstacles (0)

    Anything the robot must not drive through. Checked against the footprint along the whole route.

    Import existing Java

    Pedro Pathing code

    package org.firstinspires.ftc.teamcode.pedroPathing;
    
    import com.pedropathing.follower.Follower;
    import com.pedropathing.geometry.BezierCurve;
    import com.pedropathing.geometry.BezierLine;
    import com.pedropathing.geometry.Pose;
    import com.pedropathing.paths.PathChain;
    import com.qualcomm.robotcore.eventloop.opmode.Autonomous;
    import com.qualcomm.robotcore.eventloop.opmode.OpMode;
    
    @Autonomous(name = "GeneratedPath")
    public class GeneratedPath extends OpMode {
    
        private Follower follower;
        private PathChain path;
    
        private final Pose startPose = new Pose(9, 60, Math.toRadians(0));
        private final Pose scorePose = new Pose(60, 84, Math.toRadians(90));
        private final Pose pickupPose = new Pose(108, 60, Math.toRadians(0));
    
        @Override
        public void init() {
            follower = Constants.createFollower(hardwareMap);
            follower.setStartingPose(startPose);
            path = follower.pathBuilder()
                    .addPath(new BezierLine(startPose, scorePose))
                    .setLinearHeadingInterpolation(startPose.getHeading(), scorePose.getHeading(), 0.8)
                    .addPath(new BezierCurve(scorePose, new Pose(84, 96), pickupPose))
                    .setLinearHeadingInterpolation(scorePose.getHeading(), pickupPose.getHeading(), 0.8)
                    .build();
        }
    
        @Override
        public void start() {
            follower.followPath(path);
        }
    
        @Override
        public void loop() {
            follower.update();
            // isBusy() goes false once the follower has finished correcting.
            if (!follower.isBusy()) {
                telemetry.addLine("Path complete");
            }
            telemetry.addData("x", follower.getPose().getX());
            telemetry.addData("y", follower.getPose().getY());
            telemetry.addData("heading (deg)", Math.toDegrees(follower.getPose().getHeading()));
            telemetry.update();
        }
    }