Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Now that we have our Control System all set up and ready to program it's time to get a full robot running, right?
While we will be getting motors moving and sensors sensing during this section, it's important that we first start small. In this section, we'll be working with a simple test bed as we breakdown how to program some of the components that can be connected to the Control Hub.
By tackling these components individually we'll be able to explore more of their capabilities, common uses, and discuss errors that may occur while working with a full robot.
During Hello Robot you will encounter sections called "Quick Check!" These pauses are intend to be moments to think deeper on a topic or to self-check your understanding as you progress. It's is expected that the completion of Hello Robot may take multiple days, meetings, or classes.
As mentioned, during this section we will be focus first on the concept of testing. Why do you think testing might be important in robotics?
One of the best practices to get into the routine of is testing all your components individually when they are first received. That's where out test bed comes into play. For our test bed we will be sticking to the basics with our components connected directly to our Control Hub rather than something like a Servo Power Module or Expansion Hub. If desired, we could add some mechanical parts, such as a servo horn or wheel, to aid with visualizing our testing, but this is not required.
in this tutorial we'll be using our test bed to learn about programming basics, however it is highly encourage to maintain a test bed for future testing.
Remember when testing a component there may be multiple points of failure such as the port, wire, program, or device itself. Utilizing a test bed helps to narrow down those failure points by making it easier to test and compare in a system's simplest state.
To create our test bed for this tutorial you will need the following. The names we used in our configuration are included:
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 here 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.
Be sure to complete your configuration on the Driver Hub once you have assembled your test bed.
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.
Well a test bed is recommended, in the case of time restrictions, space, or other limitations, individual components may be added or removed during each section of Hello Robot. Make sure moving components, such as motors or servos are ALWAYS secured while running, even at low speeds.
Add the line test_servo.setPosition(1);
to the OpMode while loop.
Select Build Everything to build the code.
Let's give our program a try. Take a moment to observe what happens.
When running our program for the first time, we should have seen our servo move itself to position 1 and maintain that position. But what happens if we run it again? Does the servo move?
If your servo did not move as expected, double check your wiring and port are correct compared to your configuration.
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).
In this case, we do not want our servo to reset to 0 every time our code repeats. Because of this where do you think we would add this line?
Recall when we discussed the different sections of our OpMode during Programming Essentials. Since we only want our servo to reset ONCE we will request it do so during the initialization process when the code is first activated, but before play is pressed.
Try running this op mode on the test bed and consider the following question:
What is different from the previous run?
In many 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 OpMode runs.
Take a moment to think about where setting the servo to a known state during initialization may be helpful before moving to the next section!
The time has come to create our first OpMode. We want to make sure to choose a clear and unique name each time we make a program. This will help us to find it again later or to communicate with teammates who may also be driving the robot.
In the programming world, there are common naming conventions that have been established to denote variables, classes, functions, etc. OpModes share some similarities to classes, a program-code-template. Thus the naming convention for OpModes tends to follow the naming convention for classes, which has the first letter of every word is capitalized.
While there are standardized naming conventions in programming, at the end of the day you will want to pick something that makes sense to YOU or your team. This might include having your name, team name, a school class period, or similar in your name.
Your OpMode name should not be the same as a created variable name.
To start, let's take a look at the OnBot Java layout in the REV Hardware Client:
Create New OpMode - The plus sign button opens up a window to create a new OpMode.
Project Browser Pane - This pane shows all the Java project files on the Robot Controller.
Source Code Editing Pane - This is the main code editing area
Message Pane - This pane provides information on the success or failure of code builds, as well as where to check for errors after attemping a build
Build Everything - Builds ALL of the .java files on a Robot Controller.
Selecting to "Build Everything" will attempt to compile ALL your OnBot Java files. Errors may appear for incomplete or test files along with the active file.
To temporarily disable an OpMode, right click the file name and select "Disable / Comment":
OpModes may be reenable the same way!
Select the Create New OpMode button. This will open the New File window.
There are a lot of things we can modify while setting up our OpMode, such as the name, sample in use, and kind of OpMode. For Hello Robot, use the following settings for reference:
File Name: HelloRobot_TeleOp
Sample: BlankLinearOpMode
OpMode Type: TeleOp
Setup for Configured Hardware: on
Setup Code for Configured Hardware is an incredibly useful tool that allows for OnBot to help create the hardwareMap based on the current active configuration!
Your intended configuration file should be active BEFORE creating an OpMode using this feature.
Once the proper settings have been choose, select "OK" to create the OpMode!
Telemetry is the process of collecting and transmitting data. In robotics ,telemetry is used to output internal data from the actuators and sensors to the Driver Hub. It is a way for the robot to communicate back to you the programmer what the robot thinks its doing or seeing. This information can then be used to improve your code, make adjustments to a mechanism, or to strategize when driving around the field if competing.
For OnBot Java we can use the following to request the servo's position:
We already have a couple lines of telemetry within our code to let us know what state our program is in: "Initialized" or "Running". Below our if/else if statement we can add another telemetry.addData();
.
First, we need to add a "string" or the text that we want to appear on our Driver Hub. For now we will enter this as "Servo Position"
. After our comma, we will add the data we want outputted to the Driver Hub, which is test_servo.getPosition();
.
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 or changing the Servo's mode via the by clicking the hyperlinks.
A servo is a form of actuator, or a device designed for moving. With a typical servo, you can specify a target position. 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 Hello Robot we will be using the , which is able to switch between a continuous and angular mode.
Continuous mode allows for the servo to rotate a full 360°, either direction, indefinitely similar to a standard motor.
Angular mode sets the servo to move to specified positions within a 270° range of motion.
Let's take a look at how to program our servo while it is on angular mode:
While most common servos have a range of 180° for motion, the Smart Robot Servo has a range of 270° due to its ability to switch between modes. When programming this means our 0 and 1 position might be a little different than what you'd expect.
Looking at the image above we can see that on default when asking our servo to move to its position 0 it will be at -135° . On the opposite end, moving to its position 1 takes our servo to +135° . Therefore if we wanted to return to 0° we would need to program it to move to its position 0.5.
A servo horn attachment connected to your Smart Robot Servo may effect where 0° appears. We recommend using a SRS programmer to set the servo to zero before adding attachments. This may also be done using the code learned in this section!
Let's review quick our basic positions:
Based on what we've learned so far, think about the follow two questions:
If we wanted our servo to move to -67.5° what position would we program it move to?
If we have programmed our servo to move to position 0.7, what would that equal in degrees?
In the next few sections, we will be learning to program our servo to first move automatically to different requested positions then in response to our gamepad's input.
Below is a sneak peek of our final full code:
Modify your OpMode to add the motor related code. For now your completed servo code can be dragged to the side of your work space. You may alternatively choose to create a second program.
Just like servos, a motor is a form of actuator. You may picture a dozen different things when you think of a motor, from those used to spin the wheels of a car to the large turbines that allow a plane to fly. For our robots, we will be focusing on DC motors. These are a type of electrical motor that use direct current, or DC, to rotate and produce the mechanical force needed to move an attached mechanism.
For this tutorial, either a Core Hex Motor or HD Hex Motor may be used as long as they have been properly configured on the Driver Hub.
Most standard motors are able to continuously rotate in either direction with an adjustable speed or power. Some motors may also include a built in encoder, which allows them to move to a specified position, similar to a servo, or to collect data like the number of completed rotations!
In the next few sections, we will be learning to program our motor to first move automatically in different directions then in response to our gamepad inputs. In our final section we will take a look at using telemetry with our motor's built in encoder.
Below is a sneak peek of our full code:
During the process of creating an OpMode the OnBot Java tool prompted the selection of a sample code. In OnBot these samples act as templates; providing the outline and logical structure for different robotics use cases. In the previous section the sample code BlankLinearOpMode was selected. This sample code, seen in below, is the structural shell needed in order to have a working Linear OpMode.
Throughout Hello Robot we will primarily be focusing on modifying the code found during our initialization process and while loop that runs when the Play button is pressed on the Driver Hub. As such, most examples will begin at public void runOpMode()
.
When utilizing the samples provided in this tutorial, double check that the correct number of brackets and file names are added to your final program!
Let's take a quick tour of this template!
Our first section of code is our hardwareMap. This is where our attached components are called and defined between the program and the configuration file
Within this area of our OpMode is anything we want to run BEFORE we press Play on the Driver Hub, but AFTER we press to initialize. This might include defining variables, motor directions, or servo positions!
Any code following this our waitForStart(); but before our while loop begins will be read ONCE when our play button is pressed! This might be used for resetting timers.
Last is our while loop! This is where any code we want to actively run and/or repeat until we press STOP is entered.
You will complete the majority of your program here.
Comments are lines of code intended to help you the programmer.
They can be used 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.
You can see a few premade comments already in our template written by the FIRST Tech Team to help get started!
To create a comment add //
before the comment to be made. This can also be used to temporarily remove a line of code as the robot will not read comments!
OnBot Java will attempt to notify you if there are either TOO MANY brackets within your code or NOT ENOUGH brackets by highlighting the final line in red as seen below:
The build errors may appear as below:
Keep in mind while checking your brackets that the error may be on a different line than the one reported! Take a look at the following example:
In this case, the missing bracket is on line 75 where my loop begins and should match with line 84's bracket. Once I have this corrected I can see the error clears:
While building your program you may encounter an error stating the class name is public and needs to be declared. This error can be common while copying and pasting from an example or tutorial and is the result of a mismatched name between the file name and public class.
Looking at the above example I can see my file is named "HelloRobot_TeleOp.java", but my class is "HelloWorld_TeleOp"!
To remedy this error, I could change my class name to match OR my file name. Which option is more ideal can be dependent on your end goal and how all your programs interact.
To change the name of a file, right click it on the list:
When renaming an OnBot Java file, the name is case sensitive and requires .java to be added to the end:
Alternatively, as previously mentioned, the public class name can be updated before building again to clear the error:
Always remember to Build your program after making major changes and before testing with your robot!
Having our robot able to rotate the servo automatically can be incredibly useful, especially when writing an autonomous program, but what if I want to control the positions with my gamepad?
Let's take a look at how we can add input commands to our code!
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, selecting the appropriate button from the dropdown in Blocks may be easier to follow when looking back at your code. The buttons are also interchangeable when programming in Blocks. (ex: Y in code = Triangle pressed on controller)
One of the most common logic statements used in programming is an if/else statement, also known as an if/then statement. In its most simple format we will be asking our robot to check IF something is happening and if the answer is yes, or true in our robot's mind, THEN it will DO what has been asked.
During this section we are going to be asking "If the Y button is pressed on our controller then move our servo to position 0."
If our servo will move to position 0 when the previous statement is TRUE, what do expect to happen when the answer is FALSE (or the Y button is not pressed)?
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.
Let's add to our existing logic statement the ability to move our servo to position 1 when A is pressed on our controller. Give it a try first before revealing the answer below!
How would our full logic statement be read once our new blocks are added?
If you have not already, test the code we have written thus far! The previous test_servo.setPosition(1);
should be removed if it has not already.
What happens when both buttons are pressed at the same time?
We've previously added our ability to move to position 0 and 1, but what about 0.5?
You may have noticed in our gamepad chart at the beginning of this section that we are going to have two buttons able to move our servo to position 0.5. This is so we can practice using a logical operator.
In OnBot Java, ||
means "or" allowing the robot to check if one of two buttons things are true. In this case, it will check if the x OR b button are pressed on the gamepad.
Click to Build Everything and give your program a try!
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 means the order we add our pathways DOES matter. If X and A are pressed at the same time, the robot will will try to prioritize the X button first.
Let's start by getting a motor spinning by adding the line test_motor.setPower(1);
Select Build Everything to build the code.
Try running this OpMode 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 5? What about 100?
What happens if you change the power from 1 to 0.3?
This is a good time to experiment with different values to see how our motor reacts. You might notice that setting our power to 5 or even 100 does not make the motor spin any fast than when set to 1. But setting our power to 0.3 significantly slows our motor's speed, right?
Now what happens if you change the power from 1 to -1?
From our perspective, a power level of 1 probably doesn't sound very strong. However, to our robot the power being set to 1 translates to the motor running at 100%. That would mean setting the power to 0.3 requests the motor to spin at 30% of power.
When we set our power to a negative power, the motor is told to reverse direction while maintaining that power. So if we set our power to -1 then our motor will still run at 100%, but in the opposite direction than when set to 1.
The direction a motor spins may be determined by the power OR may be designated during the initialization process.
For Hello Robot we will only be programming using positions. Understanding their translation to degrees is still important, however, to help think through designing a mechanism. Degrees may also be preferred when using a direct to program the servo.
0
-135°
0.5
0°
1
135°
1
Control Hub
2
Core Hex Motor
test_motor
3
Smart Robot Servo
test_servo
4
REV Touch Sensor
test_touch
5
Color Sensor V3
test_color
6
Battery
Button
Degree Position
Code Position
Y/Triangle
-135
0
X/Square
0
0.5
B/Circle
0
0.5
A/Cross
135
1
Recall that telemetry is the process of collecting and transmitting data. There is a lot of useful information our motors could send back to us, but to start let's have it output the power based on the joystick's movement.
Similar to our servo program, let's add a new line of telemetry.addData();
.
This time we are going to set our string as "Motor Power" and after our comma will use test_motor.getPower()
In the previous section you learned how to set the motor to run at a specific power level in a specific direction. However, in most applications, it will be necessary to control the motor with a gamepad, to easily change the direction or power level of a mechanism.
We are able to use a button to set the motor to a specific power or we can program it so it changes based on the direction of one of the gamepad's joysticks!
Using our existing test_motor.setPower(1);
we can replace the value of 1 with this.gamepad1.left_stick_y;
Now the power of our motor will be set in response to the position of the gamepad's left joystick as it along the y-axis!
Build your OpMode and test it out with your gamepad! Think about the following questions while testing:
What happens when you move the left joystick up a small amount versus a large amount?
What happens if you move the joystick to the left or right along the X-axis?
What happens if you move the joystick at a diagonal or rotate it 360 degrees?
You may notice that when moving along the X-axis nothing happens at the moment. However, once the joystick hits an angle near the Y-axis vertices the motor may start to jitter and spin.
When you tested your program, did the motor spin the expected direction while moving the joystick up or down?
In the FTC SDK for most controllers 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.
That may be a little confusing to control, but we can add a negative symbol, or negation operator, to the line of code to change the direction of the motor in relation to the gamepad.
This section applies to the use of the REV Touch Sensor or Limit Switch. Requirements may vary when using other 3rd party touch sensors.
The REV Touch Sensor must be configured to digital port 1, 3, 5, or 7.
The following example code's file name is: HelloRobot_TouchSensor
Let's start by breaking down how a touch sensor works at its core!
The information collected by a touch sensor comes in two states, also known as binary states. This information is perfect to use with a conditional statement like an if/else
statement.
The line test_touch.isPressed();
collects the binary TRUE/FALSE
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 touch sensor. We could read this line of code as "If the touch sensor is pressed do ____, else if the touch sensor is not pressed do _____."
So with this in mind:
Touch sensor pressed = true
Touch sensor NOT pressed = false
It's always helpful for us to be able to see what the robot thinks its doing on our Driver Hub's screen. To do this let's request the robot shares some telemetry data while our program is active.
Within our if/else statement we'll add a telemetry.addData for whether the touch sensor is pressed or not.
How our robot displays this data back to our Driver Hub is up to us to define. In this case we would see something similar to the following when the touch sensor is pressed:
The blue text within our quotation marks controls what will show on the Driver Hub. With that in mind we could have the robot say "Hello World!" when the button is pressed:
To finish our program before testing we need to add a telemetry.update(); after our if/else statement to request our robot updates the telemetry each time it loops:
At the moment, our robot does not have any senses to help navigate the world around it like you might. However, that's the key advantage to adding sensors to our design.
For the touch sensor, one of the most common uses is for it to act as a limit switch. This will help the robot know when it needs to halt the movement of a mechanism, like an arm or lift, that's at its limit similar to how your nerves help to tell your brain to do the same.
We can test this idea by adding on to our existing if/else statement. This time we are going to ask our motor to move until our sensor is pressed:
Test it out! What happens when you test your program?
You'll learn more about how to use this with a completed arm in Part 2: Robot Control!
In the above example the if/else is checking first for if the touch sensor is pressed. The full statement could be read as "If the touch sensor is pressed set the motor's power to 0 else, if it is not pressed, set the power to 0.3". This statement can be reversed by adding a ! before test_touch.isPressed().
In OnBot Java the operator ! tells the code to look for the opposite or to "not" be what is being called. So in this instance our if/else statement is checking if the touch sensor is NOT pressed first.
Give it a try!