One of the most important steps in the engineering design process and the software development lifecycle is testing. When working with code, ensuring that it works without errors and works to the standard decided upon in the planning stage of the process is crucial. In order to ensure that the code is working as intended testing needs to be performed.
Before delving into the introduction to programming sections, Test Bed - Blocks or Test Bed - OnBot Java; its important to understand testing, the benefits of creating a test bed, the components needed for the next sections, and how to use gamepads. Follow through the rest of this section to learn more about testing!
Keep in mind that this is the introduction to the basic programming guide. Test Best - Blocks and Test Bed - OnBot Java will walk you through the basics of programming with the REV Control System.
The purpose of testing is to identify, isolate, and correct potential issues in a design before the design is put into use. Testing takes on different forms or provides different metrics for various intents in design. A mechanism, like a shooter for instance, might be tested to confirm that it is running reliably. During the planning phase of the design process you should create various performance, quality, and reliability metrics. When the design is built, or the program is written, these metrics will help you identify whether the mechanism meets the standards you expect it to. If the standards of operation are not met then the problem needs to be isolated.
In order to fix a problem in the design process, you must isolate the source of the issue. To understand how this works consider the following example:
A team has recently purchased a Control Hub and a Core Hex Motor. They plug the Core Hex Motor into the Control Hub using the correct wiring, but when they go to run their code the motor doesn't move. What is the most likely reason for this failure:
The program is the issue
The motor is the issue
The wire connecting the motor to the Hub is the issue
The Hub is the issue.
Without more information there is not a good way to discover why the motor is not running. In order to narrow things down the different components have to be tested until the root of the issue is found. Common practice is to start with a code that is known to work, such as one of the sample codes in the SDK. If the motor still doesn't run the next thing the team should check is whether or not the wires are working as intended. One by one the team should go through and test, or troubleshoot, the different potential origins of the problem to see what is working and what isn't.
Once the source of an issue has been isolated, the issue needs to be corrected. The duration of the fix depends on the sources of the problem and how deep it runs. For instance, if an op mode doesn't work as intended the fix may be a simple change, like to the configuration file or the hardwareMap. A larger issue that requires a redesign, like a mechanism not meeting performance metrics, triggers a restart of the engineering design process.
Previously, testing was defined as the process of identifying, isolating, and correcting potential issues during the design process. This differs from troubleshooting which is the process of identifying, isolating, and correcting issues of a mechanism that went through the testing process and worked as intended.
In the troubleshooting section the examples of a cars check engine light was used. In this example, the known indicator of a failure was the cars engine light. The check engine light informs the driver that something is wrong with the car but in order to find the cause of the issue troubleshooting and diagnostic steps must be performed. To maintain that comparison, testing is what the engineers of the car use to establish the metrics of expected engine performance. If those standards are not met then the check engine light turns on to warn the driver of the issue.
One of the fallbacks to testing code in a system of components, like the REV Control System, is that there is not a guarantee that all components are functioning as they should be. For instance, if a motor on the robot isn't working there are several potentials reasons for the failure. The motor, the motor port on the Control Hub, the wire connecting the motor to the port, and the code are all potential causes of motor failure.
If a failure occurs after the Robot is assembled it can be hard to go back and make changes, or troubleshoot without having to disassemble the robot. One of the ways to plan ahead for this circumstance is to create a test bed prior to creating a robot.
When testing code do not assume that a failure is due to the mechanism rather than the code. Testing and troubleshooting, while being similar concepts, are fundamentally different. Checking the code or using a known code that works should always occur before troubleshooting components like actuators and sensors.
A test bed is a testing environment for hardware and software components, commonly used in the engineering world. Test bed applications includes a broad range of different equipment and measurement testing. In some cases a test bed is a piece of equipment for testing a specific product, in other cases it is a system of components that create a testing environment. Regardless, the end goal of a test bed is to ensure a component is working before it is used for its intended purpose.
Creating a test bed eases the process of troubleshooting if there is a failure during code testing. The purpose of this section is to create a test bed to test basic code in the Test Bed - Blocks and Test Bed - OnBot Java sections.
The design of a test bed depends on the use case and available resources. For instance, one of the design requirements for the test bed featured below was accessibility. Notice that the placement of the hardware components on the Extrusion allows for the actuators, sensors, and Control Hub to be removed or swapped out with ease.
Another major design consideration for this test bed was that it include the common components necessary to teach users the basics of programming with the REV Control System. In this case components were chosen from the REV FTC Starter Kit.
Control Hub
REV Core Hex Motor
Smart Robot Servo
Touch Sensor
Color Sensor V3
Battery
Any one of these test beds components can be swapped out for an equivalent component. For instance, if you have an Expansion Hub rather than a Control Hub. However, with an Expansion Hub you may need to consider placement for the Robot Controller Phone.
There are other minor, but important, design considerations to make for a test bed. For example, when adding an actuator to a test bed consider the following questions:
What level of constraint does the actuator need? One of the benefits of creating a test bed for motors, or other actuators, is that the motors can be properly constrained during the testing process. In this case providing basic motion support and constraint is valuable.
How will you be able to tell the behavior of the actuator? The example test bed uses a wheel with a zip tie to help users visualize the behavior of the motor. Tape or other markers can be used, as well.
For the purpose of this guide a test bed similar to the example one can be built.
The Test Bed sections highlights the necessary robot components needed to learn the basic programming concepts used in the Test Bed - Blocks and Test Bed - OnBot Java sections. However, there are two more components needed to succeed in testing your code: A Driver Hub (or equivalent Driver Station Android Device) and a gamepad.
For information on setting up a Driver Hub and gamepad please visits the Getting Start with Driver Hub guide.
All buttons on a gamepad can be programmed to a specific task or behavior. Throughout the Hello Robot Guide you will encounter several different places where the gamepad is utilized. Knowing the general naming convention for the gamepads will help you program them correctly. The guide assumes you are using either a Logitech gamepad or a PS4 gamepad, like Etpark Wired Controller for PS4 (REV-39-1865). To understand how to program a gamepad, especially with difference in the way certain buttons are named, please see the following graphic and table, showcasing what the code lines correspond with which button.
Boolean data has two possible values: True and False. These two values can also be represented by On and Off or 1 and 0. Buttons, bumpers, and triggers on the gamepad provide boolean data to your robot. For example, a button that is not pressed will return a value of False and a button that is pressed will return the value True.
Float data is a number that can include decimal places and positive or negative values. On the gamepad, the float data returned will be between 1 and -1 for the joystick's position on each axis. Some examples of possible values are 0.44, 0, -0.29, or -1.
Section
Goals of Section
Learn why is one of the most important aspects of Software Development and how it differs from troubleshooting.
Why creating a test bed of actuators and sensors can help with programming. This test bed, or something equivalent, will be used in following sections.
Understanding the naming conventions for programming a gamepad.
PS4 Controllers
Default (Logitech Gamepad)
Blocks
Java
Data Type
Cross
a
gamepad1.a
Boolean
Circle
b
gamepad1.b
Boolean
Triangle
y
gamepad1.y
Boolean
Square
x
gamepad1.x
Boolean
Dpad Up
Dpad Up
gamepad1.dpad_up
Boolean
Dpad Down
Dpad Down
gamepad1.dpad_down
Boolean
Dpad Left
Dpad Left
gamepad1.dpad_left
Boolean
Dpad Right
Dpad Right
gamepad1.dpad_right
Boolean
Left Bumper
Left Bumper
gamepad1.left_bumper
Boolean
Right Bumper
Right Bumper
gamepad1.right_bumper
Boolean
Left Trigger
Left Trigger
gamepad1.left_trigger
Float
Right Trigger
Right Trigger
gamepad1.right_trigger
Float
PS
n/a
gamepad.ps
Boolean
Options
Start
gamepad1.start
Boolean
Share
Back
gamepad1.back
Boolean
Left Stick Button
Left Stick Button
gamepad1.left_stick_button
Boolean
Left Stick X Axis
Left Stick X Axis
gamepad1.left_stick_x
Float
Left Stick Y Axis
Left Stick Y Axis
gamepad1.left_stick_y
Float
Right Stick Button
Right Stick Button
gamepad1.right_stick_button
Boolean
Right Stick X Axis
Right Stick X Axis
gamepad1.right_stick_x
Float
Right Stick Y Axis
Right Stick Y Axis
gamepad1.right_stick_y
Float
OnBot Java is a text-based programming tool that lets programmers use a web browser to create, edit and save their Java op modes. In this section users can learn how to create an op mode, as wells as the basics of programming the actuators and sensors featured on the test bed.
Follow the guide in order to get an in depth understanding of working with OnBot Java or navigate to the section that fits your needs:
Before diving in and creating your first op mode, you should consider the concept of naming conventions. When writing code the goal is to be as clear as possible about what is happening within the code. This is where the concept of naming conventions comes into play. Common naming conventions have been established by the programming world to denote variables, classes, functions, etc. Op modes share some similarities to classes. Thus the naming convention for op modes tends to follow that naming convention for classes; where the first letter of every word is capitalized.
This section assumes that you have already accessed the OnBot Java platform during the Hello Robot - Introduction to Programming. If you are unsure how to access OnBot Java please revisit this section before proceeding.
To start, access the Robot Controller Console and go to the OnBot Java page. There are a few key things to take note of on the main Onbot Java page.
Create New Op Mode - The plus sign button opens up a window to create a new op more.
Project Browser Pane - This pane shows all the java project files on the Robot Controller.
Source Code Editing Pane - This pane is the main code editing area.
Message Pane - This pane provides messages on the success or failure of code builds.
Build Everything - Builds all of the .java files on a Robot Controller.
When an op mode is created or edited the OnBot Java editor will auto-save the .java file to the file of system of the Robot Controller. However, in order to execute the code on the Robot Controller the .java text file needs to be converted to a binary that can be loaded dynamically onto the FTC Robot Controller app. This conversion is done by building the op modes.
Select the Create New Op Mode button. This will open the New File window. This window allows users to choose settings like: naming their op modes, selecting a sample code to build off of, or choosing op mode type.
For this guide select the following sections:
File Name: HelloRobot_TeleOp
Sample: BlankLinearOpMode
Op Mode Type: TeleOp
Setup for Configured Hardware: on
Once the proper settings have been choose, select "OK" to create the op mode. The new file will populate the Project Browser Pane.
During the process of creating an op mode the Onbot Java tool had several options to choose from. Those options define what information is already included in the op mode, which can simplify what a programmer has to do on their end. For instance, an option was given to select a sample. In OnBot Java these samples act as templates; providing statements, logical structure, and syntax for different robotics use cases.
In the previous section the following settings were selected: the Setup Code for Configured Hardware option, the TeleOp option, and a sample code called BlankLinearOpMode. These options combined setup the shell of code needed to have a functional op mode.
An op mode is considered a set of instructions for a robot to follow in order to understand the world around it. Even though the SDK provides readily available op mode structures, understanding what concepts the template is utilizing, and why, helps increase programming knowledge. Follow through this section to learn more about the op mode template and the programming concepts that make up its structure.
The code block provides the structure of the template op mode based on the Hello Robot Configuration and with some comments missing. If another configuration is being used the code will be slightly different but many of the underlying concepts are the same.
At the start of the op mode there is an annotation that occurs before the class definition. This annotation states that this is a tele-operated (i.e., driver controlled) op mode:
In Java annotations are metadata, or descriptive information about the code. In this case the annotation is being used to tell the system that this op mode is tele-operated. Changing the annotation from @TeleOp
to @Autonomous
will change the code to an autonomous op mode.
You can also see that the OnBot Java editor created five private member variables for this op mode. These variables will hold references to the five configured devices that the OnBot Java editor detected in the active configuration.
Next, there is an overridden method called runOpMode
. Every op mode of type LinearOpMode
must implement this method. This method gets called when a user selects and runs the op mode.
Hardware mapping was introduced in the configuration section, as a two part process. The first part of the process was creating a configuration file. The second part of the process is retrieving references to hardware devices from the hardwareMap
object.
ThehardwareMap
object is available to use in the runOpMode
method. It is an object of type hardwareMap
class.
At the start of the runOpMode
method, the op mode uses the hardwareMap
object to get references to the hardware devices that are listed in the Robot Controller’s configuration file:
The hardwareMap.get()
method call is used to retrieve the hardware devices and assign them to variables. The method call accepts two arguments: a reference to the particular class of hardware devices the device belongs to and the name of the hardware device in the configuration file. The name in the hardwareMap.get()
needs to match the name of the device in the configuration file. If the names do not match, the op mode will throw a runtime error indicating that it can not find the device.
For more information on the runtime error check out the Common Errors in Hardware Mapping section.
In the next few statements of the example, the op mode prompts the user to push the start button to continue. It uses another object that is available in the runOpMode
method. This object is called telemetry and the op mode uses the addData
method to add a message to be sent to the Driver Station. The op mode then calls the update method to send the message to the Driver Station. Then it calls the waitForStart
method, to wait until the user pushes the start button on the driver station to begin the op mode run.
Telemetry is the process of collecting and transmitting data. In Robotics telemetry is often used to output internal data from actuators and sensors to the Driver Station. This data can then be analyzed by users to make decisions that can improve code.
All linear op modes should have a waitForStart
statement to ensure that the robot will not begin executing the op mode until the driver pushes the start button.
After a start command has been received, the op mode enters a while loop and keeps iterating in this loop until the op mode is no longer active (i.e., until the user pushes the stop button on the Driver Station):
As the op mode iterates in the while loop, it will continue to send telemetry messages with the index of “Status” and the message of “Running” to be displayed on the Driver Station.
Programming languages, much like any language, have a set of guiding rules and principals that allow statements to be universally understood. Things like punctuation, word structure, and formatting all play a part in how a line of code is interpreted. In linguistics and computer science the rules that govern the structure of a sentence are known as syntax.
It is important to understand the syntax for Java, as syntax errors will be common and hard to track without a basic level of understanding.
This section dropped a lot of references to methods, object, and classes. These are all intermediate to advance programming topics often centered around the concept of object oriented programming. The purpose of the Hello Robot guide is to act as a introductory course to robotics programming rather than deep dive into programming concepts.
However, keep object oriented programming in mind as your skills grow. For now the most important thing to know is that occasionally methods within the SDK libraries will need to be called in order to perform a certain task. For instance, the line HelloRobot_TeleOp.opModeIsActive()
line calls the method opModeIsActive
, which is the procedure in the SDK that is able to tell when the op mode has been activate by the driver station phone.
Going forward many of the motor, servo, or sensor specific code will deal with calls to other methods or classes.
For more information on classes and methods in the SDK check out the Java Doc.
The goal of this section is to cover some of the basics of programming a servo within OnBot Java. By the end of this section users should be able to control a servo with a gamepad, as well as understand some of the key programming needs of the servo.
This section is considering the Smart Robot Servo in its default mode. If your servo has been changed to function in continuous mode or with angular limits it will not behave the same using the code examples below. You can learn more about the Smart Robot Servo or changing the Servo's mode via the SRS Programmer by clicking the hyperlinks.
With a typical servo, you can specify a target position for the servo. The servo will turn its motor shaft to move to the target position, and then maintain that position, even if moderate forces are applied to try and disturb its position.
For both Blocks and OnBot Java, you can specify a target position that ranges from 0 to 1 for a servo. For a servo with a 270° range, if the input range was from 0 to 1 then a signal input of 0 would cause the servo to turn to point -135°. For a signal input of 1, the servo would turn to +135°. Inputs between the minimum and maximum have corresponding angles evenly distributed between the minimum and maximum servo angle. This is important to keep in mind as you learn how to code servos.
Add the line test_servo.setPosition(1);
to the op mode while loop.
Select Build Everything to build the code.
Try running this op mode on the test bed two times and consider the following questions:
Did the servo move during the first run?
Did the servo move during the second run?
If the servo did not move switch the test_servo.setPosition(1);
to test_servo.setPosition(0);
and try again.
The intent of thetest_servo.setPosition();
is to set the position of the servo. If the servo is already in the set position when a code is run, it will not change positions. Lets try adding the line test_servo.setPosition(0);
to the code in the initialization section.
Try running this op mode on the test bed. Give some time between hitting init and hitting play and consider the following question:
What is different from the previous run?
The test_servo.setPosition(0);
that was added in the step above changes the servo position to 0 during the initialization phase, so when the op mode is run the servo will always move to position 1. For some applications starting the servo in a known state, like at position zero, is beneficial to the operation of a mechanism. Setting the servo to the known state in the initialization ensures it is in the correct position when the op mode runs.
The focus of this example is to assign certain servo positions to buttons on the gamepad. For this example the known state will stay at position 0, so that after initialization the servo will be a the -135 degree position of the servo range. The following list shows what buttons correspond with which servo position.
The best way to switch the servo position will be to use a conditional if/ else if
statement. An if statement considers whether a conditional statement is true or false. If the conditional statement is true a defined action (like the servo moving) is performed. If the conditional statement is false the action is not performed.
An if/else if
statement takes in multiple different conditional statements. If the first conditional statement is found to be false then the second conditional state is analyzed. To better understand this concept consider the following code:
There are three different paths in this if/else if
statement. If the first conditional statement is true (the Y button is pressed) the servo moves to code position 0 and the other conditional statements are ignored. If the first condition is false (the Y button is not pressed) the second condition is analyzed. This behavior repeats until a condition is met or all conditions have been tested and found false.
||
is a logical operator in Java. This symbol is the Java equivalent of "or." Using this in a conditional statement says that either button x or button b can be pressed for this condition to be considered true.
Recall that telemetry is the process of collecting and transmitting data. In Robotics telemetry is used to output internal data from actuators and sensors to the Driver Station. This data can then be analyzed by users to make decisions that can improve code.
The most useful telemetry from the servo is the the position of the servo along its 270 degree range. In order to get that information the following line needs to be used.
In the programming essentials section the telemetry.addData();
line was briefly discussed. This method call takes in a key and variable parameter and outputs the information to the Driver Station. The key is a string, or a line of text, that should define the variable. In this case the telemetry.addData();
is being used to output the position of the servo as it is changed so the key can be "Servo Position" The parameter however will be the the test_servo.getPosition();
method call.
Modify your op mode to add the motor related code. This can be done by clearing out your current code modifications or adding the motor related code to your current op mode.
The goal of this section is to cover some of the basics of programming a motor within OnBot Java. By the end of this section users should be able to control a motor using a gamepad, as well as understand some of the basics of working with motor encoders.
Add the line test_motor.setPower(1);
to the op mode while loop.
Select Build Everything to build the code.
Try running this op mode on the test bed and consider the following questions:
How fast is the motor running?
What happens if you change the power from 1 to 0.3?
What happens if you change the power to -1?
The level of power sent to the motor is dependent on the numerical number assigned to the motor. The change from 1 to 0.3 decreased the motors speed from 100% of duty cycle to 30% of duty cycle. Meanwhile, the change to -1 allowed the motor to rotate at 100% duty cycle in the opposite direction. So, power can be fluctuated to drive a motor forward or backwards.
However, the test_motor.setPower(1);
line will run the motor in the assigned direction until something in the code stops the motor or causes a change in direction.
In the previous section you learned how to set the motor to run at a specific power level in a specific direction. However, in some applications, it may be necessary to control the motor with a gamepad, to easily change the direction or power level of a mechanism.
For this section lets create a double variable motorPower
. This variable will be created within the op mode but outside of the while loop.
A double is numerical data type that can store numbers with decimal points. Since the power, or duty cycle, of the motor runs on a scale between 1 to -1; the motorPower
variable will need to be able to hold numerical data with decimal points.
Consider the following lines of code:
The line motorPower = - this.gamepad1.left_stick_y;
takes an numerical input that corresponds with the position of the gamepad joystick as it moves along the y-axis and assigns it as the motorPower
variable. The next line test_motor.setPower(motorPower);
sets the motor power equal to the motorPower
variable.
Note that for the Logitech F310 gamepads, the Y value of a joystick ranges from -1, when a joystick is in its topmost position, to +1, when a joystick is in its bottommost position. In order to change the directional relationship between the motor and the joystick, so that the topmost position of the joystick correlates with the forward direction of the motor, a negative symbol, or negation operator needs to be used.
Recall that telemetry is the process of collecting and transmitting data. In Robotics telemetry is used to output internal data from actuators and sensors to the Driver Station. This data can then be analyzed by users to make decisions that can improve code.
One of the most common forms of telemetry data from motors is the data pulled from the motor encoder. REV DC Motors, like the Core Hex Motor, are equipped with internal encoders that relays positional information in the form of counts. In order to get information from the encoders the following line needs to be used:
In the programming essentials section the telemetry.addData();
line was briefly discussed. This method call takes in a key and variable parameter and outputs the information to the Driver Station. The key is a string, or a line of text, that should define the variable. In this case the telemetry.addData();
is being used to output the position of the motor in the form of encoder counts so the key can be "Encoder Value." The parameter however will be the the test_motor.getCurrentPosition();
method call.
For more information on programming encoders check out the Using Encoders page. For more information the counts per revolution metric and how to use it check out the Encoders page.
The goal of this section is to cover some of the basics of programming a digital device, or Touch Sensor, within Blocks.
Before programming with a Touch Sensor or other digital device it is important to understand what a digital device is and what the common applications for digital devices are. Visit the Digital Sensors page for more info.
Modify your op mode to add the digital device related code. This can be done by clearing out your current code modifications or adding the digital device code to your op mode.
The information from digital devices comes in two states, also known as binary states. The most common way to utilize this information is to use a conditional statement like an if/else
statement. The line test_touch.getState();
collects the binary FALSE/TRUE
state from the touch sensor and acts as the condition for the if/else
statement.
The code above highlights the basics structure of the if/else
statement for a digital device. The FALSE/TRUE
state of a REV Touch Sensor corresponds with whether or not the button on the Touch Sensor is pressed. When the button is not pressed the state of the Touch Sensor is true. When the button is pressed the state of the Touch Sensor is false. This status is reflected by the comments in the code.
The most basic way to use a digital device is to use telemetry to output information, like the status of the Touch Sensor button. To do this, lets create a string variable called touchStatus
. This variable will be created within the op mode.
String refers to data that consists of a sequence of characters. String datatypes are indicated in code by a set of quotation marks. For instance, "Hello Robot" is a string but Hello Robot is not.
The line String touchStatus = "";
declares that the variable touchStatus is an empty string variable. Which means that touchStatus
is currently holding a string with zero characters in it.
Add the if/else
statement to the while loop.
Right now the variable touchStatus
is empty, but for this example it should change to reflect the status of the touch sensor. To do this touchStatus
should be set to either "Not Pressed"
or "Pressed"
.
To display in the information assigned to touchStatus
, telemetry needs to be used. In the programming essentials section the telemetry.addData()
line was briefly discussed. This method call takes in a key and variable parameter and outputs the information to the Driver Station. The key is a string, or a line of text, that should define the variable. In this case the telemetry.addData();
is being used to output changes in the touchStatus
variable so "Touch Status"
would be a good key. The parameter will be thetouchStatus
variable. Add this line above the telemetry.update();
line in the while loop.
One of the most common uses for a digital device like a touch sensor is to use it as a limit switch. The intent of a limit switch is to stop a mechanism, like an arm or lift, before it exceeds its physical limitations. In this application power needs to be cut from the motor when the limit is met.
Programming a limit switch requires the same if/else logic applied in the previous section. If the touch sensor state is true (it is not pressed) the motor will have power. Else (it is pressed) the motor will not have power.
The code block above introduces the basics of a limit switch. Like with most sensors, its good to have telemetry that updates the Driver Station on the status of the sensor. Consider the following code:
The Blocks Programming Tool is a visual, programming tool that lets programmers use a web browser to create, edit and save their op modes. Blocks, like other scratch based programming tools, is a collection of preset code snippets that users can drag-and-drop into the appropriate code line. In this section users can learn how to create an op mode, as wells as the basics of programming the actuators and sensors featured on the test bed.
Follow the guide in order to get an in depth understanding of working with Blocks or navigate to the section that fits your needs:
Before diving in and creating your first op mode, you should consider the concept of naming conventions. When writing code the goal is to be as clear as possible about what is happening within the code. This is where the concept of naming conventions comes into play. Common naming conventions have been established by the programming world to denote variables, classes, functions, etc. Op modes share some similarities to classes. Thus the naming convention for op modes tends to follow the naming convention for classes; where the first letter of every word is capitalized.
This section assumes that you have already accessed the Blocks platform during the Hello Robot - Introduction to Programming. If you are unsure how to access blocks please revisit this section before proceeding.
To start, access the Robot Controller Console and go to the Blocks page. In the upper right-hand corner of there is a Create New Op Mode button, click it.
Clicking the Create New Op Mode button will open up the Create New Op Mode window. This window allows users to name their op modes and select a sample code to build off of. For this guide use the default BasicOpMode sample and name the op mod HelloRobot_TeleOp as shown in the image below.
Once the op mode has been named click 'OK' to proceed forward. Creating an op mode will open up the main Blocks programming page. Before moving on to programming, take some time to learn and understand the following key components of Blocks featured in the image below.
Save Op Mode - Click this button to save an op mode to the robot. It is important to save the op mode any time you stop working on a code, so that progress is not lost.
TeleOp/Autonomous - This section of blocks allows users to change between the two types of op modes: teleop and autonomous.
Categorized Blocks - This section of the screen is where the programming blocks are categorized and accessible. For instance, clicking Logic will open access to programming blocks like if/else statements.
Programming Space - This space is where blocks are added to build programs.
If a configuration has been made then the Actuators, Sensors, and Other Devices in the Categorized Blocks section should appear as drop down menus, where blocks that are unique to specific hardware can be accessed. If this is not the case a configuration file has not been made. For more information visit the Configuration page, before moving forward with programming.
During the process of creating an op mode the Blocks tool prompted the selection of a sample code. In Blocks these samples act as templates; providing the blocks and logical structure for different robotics use cases. In the previous section the sample code BasicOpMode was selected. This sample code, seen in the image below, is the structural shell needed in order to have a working op mode.
An op mode can often be considered a set of instructions for a robot to follow in order to understand the world around it. The BasicOpMode provides the initial set of instructions that are needed in order for an op mode to properly function.
Though this sample is given to users to reduce some of complexities of programming as they learn; it introduces some of the most important code blocks. It is also important to understand what is happening in the structure of the BasicOpMode, so that code blocks are put in the correct area.
A variable is a storage location with an associated symbolic name, which contains some known or unknown quantity of information referred to as a value. Variables can be numbers, characters, or even motors and servos.
If-then (if-else) statements are similar to the concept of cause and effect. If cause (or condition) happens, then perform effect.
The previous section did not go into a detailed discussion of the purple function (or method) blocks. Functions and methods are similar procedures in programming that are more advance than what will be covered in this guide.
When your programming skills have advanced take sometime to visit the concepts of functions and methods and explore how they can help you enhance your code.
The goal of this section is to cover some of the basics of programming a servo within Blocks. By the end of this section users should be able to control a servo with a gamepad, as well as understand some of the key programming needs of the servo.
This section is considering the Smart Robot Servo in its default mode. If your servo has been changed to function in continuous mode or with angular limits it will not behave the same using the code examples below. You can learn more about the Smart Robot Servo or changing the Servo's mode via the SRS Programmer by clicking the hyperlinks.
With a typical servo, you can specify a target position for the servo. The servo will turn its motor shaft to move to the target position, and then maintain that position, even if moderate forces are applied to try and disturb its position.
For both Blocks and OnBot Java, you can specify a target position that ranges from 0 to 1 for a servo. For a servo with a 270° range, if the input range was from 0 to 1 then a signal input of 0 would cause the servo to turn to point -135°. For a signal input of 1, the servo would turn to +135°. Inputs between the minimum and maximum have corresponding angles evenly distributed between the minimum and maximum servo angle. This is important to keep in mind as you learn how to code servos.
Since this section will focus on servos it is important to understand how to access servos within Blocks. At the top of the Categorize Blocks section there is a drop down menu for Actuators. When the menu is selected it will drop down two choices: DcMotor or Servo. Selecting Servo will open a side window filled with various servo related blocks.
The block above will change names depending on the name of the servo in a configuration file. If there are multiple motors in a configuration file the arrow next to test_servo will drop down a menu of all the servos in a configuration.
Select Save Op Mode in the upper right corner in the Robot Controller Console.
Try running this op mode on the test bed two times and consider the following questions:
Did the servo move during the first run?
Did the servo move during the second run?
Try running this op mode on the test bed and consider the following question:
What is different from the previous run?
The focus of this example is to assign certain servo positions to buttons on the gamepad. For this example the known state will stay at position 0, so that after initialization the servo will be a the -135 degree position of the servo range. The following list shows what buttons correspond with which servo position.
If you are using a PS4 Controller, like the Etpark Wired Controller for PS4 (REV-39-1865), see the Using Gamepads section to determine how the gamepad code used in this section translates to the PS4 Gamepad.
The best way to switch the servo position will be to use a conditional if/ else if
statement. An if statement considers whether a conditional statement is true or false. If the conditional statement is true a defined action (like the servo moving) is performed. If the conditional statement is false the action is not performed.
An if/ else if
statement takes in multiple different conditional statements. If the first conditional statement is found to be false then the second conditional state is analyzed. Each statement in the if/ else if
will be analyzed one by one until a statement is found true or all statements are found false. For this example, there will be three conditions that will need to be checked.
There are three different paths in this if/else if
block. Each one corresponds with one of the three chosen servo positions 0, 0.5, and 1. However, there are four different buttons that will be used for this example. Both button B and button X should be able to move the servo to position 0.5. In order to do this the logical operator or needs to be used.
The logical operator or considers two operands if either (or both) are true the or statement is true. If both operands are false the or statement is false.
All gamepad related blocks are in the Gamepad Menu.
Add each button to the if/else if
block as seen in the image below.
There are three different paths in thisif/else if
statement. If the first conditional statement is true (the Y button is pressed) the servo moves to code position 0 and the other conditional statements are ignored. If the first condition is false (the Y button is not pressed) the second condition is analyzed. Recall that this behavior repeats until a condition is met or all conditions have been tested and found false.
Telemetry is the process of collecting and transmitting data. In Robotics telemetry is used to output internal data from actuators and sensors to the Driver Station. This data can then be analyzed by users to make decisions that can improve code.
The most useful telemetry from the servo is the the position of the servo along its 270 degree range. In order to get that information the following line needs to be used.
Change the key parameter to "Servo Position"
When the op mode is run the telemetry block will display the current position information will be displayed with the Servo Position Key. The number that corresponds with the current position will change as the servo shaft position changes.
Modify your op mode to add the motor related code. This can be done by clearing out your current code modifications or adding the motor related code to your current op mode.
The goal of this section is to cover some of the basics of programming a motor within Blocks. By the end of this section users should be able to control a motor using a gamepad, as well as understand some of the basics of working with motor encoders.
Since this section will focus on motors it is important to understand how to access motors within Blocks. At the top of the Categorize Blocks section there is a drop down menu for Actuators. When the menu is selected it will drop down two choices: DcMotor or Servo. Selecting DC Motor will open a side window filled with various motor related blocks.
The block above will change names depending on the name of the motor in a configuration file. If there are multiple motors in a configuration file the arrow next to test_motor will drop down a menu of all the motors in a configuration.
Add this block to the op mode code within the while loop.
Select Save Op Mode in the upper right corner in the Robot Controller Console.
Try running this op mode on the test bed and consider the following questions:
How fast is the motor running?
What happens if you change the power from 1 to 0.3?
What happens if you change the power to -1?
The level of power sent to the motor is dependent on the numerical number assigned to the motor. The change from 1 to 0.3 decreased the motors speed from 100% of duty cycle to 30% of duty cycle. Meanwhile, the change to -1 allowed the motor to rotate at 100% duty cycle in the opposite direction. So, power can be fluctuated to drive a motor forward or backwards.
To better understand motors and the concept of duty cycle check out the our Motors and Choosing an Actuator documentation.
In the previous section you learned how to set the motor to run at a specific power level in a specific direction. However, in some applications, it may be necessary to control the motor with a gamepad, to easily change the direction or power level of a mechanism.
Note that for the Logitech F310 gamepads, the Y value of a joystick ranges from -1, when a joystick is in its topmost position, to +1, when a joystick is in its bottommost position. If the motor is not running in the intended direction adding a negative symbol, or negation operator, to the line of code will change the direction of the motor in relation to the gamepad.
Recall that telemetry is the process of collecting and transmitting data. In Robotics telemetry is used to output internal data from actuators and sensors to the Driver Station. This data can then be analyzed by users to make decisions that can improve code.
In order to gain telemetry data from the motor, motor encoders need to be used. REV DC Motors, like the Core Hex Motor, are equipped with internal encoders that relay information in the form of counts.
Change the key parameter to "Counts Per Revolution: "
When the op mode is run the telemetry block will display the current position information will be displayed with the Counts Per Revolution Key. The number that corresponds with the current position will change as the motor shaft position is changed.
For more information on programming encoders check out the Using Encoders page. For more information the counts per revolution metric and how to use it check out the Encoders page.
Modify your op mode to add the digital device related code. This can be done by clearing out your current code modifications or adding the digital device code to your op mode.
The goal of this section is to cover some of the basics of programming a digital device, or Touch Sensor, within Blocks.
Before programming with a Touch Sensor or other digital device it is important to understand what a digital device is and what the common applications for digital devices are. Visit the Digital Sensors page for more info.
The information from digital devices comes in two states, also known as binary states. The most common way to utilize this information is to use a conditional statement like an if/else
statement.
The FALSE/TRUE
state of a REV Touch Sensor corresponds with whether or not the button on the Touch Sensor is pressed. When the button is not pressed the state of the Touch Sensor is True. When the button is pressed the state of the Touch Sensor is False,
To help remember how the physical and digital states of the sensor correspond in the next few sections lets use some comments.
Comment blocks can be found in the Miscellaneous menu.
The next step in the process is to use telemetry to display the status of the Touch Sensor on the Driver Station phone. To do this, lets create a string variable called touchStatus
.
String refers to data that consists of a sequence of characters.
Click on the Variables menu. This will open a side window
Select the Create variable... block
A prompt from the FIRST Robot Controller will appear asking for a name for the variable. Name the variable touchStatus
. Click okay
Change the key parameter to "Button Status: "
When this program is run the touchStatus
telemetry will appear on the Driver Station phone. The touchStatus
information will change based on the state of the Touch Sensor button.
One of the most common uses for a digital device like a touch sensor is to use it as a limit switch. The intent of a limit switch is to stop a mechanism, like an arm or lift, before it exceeds its physical limitations. In this application power needs to be cut from the motor when the limit is met.
The concept of a limit switch involves many of the same steps from the previous section on programming a digital device. For that reason lets pick up from the following block set:
For information on where to find motor specific blocks please revisit the motor section.
Comments are blocks of code that benefit the human user. They are used by programmers to explain the function of a section of code. This is especially helpful in collaborative programming environments. If code is handed from one programmer to another, comments communicate the intent of the code to the other programmer. Blocks like are comments written by the FIRST Tech Team to inform the user what will happen when blocks are added directly beneath the comment.
For instance, any programming blocks that are placed after thecomment (and before the block) will be executed when the op mode is first selected by a user at the Driver Station. Typically, blocks put in this section are meant to create and define variables between the initialization and start phases of the op mode.
When the Robot Controller reaches the block it will stop and wait until it receives a Start command from the Driver Station. A Start command will not be sent until the user pushes the Start button on the Driver Station. Any code after the block will get executed after the Start button has been pressed.
After the , there is a conditional if block that only gets executed if the op mode is still active (i.e., a stop command hasn't been received).
Any blocks that are placed after the comment and before the will be executed sequentially by the Robot Controller after the Start button has been pressed.
The is an iterative or looping control structure.
This control will perform the steps listed under the “do” portion of the block as long as the condition is true. What this means is that the statements included in the “do” portion of the block will repeatedly be executed as long as the op mode HelloRobot_TeleOp is running.
Once the user presses the Stop button, the clause is no longer true and the loop will stop repeating itself.
For now the most important thing to know is that occasionally methods within the SDK libraries will need to be called in order to perform a certain task. For instance, the line calls the method opModeIsActive, which is the procedure in the SDK that is able to tell when the robot was been started or stopped.
From the Servo menu select the block
Add this block to the op mode code within the . Click on the number block to change from to .
If the servo did not move switch from back to and try again.
The intent of the is to set the position of the servo. If the servo is already in the set position when a code is run, it will not change positions. Lets try adding another block and see what changes.
Drag an additional block into the op mode code under the comment.
The that was added in the step above changes the servo position to 0 during the initialization phase, so when the op mode is run the servo will always move to position 1. For some applications starting the servo in a known state, like at position zero, is beneficial to the operation of a mechanism. Setting the servo to the known state in the initialization ensures it is in the correct position when the op mode runs.
From the Logic Menu in Blocks select the block and drag in into the op mode's while loop.
Click on the blue and white Settings icon for the block. This will display a pop-up menu that lets you modify the block.
Drag an block from the left side of the pop-up menu and snap it into place under the block. Drag a second block from the left side and snap it into place on the right side under the first block.
From the Logic Menu in Blocks select the block.
Add this block to the If/else if
block, as shown in the image below. Use the drop down menu on the block to change it from an block to an block.
Add blocks to each section of the If/else if block. Set the servo position to correspond with the assigned gamepad button.
In order to access the telemetry blocks select the Utilities drop down. The utilities drop down is in alphabetical order, so telemetry is towards the bottom of the drop down options. Select the block from the telemetry menu.
Drag the block and place it beneath theif/else if
block set.
From the Servo menu pullout the block Drag the Block and attach it to the number parameter on the telemetry blocks.
From the Dc Motor menu in Blocks select the block .
However, the block will run the motor in the assigned direction until something in the code stops the motor or causes a change in direction.
From the Gamepad Menu in Blocks select the Block.
Drag the block so it snaps in place onto the right side of the block. This set of blocks will continually loop and read the value of gamepad #1’s left joystick (the y position) and set the motor power to the Y value of the left joystick.
From the Math Menu in Blocks select the block in the image below.
Drag the negative symbol block so it snaps in place between the and blocks.
In order to access the telemetry blocks select the Utilities drop down. The utilities drop down is in alphabetical order, so telemetry is towards the bottom of the drop down options. Select the block from the telemetry menu.
Drag the block and place it beneath the block set.
From the DC Motor menu pullout the block . Drag the Block and attach it to the number parameter on the telemetry blocks.
Since this section will focus on digital devices it is important to understand how to access digital device specific blocks. At the top of the Categorize Blocks section there is a drop down menu for Other Devices. When the menu is selected it will drop down an option for Digital Devices. Selecting Digital Devices will open a side window filled with various digital device related blocks. The one that will most commonly be used is .
From the Logic Menu in Blocks select the block.
Drag the block and place it beneath the comment.
Select a block from the Digital Devices menu and add it to the if/do/else block as shown in the image below.
The block stores the binary FALSE/TRUE
information from the touch sensor and acts as the condition for the statement. If is true, any code placed in the do portion of the block will be activated. If is false anything placed in the else portion of the clock will be activated
Place one comment block in the do portion of the block and change the comment to say Add another comment to the else portion of the block and change that comment to say , as shown in the image below.
This process created a variable named touchStatus
. Currently touchStatus
is undefined, in order to define it the block needs to be used. This block can be found in the Variables menu now that the variable has been created.
Drag a block and place it beneath the comment block. Add another block to the block set under the comment.
The block allows you to define the touchStatus
variable. Depending on what the status is of the touch sensor is, touchStatus
will be set to a different string. For this select the string block from the Text menu, as seen in the image below.
Attach a string block to both blocks. Fill the blocks with a status message that relates to the state of the Touch Sensor. For instance, and .
To display this information on the Driver Station phone telemetry must be used. In order to access the telemetry blocks select the Utilities drop down. The utilities drop down is in alphabetical order, so telemetry is towards the bottom of the drop down options. Select the block from the telemetry menu.
Drag the block and place it beneath the block set.
From the Variables menu select the block. Drag the Block and attach it to the text parameter on the telemetry block.
The block establishes a conditional environment for the limit switch. If the touch sensor is not pressed the motor can run, however, if it is pressed the motor can not run. To add this to the code the block needs to be used.
Add a block under the comment. Change the power to 0.3. Add another block under the comment. Change the power to 0.
This block introduces the basics of a limit switch. Like with most sensors, its good to have telemetry that updates the Driver Station on the status of the sensor. Consider the code from the previous section, or the following code as potential ideas for telemetry.
Section
Goals of Section
Focuses on how to navigate the OnBot Java interface and create an op mode.
Breaks down the structure and key elelments needed for an op mode, as well as some of the essential components of Java.
How to code servos and motors. This section walks through the basic logic of coding actuators, controlling actuators with a gamepad, and using telemetry.
How to code a digital device. The section focuses on the basic logic of coding a digital device, like a REV Touch Sensor.
Button
Degree Position
Code Position
Y
-135
0
X
0
0.5
B
0
0.5
A
135
1
Section
Goals of Section
Focuses on how to navigate the Blocks interface and create an op mode.
Breaks down the structure and key elelments needed for an op mode, as well as some of the essential components of Blocks and programming logic.
How to code servos and motors. This section walks through the basic logic of coding actuators, controlling actuators with a gamepad, and using telemetry.
How to code a digital device. The section focuses on the basic logic of coding a digital device, like a REV Touch Sensor.
Button
Degree Position
Code Position
Y
-135
0
X
0
0.5
B
0
0.5
A
135
1