Westlake

Vault

Official FTC references and reusable team code for quick lookup while you work.

Reference shelf

Lessons teach a skill in sequence. Use this shelf for official version details, current downloads, and optional deeper reading while you work.

RobotHardware

One team-owned place to map devices, establish safe defaults, and stop every output. Configuration names must match the active Robot Controller configuration exactly.

RobotHardware.java
package org.firstinspires.ftc.teamcode;

import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.hardware.DcMotorEx;
import com.qualcomm.robotcore.hardware.DcMotorSimple;
import com.qualcomm.robotcore.hardware.HardwareMap;

import java.util.Arrays;
import java.util.List;

public final class RobotHardware {
    public DcMotorEx frontLeft;
    public DcMotorEx frontRight;
    public DcMotorEx backLeft;
    public DcMotorEx backRight;

    private List<DcMotorEx> driveMotors;

    public void init(HardwareMap hardwareMap) {
        frontLeft = hardwareMap.get(DcMotorEx.class, "front_left_drive");
        frontRight = hardwareMap.get(DcMotorEx.class, "front_right_drive");
        backLeft = hardwareMap.get(DcMotorEx.class, "back_left_drive");
        backRight = hardwareMap.get(DcMotorEx.class, "back_right_drive");

        driveMotors = Arrays.asList(frontLeft, frontRight, backLeft, backRight);

        // Example only: reverse the side your physical wheel test requires.
        frontLeft.setDirection(DcMotorSimple.Direction.REVERSE);
        backLeft.setDirection(DcMotorSimple.Direction.REVERSE);

        for (DcMotorEx motor : driveMotors) {
            motor.setZeroPowerBehavior(DcMotor.ZeroPowerBehavior.BRAKE);
            motor.setPower(0.0);
        }
    }

    public void setDrivePowers(
            double frontLeftPower,
            double frontRightPower,
            double backLeftPower,
            double backRightPower
    ) {
        frontLeft.setPower(frontLeftPower);
        frontRight.setPower(frontRightPower);
        backLeft.setPower(backLeftPower);
        backRight.setPower(backRightPower);
    }

    public void stopDrive() {
        for (DcMotorEx motor : driveMotors) {
            motor.setPower(0.0);
        }
    }

    public void stopAll() {
        stopDrive();
        // Stop each mechanism here as the robot grows.
    }
}

Button edges

Use an edge when an action should happen once. Read the current value when behavior should remain active for as long as the driver holds the control.

Held
button == true
Slow mode, manual intake
Rising edge
false → true
Preset, toggle, reset
Falling edge
true → false
Release action, commit value
EdgeDetector.java
package org.firstinspires.ftc.teamcode;

public final class EdgeDetector {
    private boolean previous;
    private boolean current;

    // Call exactly once per control loop before reading rose() or fell().
    public void update(boolean value) {
        previous = current;
        current = value;
    }

    public boolean rose() {
        return current && !previous;
    }

    public boolean fell() {
        return !current && previous;
    }
}
TeleOp usage
private final EdgeDetector aButton = new EdgeDetector();

// Inside the OpMode loop:
aButton.update(gamepad2.a);

if (aButton.rose()) {
    arm.goToDeposit();
}

// A held control should still read the current value directly.
boolean slowMode = gamepad2.left_bumper;

// Alternative: if you do not use EdgeDetector, FTC SDK 11.2 provides:
// if (gamepad2.aWasPressed()) {
//     arm.goToDeposit();
// }

Prefer the FTC SDK edge methods when your project version includes them. The generic helper remains useful for sensor thresholds and other derived boolean signals.

Stop-aware, timeout-bounded loops

Every autonomous wait needs a success condition, a timeout, Stop-button awareness, and guaranteed zero output when the loop exits.

BoundedAutoStep.java
ElapsedTime runtime = new ElapsedTime();
String exitReason = "stopped";
runtime.reset();

try {
    while (opModeIsActive()) {
        if (targetReached()) {
            exitReason = "target";
            break;
        }

        if (runtime.seconds() >= 2.0) {
            exitReason = "timeout";
            break;
        }

        robot.setDrivePowers(0.25, 0.25, 0.25, 0.25);
        telemetry.addData("auto/elapsed_s", runtime.seconds());
        telemetry.addData("auto/exit", "running");
        telemetry.update();
    }
} finally {
    robot.stopAll();
}

telemetry.addData("auto/exit", exitReason);
telemetry.update();

These are starting patterns, not a substitute for the robot’s reviewed configuration map, physical low-power tests, or season-specific SDK verification.