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.
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
@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.