-
Notifications
You must be signed in to change notification settings - Fork 3
Editing code in a nutshell
| Table of Contents |
|---|
| What's what in the code |
| Creating an OpMode |
| OpMode Examples |
| Creating a Component |
| Testing Code |
| 1. Click the bar above the files and select "Android" | 2. Please see the following diagram for the useful code files we can edit. They will be commented with documentation. |
|---|---|
![]() |
The libs.brightonCollege folder is outdated and has been removed as it overcomplicates matters. In its place is a components folder for storing components as described below. |
- There are also external libraries not visible in this view. To show one,
Ctrl+Clicka reference to it in the code.
-
com.arcrobotics.ftclibFTCLib - our main library for hardware, etc. [Docs] [Reference] -
com.qualcomm.robotcore.hardwareHardware - Use FTCLib instead of these if you can. [Reference]
❕ If you programmed in last year's team, the code would have been slightly different. To make things simpler, this year we are not using "our own library" and instead are using the default FTCLib way of doing things.
- Either:
a) Right-click the file and copy your OpMode from the external.samples folder, then paste it in our opModes folder (see above). Rename it (using PascalCaseWhereWordsAreJoinedLikeThis), click "OK", then comment out the @Disabled line (Ctrl+/)
| 1 | 2 | 3 |
|---|---|---|
![]() |
![]() |
![]() |
or:
b) Right-click our opModes folder, create a new Java class, give it a name, and paste one of the templates below into the file. Click the first package line where an error may appear and then Alt+Enter and Enter, to fix it if necessary. Then, replace "<ClassName>" with the name you just used for the class.
| 1 | 2 | 3 |
|---|---|---|
![]() |
![]() |
![]() |
Please click a heading to view the code.
Driver-Controlled (Iterative)
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.OpMode;
/**
* TODO: Fill in
* Description: [Fill in]
* Hardware:
* [motor0] Unused
* [motor1] Unused
* [motor2] Unused
* [motor3] Unused
* [servo0] Unused
* [servo1] Unused
* [servo2] Unused
* [servo3] Unused
* Controls:
* [Button] Function
*/
@TeleOp(name="<OpMode name>", group="<OpMode group name>")
public abstract class <ClassName> extends OpMode {
// TODO: Declare class members here
@Override
public void init() {
// TODO: Code to run once after `INIT` is pressed
}
@Override
public void loop() {
// TODO: Code to run repeatedly after `PLAY` is pressed
CommandScheduler.getInstance().run(); // Trigger FTCLib commands if necessary
telemetry.update(); // Update telemetry (output stream on Driver Station)
}
}
Driver-Controlled (Linear)
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
/**
* TODO: Fill in
* Description: [Fill in]
* Hardware:
* [motor0] Unused
* [motor1] Unused
* [motor2] Unused
* [motor3] Unused
* [servo0] Unused
* [servo1] Unused
* [servo2] Unused
* [servo3] Unused
* Controls:
* [Button] Function
*/
@TeleOp(name="<OpMode name>", group="<OpMode group name>")
public abstract class <ClassName> extends LinearOpMode {
@Override
public void runOpMode() {
// TODO: Code to run once after the `INIT` button is pressed.
waitForStart();
// TODO: Code to run once after the `PLAY` button is pressed.
while (opModeIsActive()) {
// TODO: Code to run repeatedly after the `PLAY` button is pressed and until the `STOP` button is pressed.
CommandScheduler.getInstance().run(); // Trigger FTCLib commands if necessary
telemetry.update(); // Update telemetry (output stream on Driver Station)
}
}
}
Autonomous (Iterative)
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.OpMode;
/**
* TODO: Fill in
* Description: [Fill in]
* Hardware:
* [motor0] Unused
* [motor1] Unused
* [motor2] Unused
* [motor3] Unused
* [servo0] Unused
* [servo1] Unused
* [servo2] Unused
* [servo3] Unused
*/
@Autonomous(name="<OpMode name>", group="<OpMode group name>")
public abstract class <ClassName> extends OpMode {
// TODO: Declare class members here
@Override
public void init() {
// TODO: Code to run once after `INIT` is pressed
}
@Override
public void loop() {
// TODO: Code to run repeatedly after `PLAY` is pressed
CommandScheduler.getInstance().run(); // Trigger FTCLib commands if necessary
telemetry.update(); // Update telemetry (output stream on Driver Station)
}
}
Autonomous (Linear)
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
/**
* TODO: Fill in
* Description: [Fill in]
* Hardware:
* [motor0] Unused
* [motor1] Unused
* [motor2] Unused
* [motor3] Unused
* [servo0] Unused
* [servo1] Unused
* [servo2] Unused
* [servo3] Unused
*/
@Autonomous(name="<OpMode name>", group="<OpMode group name>")
public abstract class <ClassName> extends LinearOpMode {
@Override
public void runOpMode() {
// TODO: Code to run once after the `INIT` button is pressed.
waitForStart();
// TODO: Code to run once after the `PLAY` button is pressed.
while (opModeIsActive()) {
// TODO: Code to run repeatedly after the `PLAY` button is pressed and until the `STOP` button is pressed.
CommandScheduler.getInstance().run(); // Trigger FTCLib commands if necessary
telemetry.update(); // Update telemetry (output stream on Driver Station)
}
}
}- You're now ready to use the OpMode!
If you want to code a modular system like an arm, the drivetrain, an intake, etc., it is good practise to make a specific class in a specific file containing only that class in the components folder. Use Javadocs to describe each method's purpose (this linked way to generate them will work in Android Studio, which is a version of "IntelliJ").
Please click here for an example.
This is quite complicated - please don't feel you need to understand everything. Please just take away these key points:
- Everything contained in the component is inside its class, in a single file in the
componentsfolder, or imported as a separate class from a different folder. - They are all documented.
- Wherever possible, FTCLib features are used to save time.
- Easily-understandable functions in the component like
setTargetPositioncan be called from an OpMode.
Path: TeamCode/src/main/java/org/firstinspires/ftc/teamcode/components/LiftComponent.java
package org.firstinspires.ftc.teamcode.components;
import com.acmerobotics.dashboard.config.Config;
import com.arcrobotics.ftclib.controller.PIDController;
import com.arcrobotics.ftclib.controller.wpilibcontroller.SimpleMotorFeedforward;
import com.arcrobotics.ftclib.hardware.motors.Motor;
// Old packages that no longer exist for this year, but you can find them in the brightonCollege repository and copy them over if needed.
import org.firstinspires.ftc.teamcode.libs.brightonCollege.motors.BCLibMotor;
import org.firstinspires.ftc.teamcode.libs.brightonCollege.motors.MotorVelocityController;
import org.firstinspires.ftc.teamcode.libs.brightonCollege.motors.TrapezoidalProfile;
import org.firstinspires.ftc.teamcode.libs.brightonCollege.motors.TrapezoidalProfileMotor;
/**
* Lift with pulleys which lifts to a certain height
*/
@Config
public class LiftComponent {
/**
* An enum that contains the possible lift positions
*/
public enum LiftPosition {
GROUND(0),
LOW(1200),
MIDDLE(2050),
HIGH(2550);
private final int counts;
LiftPosition(int counts) {
this.counts = counts;
}
public double getCounts(){
return this.counts;
}
}
/**
* The Core Hex Motor used to move the lift from the bottom
* Static to allow it being read from the dashboard
*/
public Motor motor;
public final static double MAX_TICKS_PER_SECOND = 2000;
public TrapezoidalProfileMotor trapezoidalProfileMotor;
/**
* The number of counts needed to reach the initial position
*/
private final int initialPositionCounts;
/**
* Create a {@code LiftComponent}
* @param motor The Motor used to move the lift
*/
public LiftComponent(BCLibMotor motor, LiftPosition initialPosition) {
MotorVelocityController motorVelocityController = new MotorVelocityController(motor,
MAX_TICKS_PER_SECOND,
new PIDController(0, 0, 0),
new SimpleMotorFeedforward(120, 0.6, 0),
(counts) -> 170
);
trapezoidalProfileMotor = new TrapezoidalProfileMotor(motorVelocityController, new TrapezoidalProfile(MAX_TICKS_PER_SECOND, 3000));
// Reset the encoder counts to start from the initial position
motor.resetEncoder();
initialPositionCounts = initialPosition.counts;
this.motor = motor;
setTargetPosition(initialPosition);
}
/**
* Start moving the motor to a given position
* @param position The desired final position of the arm
*/
public void setTargetPosition(LiftPosition position) {
trapezoidalProfileMotor.setTargetPosition(position.counts - initialPositionCounts);
}
public void adjustTargetPosition(int changeCounts) {
trapezoidalProfileMotor.setTargetPosition(this.motor.getCurrentPosition() + changeCounts);
}
/**
* Runs the motor at the given speed in an appropriate mode. Needs to be called every tick
*/
public void run(){
trapezoidalProfileMotor.run();
}
}- Anywhere, when not connected to the robot, click "Build" to check that the code can compile.
| 1 - Build the project | 2 - View the logs |
|---|---|
![]() |
![]() |
Finally, please make sure you save and upload your changes.
| Shortcuts: | 🧑💻 Code |
🏠 Wiki Home |
🧾 FTCLib Docs |
☑️ Project |
|---|

The 






