Lesson 7.5: Keep Shared Hardware Classes Consistent Across OpModes
Technical Context
As robots become complex, putting all hardware mapping in a single OpMode file leads to unmaintainable "spaghetti code." Creating a dedicated Hardware Class (or Mechanism Class) allows you to define your hardware once and share it across every Autonomous and TeleOp program on the robot. If a motor port changes, you update one file: not every OpMode.
Why Shared Mechanism Classes Save Time
A mechanism class can use a custom init() method that accepts the HardwareMap from the parent OpMode. The mechanism does not automatically receive an OpMode's hardwareMap; passing the dependency explicitly lets the class perform its own registry lookups and makes it easier to reuse.
Passing HardwareMap into the mechanism constructor or init() method gives that class the dependency it needs without relying on a global variable. The mechanism class can then keep its hardware names, directions, and run modes together while the OpMode works through a smaller public interface.
Annotated Code
The mechanism class (separate file):
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.hardware.HardwareMap;
public class IntakeSystem {
private DcMotor intakeMotor;
// The OpMode passes its hardwareMap into this method
public void init(HardwareMap hwMap) {
intakeMotor = hwMap.get(DcMotor.class, "intake");
intakeMotor.setDirection(DcMotor.Direction.REVERSE);
intakeMotor.setPower(0);
}
// Clean public interface: OpMode never touches the motor directly
public void setIntakePower(double power) {
intakeMotor.setPower(power);
}
public void stop() {
intakeMotor.setPower(0);
}
}
Using the mechanism inside a TeleOp:
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
@TeleOp(name="Intake_TeleOp")
public class IntakeTeleOp extends OpMode {
private IntakeSystem intake = new IntakeSystem();
@Override
public void init() {
// Pass the OpMode's hardwareMap into the mechanism
intake.init(hardwareMap);
telemetry.addData("Status", "Intake ready");
}
@Override
public void loop() {
intake.setIntakePower(gamepad1.right_trigger);
}
}
Fill-in-the-Blank Practice
- To share hardware across files, we encapsulate the mapping logic into a
__________class. - The mechanism's
init()method must accept a__________object as a parameter so it can perform registry lookups. - Encapsulation is a best practice because it isolates hardware "quirks" (like reversed directions) from the
__________logic.
Show answers
- mechanism (or hardware) class
HardwareMap- main OpMode (match / driving) logic
Simulator Practice
Use the simulator below to practice wiring a reusable mechanism class into a TeleOp. The starter project reveals both SlideTeleOp.java and the supplied LinearSlide.java in the file tabs. Select LinearSlide.java to complete the mechanism's mapping and movement methods, then return to SlideTeleOp.java to initialize and drive it.
Any additional Java file you create with + starts with:
package org.firstinspires.ftc.teamcode;
The supplied mechanism file keeps its own DcMotor and HardwareMap imports. Imports apply to one source file only: importing DcMotor in the OpMode would not make it available in LinearSlide.java. LinearSlide itself needs no import in the OpMode because both classes use the same package. These are the Java package and import rules.
All tabs compile and run together, including when a helper tab is open. The + card can also import .java files, an exported Telemark project, or code from a completed lesson. Code saves in this browser for everyone, including guests; open an older lesson once to save its existing draft into this library. Use Export to keep a copy or move your code to another device.
A Team Gives Hardware One Owner
Titan Robotics Club constructs an actuator inside its subsystem and reads the device name from RobotParams. This direct SDK adaptation uses the same boundary:
public class LinearSlide {
private DcMotor motor;
public void init(HardwareMap hardwareMap) {
motor = hardwareMap.get(
DcMotor.class, RobotConfig.SLIDE_NAME);
}
}
The framework actuator and its parameter builder were replaced with DcMotor. The subsystem still owns the mapping, while configuration owns the name. Adapted from Team 3543 Titan Robotics Club's subsystem guide at a pinned commit under the MIT License.
Ready to move on?
Only mark complete if you genuinely understand the material. Your progress will be saved in this browser.
Stuck on this lesson?
Ask about anything on this page. It can see which lesson you have open and which part you are reading.