ecrl
Enka-Candler Robotics Language
The Enka-Candler Robotics Language (ECRL, pronounced eck-ruhl) is a language that compiles to Java and the FTC SDK. Because it compiles to the FTC SDK, this language is meant for FTC teams.
Official Locations
These are official locations of ECRL. It is recommended to only get ECRL from these locations.
Getting Started
Prerequisites
Build the compiler
just build
This produces the ecrl binary at bin/ecrl.
Compile an ECRL program
just run path/to/program.ecr
This writes Java output to path/to/program.ecr.java. You can also invoke the compiler directly:
./bin/ecrl -s path/to/program.ecr -o path/to/output.java
./bin/ecrl -s path/to/program.ecr -o path/to/output.java -p com.myteam.teleop
The -p / --package flag overrides any package directive in the source file.
Run tests
just test
Language Overview
An ECRL program has a define block, optional routines, and exactly one OpMode (teleop or autonomous):
package "org.firstinspires.ftc.teamcode.teleop"
module "MyRobot"
define {
drivetrain {
fl: "leftFront" FORWARD
fr: "rightFront" REVERSE
bl: "leftBack" FORWARD
br: "rightBack" FORWARD
}
var speed = 1.0
dc "intake"
servo "wrist"
}
routine pulse_intake(power) {
robot.intake.set_power(power)
wait(0.5)
robot.intake.stop()
}
teleop "Drive Mode" group "Main" {
loop {
drive(
deadzone(gpad1.left_stick_y, 0.05),
deadzone(gpad1.left_stick_x, 0.05),
deadzone(gpad1.right_stick_x, 0.05)
)
if gpad1.square && gpad2.triangle {
robot.intake.set_power(speed * 0.5)
} else if gpad1.right_trigger >= 0.5 {
robot.intake.stop()
}
while gpad1.dpad_up {
pulse_intake(1.0)
}
robot.wrist.set_position(0.5)
robot.tel.show("Speed", "Target: #{speed}")
robot.tel.update()
}
}
Autonomous programs use a sequential body (no outer loop):
package "org.firstinspires.ftc.teamcode.auto"
module "RedAuto"
define {
drivetrain {
fl: "lf" FORWARD
fr: "rf" REVERSE
bl: "lb" FORWARD
br: "rb" FORWARD
}
dc "intake"
}
autonomous "Red Auto" group "Auto" {
drive(0.5, 0.0, 0.0)
wait(1.5)
drive(0.0, 0.0, 0.0)
for i = 0; i < 3; i = i + 1 {
wait(0.25)
}
}
Features
!starts a line commentpackagesets the generated Java package (default:org.firstinspires.ftc.teamcode.teleop)modulesets the generated Java class namedefinedeclares hardware, variables, and the mecanum drivetrainteleop/autonomous— exactly one OpMode per file (@TeleOpor@Autonomous)routine name(params) { ... }— reusable void helpers; call withname(args)gpad1.*maps togamepad1.*;gpad2.*maps togamepad2.*- Arithmetic in values:
+,-,*,/, parentheses, unary- while cond { }andfor i = init; cond; i = step { }wait(seconds)— interruptible delay (waitSecondshelper)deadzone(value, threshold)— builtin stick deadzone helperdc/servodeclare motors and servosifsupports comparisons (>,<,>=,<=,==,!=),&&, and||robot.<device>.set_power/set_velocity/stopcontrols motors;set_positioncontrols servosrobot.tel.show/updatehandles telemetry
Examples
- Limelight Robotics #23574 2025-2026 TeamCode re-creation — full competition-style teleop with multiple motors
- Dual driver arm — two-gamepad setup with servos, deadzone, and compound conditions
- Simple auto — autonomous with routines,
wait, andfor
Compile an example with:
just buildrun examples/dual_driver_arm.ecr
Or the autonomous example:
just buildrun examples/simple_auto.ecr
Contributing
ECRL is open to contributions! To contribute, follow these steps:
- Fork the repository here: https://codeberg.org/zanderlewis/ecrl
- Create a new branch:
git switch -c my-awesome-new-feature - Make your changes and run
just test - Commit and submit a pull request describing your changes
ecrl
- 0
- 0
- 0
- 0
- 0
- about 6 hours ago
- June 24, 2026
Apache License 2.0
Tue, 28 Jul 2026 00:50:57 GMT