Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
This year's Starter Bot is designed for split arcade drive. This means the left joystick controls the forward and back motion while the right joystick allows for rotation.
By adding a "clip" block to our drive program, we determine the minimum and maximum number or equation can equal out to. This reduces the possibility of an error occurring in the scenario where the value equals something higher than 1 or lower than -1, the motor's max range, which may cause a missed input.
Telemetry helps our robot to communicate to use what it thinks it is doing.
As part of our telemetry function, we have our robot reading out the currentState variable letting us know if the arm/wrist are in manual mode or at one of our various preset positions.
Claw Position shows us if the claw is currently open or closed. The "test" block can be found under the logic menu!
Lastly, our robot provides the current position and power of the arm and wrist. This is helpful for if we need to change a preset or for adding new code using the encoders on the motors!
When one of the triggers on the gamepad is pressed, it activates our GAMEPAD_INTAKE function. This simple if/then statement just checks which trigger is being pressed so our servo knows which way to rotate.
Because our servo is set to continuous mode in our configuration, we have the ability to tell our servo to set a power instead of moving by position increments!
When the right bumper is pressed on the gamepad, the claw on the robot either opens or closed. This prevents the driver from having to hold down the button to maintain control of a picked up specimen!
Because togglable control is not natively available in the FTC SDK, we have to make use of a couple of variables to help the robot check the state of the claw's servo and the right bumper.
Similar to what's used in our arm control's presets, lastBump checks if the right bumper is being held down and won't accept another input until its been released.
Meanwhile, clawOpen allows the servo to shift between the two set positions based on where it has last moved to. You can adjust these values based on your specific robot to have the claw open more or less.
This year's Starter Bot program offers a slightly more technical solution than previous years. If your team is new to FTC, or in need of a review, we strongly recommend checking out our updated Hello Robot Programming Guide before diving in!
To begin, let's take a look at the configuration and actuators used in this year's design.
Before getting started with programming we needed to create a configuration file. Below is an overview of how the robot is configured for the TeleOp code to function as expected:
Port Type | Port Number | Device Type | Name |
---|---|---|---|
Right click the file below and select "save link as". To put this configuration file on your robot, drag this file into the "FIRST" folder of your Control Hub's file system.
You will need to activate the configuration using the Driver Hub before proceeding. Click here to learn more about the configuration process.
The Smart Robot Servo can be changed to continuous mode using the SRS Programmer!
The 2024-25 REV DUO FTC Starter Bot is designed to use a split arcade drive for the default. Check out our Upgrades page for the arcade drive version of the program.
In split arcade drive, the left joystick will control forward and reverse motion of the robot, and the right joystick will control turning. This is similar to how some RC cars are driven and video games are played.
Not all gamepads have buttons labeled the same way. Check the manufacturer's documentation for accurate button mapping.
More information on programming gamepads for use with your robot can be found at Hello Robot - Using Gamepads.
The REV USB PS4 Compatible Gamepad (REV-31-2983) has two remappable M-buttons on the back side of the controller. By default, these are mapped to circle and cross.
Please see the product page for directions on remapping these buttons.
Check out FIRST's guide on uploading a Blocks program!
Any updates to our example programs are documented in our changelog.
While most of our example program is the same between Blocks and OnBot Java there are a couple differences and some cool parts to the OnBot Java code we want to point out here!
In the OnBot Java version of this code, we use something called "enum". This allows us to declare the variable name and have it treated as a unique value.
For example: the robot interprets the variable "MANUAL" as one of the states within our switch case in OnBot Java.
With these variables defined we can now have all of our preset positions stored and easily updatable in our state machine:
Our robot will switch states depending on which button on the gamepad is pressed for the arm/wrist!
Within our program there are a few buttons set up to work like a toggle. This means the button only needs to be pressed once rather than held for the code to run. In our Starter Bot code, we're taking advantage of this toggle to have one button be able to do multiple things. For example, our claw can switch between open and closed with just the right bumper.
In other programming languages, you might have an option such as "on button pressed", however that's not available to us here so we have to be a little clever to mimic this concept. Our claw is using two simple variables to make this possible.
The variable clawOpen
allows the servo to move between its two set positions. At the start of our program this is set to false, but will switch each time the right bumper is pressed.
Meanwhile the variable lastBump
checks if the right bumper is currently being held down. If it is set to true, the button is held down so the claw will not move again until it is released, changing the value back to false, then pressed again.
Along with the claw, our robot is using a togglable button for retrieving specimens and hooking them on the high rung!
This year in our Starter Bot Blocks code we are using "functions" for the first time.
Functions act similar to a variable in that we are using one thing to represent another. However, where a variable typically is used in place of something short, such as a number or equation, a function can take the place of several lines of code.
This can be incredibly useful if there is a section of code we know will be repeated or to break apart our code into chunks for easy editing.
Below is a breakdown of our functions:
When using functions, our Blocks program becomes divided into different sections containing separate series of code:
Without the use of functions our code would end up a little long and clunky:
Next we will replace "do something" with an appropriate name. Maybe in this case we are adding a new function for climbing:
Once our function is named it will appear in the "Functions" menu to be added to the main loop or wherever we need it within our code!
All that's left is to add whatever code we'd like to be within this function:
The Starter Bot is able to climb the lower rung using the existing example program!
By default, the Starter Bot's program only references each function once during our loop. The following is intended to be an additional example for reusing functions throughout a program and as an additional educational resource!
This program can be tested on the Starter Bot or another robot using the same configuration file! Create a new OpMode to begin. Ours is called FunctionsDemo
.
If you are using the Starter Bot, make sure the arm is adjusted to not drag while the robot drives autonomously.
Let's say we are working on an autonomous code where we want our robot to drive roughly in a square. Remember that autonomous means this code will move the robot on its own when play is pressed:
Next, let's say we need the robot to do something between one of the turns, such as move its arm or open a servo's claw. There's a couple of ways we could approach this without functions:
Already our code is getting a little long so let's move our side motion and turn into a function:
Now our loop may look like this:
When we test our code we may notice our robot isn't exactly driving in a square shape. Thankfully with our function in place we only need to change the needed value in one place:
This change to the function will be reflected anywhere DRIVE_AND_TURN
used.
Give it a try by changing the right motor's power or the timer to refine your square!
As part of our main loop, our arm and wrist motors are set to RUN_TO_POSITION mode with their TargetPosition set to the appropriate variable. Additionally, our arm and wrist motors are set to full power whenever they are moving.
Because our targetArm and targetWrist values change throughout our code, we include this as part of our loop rather than initialization.
The GAMEPAD_INPUT_STATE function contains all our code for controlling the arm and wrist. Let's break it down by what each button does in our If/Else statement!
When the A/Cross button on the gamepad is pressed our currentState switches to INTAKE meaning our robot's arm will move down and wrist will unfold to be ready to pick up samples.
This section of code allows for a togglable state between two positions of our arm/wrist when B/Circle are pressed. Because we want this to be togglable and not require the button to be held, we want to have our robot check the state of the B/Circle button each loop.
The lastGrab variable will change between true or false based on the state of the button. If the driver holds down the B/Circle button its state will not update again until it is first released.
If B/Circle is pressed AND is not currently held then the robot will run a second if/then statement to determine which of the Wall positions the arm/wrist should move to.
With this statement the robot knows that if the arm is already at our WALL_GRAB preset it should move to unhook. The opposite is also true where if the arm/wrist is in the WALL_UNHOOK preset it will go back to grab.
This section functions similarly to B/Circle providing a togglable control for clipping a specimen!
In this case lastHook allows the robot to determine if the Y/Triangle button is being held before the robot moves between the two positions.
When the X/Square button on the gamepad is pressed our currentState switches to LOW_BASKET meaning our robot's arm will move up and wrist will unfold to be ready to deposit samples in the low basket.
It's always good to have a way to reset our robot if needed! By pressing left bumper, currentState will be set to INIT moving our robot back to its initilization configuration, like what might be used at the start of a match.
Beyond our preset movements, we want our robot to have refined control for the arm and wrist as we navigate the field.
Whenever we press a button on the d-pad our currentState will switch to MANUAL allowing the arm or wrist to move in increments until the button is released.
Because we have our motors set to "RUN_TO_POSITION" mode we can't just turn the power on for manual control. Instead we have the robot changing the position in the appropriate direction in chunks. Depending our your driver's preference, you may choose to adjust these values for quicker or more refined control!
By default, these position values are different in the OnBot Java and Blocks version of the provided code. This is due to a difference in how quickly OnBot Java loops through a program compared to Blocks.
Before the bulk of our program begins, we need to first establish our variables and tell our motors how we want them to run. This section of code will run once when the program is activated and before we hit "Play" on the Driver Hub.
Since the motors on our drive train are a mirror of each other, one needs to be set to run in reverse. In this case we have the leftDrive motor set to run in reverse.
By default, our drivetrain motors will not be using encoder data so we can set them to RUN_WITHOUT_ENCODER. Your team may choose to change this later when working on autonomous programming!
There are two parts to our variable set up in this year's Starter Bot program. Often times we use variables in place of a number or equation, but in this case we will be using them to help our robot move between functions in our code and determine preset arm/wrist positions.
Let's take a look at what all our variables do:
In the OnBot Java version of this code, we use something called "enum". This allows us to declare the variable name and have it treated as a unique value.
For example: the robot interprets the variable "MANUAL" as one of the states within our switch case in OnBot Java. We'll discuss more about the switch case down below!
However, "enum" is not available in Blocks meaning we have to be a little clever to mimic this process. We created strings using the "text" block to do a similar thing. This will have the robot understand MANUAL equals the word "manual", which allows it to move between cases.
You'll notice the variable currentState appears throughout our program repeatedly. But what does it do?
This variable is what will allow our robot to switch between its various preset configurations based on what button is pressed on the gamepad. It's one variable that can be set to a number of different constant states. In comparison, our position variables will remain constant.
When we press one of the buttons on our gamepad it changes our currentState. In turn, this tells our arm and wrist on the robot to move to one of the predetermined positions seen below.
If we needed to update the position value for one of our presets, we can do so within this if/else statement and it will be reflected throughout the entire code without having the hunt down every instance it may be used.
Device Name | Device Type | Port |
---|---|---|
Gamepad Input | Function |
---|---|
Quick Links |
---|
Function | Purpose |
---|
So let's say we wanted to change how quickly our robot's arm moves during with the d-pad. With our functions organizing our code in chunks, it's easy to find the values we want to change:
If we want to create a new function in our Blocks program, we start by pulling a block from the Functions menu:
If the block is deleted this will remove the function from the "Functions" menu.
Variable | Purpose |
---|
arm
UltraPlanetary Gearbox Kit and HD Hex Motor
Motor/Encoder Port 0
wrist
Core Hex Motor
Motor/Encoder Port 1
leftDrive
UltraPlanetary Gearbox Kit and HD Hex Motor
Motor/Encoder Port 2
rightDrive
UltraPlanetary Gearbox Kit and HD Hex Motor
Motor/Encoder Port 3
claw
Smart Robot Servo
Servo Port 4
intake
Smart Robot Servo - set to continuous mode
Servo Port 5
Right Joystick
Turn left and right
Left Joystick
Drive forward and reverse
A/Cross
Intake Preset Position
Arm down, wrist out
B/Circle
Wall Grab and Unhook Preset Position
Arm up to grab, wrist in - first click
Arm up to unhook, wrist in - second click
Y/Triangle
Hover High and Clip High Preset Position
Arm up to low basket height, wrist in
Arm lower to clip, wrist in
X/Square
Low Basket Preset Position
Arm up to low basket height, wrist out
D-pad Up
Arm Up
D-pad Down
Arm Down
D-pad Left
Wrist Out
D-pad Right
Wrist In
Left Bumper
Reset arm/wrist to Initialization Position
Right Bumper
Claw toggle to open or close
Left Trigger
Reverse intake flaps
Right Trigger
Run intake flaps
GAMEPAD_INPUT_STATE | Contains the code related to the arm/wrist presets |
GAMEPAD_INPUT_TOGGLE | Contains the code for the claw toggle |
GAMEPAD_INPUT_MANUAL | Contains the code for manual control of the arm/wrist |
GAMEPAD_INTAKE | Contains the code for running the servo on the intake |
STATE_MACHINE | Contains all the preset positions for currentState |
SPLIT_STICK_ARCADE_DRIVE | Contains the code for driving the robot |
TELEMETRY | Contains the telemetry read out code |
MANUAL | Switches the arm and wrist to being manually controlled by the Dpad |
INTAKE | Sets the arm and wrist to a preset position to intake game pieces |
WALL_GRAB | Sets the arm and wrist to a preset position to pick up clipped specimens from human player |
WALL_UNHOOK | Raises the arm from the wall (human player) position to remove clipped specimens |
HOVER_HIGH | Sets the arm and wrist to a preset position to place specimens on the high rung |
CLIP_HIGH | Moves the arm to clip specimens on the high rung |
LOW_BASKET | Sets the arm/wrist to the needed high to score in the low basket |
INIT | Resets the robot to its start up configuration |
currentState | Switches the arm/wrist between the above preset positions and provides a readout for telemetry |
clawOpen | Allows for the toggle control of the claw |
lastBump | Allows for toggling the claw open or closed |
lastHook | Allows for toggling between the two clip positions |
lastGrab | Allows for toggling between the wall (human player) positions |
Motor
0
REV Robotics Ultraplanetary HD Hex Motor
arm
Motor
1
REV Robotics Core Hex Motor
wrist
Motor
2
REV Robotics Ultraplanetary HD Hex Motor
leftDrive
Motor
3
REV Robotics Ultraplanetary HD Hex Motor
rightDrive
Servo
4
Servo
claw
Servo
5
Continuous Servo
intake