Skip to content

Editing code in a nutshell

WebCoder49 edited this page Aug 31, 2023 · 4 revisions

🥜 Editing code: in a nutshell

Table of Contents
What's what in the code
Creating an OpMode
OpMode Examples
Testing Code

What's what in the 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.
image image 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.
  1. There are also external libraries not visible in this view. To show one, Ctrl+Click a reference to it in the code.
  • com.arcrobotics.ftclib FTCLib - our main library for hardware, etc. [Docs] [Reference]
  • com.qualcomm.robotcore.hardware Hardware - Use FTCLib instead of these if you can. [Reference]

Creating an OpMode

⚠️ Our method of creating an OpMode with our libraries is slightly different to the vanilla methods. Please be careful when looking at other documentation.

  1. 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 CamelCaseWhereWordsAreJoinedLikeThis), click "OK", then comment out the @Disabled line (Ctrl+/)

1 2 3
image image image

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
image image image

Creating a component

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:

  1. Everything contained in the component is inside its class, in a single file in the components folder, or imported as a separate class from a different folder.
  2. They are all documented.
  3. Wherever possible, FTCLib features are used to save time.
  4. Easily-understandable functions in the component like setTargetPosition can 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();
    }
}

OpMode Examples

Driver-Controlled (Iterative)

package org.firstinspires.ftc.teamcode.opModes;

import com.qualcomm.robotcore.eventloop.opmode.TeleOp;

import org.firstinspires.ftc.teamcode.libs.brightonCollege.modeBases.TeleOpModeBase;

/**
 * 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 class <ClassName> extends TeleOpModeBase {
    // Declare class members here

    @Override
    public void setup() {
        // Code to run once after `INIT` is pressed
    }

    @Override
    public void every_tick() {
        // Code to run in a loop after `PLAY` is pressed
    }
}

Autonomous (Iterative)

package org.firstinspires.ftc.teamcode.opModes;

import com.qualcomm.robotcore.eventloop.opmode.Autonomous;

import org.firstinspires.ftc.teamcode.libs.brightonCollege.modeBases.AutonomousModeBase;

/**
 * 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 class <ClassName> extends AutonomousModeBase {
    // Declare class members here

    @Override
    public void setup() {
        // Code to run once after `INIT` is pressed
    }

    @Override
    public void every_tick() {
        // Code to run in a loop after `PLAY` is pressed
    }
}

Autonomous (Linear)

package org.firstinspires.ftc.teamcode.opModes;

import com.qualcomm.robotcore.eventloop.opmode.Autonomous;
import com.qualcomm.robotcore.util.ElapsedTime;

import org.firstinspires.ftc.teamcode.libs.brightonCollege.modeBases.AutonomousLinearModeBase;

/**
 * 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 class <ClassName> extends AutonomousLinearModeBase {
    // Declare class members here
    private ElapsedTime runtime = new ElapsedTime();


    @Override
    public void run() {
        // Code to run once INIT is pressed
        waitForStart();
        // Code to run once PLAY is pressed
        runtime.reset();
        // Run until the driver presses STOP
        while (opModeIsActive()) {
        // Code to run in a loop
        telemetry.addData("Status", "Run Time: " + runtime.toString());
        telemetry.update();
        }
    }
}

Please click a heading to view the code.

  1. You're now ready to use the OpMode! Here are some vital classes from our library:
  • Inputs.gamepad1 and Inputs.gamepad2 - the GamepadEx classes for getting inputs from the driver. Please use gamepad1 most of the time. (Only works in Driver-Controlled)
  • TelemetryContainer.getTelemetry() - returns a Telemetry object used to print messages to the driver.
  • HardwareMapContainer.getMap() - returns a HardwareMap needed in some situations, e.g. with FTCLib.
  • HardwareMapContainer.motor0 through to HardwareMapContainer.motor3 - returns a Motor plugged into the port indicated by the number.
  • HardwareMapContainer.servo0 through to HardwareMapContainer.servo3 - returns a Servo plugged into the port indicated by the number.

Testing Code

  1. Anywhere, when not connected to the robot, click "Build" to check that the code can compile.
1 - Build the project 2 - View the logs
image image
  1. Install the code onto the robot as shown here.

Finally, please make sure you save and upload your changes.

Clone this wiki locally