Bezier Curves Deep Dive
Understanding the mathematics and control of Bezier curve paths
What Are Bezier Curves?
Bezier curves are parametric curves defined by control points. They create smooth, predictable paths that are perfect for robot navigation. VingVing Robot supports both quadratic (3 points) and cubic (5 points) Bezier curves.
Cubic Bezier Curves
Anatomy of a Cubic Bezier:
new BezierCurve(
new Point(0, 0, Point.CARTESIAN), // P0: Start point
new Point(0, 0, Point.CARTESIAN), // P1: Start point (duplicated for continuity)
new Point(12, 12, Point.CARTESIAN), // P2: First control point
new Point(36, 12, Point.CARTESIAN), // P3: Second control point
new Point(48, 0, Point.CARTESIAN) // P4: End point
)
// 5 points total:
// - 2 identical start points (P0, P1)
// - 2 control points (P2, P3) that shape the curve
// - 1 end point (P4)How Control Points Work:
- P2 (first control): Pulls curve in direction from start - determines initial curve direction
- P3 (second control): Pulls curve toward itself from end - determines final approach angle
- Distance matters: Control points farther from start/end create gentler curves
- Positioning: Control points don't have to lie on the curve - they define its shape
Example: S-Curve
// Create smooth S-shaped path
new BezierCurve(
new Point(0, 0, Point.CARTESIAN),
new Point(0, 0, Point.CARTESIAN),
new Point(16, 16, Point.CARTESIAN), // Pull up-right from start
new Point(32, -16, Point.CARTESIAN), // Pull down-right to end
new Point(48, 0, Point.CARTESIAN)
).setTangentHeadingInterpolation()Quadratic Bezier Curves
// Simpler 3-point Bezier
new BezierCurve(
new Point(0, 0, Point.CARTESIAN), // Start
new Point(24, 24, Point.CARTESIAN), // Single control point
new Point(48, 0, Point.CARTESIAN) // End
)
// Creates symmetric arc with peak at control point projectionWhen to Use Quadratic:
- Simple arc paths (avoid obstacle, round corner)
- Symmetric curves (same curvature in and out)
- Easier to visualize and plan than cubic
- Less control than cubic but simpler to tune
Designing Effective Curves
Rule 1: Control Point Distance = Curve Gentleness
// Tight curve - control points close to endpoints
new BezierCurve(
new Point(0, 0, Point.CARTESIAN),
new Point(0, 0, Point.CARTESIAN),
new Point(6, 6, Point.CARTESIAN), // Close
new Point(42, 6, Point.CARTESIAN), // Close
new Point(48, 0, Point.CARTESIAN)
) // Sharp S-curve
// Gentle curve - control points far from endpoints
new BezierCurve(
new Point(0, 0, Point.CARTESIAN),
new Point(0, 0, Point.CARTESIAN),
new Point(20, 20, Point.CARTESIAN), // Far
new Point(28, 20, Point.CARTESIAN), // Far
new Point(48, 0, Point.CARTESIAN)
) // Smooth, wide S-curveRule 2: Symmetrical Control = Balanced Curve
// Symmetrical control points create balanced curves
new BezierCurve(
new Point(0, 0, Point.CARTESIAN),
new Point(0, 0, Point.CARTESIAN),
new Point(12, 18, Point.CARTESIAN), // Distance from start: ~21 inches
new Point(36, 18, Point.CARTESIAN), // Distance from end: ~21 inches
new Point(48, 0, Point.CARTESIAN)
) // Smooth, predictable curve
// Asymmetrical = unbalanced (but sometimes useful!)
new BezierCurve(
new Point(0, 0, Point.CARTESIAN),
new Point(0, 0, Point.CARTESIAN),
new Point(6, 12, Point.CARTESIAN), // Close to start
new Point(42, 24, Point.CARTESIAN), // Far from end
new Point(48, 0, Point.CARTESIAN)
) // Sharp initial turn, gentle approachRule 3: Approximate Circles
// Magic number for circular arcs: 0.551915024494
double radius = 24.0;
double controlDist = radius * 0.551915024494;
// Quarter circle (90° arc)
new BezierCurve(
new Point(0, radius, Point.CARTESIAN),
new Point(0, radius, Point.CARTESIAN),
new Point(controlDist, radius, Point.CARTESIAN),
new Point(radius, controlDist, Point.CARTESIAN),
new Point(radius, 0, Point.CARTESIAN)
) // Perfect 90° arc
// Chain 4 of these for complete circleChaining Bezier Curves
Smooth Transitions Between Curves:
// Each curve's end point = next curve's start point
follower.followPath(
// Curve 1
new BezierCurve(
new Point(0, 0, Point.CARTESIAN),
new Point(0, 0, Point.CARTESIAN),
new Point(12, 8, Point.CARTESIAN),
new Point(20, 12, Point.CARTESIAN),
new Point(24, 12, Point.CARTESIAN) // End here
).setTangentHeadingInterpolation(),
// Curve 2 starts where Curve 1 ended
new BezierCurve(
new Point(24, 12, Point.CARTESIAN), // Start here
new Point(24, 12, Point.CARTESIAN),
new Point(30, 12, Point.CARTESIAN),
new Point(42, 24, Point.CARTESIAN),
new Point(48, 24, Point.CARTESIAN)
).setTangentHeadingInterpolation()
);
// Robot smoothly transitions between curvesVisualization and Debugging
Using FTC Dashboard:
FTC Dashboard shows your Bezier curves as green lines before running. Use this to verify:
- Curve doesn't intersect obstacles or go out of bounds
- Control points create desired shape (adjust if too sharp/gentle)
- Path length is reasonable for time constraints
- Multiple curves chain smoothly without kinks
Common Issues:
Sharp kinks: Control points too close to endpoints - move them farther away
Curve goes backward: Control points placed behind start/end - reposition forward
Not smooth enough: Control points too far - bring them closer for tighter curve
Bezier Tips
💡 Start with Simple Arcs
Use quadratic (3-point) Beziers first to get comfortable. Graduate to cubic (5-point) when you need more control over curve shape.
💡 Measure on Field
Place tape or markers on field tiles for your endpoints and control points. Easier than guessing coordinates.
💡 Use Tangent Heading on Curves
Bezier curves work best with tangent heading interpolation - robot naturally follows the curve direction.
💡 Test One Curve at a Time
When designing complex paths with multiple curves, test each curve individually before chaining them together.