Example Code
Example Code
If you are just starting out, click the '+' (Add File) icon in the top left corner.
Enter your new file name, and then choose one of the many samples.
If you just want to drive a basic robot, select the "BasicOpMode_Linear" sample.
Select the "TeleOp" radio button, and then click "OK".
The sample you chose will be renamed to match the name you entered, and it
will appear on the "project files" list in the left pane.
To edit your code, just click on the desired file in the left hand pane,
and it will be loaded into this Code Editor window. Make any changes. You can also
use Ctrl-F (or Cmd-F on Macs) to search the file you are working on.
Once you are done, click the "Build Everything" icon at the bottom of this pane.
This will build your OpModes and report any errors.
If there are no errors, the OpModes will be stored on the Robot for immediate use.
## Samples
eg: The name's prefix describes the general purpose, which can be one of the
following:
For more help, visit the FTC Control System Wiki (https://github.com/FIRST-Tech-
Challenge/FtcRobotController/wiki)
## What's Java 8?
Java 8 provides more ways to help you write more concise, readable, and
maintainable code
for your robot.
```
/**
* As an illustration, the first line on our telemetry display will display the
* battery voltage. The idea here is that it's expensive to compute the voltage
* (at least for purposes of illustration) so you don't want to do it unless the
* data is <em>actually</em> going to make it to the driver station (recall that
* telemetry transmission is throttled to reduce bandwidth use.
* Note that getBatteryVoltage() below returns 'Infinity' if there's no voltage
* sensor attached.
*
* @see Telemetry#getMsTransmissionInterval()
*/
telemetry.addData("voltage", "%.1f volts", new Func<Double>() {
@Override public Double value() {
return getBatteryVoltage();
}
});
```
There's a few ways to rewrite the same snippet to be more concise by using
what's called a lambda (lamb-da) expression[1] from the new Java 8 editor support.
The part of the code that simply defines what's called an "anonymous class"
can be actually rewritten as a lambda expression.
As a general pattern, for a function that takes no arguments, you can remove
the class declaration, method return type, and method name and the compiler
will get what you are implying.
This leaves the lambda body intact and is a useful pattern if your return value
needs a multiline calculation.
In this case, we only have the method return taking a single line, so we can
"unwrap" the return expression:
```
() -> getBatteryVoltage()
```
This again leaves a bit of room to make more concise, applying the same pattern,
what can we remove?
```
this::getBatteryVoltage
```
This is called a method reference, which requires only two things, the object and
the method you want to call on the object,
Advanced note: the `this` comes from the `this` that was implied indirectly in the
anonymous class
usage through a capture, but now you actually need to add this `this` reference.
Put all together, the same snippet can be rewritten simply as:
```
telemetry.addData("voltage", "%.1f volts", this::getBatteryVoltage);
```
We're still bound by some limitations of the Android platform, you can check
https://developer.android.com/studio/write/java8-support-table for known
limitations for more advanced features.
0:
https://github.com/FIRST-Tech-Challenge/FtcRobotController/blob/00cbf344526d991ce33
452437018af9f119d22d1/FtcRobotController/src/main/java/org/firstinspires/ftc/
robotcontroller/external/samples/ConceptTelemetry.java#L110-L123
1: https://docs.oracle.com/javase/tutorial/java/javaOO/lambdaexpressions.html
2:
https://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html#accessing
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.Disabled;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.util.ElapsedTime;
/*
* This file contains an example of a Linear "OpMode".
* An OpMode is a 'program' that runs in either the autonomous or the teleop period
of an FTC match.
* The names of OpModes appear on the menu of the FTC Driver Station.
* When a selection is made from the menu, the corresponding OpMode is executed.
*
* This particular OpMode illustrates driving a 4-motor Omni-Directional (or
Holonomic) robot.
* This code will work with either a Mecanum-Drive or an X-Drive train.
* Both of these drives are illustrated at https://gm0.org/en/latest/docs/robot-
design/drivetrains/holonomic.html
* Note that a Mecanum drive must display an X roller-pattern when viewed from
above.
*
* Also note that it is critical to set the correct rotation direction for each
motor. See details below.
*
* Holonomic drives provide the ability for the robot to move in three axes
(directions) simultaneously.
* Each motion axis is controlled by one Joystick axis.
*
* 1) Axial: Driving forward and backward Left-joystick
Forward/Backward
* 2) Lateral: Strafing right and left Left-joystick Right and
Left
* 3) Yaw: Rotating Clockwise and counter clockwise Right-joystick Right
and Left
*
* This code is written assuming that the right-side motors need to be reversed for
the robot to drive forward.
* When you first test your robot, if it moves backward when you push the left
stick forward, then you must flip
* the direction of all 4 motors (see code below).
*
* Use Android Studio to Copy this Class, and Paste it into your team's code folder
with a new name.
* Remove or comment out the @Disabled line to add this OpMode to the Driver
Station OpMode list
*/
@Override
public void runOpMode() {
// Initialize the hardware variables. Note that the strings used here must
correspond
// to the names assigned during the robot configuration step on the DS or
RC devices.
frontLeftDrive = hardwareMap.get(DcMotor.class, "front_left_drive");
backLeftDrive = hardwareMap.get(DcMotor.class, "back_left_drive");
frontRightDrive = hardwareMap.get(DcMotor.class, "front_right_drive");
backRightDrive = hardwareMap.get(DcMotor.class, "back_right_drive");
//
###################################################################################
#####
// !!! IMPORTANT Drive Information. Test your motor directions.
!!!!!
//
###################################################################################
#####
// Most robots need the motors on one side to be reversed to drive forward.
// The motor reversals shown here are for a "direct drive" robot (the
wheels turn the same direction as the motor shaft)
// If your robot has additional gear reductions or uses a right-angled
drive, it's important to ensure
// that your motors are turning in the correct direction. So, start out
with the reversals here, BUT
// when you first test your robot, push the left joystick forward and
observe the direction the wheels turn.
// Reverse the direction (flip FORWARD <-> REVERSE ) of any wheel that runs
backward
// Keep testing until ALL the wheels move the robot forward when you push
the left joystick forward.
frontLeftDrive.setDirection(DcMotor.Direction.REVERSE);
backLeftDrive.setDirection(DcMotor.Direction.REVERSE);
frontRightDrive.setDirection(DcMotor.Direction.FORWARD);
backRightDrive.setDirection(DcMotor.Direction.FORWARD);
waitForStart();
runtime.reset();
// POV Mode uses left joystick to go forward & strafe, and right
joystick to rotate.
double axial = -gamepad1.left_stick_y; // Note: pushing stick
forward gives negative value
double lateral = gamepad1.left_stick_x;
double yaw = gamepad1.right_stick_x;
/*
frontLeftPower = gamepad1.x ? 1.0 : 0.0; // X gamepad
backLeftPower = gamepad1.a ? 1.0 : 0.0; // A gamepad
frontRightPower = gamepad1.y ? 1.0 : 0.0; // Y gamepad
backRightPower = gamepad1.b ? 1.0 : 0.0; // B gamepad
*/
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.Disabled;
import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.util.ElapsedTime;
import com.qualcomm.robotcore.util.Range;
/*
* This file contains an example of an iterative (Non-Linear) "OpMode".
* An OpMode is a 'program' that runs in either the autonomous or the teleop period
of an FTC match.
* The names of OpModes appear on the menu of the FTC Driver Station.
* When a selection is made from the menu, the corresponding OpMode
* class is instantiated on the Robot Controller and executed.
*
* This particular OpMode just executes a basic Tank Drive Teleop for a two wheeled
robot
* It includes all the skeletal structure that all iterative OpModes contain.
*
* Use Android Studio to Copy this Class, and Paste it into your team's code folder
with a new name.
* Remove or comment out the @Disabled line to add this OpMode to the Driver
Station OpMode list
*/
/*
* Code to run ONCE when the driver hits INIT
*/
@Override
public void init() {
telemetry.addData("Status", "Initialized");
// Initialize the hardware variables. Note that the strings used here as
parameters
// to 'get' must correspond to the names assigned during the robot
configuration
// step (using the FTC Robot Controller app on the phone).
leftDrive = hardwareMap.get(DcMotor.class, "left_drive");
rightDrive = hardwareMap.get(DcMotor.class, "right_drive");
// To drive forward, most robots need the motor on one side to be reversed,
because the axles point in opposite directions.
// Pushing the left stick forward MUST make robot go forward. So adjust
these two lines based on your first test drive.
// Note: The settings here assume direct drive on left and right wheels.
Gear Reduction or 90 Deg drives may require direction flips
leftDrive.setDirection(DcMotor.Direction.REVERSE);
rightDrive.setDirection(DcMotor.Direction.FORWARD);
/*
* Code to run REPEATEDLY after the driver hits INIT, but before they hit START
*/
@Override
public void init_loop() {
}
/*
* Code to run ONCE when the driver hits START
*/
@Override
public void start() {
runtime.reset();
}
/*
* Code to run REPEATEDLY after the driver hits START but before they hit STOP
*/
@Override
public void loop() {
// Setup a variable for each drive wheel to save power level for telemetry
double leftPower;
double rightPower;
// POV Mode uses left stick to go forward, and right stick to turn.
// - This uses basic math to combine motions and is easier to drive
straight.
double drive = -gamepad1.left_stick_y;
double turn = gamepad1.right_stick_x;
leftPower = Range.clip(drive + turn, -1.0, 1.0) ;
rightPower = Range.clip(drive - turn, -1.0, 1.0) ;
/*
* Code to run ONCE after the driver hits STOP
*/
@Override
public void stop() {
}
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.Disabled;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import com.qualcomm.robotcore.hardware.DcMotor;
import com.qualcomm.robotcore.util.ElapsedTime;
import com.qualcomm.robotcore.util.Range;
/*
* This file contains an minimal example of a Linear "OpMode". An OpMode is a
'program' that runs in either
* the autonomous or the teleop period of an FTC match. The names of OpModes appear
on the menu
* of the FTC Driver Station. When a selection is made from the menu, the
corresponding OpMode
* class is instantiated on the Robot Controller and executed.
*
* This particular OpMode just executes a basic Tank Drive Teleop for a two wheeled
robot
* It includes all the skeletal structure that all linear OpModes contain.
*
* Use Android Studio to Copy this Class, and Paste it into your team's code folder
with a new name.
* Remove or comment out the @Disabled line to add this OpMode to the Driver
Station OpMode list
*/
// Initialize the hardware variables. Note that the strings used here as
parameters
// to 'get' must correspond to the names assigned during the robot
configuration
// step (using the FTC Robot Controller app on the phone).
leftDrive = hardwareMap.get(DcMotor.class, "left_drive");
rightDrive = hardwareMap.get(DcMotor.class, "right_drive");
// To drive forward, most robots need the motor on one side to be reversed,
because the axles point in opposite directions.
// Pushing the left stick forward MUST make robot go forward. So adjust
these two lines based on your first test drive.
// Note: The settings here assume direct drive on left and right wheels.
Gear Reduction or 90 Deg drives may require direction flips
leftDrive.setDirection(DcMotor.Direction.REVERSE);
rightDrive.setDirection(DcMotor.Direction.FORWARD);
// Setup a variable for each drive wheel to save power level for
telemetry
double leftPower;
double rightPower;
// POV Mode uses left stick to go forward, and right stick to turn.
// - This uses basic math to combine motions and is easier to drive
straight.
double drive = -gamepad1.left_stick_y;
double turn = gamepad1.right_stick_x;
leftPower = Range.clip(drive + turn, -1.0, 1.0) ;
rightPower = Range.clip(drive - turn, -1.0, 1.0) ;
package org.firstinspires.ftc.teamcode;
import android.util.Size;
import com.qualcomm.robotcore.eventloop.opmode.Disabled;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import
org.firstinspires.ftc.robotcore.external.hardware.camera.BuiltinCameraDirection;
import org.firstinspires.ftc.robotcore.external.hardware.camera.WebcamName;
import org.firstinspires.ftc.vision.VisionPortal;
import org.firstinspires.ftc.vision.apriltag.AprilTagDetection;
import org.firstinspires.ftc.vision.apriltag.AprilTagProcessor;
import java.util.List;
/*
* This OpMode illustrates the basics of AprilTag recognition and pose estimation,
* including Java Builder structures for specifying Vision parameters.
*
* For an introduction to AprilTags, see the FTC-DOCS link below:
* https://ftc-docs.firstinspires.org/en/latest/apriltag/vision_portal/
apriltag_intro/apriltag-intro.html
*
* In this sample, any visible tag ID will be detected and displayed, but only tags
that are included in the default
* "TagLibrary" will have their position and orientation information displayed.
This default TagLibrary contains
* the current Season's AprilTags and a small set of "test Tags" in the high number
range.
*
* When an AprilTag in the TagLibrary is detected, the SDK provides location and
orientation of the tag, relative to the camera.
* This information is provided in the "ftcPose" member of the returned
"detection", and is explained in the ftc-docs page linked below.
* https://ftc-docs.firstinspires.org/apriltag-detection-values
*
* To experiment with using AprilTags to navigate, try out these two driving
samples:
* RobotAutoDriveToAprilTagOmni and RobotAutoDriveToAprilTagTank
*
* There are many "default" VisionPortal and AprilTag configuration parameters that
may be overridden if desired.
* These default parameters are shown as comments in the code below.
*
* Use Android Studio to Copy this Class, and Paste it into your team's code folder
with a new name.
* Remove or comment out the @Disabled line to add this OpMode to the Driver
Station OpMode list.
*/
@TeleOp(name = "Concept: AprilTag", group = "Concept")
private static final boolean USE_WEBCAM = true; // true for webcam, false for
phone camera
/**
* The variable to store our instance of the AprilTag processor.
*/
private AprilTagProcessor aprilTag;
/**
* The variable to store our instance of the vision portal.
*/
private VisionPortal visionPortal;
@Override
public void runOpMode() {
initAprilTag();
if (opModeIsActive()) {
while (opModeIsActive()) {
telemetryAprilTag();
// Push telemetry to the Driver Station.
telemetry.update();
/**
* Initialize the AprilTag processor.
*/
private void initAprilTag() {
// == CAMERA CALIBRATION ==
// If you do not manually specify calibration parameters, the SDK will
attempt
// to load a predefined calibration for your camera.
//.setLensIntrinsics(578.272, 578.272, 402.145, 221.506)
// ... these parameters are fx, fy, cx, cy.
.build();
// Set the stream format; MJPEG uses less bandwidth than default YUY2.
//builder.setStreamFormat(VisionPortal.StreamFormat.YUY2);
/**
* Add telemetry about AprilTag detections.
*/
private void telemetryAprilTag() {
// Step through the list of detections and display info for each one.
for (AprilTagDetection detection : currentDetections) {
if (detection.metadata != null) {
telemetry.addLine(String.format("\n==== (ID %d) %s", detection.id,
detection.metadata.name));
telemetry.addLine(String.format("XYZ %6.1f %6.1f %6.1f (inch)",
detection.ftcPose.x, detection.ftcPose.y, detection.ftcPose.z));
telemetry.addLine(String.format("PRY %6.1f %6.1f %6.1f (deg)",
detection.ftcPose.pitch, detection.ftcPose.roll, detection.ftcPose.yaw));
telemetry.addLine(String.format("RBE %6.1f %6.1f %6.1f (inch, deg,
deg)", detection.ftcPose.range, detection.ftcPose.bearing,
detection.ftcPose.elevation));
} else {
telemetry.addLine(String.format("\n==== (ID %d) Unknown",
detection.id));
telemetry.addLine(String.format("Center %6.0f %6.0f (pixels)",
detection.center.x, detection.center.y));
}
} // end for() loop
} // end class
package org.firstinspires.ftc.teamcode;
import com.qualcomm.robotcore.eventloop.opmode.Disabled;
import com.qualcomm.robotcore.eventloop.opmode.OpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
/*
* Demonstrates how to use an OpMode to store data in the blackboard and retrieve
it.
* This is useful for storing information in Auto and then retrieving it in your
TeleOp.
*
* Be aware that this is NOT saved across power reboots or downloads or robot
resets.
*
* You also need to make sure that both the storing and retrieving are done using
the same
* type. For example, storing a Double in the blackboard and retrieving it as an
Integer
* will fail when you typecast it.
*
* The blackboard is a standard hashmap so you can use methods like:
* put, get, containsKey, remove, etc.
*/
@TeleOp(name = "Concept: Blackboard", group = "Concept")
/**
* This method will be called once, when the INIT button is pressed.
*/
@Override
public void init() {
// This gets us what is in the blackboard or the default if it isn't in
there.
Object timesStarted = blackboard.getOrDefault(TIMES_STARTED_KEY, 0);
blackboard.put(TIMES_STARTED_KEY, (int) timesStarted + 1);
/**
* This method will be called repeatedly during the period between when
* the START button is pressed and when the OpMode is stopped.
* <p>
* If the left bumper is pressed it will store the value "RED" in the
blackboard for alliance.
* If the right bumper is pressed it will store the value "BLUE" in the
blackboard for alliance.
* <p>
* You'll notice that if you quit the OpMode and come back in, the value will
persist.
*/
@Override
public void loop() {
if (gamepad1.left_bumper) {
blackboard.put(ALLIANCE_KEY, "RED");
} else if (gamepad1.right_bumper) {
blackboard.put(ALLIANCE_KEY, "BLUE");
}
telemetry.addData("Alliance", blackboard.get(ALLIANCE_KEY));
}
}
package org.firstinspires.ftc.teamcode;
import com.qualcomm.hardware.bosch.BNO055IMU;
import com.qualcomm.hardware.bosch.JustLoggingAccelerationIntegrator;
import com.qualcomm.robotcore.eventloop.opmode.Disabled;
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
import com.qualcomm.robotcore.eventloop.opmode.TeleOp;
import org.firstinspires.ftc.robotcore.external.Func;
import org.firstinspires.ftc.robotcore.external.navigation.Acceleration;
import org.firstinspires.ftc.robotcore.external.navigation.AngleUnit;
import org.firstinspires.ftc.robotcore.external.navigation.AxesOrder;
import org.firstinspires.ftc.robotcore.external.navigation.AxesReference;
import org.firstinspires.ftc.robotcore.external.navigation.Orientation;
import org.firstinspires.ftc.robotcore.external.navigation.Position;
import org.firstinspires.ftc.robotcore.external.navigation.Velocity;
import java.util.Locale;
/*
* This OpMode gives a short demo on how to use the BNO055 Inertial Motion Unit
(IMU) from AdaFruit.
*
* Note: this is a Legacy example that will not work with newer Control/Expansion
Hubs that use a different IMU
* Please use the new SensorIMUOrthogonal or SensorIMUNonOrthogonal samples for a
more universal IMU interface.
*
* Use Android Studio to Copy this Class, and Paste it into your team's code folder
with a new name.
* Remove or comment out the @Disabled line to add this OpMode to the Driver
Station OpMode list
*
* @see <a href="http://www.adafruit.com/products/2472">Adafruit IMU</a>
*/
@TeleOp(name = "Sensor: BNO055 IMU", group = "Sensor")
//-----------------------------------------------------------------------------
-----------------
// Main logic
//-----------------------------------------------------------------------------
-----------------
// Set up the parameters with which we will use our IMU. Note that
integration
// algorithm here just reports accelerations to the logcat log; it doesn't
actually
// provide positional information.
BNO055IMU.Parameters parameters = new BNO055IMU.Parameters();
parameters.angleUnit = BNO055IMU.AngleUnit.DEGREES;
parameters.accelUnit = BNO055IMU.AccelUnit.METERS_PERSEC_PERSEC;
parameters.calibrationDataFile = "BNO055IMUCalibration.json"; // see the
calibration sample OpMode
parameters.loggingEnabled = true;
parameters.loggingTag = "IMU";
parameters.accelerationIntegrationAlgorithm = new
JustLoggingAccelerationIntegrator();
//-----------------------------------------------------------------------------
-----------------
// Telemetry Configuration
//-----------------------------------------------------------------------------
-----------------
void composeTelemetry() {
telemetry.addLine()
.addData("status", new Func<String>() {
@Override public String value() {
return imu.getSystemStatus().toShortString();
}
})
.addData("calib", new Func<String>() {
@Override public String value() {
return imu.getCalibrationStatus().toString();
}
});
telemetry.addLine()
.addData("heading", new Func<String>() {
@Override public String value() {
return formatAngle(angles.angleUnit, angles.firstAngle);
}
})
.addData("roll", new Func<String>() {
@Override public String value() {
return formatAngle(angles.angleUnit, angles.secondAngle);
}
})
.addData("pitch", new Func<String>() {
@Override public String value() {
return formatAngle(angles.angleUnit, angles.thirdAngle);
}
});
telemetry.addLine()
.addData("grvty", new Func<String>() {
@Override public String value() {
return gravity.toString();
}
})
.addData("mag", new Func<String>() {
@Override public String value() {
return String.format(Locale.getDefault(), "%.3f",
Math.sqrt(gravity.xAccel*gravity.xAccel
+ gravity.yAccel*gravity.yAccel
+ gravity.zAccel*gravity.zAccel));
}
});
}
//-----------------------------------------------------------------------------
-----------------
// Formatting
//-----------------------------------------------------------------------------
-----------------