Bindings
A registry of named inputs that decouples where a control comes from (a gamepad button, a stick axis, a robot state) from the code that reacts to it. You wire inputs once by id, then query them by id from anywhere.
The bindings system lives in com.cdarobotics.cdalib.bindings. There are two
flavors of control:
- Boolean controls — a
Bindingwrapping aBooleanSupplier(e.g. a button press or a state condition). - Analog controls — an
AnalogBindingwrapping aDoubleSupplier(e.g. a trigger pull or a joystick axis).
Both are registered with, and queried through, a BindingManager. Because reactive
code only knows the id string — never which physical control is behind it — you can rebind a
control in one place without touching the logic that consumes it. This is exactly how the reusable
modules find their inputs: TeleOpPedroModule reads the ids
"drive", "strafe", "turn", and "slowMode".
BindingManager
Holds a registry of boolean bindings and a registry of analog bindings, each keyed by id
(internally sorted maps). The add* methods are non-destructive — they refuse to
overwrite an existing id — while the replace* methods always overwrite.
| Method | Returns | Behavior |
|---|---|---|
addBinding(String id, BooleanSupplier condition) | boolean |
Registers a new boolean binding built from the supplier. Returns true if added, false if the id was already taken (existing binding left untouched). |
addBinding(Binding binding) | boolean |
Registers a pre-built Binding under its own id. Returns false if that id was already taken. Use this overload to add a ToggleBinding. |
replaceBinding(String id, BooleanSupplier condition) | void |
Registers a boolean binding under the id, overwriting any existing one. |
replaceBinding(Binding binding) | void |
Registers the given binding under its own id, overwriting any existing one. |
addAnalog(String id, DoubleSupplier provider) | boolean |
Registers a new analog binding. Returns true if added, false if the id was already taken. |
replaceAnalog(String id, DoubleSupplier provider) | void |
Registers an analog binding under the id, overwriting any existing one. |
replaceAnalog(AnalogBinding analog) | void |
Registers the given analog binding under its own id, overwriting any existing one. |
checkBinding(String id) | boolean |
Evaluates the boolean binding registered under the id and returns its current status. Returns false if no non-null binding is registered under that id. |
checkAnalog(String id) | double |
Reads the analog binding registered under the id. Returns 0 if no non-null analog binding is registered under that id. |
checkBinding returns
false and checkAnalog returns 0 for an unknown id, so
consumers never NPE on a control that was never wired. A module that expects
"slowMode" simply behaves as if the button is unpressed until you bind it.Binding
A named boolean condition. It pairs a BooleanSupplier with an id and evaluates the
condition on demand.
| Member | Signature | Description |
|---|---|---|
| constructor | Binding(BooleanSupplier condition, String id) | Wraps a condition under an id. |
getStatus | boolean getStatus() | Evaluates the condition right now. |
getId | String getId() | Returns the id. |
getCondition | BooleanSupplier getCondition() | Returns the underlying supplier. |
AnalogBinding
A named analog input. It pairs a DoubleSupplier with an id and reads the value on
demand.
| Member | Signature | Description |
|---|---|---|
| constructor | AnalogBinding(DoubleSupplier provider, String id) | Wraps a value source under an id. |
getValue | double getValue() | Reads the current value right now. |
getId | String getId() | Returns the id. |
getProvider | DoubleSupplier getProvider() | Returns the underlying supplier. |
ToggleBinding
A Binding subclass that treats its condition as a momentary button and flips a
latched state on every rising edge (a transition from false to
true). getStatus() returns the latched toggle state, not the raw
button.
ToggleBinding(BooleanSupplier condition, String id)
The implementation tracks the previous raw value: when the raw condition is currently pressed and was not pressed last time, it inverts the toggle. So a single press-and-release turns it on, the next turns it off, and holding the button does not repeatedly flip it.
getStatus() updates the "last pressed" memory. Calling it more than once per
loop (for instance, checking the same id twice) can miss or double-count edges. Register it once
and read it once via checkBinding.End-to-end example
Wire physical controls in your OpMode's preload(), then read them by id anywhere
— including inside library modules that never reference your gamepads directly.
@Override
public void preload() {
// Boolean controls: id -> button
bindingManager.addBinding("slowMode", () -> gamepad1.left_bumper);
// A latching control: press once to toggle field-centric on/off
bindingManager.addBinding(
new ToggleBinding(() -> gamepad1.y, "fieldCentric"));
// Analog controls: id -> stick axis (note the negated Y for forward = +)
bindingManager.addAnalog("drive", () -> -gamepad1.left_stick_y);
bindingManager.addAnalog("strafe", () -> gamepad1.left_stick_x);
bindingManager.addAnalog("turn", () -> gamepad1.right_stick_x);
}
Elsewhere — in a subsystem, a module, or the loop — consume them by id:
double drive = bindingManager.checkAnalog("drive"); // 0 if unbound
double strafe = bindingManager.checkAnalog("strafe");
double turn = bindingManager.checkAnalog("turn");
boolean slow = bindingManager.checkBinding("slowMode"); // false if unbound
if (slow) {
drive *= 0.4;
strafe *= 0.4;
turn *= 0.4;
}
Because TeleOpPedroModule reads exactly the ids "drive",
"strafe", "turn", and "slowMode", wiring those four in
preload() is all it takes to drive the robot — see
OpMode and Modules.