VingVing Robot LogoVingVing Robot

Documentation v0.0.3

VingVing Robot Docs

Path Builder

Create smooth, efficient autonomous paths using Bezier curves and path chaining

Path Following Basics

VingVing Robot uses Bezier curves to create smooth paths between waypoints. You can chain multiple path segments together for complex autonomous routines with precise heading control.

BezierLine: Straight line segment between two points
BezierCurve: Smooth curved path with control points

Points and Coordinates

All paths are built using Point objects. VingVing Robot supports both Cartesian and Field coordinate systems.

Cartesian Coordinates

Standard X-Y coordinates where (0,0) is the robot's starting position. X is forward/backward, Y is left/right, heading in radians.

// Cartesian point: (x, y, heading)
Point target = new Point(24, 12, Math.toRadians(90), Point.CARTESIAN);

// Move 24 inches forward, 12 inches left, face 90°

Field Coordinates

FTC field coordinates where (0,0) is a corner of the field. Useful for absolute positioning on the competition field.

// Field point: (x, y, heading)
Point spike = new Point(36, 60, Math.toRadians(180), Point.FIELD);

// Absolute field position

💡 Coordinate Tips

  • Cartesian is easier for relative movements from start position
  • Field coordinates are better for multi-robot coordination
  • Heading is in radians: 0° = 0, 90° = Math.toRadians(90), 180° = Math.PI
  • Positive X = forward, Positive Y = left in Cartesian mode

BezierLine - Straight Paths

BezierLine creates a straight path segment between two points. Simplest path type for direct movements.

Basic Usage:

// Single straight line from (0,0) to (48,0)
Path straightPath = new BezierLine(
    new Point(0, 0, Point.CARTESIAN),
    new Point(48, 0, Point.CARTESIAN)
);

follower.followPath(straightPath);

With Heading Interpolation:

Control how the robot rotates while moving along the path:

// Constant heading - maintain 0° throughout
Path line1 = new BezierLine(new Point(48, 0, Point.CARTESIAN))
    .setConstantHeadingInterpolation(Math.toRadians(0));

// Linear heading - smoothly rotate from start to end heading
Path line2 = new BezierLine(new Point(48, 24, Math.toRadians(90), Point.CARTESIAN))
    .setLinearHeadingInterpolation();

// Tangent heading - always point in direction of movement
Path line3 = new BezierLine(new Point(0, 48, Point.CARTESIAN))
    .setTangentHeadingInterpolation();

When to Use BezierLine:

  • Direct point-to-point movements
  • Creating sharp corners (chain multiple lines)
  • Simple geometric patterns (squares, triangles)
  • When you want predictable straight-line behavior

BezierCurve - Smooth Curves

BezierCurve creates smooth curved paths using control points. Allows for elegant, flowing movements.

Cubic Bezier Curve:

Defined by 4 points: start point, two control points, and end point.

// Create smooth S-curve
Path curve = new BezierCurve(
    new Point(0, 0, Point.CARTESIAN),      // Start point
    new Point(0, 0, Point.CARTESIAN),      // Start point (repeated for continuity)
    new Point(12, 12, Point.CARTESIAN),    // Control point 1 - pulls curve this direction
    new Point(36, 12, Point.CARTESIAN),    // Control point 2 - pulls curve this direction
    new Point(48, 0, Point.CARTESIAN)      // End point
).setTangentHeadingInterpolation();

follower.followPath(curve);

Control Point Tips:

  • First control point: Determines initial curve direction from start
  • Second control point: Determines final curve direction to end
  • Distance from endpoints: Closer = tighter curve, farther = gentler curve
  • Symmetrical control points: Creates balanced, smooth S-curves

Quadratic Bezier (3 points):

// Simpler curve with single control point
Path quadCurve = new BezierCurve(
    new Point(0, 0, Point.CARTESIAN),      // Start
    new Point(24, 24, Point.CARTESIAN),    // Control point - peak of arc
    new Point(48, 0, Point.CARTESIAN)      // End
);

💡 When to Use Curves

  • Avoiding obstacles with smooth arcs
  • High-speed autonomous routines (curves faster than sharp turns)
  • Approaching game elements at specific angles
  • Creating circular or arc-like paths

Path Chaining

Chain multiple path segments together to create complex autonomous routines. The robot smoothly transitions from one segment to the next.

Basic Chaining:

// Follow multiple paths in sequence
follower.followPath(
    // Segment 1: Drive forward
    new BezierLine(new Point(24, 0, Point.CARTESIAN))
        .setConstantHeadingInterpolation(Math.toRadians(0)),

    // Segment 2: Curve left
    new BezierCurve(
        new Point(24, 0, Point.CARTESIAN),
        new Point(24, 0, Point.CARTESIAN),
        new Point(36, 12, Point.CARTESIAN),
        new Point(48, 24, Point.CARTESIAN),
        new Point(48, 24, Point.CARTESIAN)
    ).setLinearHeadingInterpolation(Math.toRadians(90)),

    // Segment 3: Straight to end
    new BezierLine(new Point(48, 48, Math.toRadians(90), Point.CARTESIAN))
        .setConstantHeadingInterpolation(Math.toRadians(90))
);

Important Rules:

  • Continuity: Each segment's start point should match previous segment's end point
  • Heading: Set heading interpolation on each segment independently
  • Smoothness: Use BezierCurves for smooth transitions, BezierLine for sharp corners
  • Order matters: Segments execute in the order you list them

Example: Complete Autonomous

// Realistic autonomous routine
follower.followPath(
    // 1. Leave starting position
    new BezierLine(new Point(30, 0, Point.CARTESIAN))
        .setConstantHeadingInterpolation(0),

    // 2. Curve to spike mark
    new BezierCurve(
        new Point(30, 0, Point.CARTESIAN),
        new Point(30, 0, Point.CARTESIAN),
        new Point(36, 8, Point.CARTESIAN),
        new Point(42, 16, Point.CARTESIAN),
        new Point(42, 24, Point.CARTESIAN)
    ).setLinearHeadingInterpolation(Math.toRadians(45)),

    // 3. Back up slightly
    new BezierLine(new Point(38, 20, Point.CARTESIAN))
        .setConstantHeadingInterpolation(Math.toRadians(45)),

    // 4. Drive to backstage
    new BezierCurve(
        new Point(38, 20, Point.CARTESIAN),
        new Point(38, 20, Point.CARTESIAN),
        new Point(32, 32, Point.CARTESIAN),
        new Point(16, 40, Point.CARTESIAN),
        new Point(8, 48, Math.toRadians(180), Point.CARTESIAN)
    ).setTangentHeadingInterpolation(),

    // 5. Park
    new BezierLine(new Point(0, 48, Math.toRadians(180), Point.CARTESIAN))
        .setConstantHeadingInterpolation(Math.toRadians(180))
);

Heading Interpolation

Control how the robot rotates while following a path. Different strategies for different situations.

Constant Heading

Robot maintains a fixed heading throughout the entire path segment.

.setConstantHeadingInterpolation(
    Math.toRadians(90)
)

Use when: Intake/mechanism needs to stay pointed in one direction

Linear Heading

Robot smoothly rotates from start heading to end heading over the path.

.setLinearHeadingInterpolation(
    Math.toRadians(180)
)

Use when: Need to arrive at target with specific heading

Tangent Heading

Robot always points in the direction it's moving (follows path tangent).

.setTangentHeadingInterpolation()

Use when: Want most natural-looking movement on curves

Path Callbacks

Execute actions at specific points along the path without stopping the robot.

Adding Callbacks:

Path pathWithActions = new BezierLine(new Point(48, 0, Point.CARTESIAN))
    .setConstantHeadingInterpolation(0)
    .addCallback(0.25, () -> {
        // Execute when 25% complete
        intake.setPower(1.0);
    })
    .addCallback(0.75, () -> {
        // Execute when 75% complete
        arm.setPosition(0.5);
    })
    .setPathEndCallback(() -> {
        // Execute when path segment completes
        intake.setPower(0);
    });

follower.followPath(pathWithActions);

Callback Uses:

  • Start intake as robot approaches game element
  • Raise arm while driving to scoring position
  • Activate pixel release mechanism at precise moment
  • Switch between fast and precise movement modes

Complete Example: Score and Park

ExampleAuto.java
@Autonomous(name = "Score and Park")
public class ScoreAndPark extends LinearOpMode {
    Robot robot;
    Follower follower;

    @Override
    public void runOpMode() {
        robot = new Robot(hardwareMap, RobotConfig.class);
        robot.initializeLocalizer(hardwareMap);
        follower = new Follower(hardwareMap);

        waitForStart();

        // Build the complete autonomous path
        follower.followPath(
            // 1. Drive forward to spike marks
            new BezierLine(new Point(24, 0, Point.CARTESIAN))
                .setConstantHeadingInterpolation(0)
                .setPathEndCallback(() -> {
                    // Release purple pixel
                    releasePixel();
                }),

            // 2. Smooth curve to backstage
            new BezierCurve(
                new Point(24, 0, Point.CARTESIAN),
                new Point(24, 0, Point.CARTESIAN),
                new Point(32, 16, Point.CARTESIAN),
                new Point(16, 32, Point.CARTESIAN),
                new Point(8, 48, Point.CARTESIAN)
            ).setLinearHeadingInterpolation(Math.toRadians(90))
                .addCallback(0.5, () -> {
                    // Raise arm halfway through
                    arm.setTargetPosition(1000);
                }),

            // 3. Final positioning at backdrop
            new BezierLine(new Point(4, 52, Math.toRadians(90), Point.CARTESIAN))
                .setConstantHeadingInterpolation(Math.toRadians(90))
                .setPathEndCallback(() -> {
                    // Score yellow pixel
                    scorePixel();
                }),

            // 4. Park in backstage
            new BezierLine(new Point(8, 58, Math.toRadians(90), Point.CARTESIAN))
                .setConstantHeadingInterpolation(Math.toRadians(90))
        );

        // Execute the path
        while (!follower.isPathComplete() && opModeIsActive()) {
            robot.update();
            follower.update();
            robot.setDrivePowers(follower.getMotorPowers());
        }
    }
}

Path Building Tips

💡 Visualize with Dashboard

Always use FTC Dashboard to visualize your paths before running them. Green lines show the planned path - verify it doesn't hit obstacles or go out of bounds.

💡 Start Simple

Build complex paths incrementally. Test each segment individually before chaining them together. Easier to debug when you know each piece works.

💡 Measure Carefully

Measure actual field positions with a tape measure. Even small coordinate errors accumulate over long paths. Use field tiles as reference (each tile is 24 inches).

💡 Consider Recovery

Plan paths that can recover from small positioning errors. Avoid driving close to walls or obstacles where a tiny error causes collisions.

Next Steps

Learn about advanced path features like constraints, deceleration zones, and completion callbacks.