Middle School

Explore an example program that uses the Xbox controller to drive in Arcade (one joystick) mode.

Understand driving under joystick control using one joystick to control both motors (Arcade mode).


Lets look at another style of motor control (driving) called arcade. In arcade mode, a single joystick controls both forward/backward motion but also left and right. This allows the robot to be driven with one finger, typically the thumb.

In arcade mode, the joystick y axis controls the forward and reverse motion of the robot. You will need to set both motors to the power level indicated by the y axis deflection. That controls forward and backward motion. So how do we turn? We use the x axis (side to side) deflection to cause the motors to run at different speeds by adding the x value to one motor power level and subtracting the x value from the other motor power level. Here is the code:

Here we are using the x and y axis deflection values from the right joystick only. We combine the x and y values to get the motor power setting. Again, which side is added to and which is subtracted from is determined by your motor gearing which determines the rotation direction of the motor. In our test case negative y axis values make the motors turn in the direction that yields forward motion. Since the joystick x axis returns negative values for left deflection, for a left turn (for example) we subtract the x value from the left motor (minus a minus) yielding a positive value for the left motor (backward) and add a negative yielding a negative value for the right motor (forward). If no y deflection is present, the left motor turns backward and the right forward and the robot spins left. When you add some y deflection the spin turns into an arc.

Arcade driving is more complex to understand and program and more difficult to operate but may make sense for some robots and some drivers.

This sample and the previous one introduces the idle() method which is part of the super class LinearOpMode. When you program a loop as we have here, it is possible and likely for that loop to run without interruption, monopolizing the phone cpu  and causing other parts of the robot controller application, like the part that communicates with the driver station phone for example, to be starved for cpu time and not function. The idle() method interrupts your loop momentarily and allows the other classes in the robot controller app to get some cpu time to perform thier functions before resuming your loop.

Copy and paste this code into a new class called DriveArcade, compile and demonstrate arcade mode driving.



Explore driving the robot with two joysticks (Tank mode) on a controller.

Understand Tank mode driving and using input from two joysticks to drive the robot.


Now lets look at a teleop example. Here we will use the joysticks on one of the Xbox controllers to drive the robot. We will use tank style driving. In tank mode each joystick controls the motor on one side of the robot. Moving the joystick forward or backward will cause the motor on the corresponding side of the robot to turn in that direction and the power level will be determined by how much the joystick is moved off of center. In this mode, to drive straight you have to move each joystick the same amount. Varying the deflection of the joysticks causes the robot to turn. Here is the code:

Here we are using the built-in reference variable for the left gamepad. We are interested in the y axis which is forward and backward.The joysticks return negative values when pushed forward and positive when pushed backward. The test robot also uses negative values to go forward so you can set the motor power directly from the joystick y axis value. If your robot needs positive values to go forward, you would need to reverse the sign of the y axis value.

We also introduce an object in the FTC SDK API, Range. This object exposes a number of static functions (don't need an instance) useful in robot control. Since the motor power level ranges from -1 to +1, we will use the range.clip() function to apply those limits to the right and left values to make sure the input never exceeds the allowed power values. While the values returned from the joystick should never actually exceed the motor power limits, it is good practice to be sure.

Finally, we use the built-in function opModeIsActive() to determine when we should stop the driving loop and exit the program. This function returns true when the OpMode is running and false when stopped.

Copy and paste this code into a new class called DriveTank, compile and demonstrate tank mode driving.

At this point, you are probably getting tired of disconnecting your controller phone from the robot and connecting it to your PC with a USB cable to deploy your code. There is a better way, deploying over WiFi. Check out this lesson.



Instructions on deploying code to the robot controller over WiFi instead of USB cable.

Understand how to deploy code over WiFi.


As you have no doubt learned, deploying code with a USB cable is time consuming and means taking the controller phone off the robot. When you are developing actual robot code, you will be doing this a lot. There is a better way.

You can deploy your code over a WiFi network instead of using a cable. This is much quicker and leaves the controller phone on the robot. Here are the instructions on how to do it.

Assuming you have a local area network created by a WiFi router, you connect your development PC to that network and also the robot controller phone. On the phone, go to Settings, WiFi, and select you local network and connect to it. You should mark it to automatically connect. After connecting, on the lower right of the available WiFi networks display is a three dot menu. Open it and go to Advanced. Scroll to the bottom looking for the IP Address. This is the address assigned to the phone by the router. This IP address needs to be that same value every time the phone connects. If you see this not happening, you will need to configure the router's DHCP component to assign a fixed IP address to the phone's hardware (MAC) address (shown above the IP address).

When this is done, upload the attached text file to a location on your development PC. Edit the file to reflect your phone's IP address. Save the file and then rename to change the extension from .txt to .bat. This will make it an executable command file. You should also create a shortcut to this file on your desktop as you will be running this command file often.

With all this done, you attach the phone to the PC with the USB cable. When the PC has recognized the phone, run the command file. This will enable communication with the phone over the WiFi network using the phone's IP address. When the command file has completed, disconnect the phone and place on the robot. Now, when you compile in AS, the networked controller phone will be available as a deployment target. Compiled code will be sent to the phone over the network connection.


Attached Resource: 


Explore making a robot drive in a circle.

Understand how to make curved turns.


Now lets look at an example that drives the robot in a circle. The key idea here is that if you drive the motors in the same direction but at different power levels (speeds) the robot will drive in an arc and if it runs long enough that arc becomes a circle. Here is the code:

Copy and paste this code into a new OpMode class called DriveCircle and demonstrate your robot driving in a circle. You will need to adjust the power levels and sleep time to complete the circle. The power levels and time will depend on the motor placement and gearing of your robot.



Explore how to make turns in robot code by programming the robot to drive in a square pattern.

Understand how to make the robot turn right angles and how to use time delays.

Now lets expand on the previous example. This OpMode shows changing direction, use of a for loop and time delays to drive in a square pattern by programming only two of the moves needed (drive straight then turn).

Note that the robot steers or changes direction by varying the motor power being applied to each side. If the motors are not turning at the same power level in the same direction, the robot will turn. This is called skid steering.
Copy and paste this code into a new OpMode class called DriveSquare and demonstrate your robot driving in a square. You may need to adjust the sleep times to get accurate 90 degree turns to complete the square. Note that because of the use of the for loop and the code design that moves forward then turns for each of the four parts of the square, the robot will turn one extra time. An exercise for you is to modify the program to eliminate the extra turn.


Explore example code that shows how to drive a robot forward and then stop.

Understand basic motor control and work through an exercise in actually programming a robot.


So lets do some actual robot programming. Assuming you have constructed a simple robot chassis with two DC motors driving two wheels, one on the left and one on the right side of the robot, we will also assume you have configured the controller phone for this hardware and named the motors left_motor and right_motor. Given all this, we can write a simple LinearOpMode to drive the robot forward for 2 seconds and then stop:

Notice the method call rightMotor.setDirection(DCMotor.Direction.REVERSE). Since the motors are on opposite sides of the robot, for both wheels to turn the same direction and generate forward motion, one of the motors must turn in the opposite of its normal direction. Here we select the right motor and reverse the direction of any power setting we give it. Now both motors will turn in the same direction relative to the front of the robot. You may have to experiment to determine which motor should be reversed. Note the use of the enum data type exposed by the DCMotor class: Direction.REVERSE. We could have figured out what constant value to use here to indicate reverse direction but the enum makes it very easy to set the correct value. You can see the other choices by typing a period right after Direction which causes AS to show you the available choices.

Note that if your robot actually drives backwards, you need to reverse the sign of the power value in the SetPower() method calls. SetPower accepts values in the range of -1.0 to +1.0 with 0 being no power. The sign controls the direction, forward or backward. Note that forward and backward are relative to the way you have your motors mounted and what gearing you use to connect the motors to the wheels, not mention the idea of which end of your robot you define as the "front". For each robot you build you will have to experimentally determine the appropriate sign for "forward".
Note the use of the sleep() method. This causes your program to wait (block or delay) for the number of milliseconds specified. 1000 milliseconds equals 1 second. The power settings on your motors will remain in effect during the wait.
Note that after each call to telemetry.addData(), we call telemetry.update(). Update sends any preceeding data added with the addData method to the Driver Station. In Linear OpModes you must call telemetry.update() to send telemetry data to the DS. In regular OpModes, this update is done automatically when the loop() or init_loop() methods end.
You can now go into Android Studio to the ftc_app-master project. Locate the org.firstinspires.ftc.teamcode package node under TeamCode\java in the project navigation pane. Right click on package and select New, then Java Class. Give the class the name DriveForward. This will create a new empty class file in the opmodes directory. Double click that class file to open it in the editor window. Copy all the code above and paste into the class file replacing all of the existing contents.

The OpMode is registered with the FtcRobotContoller app with the @Autonomous annotation before the class name. This categorizes the OpMode as Autonomous and puts it in a group called "Exercises". You can un-comment the @Disabled annotation to remove the OpMode from the list of OpModes that appear on the Driver Station without having to remove the class from the project.

Note the annotation @Overrides on the runOpMode() function. This tells the Java compiler that we intended to have this runOpMode() function replace the function with the same name in the base OpMode class.
Next unplug your controller phone from the robot and plug it into your PC. When the phone is recognized click the green arrow button (top center of the AS menu bar). This will launch the compile and deployment process. You will be prompted to select your phone on a list of deployment targets and approve the download of the program. Two notes: the downloaded program is called an APK in Android parlance, and the first compile you do after starting AS make take some time whereas subsequent compiles should be quick. When the download has completed, the new controller app on your phone should restart.
Now plug the controller phone back into the robot. When the controller and driver station phones have connected and the controller has connected to the robot, you can look at the OpMode list on the driver station app. You should see DriveForwardThenStop in the OpMode list. Select it as the current OpMode. Press Init and then press Start to test your program. Your robot should drive forward for 2 seconds and then stop. You should see the telemetry messages at the bottom of the driver station app.
You can now experiment with different power settings and directions and different amounts of time by changing the program, compiling and deploying to the robot.
Note that in addition to the Java and FTC SDK documentation mentioned earlier, if you have questions about a class or method you can place the cursor over the name of an instance of that class or method and press ctrl-q. This will open a window that will contain any documentation available for the selected item.


Explore how physical robot hardware devices are mapped to names that can be used in programs to access those devices.

Understand robot hardware mapping including controller phone configuration files and how to access hardware devices in software via the mapping scheme.


A key function of the FTC SDK, and of any robotics API, is to provide access to the physical hardware of a robot to the software. A way must be provided to allow programmers to identify, in software, hardware devices on the robot so that they can write programs that interact with that hardware. On the Tetrix/FTC platform, this is called hardware mapping.

Hardware mapping consists of two parts, hardware configuration on the controller phone and hardware mapping in your OpMode class.

When the controller phone is attached to the robot's Core Power Distribution Module, the various control modules and devices plugged into the modules should be recognized by the phone. This is called scanning, and it is performed each time the phone is connected (or the robot is powered on). This set of hardware information is called a configuration. You may have more that one configuration stored on the phone. You access the configuration by clicking the three vertical dots in the upper right corner of the controller app main screen. On the menu, select Settings and then Configure Robot. If you already have one or more configuration files, they will be listed. If you have no configuration files, you will shown a list of the hardware controllers recognized by the controller app.

We will get into the details of the hardware configuration in a moment. Once a configuration has been created, when you are done you click Save Configuration at the bottom of the controller hardware list. This will save the configuration into a file, which you will be prompted to assign a name. After that you will see the list of available configuration files. For each file, you can Edit (change), Activate or Delete. Click Activate to make the selected configuration the current active configuration, which will be displayed in the title bars of each screen. Then use the back button to return to the main screen. The controller will make sure it can reach each controller module in the configuration and if there are no problems, the main screen should display Robot Status as running and Op Mode as Stop Robot, with no error messages below that. The controller is now ready to run the robot.

When editing a hardware configuration you access each controller module and for each hardware device recognized by that module, assign a unique name by which you will access that device in your programs. You can also assign more meaningful names to the controller modules themselves though this is generally not needed. 

When you click on a motor or servo controller, you will see a list of the ports the controller has. You will have plugged motors or servos into these ports when constructing your robot. On the list, check the attached box next to a port if you have attached a device to that port. Then assign a meaningful name to that device. For instance, if you have the motor on the left side of your robot plugged into port 1, you could assign the name left_motor to port 1. This name is what you will use in your OpMode to control that motor. So configuration is all about telling your software which hardware devices (motors, servos, sensors) are on your robot, which port they are plugged into and assigning the device a name by which it will be known in your program.

Here is a lesson that describes the configuation process in more detail.

New for 2017-18 season is the Rev Robotics Expansion Hub. This device replaces the 3 controller modules of the Modern Robotics control scheme. You plug all your motors and sensors into the Expansion Hub(s) (Hubs can be daisy-chained). The process of creating the hardware configuration file on the controller phone is very much the same as with the Modern Robotics modules, but there is just one control module, the Hub. Here is a detailed discussion of creating the hardware configuration file for the Expansion Hub.

Once you have a hardware configuration file defined and active on your controller phone, you can proceed to the software side of hardware mapping.

In order to control your robot, you will need to create objects that control each of your hardware devices and connect the objects to the actual hardware devices. This is done through the hardwareMap static classes. For example, lets say our robot has two DC motors, named left_motor and right_motor in the phone configuration and we want to control them in code:

Here we create two DCMotor type reference variables and then use the hardwareMap.dcMotor static class and call its method get with the names we assigned in our hardware configuration file. The get method creates a DCMotor object and maps it to the appropriate motor controller port and returns a reference to the object into leftMotor or rightMotor reference variables. Now we can control those motors using the various methods available on the DCMotor class like setPower(), which sets the power level of the motor.

This code appears in your OpMode class. The motor definitions typically are at the top of your class. The hardware mapping should occur in your initialization section, either in the init_loop() function of a regular OpMode or before the waitForStart() call in a linear OpMode. The setPower() calls would appear in your loop() method for a regular OpMode or after waitForStart(), to control actual robot movement.

There is a class for every hardware device and the hardwareMap package has subclasses to map every device. You will need to review the FTC API documentation to become familiar with the device classes available and the fields and methods each class has.

In this manner we map all of a robots hardware devices to object instances of the appropriate class. We then use the object instances to interact with the devices.

Note that the OpMode classes (that you extend) provide built-in access to the Xbox controllers through the variables gamepad1 and gamepad2. This means you don't have to do the hardware mapping for the controllers.



Explore the purpose and content of the FTC SDK Library.

Understand what the FTC SDK Library is and how to use it to interact with robot hardware.


The FTC SDK Library is a library of classes that allow your programs to access and control all aspects of the Tetrix robot control system and the hardware devices attached to it. This library is the API for the control system and robot hardware. The library is included in the FTC SDK. You can access the library with the following import statement in an OpMode class:


This provides access to the highest level of the library and all of the hardware and software classes are divided up into lower level items. you will need to import the items you need in your OpModes. All OpModes need the following import to make  the base opmodes class available for your OpMode to extend:




Another import you will always need is for the robot hardware classes:


Remember that the trailing * imports all classes in the hardware item. You can import all of the hardware classes or just the specific classes you intent to use. Either way is valid.

The documentation for the FTC SDK Library is very important to read over and get a basic understanding of what classes are available for your use. The documentation is located in the FTC SDK install directory (ftc_app-master-n.n) in the sub directory doc.javadoc. Click on the file index.html to display the documentation in your browser. The doc is in web format so you must use a browser to view it. You should create a bookmark the index.html file. Don't forget to update this bookmark when installing new versions of the SDK.

The doc directory also contains a sub directory called tutorial. This directory used to contain useful documents describing various aspects of the robot control system. These items are now located online in github attached to each release of the FTC SDK.

Of particular interest is FTC_SDK_UserMan. This document is an extensive description of the Tetrix/FTC robot control system and the software programming environment. While it overlaps our lessons, it provides a lot of detail and is a great supplement to our lessons. It is highly recommended that you at least skim this manual. Do note that the document may be out of date in some areas but is still quite helpful. An online version of the javadoc is also associated with each release.

Don't forget the example code that is included in the SDK in the FtcRobotController\java folder of the SDK project.



Examine the details of using Android Studio to create OpMode classes.

Understand how to use Android Studio to create OpMode classes, compile them and download them to the robot controller phone.


Now its time to get more familiar with Android Studio and writing OpModes.

Watch this video on writing OpModes.

Remember, each time we change an OpMode's source code, we must recompile and download the newly updated robot controller app to the controller phone. Compiling in Android Studio will take of the download as long as your PC is connected to the controller phone with a USB cable or via WiFi.

The first time you connect your controller phone to your PC with a USB cable, the phone should install the USB driver needed for AS to communicate with your phone. If this driver install is unsuccessful and the phone is the ZTE, disconnect and reconnect the phone. When the dialog opens asking what you want to do with the USB device, select the AutoRun option. This should run the ZTE USB driver installer. Once install is complete reconnect your phone. The phone should now be visible to AS. If it is still not working, go to phone settings, Connect to PC, and make sure the Media Device and Enable USB Debugging options are selected. Reconnect.

Also the first time you connect the controller phone to your PC, the phone will prompt you accept the RSA Security Key presented by your PC to the phone. Set the option to always accept the RSA Key from this PC and click Ok.



Explore the details of the linear OpMode model.

Understand how linear OpModes work and how to use them.

The Linear OpMode is much simpler than the regular OpMode. You extend LinearOpMode and there is only one method to override: runOpMode(). This method is called after the Init button is pressed on the DS. So how do you separate initialization from actually starting the program running? You use the waitForStart() method inherited from the base LinearOpMode class.
So from the start of your code in runOpMode() to the waitForStart() method call, you would place all of your initialization activity. When the Init button is pressed, all of your code up to the waitForStart() is executed and then your program waits for the Start button to be pressed. After that your program is in control until the end of the game period. You will most likely need a loop of some sort where you monitor the controllers and take action, but in the autonomous mode you may just execute a set of sequential instructions. In any case, your program must end at the appropriate time. When looping, you can monitor the OpModeIsActive() function (part of the base LinearOpMode class) to determine when you should stop your program.
Lets modify the NullOp OpMode sample to be of the linear form:

We use a while loop to continue executing as long as the OpMode is active (opModeActive() returns true).

Note that we call telemetry.update() after the addData() calls. The update() method actually sends the data added with any preceeding addData() calls to the Driver Station. This is different than the regular OpMode.

We also need to call the idle() method at the end of any looping we do to share the phone's processor with other processes on the phone.