BLine is a rapid point-to-point autonomous path planning and tracking library for FIRST Robotics Competition. It is made by students for students and built around practical tuning, quick iteration, and rapid empirical testing in time-constrained build-season environments.
Quick links
π Open the hosted editor β create, tune, preview, and export BLine paths in the browser.
π₯οΈ BLine Web β current web and desktop editor.
π¬ Chief Delphi Thread β discussion, feedback, and announcements.
π Documentation β full guides, tutorials, and reference.
BLine-Lib's recommended WPILib vendor URL is the BLine Metrics Worker endpoint. It serves the same vendor JSON as this repository while keeping aggregate fetch counts for release health.
- Open VS Code with your FRC project
- Press
Ctrl+Shift+P(orCmd+Shift+Pon Mac) - Type "WPILib: Manage Vendor Libraries"
- Select "Install new libraries (online)"
- Paste the recommended vendor URL:
https://bline-metrics.edan-liahovetsky.workers.dev/vendor/BLine-Lib.json
If the Worker URL is temporarily unavailable, use the direct GitHub vendor JSON as the fallback:
https://raw.githubusercontent.com/edanliahovetsky/BLine-Lib/main/BLine-Lib.json
Add the JitPack repository to your build.gradle:
repositories {
maven { url 'https://jitpack.io' }
}Then add the BLine-Lib dependency:
dependencies {
implementation 'com.github.edanliahovetsky:BLine-Lib:v0.9.1'
}For a complete walkthrough, see the getting started guide.
import frc.robot.lib.BLine.*;
import edu.wpi.first.math.controller.PIDController;
// 1. Set global constraints
Path.setDefaultGlobalConstraints(new Path.DefaultGlobalConstraints(
4.0, // maxVelocityMetersPerSec
3.0, // maxAccelerationMetersPerSec2
360.0, // maxVelocityDegPerSec
720.0, // maxAccelerationDegPerSec2
0.05, // endTranslationToleranceMeters
2.0, // endRotationToleranceDeg
0.3 // intermediateHandoffRadiusMeters
));
// 2. Create a reusable path builder
FollowPath.Builder pathBuilder = new FollowPath.Builder(
driveSubsystem,
driveSubsystem::getPose,
driveSubsystem::getChassisSpeeds,
driveSubsystem::drive,
new PIDController(5.0, 0.0, 0.0), // translation
new PIDController(3.0, 0.0, 0.0), // rotation
new PIDController(2.0, 0.0, 0.0) // cross-track
).withDefaultShouldFlip()
.withPoseReset(driveSubsystem::resetPose);
// 3. Load and follow a path
Path myPath = new Path("myPathFile"); // loads deploy/autos/paths/myPathFile.json
Command followCommand = pathBuilder.build(myPath);For paths that need another system to own robot heading temporarily, such as vision aiming while translating along a path, override the path follower's rotational output:
FollowPath.overrideRotation(
() -> shooterAimController.getOmegaRadiansPerSecond()
);
// Later, when normal path rotation should resume:
FollowPath.clearRotationOverride();The default override behavior bypasses BLine's rotational velocity and acceleration constraints so the caller owns the final path-follower omega command. If the supplied omega should still respect BLine's rotation limits, use the explicit constrained mode:
FollowPath.overrideRotation(
() -> shooterAimController.getOmegaRadiansPerSecond(),
FollowPath.RotationOverrideBehavior.RESPECT_CONSTRAINTS
);When a BLine path contains event triggers that schedule WPILib commands, prefer
BLineCommands for the surrounding command composition:
import static frc.robot.lib.BLine.BLineCommands.sequence;
import edu.wpi.first.wpilibj2.command.Command;
Command auto = sequence(
shooter.shoot().withTimeout(2.0),
pathing.followPath("intakethroughdepot"),
shooter.shoot()
);BLineCommands mirrors the WPILib Commands composition methods that accept
child commands, but proxies those children before building the group. This keeps
the outer auto from owning every child requirement for its whole lifetime, which
lets BLine event-trigger commands use normal WPILib scheduling. See the
BLineCommands Javadocs for method-by-method behavior and limitations. The API
intentionally contains only WPILib Commands counterparts: either, select,
defer, deferredProxy, sequence, repeatingSequence, parallel, race,
and deadline.
BLine paths are polylines, so visualizing them on a WPILib Field2d widget (in
Elastic or Glass) needs no simulation. BLineField provides small helpers for
drawing a BLine path directly as a connected field object:
import frc.robot.lib.BLine.BLineField;
import edu.wpi.first.wpilibj.smartdashboard.Field2d;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
Field2d field = new Field2d();
SmartDashboard.putData("Field", field);
// Draw a planned path once. BLine assigns a stable unique field object name for
// this path instance and returns it if you want to inspect it.
String objectName = BLineField.drawPath(field, myPath);
// Or choose the display slot yourself. BLine appends "Trajectory" if needed.
BLineField.drawPath(field, "ScoreTwo", myPath);The no-name overload generates names like "BLinePath0Trajectory" per
Field2d, reusing the same name when called again with the same Path instance.
Explicit names are treated as user-owned display slots, so reusing
"ScoreTwo" updates "ScoreTwoTrajectory". If you only need the raw polyline
points, use myPath.getTranslations().
BLine has been validated with randomized Monte Carlo trials in a WPILib physics simulation, using Theta* for initial pathfinding and an Artificial Bee Colony (ABC) optimizer to benchmark the system against PathPlanner.
| Measurement | Result |
|---|---|
| Path computation time | 97% reduction |
| Cross-track error at waypoints | 66% reduction |
| Total path tracking time | 2.6% decrease compared to PathPlanner |
Read the full white paper.
./gradlew buildGenerate Javadoc locally:
./gradlew javadoc
# Open build/docs/javadoc/index.htmlPublished API reference: Javadoc.
If another robot repo consumes your local BLine-Lib checkout (for example via
includeBuild) and you run ./gradlew clean in this repo, rebuild the jar
before the robot repo packages or runs simulation.
./gradlew jarThis regenerates build/libs/BLine-Lib-<version>.jar for downstream fat-jar
tasks.
BSD 3-Clause License. See LICENSE.

