-
Notifications
You must be signed in to change notification settings - Fork 46
Curriculum challenge ~ Tank Drive
Your goal is to write a program that will allow you to drive a robot with “Tank drive" (also known as "Differential Drive"), a simple but common drive system. When using a tank drive, the robot driver controls the robot with 2 joysticks, where the y-axis (vertical) of the left and right joysticks control the left and right side of the robot’s drive motors, respectively.
You can watch a small, two-wheeled example of tank drive here.
When using two joysticks to control a tank drive robot:
- To go forward, push both sticks forward
- To turn left, push the left stick backwards and the right stick forward
Robots are complicated, involving a lot of work in the Design, Mechanical, Electrical, and Computer aspects of engineering. As part of the programming team, we're responsible for this last part.
Since the robot is complicated, we use a well-known "architecture" (way of controlling a robot) that a lot of other teams use. Now's a great time to take a moment to read more about this Programming Robot Architecture before continuing. Go ahead, we'll wait.
When working on the curriculum, you'll only have to work with Subsystems and Commands. The test cases will run your Commands on your Subsystems.
There's one more important robot part that isn't really a part of the robot at all - the OperatorInterface. This is a fancy name for some joysticks and buttons connected to a laptop. Here is an example:
The OperatorInterface contains objects that represent all those joysticks and buttons and switches and such. If you want the robot to respond to human input, you need to use it in your code.There are 3 Java class files that you'll be interacting with:
- DriveSubsystem, which tells the robot how to actually move.
- TankDriveWithJoysticksCommand, which translates user input ("I want to turn left") into instructions that the DriveSubsystem can understand.
- TankDriveTest, which will test if your Command and Subsystem properly translate user input into robot action.
Open up the DriveSubsystem file in IntelliJ. (src/main/java/competition/subsystems/drive/DriveSubsystem.java
)
It has two major sections. The first is where we declare what "things" this Subsystem is in control of. In this case, the Subsystem is responsible for two motors (referred to as XCANTalon because it's a Talon motor controller accessed via CAN):
public XCANTalon frontLeft; public XCANTalon frontRight;
The second is the "constructor", where the Subsystem actually takes ownership of ports on the robot:
@Inject public DriveSubsystem(XCANTalonFactory talonFactory, ElectricalContract electricalContract) { log.info("Creating DriveSubsystem"); // instantiate speed controllers and sensors here, save them as class members this.frontLeft = talonFactory .create(new CANTalonInfo(1, true, FeedbackDevice.CTRE_MagEncoder_Absolute, false, simulatedEncoderFactor)); this.frontRight = talonFactory .create(new CANTalonInfo(2, true, FeedbackDevice.CTRE_MagEncoder_Absolute, false, simulatedEncoderFactor)); frontLeft.createTelemetryProperties(this.getPrefix(), "frontLeft"); frontRight.createTelemetryProperties(this.getPrefix(), "frontRight"); this.register(); }
The robot has a certain number of physical ports, and we can attach one motor to each. In the paint diagram above, you can see that the robot's front left motor is plugged into port #1. In the code, the frontLeft XCANTalon is assigned to talonFactory.create(new CANTalonInfo(1, ...))
. This is not a coincidence.
Open up the TankDriveWithJoysticksCommand file in IntelliJ: (src/main/java/competitions/subsystems/drive/commands/TankDriveWithJoysticksCommand.java
)
It has three major sections.
- What this Command has access to.
- What this Command will do the very first time it is called.
- What this Command will do 20x a second until it is finished.
@Inject public TankDriveWithJoysticksCommand(DriveSubsystem driveSubsystem, OperatorInterface oi) { drive = driveSubsystem; operatorInterface = oi; this.addRequirements(drive); }
This Command knows about two entities:
- DriveSubsystem: (we've covered this above)
- OperatorInterface: A class that has all the user input devices, like Joysticks and buttons.
@Override public void initialize() { // This code is run one time, right when the command is started. // You don't need to write any code here for this exercise. }
Right now, this is empty - so when this Command is called for the first time, it will just do nothing.
@Override public void execute() { // Execute command 20x a second until it is finished }
Execute: what the robot does 20 times a second until it is told to stop. Eventually you will fill this in with the logic that translates user input (via joysticks and buttons) into instructions for the DriveSubsystem.
Open up the TankDriveTest file in IntelliJ. (src/test/java/competition/subsystems.drive/TankDriveTest.java
)
This file contains a few simple tests of your code. It will send inputs into the TankDriveWithJosticksCommand (by manipulating fake joysticks) and call Initialize and Execute. Then it will read the output of the fake motors in the DriveSubsystem to see if they are moving in the expected way.
You won't need to modify any of the code in here, but you should know how to run the tests. There are a number of ways to do that, but any easy way is as follows:
- Have the file open.
- There will be an icon to the left of
public void
with a green arrow. Click it and select Run Test from the menu. - If the output hasn't popped up, click the icon that looks like a Play button in the left rail of IntelliJ.
These tests will not pass initially. It is your job to modify both TankDriveWithJoysticksCommand and DriveSubsystem to make the tests pass.
Now it’s time to start writing some Java code to make your new tank drive project actually do something. If you get really stuck, take a look at this page: Tank Drive Solution.
The DriveSubsystem needs to know how to drive like a tank. You'll need to fill in code for the method "tankDrive" so that it takes in two values (how much left power, and how much right power) and tells the motors what to do based on it. Some useful tips:
- Motors can be told to spin by calling XCANTalon.simpleSet(double value). An example would be: "frontLeft.simpleSet(0.5)". This would set the front left motor to run at 50% power.
- The minimum value (full reverse) is -1. The maximum value (full forward) is 1. 0 means "stop."
- The fake human in the test is going to use the Left joystick and the Right joystick located in the OperatorInterface.
- The joysticks have axes: http://a54.idata.over-blog.com/1/27/40/16/Evolution-joystick/Joystick-XYZ.png.
- When the fake human presses forward on the joystick, they expect the robot to go forward.
- The maximum value for a joystick axis is +1, and the minimum value is -1, with 0 being "not pushed along this axis."
Now that we have some new code created, we want to check it into the git repository and push it up to the central server. This way, if you ever use a different laptop you can keep working on the same code! Or if you make a mistake you can go back in time to a previous version of the code.
- Open 'GitHub Desktop'
- Click on 'Branch' on the top bar and 'New Branch...'
- This will create a new branch for you to work on that won’t affect anyone else. Name your branch something useful like 'tankdrive'
- In the rail on the left, enter a commit message. Give a useful message such as 'Initial changes to Tank Drive.'
- Once your message is typed, click 'Commit to {branch name}' and then 'Publish Branch' from the main section of the window. This will push up the new branch you created to the main github repository so you could 'pull' the changes back down on another machine.
Once you’re ready to test your code on a real robot (and you have access to a real robot), follow these steps:
- Make sure the robot is on!
- Connect your laptop to the robots wifi network: usually ‘488’
- Run 'FRC driver station'. This should have been installed when you installed the FRC {current year} Update Suite during onboarding (if you did the full onboarding).
- Deploy project using IntelliJ by pressing ctrl-shift-p and typing 'Build & Deploy Robot' into the search bar that appears, select the 'Build & Deploy Robot' option
- Deployment should take less than a minute. Afterwards, the driver station should report that the robot has code on it! Yay!
- Place robot on top of blocks (so the wheels aren't touching the ground)
- Enable robot using the FRC Driver Station
- Place a finger on enter, so that you are able to stop the robot if things goes wrong (pressing enter while the robot is enabled will immediately disable it)
- Test driving using joysticks (move each joystick one at a time forward/backwards a little and make sure the all the wheels move as you would expect). It’s very common for certain motors to be backwards from what you expected and you need to adjust the program to handle it.
With this quick quiz
Continue with the next curriculum challenge: Altering Tank Drive
- Home
- Challenges
- Setting up your environment
- Basic Robot Principles
- Tank Drive
- Altering Tank Drive
- Moving to a target position
- Rotating to a target orientation
- Factories
- The Power of Injection
- Dependency Injection with Dagger
- Upgrading Using the SeriouslyCommonLib
- Running XbotEDU on a Real Robot
- Auto Stopping Collector