Modules
A Module is an OpMode-shaped unit of behavior. It has the same lifecycle hooks as an OpMode and is installed into a ModularOpMode, which drives it for you — a clean way to package cross-cutting robot behavior and reuse it across OpModes.
What a Module is
The abstract Module class mirrors the FTC OpMode lifecycle exactly, with five
hooks:
| Hook | Called |
|---|---|
void init() | once, when the OpMode initializes. |
void init_loop() | repeatedly during init, after init() and before start(), while the driver is on the init screen. |
void start() | once, when the OpMode starts (play pressed). |
void loop() | every loop. |
void stop() | once, when the OpMode ends. |
You install a module into a ModularOpMode with
installModule(module), and from then on the OpMode calls each of the module's hooks at
the matching point in its own lifecycle. You never invoke the hooks yourself.
Built-in modules
Module
The base class. Extend it and implement the five lifecycle hooks to write your own reusable behavior.
NullModule
A module whose hooks all do nothing. A safe placeholder or default where a module is required but no behavior is wanted.
BindingModule
Runs an action whenever a binding fires, edge-wise — once
each time the binding transitions from inactive to active. The constructor takes a
BindingManager, a Binding, and a Runnable; it registers the
binding with the manager immediately on construction (via
bindingManager.replaceBinding(binding)) and remembers the binding's id. Every
loop() it reads bindingManager.checkBinding(id) and, on each rising edge,
runs the action once.
installModule(new BindingModule(
bindingManager,
new Binding("shoot", gamepad1::a),
() -> shooter.fire())); // runs once each time A is newly pressed
LambdaModule
Builds a module from four lambdas — init, start, loop,
stop — for quick inline behavior without declaring a dedicated class.
(init_loop is a no-op for this module.)
installModule(new LambdaModule(
() -> telemetry.addLine("init"), // init
() -> timer.reset(), // start
() -> telemetry.update(), // loop
() -> {})); // stop
Pedro 3.0 TeleOpPedroModule
A ready-made driving module that runs a full field/robot TeleOp drive loop through a
PedroPathing Follower. It reads four BindingManager inputs — the analog
ids "drive", "strafe", and "turn", plus the boolean
"slowMode" — and drives the follower every loop.
Constructors take a Follower, a starting Pose, a
BindingManager, and an optional slow-mode multiplier (default 1). Each
constructor calls follower.setPose(startingPose) to seed the robot's pose.
TeleOpPedroModule(Follower follower, Pose startingPose, BindingManager bindingManager)
TeleOpPedroModule(Follower follower, Pose startingPose, BindingManager bindingManager,
double slowModeMultiplier)
Wire up the inputs with setBindings(...), which registers the four ids for you:
void setBindings(DoubleSupplier drive, DoubleSupplier strafe,
DoubleSupplier turn, BooleanSupplier slowMode)
Behavior across the lifecycle:
init()callsfollower.update()once.loop()callsfollower.manual(drive, strafe, turn)each loop; when the"slowMode"binding is active,driveandstrafeare scaled by the slow-mode multiplier (turnis left unscaled).
startTeleopDrive()
call — invoking follower.manual(...) each loop puts the follower into MANUAL mode on
its own. The drive powers are applied by follower.update(), which must run every loop
(the OpMode's follower update covers this).Installing a drive module with bindings
Install the drive module alongside your drivetrain and wire the required bindings:
public class TeleOp extends ModularOpMode {
@Override
public void initialize() {
Follower follower = Constants.createFollower(hardwareMap);
Pose start = new Pose(0, 0, 0);
TeleOpPedroModule drive =
new TeleOpPedroModule(follower, start, bindingManager, 0.4); // 40% in slow mode
drive.setBindings(
() -> -gamepad1.left_stick_y, // "drive"
() -> gamepad1.left_stick_x, // "strafe"
() -> gamepad1.right_stick_x, // "turn"
() -> gamepad1.right_bumper); // "slowMode"
installModule(drive);
}
}
Holding the right bumper scales drive and strafe to 40% for fine
positioning; releasing it returns to full speed.
TeleOpPedroModule uses
com.pedropathing.follower.Follower, com.pedropathing.math.Pose,
follower.setPose(...), follower.manual(...), and
follower.update(). These replace the pre-3.0 TeleOp-drive APIs and are a breaking
change from older PedroPathing versions.