404
Page not found
diff --git a/.nojekyll b/.nojekyll new file mode 100644 index 0000000..e69de29 diff --git a/404.html b/404.html new file mode 100644 index 0000000..4185375 --- /dev/null +++ b/404.html @@ -0,0 +1,15 @@ +
Page not found
Learning What's What
public
- an object accessible by other classes (files)private
- an object only accessible by its containing class (file).protected
- like private but can be seen by subclassesreturn
- value to return or give back after method execution (run). void
- a method that returns no valuenull
- a value that means empty or nothingIMPORTANT NOTE
Java is case sensitive, meaning capitalization matters!
Example
main loads class1, class1 loads class2Example
classObject = new className();int value;
+void increment(){
+ value++;
+}
// Example of a method with a parameter
+double half(int num1){
+ double multiplier = 0.5;
+ return num1*multiplier;
+}
+
+int newNumber = half(12); // <---- Method being called (used) in code
public
or int
int
- integers (whole numbers)double
- double precision floating point (fractional/decimal values) boolean
- true or false (true = 1 or false = 0) values.string
- text values contained in parenthesesExample: int sum;
Example: boolean isFull = true;
Most variables can have their values assigned or reassigned at any point elsewhere in your program. To avoid having a variable change its value during runtime you can make it a constant
static final
keywords together in front of the data type of the variableExample: public static final double PI_VALUE = 3.14159;
public int testMethod() {
+ int example = 12; // Inside of method
+ example = example + 1;
+ return example
+}
int example = 12; // Outside of method
+public void testMethod() {
+ example = example + 1;
+ return example
+}
// This is what a single line comment looks like
+
+// You can also have multiple
+// single line comments in a row
/*
+This is what a
+multiline comment
+looks like
+*/
/**
+ * This is a doc comment
+ *
+ * <ul>
+ * <li>They can be viewed by hovering over code they are attached to</li>
+ * <li>They can be formatted with HTML</li>
+ * </ul>
+*/
Example
ThreeMotorDrive, driveForward, setSpeedInfo
There are other naming conventions, but for this tutorial we will use the camel cases
The Brains of the Bot!
How does the robot see?
Limit Switch | Grayhill brand Quadrature Encoder | Kauai Labs navX Gyro/ Accelerometer |
---|---|---|
Making life easier
Making FRC Programming Easy
int
or double
) and classes.Examples
Talon
, Solenoid
, Encoder
...//This method closes the dog eyes
+public void closeEyes(){
+ leftEye.close();
+ rightEye.close();
//This method sets the speed of the drivetrain
+public void setSpeed(double speed){
+ leftMotor.set(speed);
+ rightMotor.set(speed);
+}
Tip
Subsystems define what the robot is made of and what it can do while commands actually tell the robot to do those things//This command will continuously run the two methods in execute
+protected void execute() {
+ dog.head.closeEyes();
+ dog.head.openEyes();
+}
//This command tells the robot to drive forward full speed
+protected void initialize(){
+ robot.drivetrain.setSpeed(1.0);
+}
void initialize()
- Methods in here are called just before this Command runs the first time.void execute()
- Methods in here are called repeatedly when this Command is scheduled to runboolean isFinished()
- When this returns true, the Command stops running execute() void end()
- Methods in here are called once after isFinished returns truevoid interrupted()
- Methods in here are called when another command which requires one or more of the same subsystems is scheduled to runTip
It is good practice to callend()
in interrupted()
Example
Robot.java loads RobotContainer.java, RobotContainer.java loads DriveForward.java.RobotContainer.nameOfSubsystem.desiredMethod();
RobotMap.NameOfMotor()
Helping out with the project!
If you make Example Project Code changes please contribute changes that reflect this in the Documentation. This will make it easier for us and more likely that your contribution will be approved.
If you make documentation changes please contribute changes that reflect this in the Example Project Code. This will make it easier for us and more likely that your contribution will be approved.
There are a couple of ways to contribute to this project:
On each page there is an option to edit the page. Any changes you make through this option will be submitted and become live once they are approved.
The edit icon looks like this:
Alternatively you could create a pull request and clone the repository
You can help the project by making new pages. Any pages you make will become live once they are approved.
Click here to create a new page
Please use the New Page Template
Click here to see tips on creating markdown documents
Warning
Make sure all documentation files end in .md
Tip
You can add to a certain tab by appending /tab_name/
to the file name
Tip
Visit Admonitions (call-out) references for a list off call-outs like this one.
pip install -r requirements.txt
python -m pip install -r requirements.txt
py -m pip install -r requirements.txt
mkdocs serve
to open up a live local version of the project in your browsermkdocs serve
does not work on its own, try each one in order until successful:python -m mkdocs serve
py -m mkdocs serve
docs
directory.mkdocs.yml
file in the # Navigation
(nav:
) section.Please copy this code as a template to create your new page
# Page title
+<!-- This page was contributed by: -->
+
+Subtitle
+
+<!-- Add a page image to make it pretty! -->
+![Image Title](imageURL)
+
+## Overview
+
+This section will help you learn to BLANK.
+
+**See table of contents for a breakdown of this section.**
+
+***
+
+## Section One
+
+- Some info
+- Some other into
+ - Some sub info
+
+### Section One Subsection
+
+***
+
+## Section Two
+
+- Info
+- Info 2
+
+!!! Tip
+ This is a tip.
Subtitle
This section will help you learn to create a basic elevator or lift subsystem.
This subsystem will contain:
See table of contents for a breakdown of this section.
Tip
This is a tip.
The unofficial FIRST Robotics Competition Java Programming Tutorial.
Info
Updated for the 2021 Season
Last updated: 9/30/21
Disclaimer: Some screenshots may have different colors, icons, more/less folders/files than you due to themes or personal settings. This is normal and should not impact the tutorial. If you still have any questions please contact us.
Name | Team | Team Role |
---|---|---|
Tayler Uva | 3255 | Coach |
Isaac Sayasane | 3255 | Alumni |
Sharon Riggs | 6995 | Mentor |
In this section we will be going over
1) Create a new command called DriveDistance
2) Before the constructor create a double called distance
3) In the DriveDistance constructor add a double parameter called inches
4) Inside type:
distance = inches;
5) In initialize add our resetDriveEncoder method
6) In execute add our arcadeDrive method and change the moveSpeed parameter to a RobotPreference named driveDistanceSpeed and rotateSpeed to 0.0
7) In isFinished type:
return Robot.m_drivetrain.getDriveEncoderDistance() == distance;
8) In end stop the Drivetrain and call end in interrupted
Your full DriveDistance.java should look like this
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.Command;
+import frc.robot.Robot;
+import frc.robot.RobotPreferences;
+
+public class DriveDistance extends Command {
+
+ private double distance;
+
+ public DriveDistance(double inches) {
+ // Use requires() here to declare subsystem dependencies
+ // eg. requires(chassis);
+ requires(Robot.m_drivetrain);
+ distance = inches;
+ }
+
+ // Called just before this Command runs the first time
+ @Override
+ protected void initialize() {
+ Robot.m_drivetrain.resetDriveEncoder();
+ }
+
+ // Called repeatedly when this Command is scheduled to run
+ @Override
+ protected void execute() {
+ Robot.m_drivetrain.arcadeDrive(RobotPreferences.driveDistanceSpeed(), 0.0);
+ }
+
+ // Make this return true when this Command no longer needs to run execute()
+ @Override
+ protected boolean isFinished() {
+ return Robot.m_drivetrain.getDriveEncoderDistance() == distance;
+ }
+
+ // Called once after isFinished returns true
+ @Override
+ protected void end() {
+ Robot.m_drivetrain.arcadeDrive(0.0, 0.0);
+ }
+
+ // Called when another command which requires one or more of the same
+ // subsystems is scheduled to run
+ @Override
+ protected void interrupted() {
+ end();
+ }
+}
The code you typed in RobotPreferences.java should be this
public static final double driveDistanceSpeed() {
+ return Preferences.getInstance().getDouble("driveDistanceSpeed", 0.5);
+}
1) Create a new Command Group named Autonomous
2) In the constructor type
addSequential(new DriveDistance(RobotPreferences.autoDriveDistance()));
+addSequential(new ShooterUp());
1) Create a new command called DoDelay
2) Before the constructor add two private doubles called expireTime and timeout
3) In the constructor add a double called seconds in the parameter
4) Inside the constructor set timeout equal to seconds
5) Create a protected void method called startTimer
6) Inside set expireTime equal to timeSinceInitialized + timeout
7) In initialized add our startTimer method
8) In isFinished return timeSinceInitialized is greater or equal to expireTime
Your full DoDelay.java should look like this
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.Command;
+
+public class DoDelay extends Command {
+
+private double expireTime;
+private double timeout;
+
+ public DoDelay(double seconds) {
+ // Use requires() here to declare subsystem dependencies
+ // eg. requires(chassis);
+ timeout = seconds;
+ }
+
+ protected void startTimer() {
+ expireTime = timeSinceInitialized() + timeout;
+ }
+
+ // Called just before this Command runs the first time
+ @Override
+ protected void initialize() {
+ startTimer();
+ }
+
+ // Called repeatedly when this Command is scheduled to run
+ @Override
+ protected void execute() {
+ }
+
+ // Make this return true when this Command no longer needs to run execute()
+ @Override
+ protected boolean isFinished() {
+ return (timeSinceInitialized() >= expireTime);
+ }
+
+ // Called once after isFinished returns true
+ @Override
+ protected void end() {
+ }
+
+ // Called when another command which requires one or more of the same
+ // subsystems is scheduled to run
+ @Override
+ protected void interrupted() {
+ }
+}
Your full Autonomous.java should look like this
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.CommandGroup;
+import frc.robot.RobotPreferences;
+
+public class Autonomous extends CommandGroup {
+ /**
+ * Add your docs here.
+ */
+ public Autonomous() {
+ addSequential(new DriveDistance(RobotPreferences.autoDriveDistance()));
+ addSequential(new DoDelay(RobotPreferences.autoDelay()));
+ addSequential(new ShooterUp());
+ }
+}
The code you typed in RobotPreferences.java should look like this
public static double autoDelay() {
+ return Preferences.getInstance().getDouble("autoDelay", 5.0);
+}
+
+public static double autoDriveDistance() {
+ return Preferences.getInstance().getDouble("autoDriveDistance", 12.0);
+}
In order to run our Autonomous command in autonomous we will have to put it in Robot.java so that it will run as soon as the robot enters the autonomous mode
In Robot.java under autonomousInit find m_autonomousCommand = m_chooser.getSelected(); and change it to
public void autonomousInit() {
+m_autonomousCommand = new Autonomous();
+...
Bring your creation to life!
This section will help you learn to deploy code to your robot.
See table of contents for a breakdown of this section.
To deploy code, first make sure your computer is connected to the robot in ONE of the following ways:
Note
Make sure your team number in **wpilib_preferences.json** in the **.wpilib** folder is set to the same team number your roboRIO was programmed for (it should be the number you set when creating the project and you will NOT need to check this every time as it should not change by itself).
1) Select the W icon from the tab bar or use the shortcut by holding down Ctrl+Shift+P at the same time. (Replace ctrl with cmd on macOS)
2) Type and hit enter or select: WPILib: Deploy Robot Code
Tip
Alternatively you can do one of the following:
+
+- Use **Shift+F5** at any time to deploy. (you may also need to hold fn depending on your computer configuration)
+- Right-click on the build.gradle file in the project hierarchy and select "Build Robot Code”
+- Open the shortcut menu indicated by the ellipses in the top right corner of the VS Code window and select "Build Robot Code"
Lets get moving!
This section is designed to help you program a basic driving robot, start to finish.
See table of contents for a breakdown of this section.
Before we begin we must create the class file for the drivetrain subsystem. See Creating a New Subsystem for info on how to do this.
In the Drivetrain class we will tell the subsystem what type of components it will be using.
Tip
Be sure to read [Visual Studio Code Tips](../basics/vscode_tips.md){target=_blank} before getting started! It will make your life a lot easier.
1) Create 4 global variables of data type Talon and name them: leftFrontTalon
, rightFrontTalon
, leftBackTalon
, rightBackTalon
Talon leftFrontTalon;
2) Next assign their values to null
(more info on null
).
The code you typed should be this:
Talon leftFrontTalon = null;
+Talon leftBackTalon = null;
+Talon rightFrontTalon = null;
+Talon rightBackTalon = null;
Your full Drivetrain.java should look like this:
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj.Talon;
+import edu.wpi.first.wpilibj.command.Subsystem;
+
+/**
+ * Add your docs here.
+ */
+public class Drivetrain extends Subsystem {
+ // Put methods for controlling this subsystem
+ // here. Call these from Commands.
+
+ Talon leftFrontTalon = null;
+ Talon leftBackTalon = null;
+ Talon rightFrontTalon = null;
+ Talon rightBackTalon = null;
+
+ @Override
+ public void periodic() {
+ // This method will be called once per scheduler run
+ }
+}
1) Create the constructor for Drivetrain.java (more info on constructors)
Now that we have created the Talons we must initialize them and tell them what port on the roboRIO they are on.
2) Initialize (set value of) leftFrontTalon
to new Talon(0)
.
leftFrontTalon
, in a new piece of memory and states it is on port 0 of the roboRIO. Drivetrain()
Talon(int)
takes a variable of type int
. In this case the int
(integer) refers to the port number on the roboRIO. This calls the constructor Talon(int)
in the Talon class.
The code you typed should be this:
public Drivetrain() {
+ // Talons
+ leftFrontTalon = new Talon(0);
+}
Your full Drivetrain.java should look like this:
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj.Talon;
+import edu.wpi.first.wpilibj.command.Subsystem;
+
+/**
+ * Add your docs here.
+ */
+public class Drivetrain extends Subsystem {
+ // Put methods for controlling this subsystem
+ // here. Call these from Commands.
+
+ Talon leftFrontTalon = null;
+ Talon leftBackTalon = null;
+ Talon rightFrontTalon = null;
+ Talon rightBackTalon = null;
+
+ public Drivetrain() {
+ // Talons
+ leftFrontTalon = new Talon(0);
+ }
+
+ @Override
+ public void periodic() {
+ // This method will be called once per scheduler run
+ }
Since each subsystem has its own components with their own ports, it is easy to lose track of which ports are being used and for what. To counter this you can use a class called Constants to hold all these values in a single location.
1) To use Constants, instead of putting 0
for the port on the Talon type:
Constants.DRIVETRAIN_LEFT_FRONT_TALON
2) Click on the underlined text
3) Click on the 💡light bulb and select “create constant…”
4) Click on Constants.java tab that just popped up
5) Change the 0
to the correct port for that motor controller on your robot/roboRIO
Danger
If you set this to the wrong value, you could damage your robot when it tries to move!
6) Repeat these steps for the remaining Talons.
Tip
Remember to save both Drivetrain.java and Constants.java
The code you type should be this:
leftFrontTalon = new Talon(Constants.DRIVETRAIN_LEFT_FRONT_TALON);
Your full Drivetrain.java should look like this:
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj.Talon;
+import edu.wpi.first.wpilibj.command.Subsystem;
+import frc.robot.Constants;
+
+/**
+ * Add your docs here.
+ */
+public class Drivetrain extends Subsystem {
+ // Put methods for controlling this subsystem
+ // here. Call these from Commands.
+
+ Talon leftFrontTalon = null;
+ Talon leftBackTalon = null;
+ Talon rightFrontTalon = null;
+ Talon rightBackTalon = null;
+
+ public Drivetrain() {
+ // Talons
+ leftFrontTalon = new Talon(Constants.DRIVETRAIN_LEFT_FRONT_TALON);
+ leftBackTalon = new Talon(Constants.DRIVETRAIN_LEFT_BACK_TALON);
+ rightFrontTalon = new Talon(Constants.DRIVETRAIN_RIGHT_FRONT_TALON);
+ rightBackTalon = new Talon(Constants.DRIVETRAIN_RIGHT_BACK_TALON);
+ }
+
+ @Override
+ public void periodic() {
+ // This method will be called once per scheduler run
+ }
+}
Your full Constants.java should look similar to this:
package frc.robot;
+
+public class Constants {
+ // Talons
+ public static final int DRIVETRAIN_LEFT_FRONT_TALON = 0;
+ public static final int DRIVETRAIN_LEFT_BACK_TALON = 1;
+ public static final int DRIVETRAIN_RIGHT_FRONT_TALON = 2;
+ public static final int DRIVETRAIN_RIGHT_BACK_TALON = 3;
+}
Warning
Remember to use the values for YOUR specific robot or you could risk damaging it!
1) In the same place we created our talons (outside of the constructor) we will create a DifferentialDrive and SpeedControllerGroups for our left and right motor controllers.
Outside of the constructor type:
SpeedControllerGroup leftMotors = null;
+SpeedControllerGroup rightMotors = null;
+
+DifferentialDrive differentialDrive = null;
Warning
You should only group motors that are spinning the same direction physically when positive power is being applied otherwise you could damage your robot.
2) Now we must initialize the SpeedControllerGroups and DifferentialDrive like we did our talons. ...
In the constructor type:
leftMotors = new SpeedControllerGroup(leftFrontTalon, leftBackTalon);
+rightMotors = new SpeedControllerGroup(rightFrontTalon, rightBackTalon);
+
+differentialDrive = new DifferentialDrive(leftMotors, rightMotors);
The code you type outside the constructor should be this:
SpeedControllerGroup leftMotors = null;
+SpeedControllerGroup rightMotors = null;
+
+DifferentialDrive differentialDrive = null;
The code you type inside the constructor should be this:
leftMotors = new SpeedControllerGroup(leftFrontTalon, leftBackTalon);
+rightMotors = new SpeedControllerGroup(rightFrontTalon, rightBackTalon);
+
+differentialDrive = new DifferentialDrive(leftMotors, rightMotors);
Your full Drivetrain.java should look like this:
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj.SpeedControllerGroup;
+import edu.wpi.first.wpilibj.Talon;
+import edu.wpi.first.wpilibj.command.Subsystem;
+import edu.wpi.first.wpilibj.drive.DifferentialDrive;
+import frc.robot.Constants;
+
+/**
+ * Add your docs here.
+ */
+public class Drivetrain extends Subsystem {
+ // Put methods for controlling this subsystem
+ // here. Call these from Commands.
+
+ Talon leftFrontTalon = null;
+ Talon leftBackTalon = null;
+ Talon rightFrontTalon = null;
+ Talon rightBackTalon = null;
+
+ SpeedControllerGroup leftMotors = null;
+ SpeedControllerGroup rightMotors = null;
+
+ DifferentialDrive differentialDrive = null;
+
+ public Drivetrain() {
+ // Talons
+ leftFrontTalon = new Talon(Constants.DRIVETRAIN_LEFT_FRONT_TALON);
+ leftBackTalon = new Talon(Constants.DRIVETRAIN_LEFT_BACK_TALON);
+ rightFrontTalon = new Talon(Constants.DRIVETRAIN_RIGHT_FRONT_TALON);
+ rightBackTalon = new Talon(Constants.DRIVETRAIN_RIGHT_BACK_TALON);
+
+ leftMotors = new SpeedControllerGroup(leftFrontTalon, leftBackTalon);
+ rightMotors = new SpeedControllerGroup(rightFrontTalon, rightBackTalon);
+
+ differentialDrive = new DifferentialDrive(leftMotors, rightMotors);
+ }
+
+ @Override
+ public void periodic() {
+ // This method will be called once per scheduler run
+ }
+}
Now it’s time to make an arcadeDrive from our differentialDrive!
1) Let’s create a public void method called “arcadeDrive” with type “double” parameters moveSpeed and rotateSpeed.
Below the constructor type:
public void arcadeDrive(double moveSpeed, double rotateSpeed) {
+
+}
Tip
By putting something in the parentheses it makes the method require a parameter when it is used. When the method gets used and parameters are passed, they will be store in moveSpeed and rotateSpeed (in that order). See parameters for more info.
2) Now lets make our method call the differentialDrive's arcadeDrive method.
Inside our method type:
differentialDrive.arcadeDrive(moveSpeed, rotateSpeed);
DifferentialDrive's arcadeDrive method takes parameters moveValue and rotateValue.
Note
At this point you could instead create a tank drive, however implementation differs slightly. To do so type differentialDrive.tankDrive(moveSpeed, rotateSpeed);
instead of differentialDrive.arcadeDrive(moveSpeed, rotateSpeed);
and change the method name reflect this.
Tip
If you want to limit the max speed you can multiple the speeds by a decimal (i.e. 0.5*moveSpeed will make the motors only move half of their maximum speed)
You may want to do this for initial testing to make sure everything is going the right direction.
The code you type should be this:
public void arcadeDrive(double moveSpeed, double rotateSpeed) {
+ differentialDrive.arcadeDrive(moveSpeed, rotateSpeed);
+}
Your full Drivetrain.java should look like this:
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj.SpeedControllerGroup;
+import edu.wpi.first.wpilibj.Talon;
+import edu.wpi.first.wpilibj.command.Subsystem;
+import edu.wpi.first.wpilibj.drive.DifferentialDrive;
+import frc.robot.Constants;
+
+/**
+ * Add your docs here.
+ */
+public class Drivetrain extends Subsystem {
+ // Put methods for controlling this subsystem
+ // here. Call these from Commands.
+
+ Talon leftFrontTalon = null;
+ Talon leftBackTalon = null;
+ Talon rightFrontTalon = null;
+ Talon rightBackTalon = null;
+
+ SpeedControllerGroup leftMotors = null;
+ SpeedControllerGroup rightMotors = null;
+
+ DifferentialDrive differentialDrive = null;
+
+ public Drivetrain() {
+ // Talons
+ leftFrontTalon = new Talon(Constants.DRIVETRAIN_LEFT_FRONT_TALON);
+ leftBackTalon = new Talon(Constants.DRIVETRAIN_LEFT_BACK_TALON);
+ rightFrontTalon = new Talon(Constants.DRIVETRAIN_RIGHT_FRONT_TALON);
+ rightBackTalon = new Talon(Constants.DRIVETRAIN_RIGHT_BACK_TALON);
+
+ leftMotors = new SpeedControllerGroup(leftFrontTalon, leftBackTalon);
+ rightMotors = new SpeedControllerGroup(rightFrontTalon, rightBackTalon);
+
+ differentialDrive = new DifferentialDrive(leftMotors, rightMotors);
+ }
+
+ public void arcadeDrive(double moveSpeed, double rotateSpeed) {
+ differentialDrive.arcadeDrive(moveSpeed, rotateSpeed);
+ }
+
+ @Override
+ public void periodic() {
+ // This method will be called once per scheduler run
+ }
+}
In order to drive our robot, it needs to know what will be controlling it. To do so, we will create a new joystick in RobotContainer.java
1) Open RobotContainer.java
2) Type:
public Joystick driverController = new Joystick(Constants.DRIVER_CONTROLLER);
import edu.wpi.first.wpilibj.Joystick;
driverController
of type Joystick pointing to a joystick on port DRIVER_CONTROLLER
from Constants3) Click the 💡 light bulb to create a new CONSTANT and set the value to the port number the joystick uses on the laptop (this can be found in the Driverstation software).
The code you type should be this:
public Joystick driverController = new Joystick(Constants.DRIVER_CONTROLLER);
Your full RobotContainer.java should look like this:
package frc.robot;
+
+import edu.wpi.first.wpilibj.Joystick;
+
+/**
+ * This class is where the bulk of the robot should be declared. Since
+ * Command-based is a "declarative" paradigm, very little robot logic should
+ * actually be handled in the {@link Robot} periodic methods (other than the
+ * scheduler calls). Instead, the structure of the robot (including subsystems,
+ * commands, and button mappings) should be declared here.
+ */
+public class RobotContainer {
+ // The robot's subsystems and commands are defined here...
+ public Joystick driverController = new Joystick(Constants.DRIVER_CONTROLLER);
+}
Your full Constants.java should look similar to this:
package frc.robot;
+
+public class Constants {
+ // Talons
+ public static final int DRIVETRAIN_LEFT_FRONT_TALON = 0;
+ public static final int DRIVETRAIN_LEFT_BACK_TALON = 1;
+ public static final int DRIVETRAIN_RIGHT_FRONT_TALON = 2;
+ public static final int DRIVETRAIN_RIGHT_BACK_TALON = 3;
+
+ // Joysticks
+ public static final int DRIVER_CONTROLLER = 0;
+}
Before we begin we must create the class file for the DriveArcade command. See Creating a New Command for info on how to do this and info on what each pre-created method does.
1) In the constructor DriveArcade()
type:
addRequirements(RobotContainer.m_drivetrain);
Warning
If you use the light bulb to import ‘Robot', be sure to import the one with “frc.robot”
1) In the execute method we will create 2 variables of type double called moveSpeed and rotateSpeed.
In the execute() method type:
double moveSpeed = -RobotContainer.driverController.getRawAxis(Constants.DRIVER_CONTROLLER_MOVE_AXIS);
+double rotateSpeed = RobotContainer.driverController.getRawAxis(Constants.DRIVER_CONTROLLER_ROTATE_AXIS);
Tip
Remember to use the light bulb for importing and creating constants if needed!
2) Also in the execute method we will we want to call the arcadeDrive method we created in Drivetrain and give it the variables moveSpeed and rotateSpeed we created as parameters.
In the execute() method below rotateSpeed type:
RobotContainer.m_drivetrain.arcadeDrive(moveSpeed, rotateSpeed);
Since we will be using this command to control the robot we want it to run indefinitely.
1) To do this we are going to continue having isFinished return false, meaning the command will never finish.
(We don't need to change anything as this is the default)
Tip
(timePassed > 10)
will return true after 10 seconds but return false anytime before 10 seconds have passed.1) We will call the arcadeDrive method and give it 0 and 0 as the parameters.
In the end() method type:
RobotContainer.m_drivetrain.arcadeDrive(0, 0);
Your full Constants.java should look similar to this:
package frc.robot;
+
+public class Constants {
+ // Talons
+ public static final int DRIVETRAIN_LEFT_FRONT_TALON = 0;
+ public static final int DRIVETRAIN_LEFT_BACK_TALON = 1;
+ public static final int DRIVETRAIN_RIGHT_FRONT_TALON = 2;
+ public static final int DRIVETRAIN_RIGHT_BACK_TALON = 3;
+
+ // Joysticks
+ public static final int DRIVER_CONTROLLER = 0;
+ public static final int DRIVER_CONTROLLER_MOVE_AXIS = 1; // Change for your controller
+ public static final int DRIVER_CONTROLLER_ROTATE_AXIS = 2; // Change for your controller
+}
Your full DriveArcade.java should look like this:
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.Command;
+import frc.robot.RobotContainer;
+import frc.robot.Constants;
+
+public class DriveArcade extends Command {
+ public DriveArcade() {
+ // Use addRequirements() here to declare subsystem dependencies.
+ addRequirements(RobotContainer.m_drivetrain);
+ }
+
+ // Called just before this Command runs the first time
+ @Override
+ protected void initialize() {
+ }
+
+ // Called repeatedly when this Command is scheduled to run
+ @Override
+ protected void execute() {
+ double moveSpeed = -RobotContainer.driverController.getRawAxis(Constants.DRIVER_CONTROLLER_MOVE_AXIS);
+ double rotateSpeed = RobotContainer.driverController.getRawAxis(Constants.DRIVER_CONTROLLER_ROTATE_AXIS);
+
+ RobotContainer.m_drivetrain.arcadeDrive(moveSpeed, rotateSpeed);
+ }
+
+ // Called once the command ends or is interrupted.
+ @Override
+ protected void end(boolean interrupted) {
+ Robot.m_drivetrain.arcadeDrive(0, 0);
+ }
+
+ // Make this return true when this Command no longer needs to run execute()
+ @Override
+ protected boolean isFinished() {
+ return false;
+ }
+}
1) Back in RobotContainer.java in the constructor we will call the setDefaultCommand
of m_drivetrain
and pass it the DriveArcade
command
In the RobotContainer.java constructor type:
m_drivetrain.setDefaultCommand(new DriveArcade());
Tip
Remember to use the light bulb for importing if needed!
Your full RobotContainer.java should look like this:
package frc.robot;
+
+import edu.wpi.first.wpilibj.Joystick;
+import frc.robot.commands.*;
+import frc.robot.subsystems.*;
+import edu.wpi.first.wpilibj2.command.Command;
+
+/**
+ * This class is where the bulk of the robot should be declared. Since Command-based is a
+ * "declarative" paradigm, very little robot logic should actually be handled in the {@link Robot}
+ * periodic methods (other than the scheduler calls). Instead, the structure of the robot
+ * (including subsystems, commands, and button mappings) should be declared here.
+ */
+public class RobotContainer {
+ // The robot's subsystems and commands are defined here...
+ public static final Drivetrain m_drivetrain = new Drivetrain();
+ private final ExampleSubsystem m_exampleSubsystem = new ExampleSubsystem();
+
+ private final ExampleCommand m_autoCommand = new ExampleCommand(m_exampleSubsystem);
+
+ public Joystick driverController = new Joystick(Constants.DRIVER_CONTROLLER);
+
+ /**
+ * The container for the robot. Contains subsystems, OI devices, and commands.
+ */
+ public RobotContainer() {
+ // Configure the button bindings
+ configureButtonBindings();
+
+ // Set default commands on subsystems
+ m_drivetrain.setDefaultCommand(new DriveArcade());
+ }
+
+ /**
+ * Use this method to define your button->command mappings. Buttons can be created by
+ * instantiating a {@link GenericHID} or one of its subclasses ({@link
+ * edu.wpi.first.wpilibj.Joystick} or {@link XboxController}), and then passing it to a
+ * {@link edu.wpi.first.wpilibj2.command.button.JoystickButton}.
+ */
+ private void configureButtonBindings() {
+ }
+
+
+ /**
+ * Use this to pass the autonomous command to the main {@link Robot} class.
+ *
+ * @return the command to run in autonomous
+ */
+ public Command getAutonomousCommand() {
+ // An ExampleCommand will run in autonomous
+ return m_autoCommand;
+ }
+}
Lets get started
Before we can start programing a robot, we must create a new project in Visual Studio Code (VSCode).
See table of contents for a breakdown of this section.
1) Select the W icon from the tab bar or use the shortcut by holding down Ctrl+Shift+P at the same time. (Replace ctrl with command on macOS)
2) Type and hit enter or select WPILib: Create a new project
3) Click Select a Project Type and choose Template
4) Click Select a Language and choose Java
5) Click Select a project base and choose Command Robot
6) Click Select a new project folder and choose where on your computer you would like to store the program
7) Enter a project name in the text field labeled as such
8) Enter your team number in the text field labeled as such
9) Select Generate Project
10) When prompted “Would you like to open the folder?”, select Yes (Current Window)
Newly created projects have many files within them. We only care about the contents within the src/main/java/frc/robot/ folder. Everything else can be ignored at this point in the tutorial.
Files in the robot folder:
1) Click on the src folder to expand it.
2) Do the same for java then subsystems
3) Right click on subsystems and select Create a new class/ command.
4) Select Subsystem (New) and type your DesiredSubsystemName (i.e. Drivetrain) for the name and hit enter on your keyboard.
5) Click on the newly created DesiredSubsystemName.java (or Drivetrain.java if you named it that)
Do not forget this step!
When a robot program runs on the roboRIO it only runs the main file Robot.java and anything Robot.java links to such as RobotContainer.java.
We have created a new subsystem but we have not yet linked it to Robot.java through RobotContainer.java.
We must do this for EVERY subsystem we create
1) In RobotContainer.java we will create a new public global constant variable of type DesiredSubsystemName
(i.e. Drivetrain
):
public static final m_desiredSubsystemName = new DesiredSubsystemName();
(i.e. public static final m_drivetrain = new Drivetrain();
)
Now when we use this subsystem in commands, we must call RobotContainer.m_desiredSubsystemName.
to get access to it and its methods. (i.e. RobotContainer.m_drivetrain.someMethod()
)
Newly created subsystems are empty with the exception of the periodic.
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj2.command.SubsystemBase;
+
+public class Drivetrain extends SubsystemBase {
+ /**
+ * Creates a new Drivetrain.
+ */
+ public Drivetrain() {
+
+ }
+
+ @Override
+ public void periodic() {
+ // This method will be called once per scheduler run
+ }
+}
1) Click on the src folder to expand it (if it isn't already).
2) Do the same for commands
3) Right click on commands and select Create a new class/ command.
4) Select Command (New) and type DesiredCommandName (i.e. DriveArcade) for the name and hit enter on your keyboard.
5) Click on the newly created DesiredCommandName.java (or DriveArcade.java if you named it that)
Newly created commands have some predefined methods in them specific for a command based robot.
execute()
(initialize always runs once regardless). package frc.robot.commands;
+
+import edu.wpi.first.wpilibj2.command.CommandBase;
+
+public class DriveArcade extends CommandBase {
+ /**
+ * Creates a new DriveArcade.
+ */
+ public DriveArcade() {
+ // Use addRequirements() here to declare subsystem dependencies.
+ }
+
+ // Called when the command is initially scheduled.
+ @Override
+ public void initialize() {
+ }
+
+ // Called every time the scheduler runs while the command is scheduled.
+ @Override
+ public void execute() {
+ }
+
+ // Called once the command ends or is interrupted.
+ @Override
+ public void end(boolean interrupted) {
+ }
+
+ // Returns true when the command should end.
+ @Override
+ public boolean isFinished() {
+ return false;
+ }
+}
This page is currently a work in progress. Check back later
Check the air pressure
This section will help you learn to program pneumatic for your robot. For this section we are going to create a new subsystem called shooter and add one pneumatic piston (cylinder) which will be used for changing the pitch of the shooter.
See table of contents for a breakdown of this section.
For this section we are going to create a new subsystem called shooter and add one pneumatic piston (cylinder) which will be used for changing the pitch of the shooter.
1)
2) Create your DoubleSolenoid named pitchSolenoid now using the same technique used to create a talon but replacing Talon with DoubleSolenoid. (For single solenoids just use Solenoid).
Your full Shooter.java should look like this
package frc.robot.subsystems;
+import edu.wpi.first.wpilibj.DoubleSolenoid;
+import edu.wpi.first.wpilibj.command.Subsystem;
+import frc.robot.RobotMap;
+
+/**
+* Add your docs here.
+*/
+public class Shooter extends Subsystem {
+ // Put methods for controlling this subsystem
+ // here. Call these from Commands.
+ DoubleSolenoid pitchSolenoid = null;
+
+ public Shooter() {
+ pitchSolenoid = new DoubleSolenoid(RobotMap.SHOOTER_PITCH_SOLENOID_DEPLOY, RobotMap.SHOOTER_PITCH_SOLENOID_RETRACT);
+ }
+
+ @Override
+ public void initDefaultCommand() {
+ // Set the default command for a subsystem here.
+ // setDefaultCommand(new MySpecialCommand());
+ }
+}
The code you typed in Robot.java should be this
Outside robotInit
public static Shooter m_shooter = null;
Inside robotInit m_shooter = new Shooter();
The code you typed in RobotMap.java should be this
// Solenoids
+public static final int SHOOTER_PITCH_SOLENOID_DEPLOY = 0;
+public static final int SHOOTER_PITCH_SOLENOID_RETRACT = 1;
1) Create a public void method called pitchUp.
2) Inside type:
pitchSolenoid.set(Value.kForward);
3) Do the same for the pitchDown method but change kForward to kReverse.
The code you typed should be this
public void pitchUp(){
+ pitchSolenoid.set(Value.kForward);
+}
+
+public void pitchDown(){
+ pitchSolenoid.set(Value.kForward);
+}
1) Create a new InstantCommand called ShooterUp
2) In the constructor adds requires(Robot.m_shooter)
3) In initialize() add our newly created method pitchUp method
4) Repeat steps for ShooterDown command but change pitchUp* to **pitchDown
Your full ShooterUp.java should look like this
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.InstantCommand;
+import frc.robot.Robot;
+
+/**
+* Add your docs here.
+*/
+public class ShooterUp extends InstantCommand {
+ /**
+ * Add your docs here.
+ */
+ public ShooterUp() {
+ super();
+ // Use requires() here to declare subsystem dependencies
+ // eg. requires(chassis);
+ requires(Robot.m_shooter);
+ }
+
+ // Called once when the command executes
+ @Override
+ protected void initialize() {
+ Robot.m_shooter.pitchUp();
+ }
+}
Your full ShooterDown.java should look like this
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.InstantCommand;
+import frc.robot.Robot;
+
+/**
+* Add your docs here.
+*/
+public class ShooterDown extends InstantCommand {
+ /**
+ * Add your docs here.
+ */
+ public ShooterDown() {
+ super();
+ // Use requires() here to declare subsystem dependencies
+ // eg. requires(chassis);
+ requires(Robot.m_shooter);
+ }
+
+ // Called once when the command executes
+ @Override
+ protected void initialize() {
+ Robot.m_shooter.pitchDown();
+ }
+}
1) Open OI.java
2) Under our created joystick we will create Button variables and assign them to a button on our joystick
3) Type:
Button D1 = new JoystickButton(driverController, 1);
4) Do this for the rest of the buttons on your controller.
Your full OI.Java should look like this
package frc.robot;
+
+import edu.wpi.first.wpilibj.Joystick;
+import edu.wpi.first.wpilibj.buttons.Button;
+import edu.wpi.first.wpilibj.buttons.JoystickButton;
+
+/**
+* This class is the glue that binds the controls on the physical operator
+* interface to the commands and command groups that allow control of the robot.
+*/
+public class OI {
+ public Joystick driverController = new Joystick(RobotMap.OI_DRIVER_CONTROLLER);
+
+ Button D1 = new JoystickButton(driverController, 1);
+ Button D2 = new JoystickButton(driverController, 2);
+ Button D3 = new JoystickButton(driverController, 3);
+ Button D4 = new JoystickButton(driverController, 4);
+ Button D5 = new JoystickButton(driverController, 5);
+ Button D6 = new JoystickButton(driverController, 6);
+ Button D7 = new JoystickButton(driverController, 7);
+ Button D8 = new JoystickButton(driverController, 8);
+ Button D9 = new JoystickButton(driverController, 9);
+ Button D10 = new JoystickButton(driverController, 10);
+}
1) Create a constructor for OI
2) In the constructor type:
D1.whenPressed(new ShooterUp());
3) Create a whenPressed button for ShooterDown as well
The code you typed should be this
public OI(){
+ D1.whenPressed(new ShooterUp());
+ D2.whenPressed(new ShooterDown());
+}
Tip
You can change your import at the top of the file from:
import frc.robot.commands.ShooterUp;
to
import frc.robot.commands.*;
The asterisk (wildcard) makes it so all files in the .command package (folder) are imported. This way you only have to import once.
In this section we will be going over
1) Create a new empty class called RobotPreferences
2) Inside the constructor type:
public static double driveEncoderCountsPerFoot(){
+ return Preferences.getInstance().getDouble(“driveEncoderCountsPerFoot”, 1.0);
+}
public static variableType preferenceName(){
+ return Preferences.getInstance().getVariableType("preferenceName", value);
Your full RobotPreferences.java should look like this
package frc.robot;
+
+import edu.wpi.first.wpilibj.Preferences;
+
+/**
+* Add your docs here.
+*/
+public class RobotPreferences {
+ // Drivetrain
+ /**
+ * Default value is 1.0
+ */
+ public static double driveEncoderCountsPerFoot() {
+ return Preferences.getInstance().getDouble("driveEncoderCountsPerFoot", 1.0);
+ }
+
+}
1) Create a method called getDriveEncoderDistance inside of Drivetrain
2) Inside type:
return (getDriveEncoderCount() / RobotPreferences.driveEncoderCountsPerFoot()) * 12;
Note
You may need to invert this value if your encoder counts backward when the robot is driving forward
Example
The code you typed should be this
public double getDriveEncoderDistance() {
+ return (getDriveEncoderCount() / RobotPreferences.driveEncoderCountsPerFoot()) * 12;
+}
3) Add the method to the update method in Telemetry
Tip
If you want to save your robot preference values that you've changed make sure you hardcode them in RobotPreferences.java later or take a picture if you want to use them again later
1) Move the wheel on your robot with the Drivetrain encoder attached 1 foot or drive your robot 1 foot
2) Read how many counts your encoder has in the Drive Encoder Count window
3) Change the value of driveEncoderCountsPerFoot in the widget to this number
4) Reset the Drivetrain encoder and move the wheel 1 foot or drive the robot 1 foot again
5) Make sure your Drive Encoder Distance window reads approximately 12 (this is in inches)
6) Save your RobotPreferences widget with this value
7) Hardcode this value in RobotPreferences.java in the driveEncoderCountsPerFoot method incase you cannot recover your RobotPreferences save
In this section we will be going over
1) Create a new Subsystem called Telemetry
2) Create a constructor for the Telemetry class
3) Inside type:
SmartDashboard.putData(“Reset Drive Encoder”, new DriveResetEncoder());
4) Create a public method called update
5) Inside type:
SmartDashboard.putNumber(“Drivetrain Encoder Count”, Robot.m_drivetrain.getDriveEncoderCount());
6) Do the same for the getDriveEncoderDistance method
7) Try adding the Shooter Subsystem commands and sensor methods where they should be
Your full Telemetry.java should look like this
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj.command.Subsystem;
+import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
+import frc.robot.Robot;
+import frc.robot.commands.*;
+
+/**
+* Add your docs here.
+*/
+public class Telemetry extends Subsystem {
+ // Put methods for controlling this subsystem
+ // here. Call these from Commands.
+
+ public Telemetry() {
+ // Drivetrain
+ SmartDashboard.putData("Reset Drive Encoder", new DriveResetEncoder());
+
+ // Shooter
+ SmartDashboard.putData("Shooter Up", new ShooterUp());
+ SmartDashboard.putData("Shooter Down", new ShooterDown());
+ SmartDashboard.putData("Shooter Up Auto", new ShooterUpAuto());
+ }
+
+ public void update() {
+ // Drivetrain
+ SmartDashboard.putNumber("Drive Encoder Count", Robot.m_drivetrain.getDriveEncoderCount());
+
+ // Shooter
+ SmartDashboard.putBoolean("Shooter Switch", Robot.m_shooter.isShooterSwitchClosed());
+ }
+
+ @Override
+ public void initDefaultCommand() {
+ // Set the default command for a subsystem here.
+ // setDefaultCommand(new MySpecialCommand());
+ }
+}
1) When adding Telemetry to Robot.java, in robotInit we must add Telemetry after the other subsystems
2) It is important that we add the update method to disabledPeriodic, autonomousPeriodic, and teleopPeriodic so that the Shuffleboard is always being updated with information on our sensors.
The code you typed before robotInit should be this
public static Telemetry m_telemetry;
The code you typed in robotInit should be this
m_telemetry = new Telemetry(); //This must be initialized after all other robot subsystems
The code you typed in disabledPeriodic, autonomousPeriodic, and teleopPeriodic should be this
Robot.m_telemetry.update();
This page is currently a work in progress. Check back later
In this section we will be going over
1) For this tutorial we are going to add a switch to a shooter subsystem to automatically change the pitch of the shooter
The code you typed should be this
DigitalInput shooterSwitch = null;
In the constructor
shooterSwitch = new DigitalInput(Constants.SHOOTER_SWITCH);
In Constants.Java
// Digital Inputs
+public static final int SHOOTER_SWITCH = 0;
1) Create a public boolean method called isShooterSwitchClosed
2) Inside type:
return shooterSwitch.get();
Switches have 2 states: open and closed.
Make sure you know which is true or false or you may have to invert the switch by rewiring or using the ! operator
Your isShooterSwitchClosed() should look like this
public boolean isShooterSwitchClosed() {
+ return shooterSwitch.get();
+}
package frc.robot.subsystems;
+
+import edu.wpi.first.wpilibj.DigitalInput;
+import edu.wpi.first.wpilibj2.command.SubsystemBase;
+import frc.robot.Constants;
+
+public class Shooter extends SubsystemBase {
+ /**
+ * Creates a new Shooter.
+ */
+ DigitalInput shooterSwitch = null;
+
+ public Shooter() {
+ shooterSwitch = new DigitalInput(Constants.SHOOTER_SWITCH);
+ }
+
+ public boolean isShooterSwitchClosed() {
+ return shooterSwitch.get();
+ }
+
+ @Override
+ public void periodic() {
+ // This method will be called once per scheduler run
+ }
+}
1) For this tutorial we will use the switch to create a button that automatically pitches the shooter up after the switch is pressed
2) Create a new command called ShooterUpAuto
3) In the constructor add requires(Robot.m_Shooter)
4) In isFinished return our isShooterSwitchClosed method
5) In end add our pitchUp method
Your full ShooterUpAuto.java should look like this
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.Command;
+import frc.robot.Robot;
+
+public class ShooterUpAuto extends Command {
+ public ShooterUpAuto() {
+ // Use requires() here to declare subsystem dependencies
+ // eg. requires(chassis);
+ requires(Robot.m_shooter);
+ }
+
+ // Called just before this Command runs the first time
+ @Override
+ protected void initialize() {
+ }
+
+ // Called repeatedly when this Command is scheduled to run
+ @Override
+ protected void execute() {
+ }
+
+ // Make this return true when this Command no longer needs to run execute()
+ @Override
+ protected boolean isFinished() {
+ return Robot.m_shooter.isShooterSwitchClosed();
+ }
+
+ // Called once after isFinished returns true
+ @Override
+ protected void end() {
+ Robot.m_shooter.pitchUp();
+ }
+
+ // Called when another command which requires one or more of the same
+ // subsystems is scheduled to run
+ @Override
+ protected void interrupted() {
+ }
+}
The code you typed should be this
D3.whenPressed(new ShooterUpAuto());
Or this
D3.whileHeld(new ShooterUpAuto());
1) For this tutorial we are going to add a encoder to the Drivetrain subsystem to keep track of the distance the robot has driven
2) Inside the Drivetrain subsystem we are going to create an encoder called driveEncoder
The code you typed outside the constructor should be this
Encoder driveEncoder = null;
Inside the constructor
driveEncoder = new Encoder(Constants.DRIVETRAIN_ENCODER_A, Constants.DRIVETRAIN_ENCODER_B);
1) Create a public double method called getDriveEncoderCount
2) Inside type:
return driveEncoder.get();
3) Create a public method called resetDriveEncoderCount
4) Inside type:
driveEncoder.reset();
The code you typed should be this
public double getDriveEncoderCount() {
+ return driveEncoder.get();
+}
+
+public void resetDriveEncoder() {
+ driveEncoder.reset();
+}
1) Create a new InstantCommand called DriveResetEncoder
2) In the constructor add requires(Robot.m_drivetrain)
3) In initialize() add our resetDriveEncoder method
Your full DriveResetEncoder command should look like this
package frc.robot.commands;
+
+import edu.wpi.first.wpilibj.command.InstantCommand;
+import frc.robot.Robot;
+
+/**
+* Add your docs here.
+*/
+public class DriveResetEncoder extends InstantCommand {
+/**
+* Add your docs here.
+*/
+ public DriveResetEncoder() {
+ super();
+ // Use requires() here to declare subsystem dependencies
+ // eg. requires(chassis);
+ requires(Robot.m_drivetrain);
+ }
+
+ // Called once when the command executes
+ @Override
+ protected void initialize() {
+ Robot.m_drivetrain.resetDriveEncoder();
+ }
+}
' + escapeHtml(summary) +'
' + noResultsText + '
'); + } +} + +function doSearch () { + var query = document.getElementById('mkdocs-search-query').value; + if (query.length > min_search_length) { + if (!window.Worker) { + displayResults(search(query)); + } else { + searchWorker.postMessage({query: query}); + } + } else { + // Clear results for short queries + displayResults([]); + } +} + +function initSearch () { + var search_input = document.getElementById('mkdocs-search-query'); + if (search_input) { + search_input.addEventListener("keyup", doSearch); + } + var term = getSearchTermFromLocation(); + if (term) { + search_input.value = term; + doSearch(); + } +} + +function onWorkerMessage (e) { + if (e.data.allowSearch) { + initSearch(); + } else if (e.data.results) { + var results = e.data.results; + displayResults(results); + } else if (e.data.config) { + min_search_length = e.data.config.min_search_length-1; + } +} + +if (!window.Worker) { + console.log('Web Worker API not supported'); + // load index in main thread + $.getScript(joinUrl(base_url, "search/worker.js")).done(function () { + console.log('Loaded worker'); + init(); + window.postMessage = function (msg) { + onWorkerMessage({data: msg}); + }; + }).fail(function (jqxhr, settings, exception) { + console.error('Could not load worker.js'); + }); +} else { + // Wrap search in a web worker + var searchWorker = new Worker(joinUrl(base_url, "search/worker.js")); + searchWorker.postMessage({init: true}); + searchWorker.onmessage = onWorkerMessage; +} diff --git a/search/search_index.json b/search/search_index.json new file mode 100644 index 0000000..2bb6497 --- /dev/null +++ b/search/search_index.json @@ -0,0 +1 @@ +{"config":{"indexing":"full","lang":["en"],"min_search_length":3,"prebuild_index":false,"separator":"[\\s\\-]+"},"docs":[{"location":"index.html","text":"Introductions # The unofficial FIRST Robotics Competition Java Programming Tutorial. Info Updated for the 2021 Season Last updated: 9/30/21 Disclaimer: Some screenshots may have different colors, icons, more/less folders/files than you due to themes or personal settings. This is normal and should not impact the tutorial. If you still have any questions please contact us. Powered by # Contributors # Name Team Team Role Tayler Uva 3255 Coach Isaac Sayasane 3255 Alumni Sharon Riggs 6995 Mentor","title":"Introductions"},{"location":"index.html#introductions","text":"The unofficial FIRST Robotics Competition Java Programming Tutorial. Info Updated for the 2021 Season Last updated: 9/30/21 Disclaimer: Some screenshots may have different colors, icons, more/less folders/files than you due to themes or personal settings. This is normal and should not impact the tutorial. If you still have any questions please contact us.","title":"Introductions"},{"location":"index.html#powered-by","text":"","title":"Powered by"},{"location":"index.html#contributors","text":"Name Team Team Role Tayler Uva 3255 Coach Isaac Sayasane 3255 Alumni Sharon Riggs 6995 Mentor","title":"Contributors"},{"location":"contributing.html","text":"Contributing # Helping out with the project! Example Project Code # If you make Example Project Code changes please contribute changes that reflect this in the Documentation. This will make it easier for us and more likely that your contribution will be approved. Documentation # If you make documentation changes please contribute changes that reflect this in the Example Project Code. This will make it easier for us and more likely that your contribution will be approved. There are a couple of ways to contribute to this project: Via the web Via local source Via the web # Editing Pages # On each page there is an option to edit the page. Any changes you make through this option will be submitted and become live once they are approved. The edit icon looks like this: Alternatively you could create a pull request and clone the repository New Pages # You can help the project by making new pages. Any pages you make will become live once they are approved. Click here to create a new page Please use the New Page Template Click here to see tips on creating markdown documents Warning Make sure all documentation files end in .md Tip You can add to a certain tab by appending /tab_name/ to the file name Tip Visit Admonitions (call-out) references for a list off call-outs like this one. Via local source # Prerequisites # Install GitHub Desktop (Beginner) or Install Git (Expert) Install Python Install pip requirements Run one of the following commands. Try each one in order until successful. pip install -r requirements.txt python -m pip install -r requirements.txt py -m pip install -r requirements.txt Creating local edits # Visit https://github.com/FRCTeam3255/FRC-Java-Tutorial/tree/main/ and fork the repository. Clone your the newly created fork to your machine and open it Run the command mkdocs serve to open up a live local version of the project in your browser If mkdocs serve does not work on its own, try each one in order until successful: python -m mkdocs serve py -m mkdocs serve Make your changes or additions in the docs directory. Please maintain the organizational folder structure. If added a new page, add the relative url to the mkdocs.yml file in the # Navigation ( nav: ) section. For new pages please use the New Page Template Click here to see tips on creating markdown documents Pushing your local edits to the web # Commit your changes Push your changes to GitHub Back on the webpage for your fork of the project select Pull Request Create a new pull request Wait for the pull request to be approved. New Page Template # Please copy this code as a template to create your new page # Page title Subtitle ![Image Title](imageURL) ## Overview This section will help you learn to BLANK. **See table of contents for a breakdown of this section.** *** ## Section One - Some info - Some other into - Some sub info ### Section One Subsection *** ## Section Two - Info - Info 2 !!! Tip This is a tip.","title":"Contributing"},{"location":"contributing.html#contributing","text":"Helping out with the project!","title":"Contributing"},{"location":"contributing.html#example-project-code","text":"If you make Example Project Code changes please contribute changes that reflect this in the Documentation. This will make it easier for us and more likely that your contribution will be approved.","title":"Example Project Code"},{"location":"contributing.html#documentation","text":"If you make documentation changes please contribute changes that reflect this in the Example Project Code. This will make it easier for us and more likely that your contribution will be approved. There are a couple of ways to contribute to this project: Via the web Via local source","title":"Documentation"},{"location":"contributing.html#via-the-web","text":"","title":"Via the web"},{"location":"contributing.html#editing-pages","text":"On each page there is an option to edit the page. Any changes you make through this option will be submitted and become live once they are approved. The edit icon looks like this: Alternatively you could create a pull request and clone the repository","title":"Editing Pages"},{"location":"contributing.html#new-pages","text":"You can help the project by making new pages. Any pages you make will become live once they are approved. Click here to create a new page Please use the New Page Template Click here to see tips on creating markdown documents Warning Make sure all documentation files end in .md Tip You can add to a certain tab by appending /tab_name/ to the file name Tip Visit Admonitions (call-out) references for a list off call-outs like this one.","title":"New Pages"},{"location":"contributing.html#via-local-source","text":"","title":"Via local source"},{"location":"contributing.html#prerequisites","text":"Install GitHub Desktop (Beginner) or Install Git (Expert) Install Python Install pip requirements Run one of the following commands. Try each one in order until successful. pip install -r requirements.txt python -m pip install -r requirements.txt py -m pip install -r requirements.txt","title":"Prerequisites"},{"location":"contributing.html#creating-local-edits","text":"Visit https://github.com/FRCTeam3255/FRC-Java-Tutorial/tree/main/ and fork the repository. Clone your the newly created fork to your machine and open it Run the command mkdocs serve to open up a live local version of the project in your browser If mkdocs serve does not work on its own, try each one in order until successful: python -m mkdocs serve py -m mkdocs serve Make your changes or additions in the docs directory. Please maintain the organizational folder structure. If added a new page, add the relative url to the mkdocs.yml file in the # Navigation ( nav: ) section. For new pages please use the New Page Template Click here to see tips on creating markdown documents","title":"Creating local edits"},{"location":"contributing.html#pushing-your-local-edits-to-the-web","text":"Commit your changes Push your changes to GitHub Back on the webpage for your fork of the project select Pull Request Create a new pull request Wait for the pull request to be approved.","title":"Pushing your local edits to the web"},{"location":"contributing.html#new-page-template","text":"Please copy this code as a template to create your new page # Page title Subtitle ![Image Title](imageURL) ## Overview This section will help you learn to BLANK. **See table of contents for a breakdown of this section.** *** ## Section One - Some info - Some other into - Some sub info ### Section One Subsection *** ## Section Two - Info - Info 2 !!! Tip This is a tip.","title":"New Page Template"},{"location":"why_software.html","text":"What is software # What is software? Why should you care? Where is software # Everywhere! Games, apps, websites All smart devices It\u2019s the stuff on your phone and computer that you see and interact with It is also handling complex parts behind what you see and interact with Even things that didn't before have software now Cars, Planes, Ovens, Light Bulbs, Garbage Trucks, Children's Toys, etc. But what is it # It\u2019s the language of computers! Logical building blocks for controlling the devices around us Software makes devices smart Software allows us to automate things Why should you do software # Learn Creative Problem Solving Peek be hind the curtain of what makes technology tick Better understanding and appreciation of technology Programming is the FUTURE Your imagination is your only limitation Low barrier to entry Only need a computing device (can be a cheap $35 computer or even your phone) Lucrative job opportunities Many job opportunities from Game Development to App Development to Robotics","title":"Why software"},{"location":"why_software.html#what-is-software","text":"What is software? Why should you care?","title":"What is software"},{"location":"why_software.html#where-is-software","text":"Everywhere! Games, apps, websites All smart devices It\u2019s the stuff on your phone and computer that you see and interact with It is also handling complex parts behind what you see and interact with Even things that didn't before have software now Cars, Planes, Ovens, Light Bulbs, Garbage Trucks, Children's Toys, etc.","title":"Where is software"},{"location":"why_software.html#but-what-is-it","text":"It\u2019s the language of computers! Logical building blocks for controlling the devices around us Software makes devices smart Software allows us to automate things","title":"But what is it"},{"location":"why_software.html#why-should-you-do-software","text":"Learn Creative Problem Solving Peek be hind the curtain of what makes technology tick Better understanding and appreciation of technology Programming is the FUTURE Your imagination is your only limitation Low barrier to entry Only need a computing device (can be a cheap $35 computer or even your phone) Lucrative job opportunities Many job opportunities from Game Development to App Development to Robotics","title":"Why should you do software"},{"location":"basics/driverstation_tips.html","text":"","title":"Driverstation tips"},{"location":"basics/java_basics.html","text":"Java Programming Basics # Learning What's What Overview # Objects, variables, and classes (in Java) make up our programs. We define, modify, and use these variables and objects to make our programs run. Programs use key words to define characteristics of variables or objects. Basic keywords: public - an object accessible by other classes (files) private - an object only accessible by its containing class (file). protected - like private but can be seen by subclasses return - value to return or give back after method execution (run). void - a method that returns no value null - a value that means empty or nothing IMPORTANT NOTE Java is case sensitive, meaning capitalization matters! Classes # Classes are the files that contain our programming A program can be made up of one class but can also be made up of many classes All programs run a main class that can optionally load additional classes either directly or indirectly Example main loads class1, class1 loads class2 Classes are made up of variables and methods and are often used to separate and organize your code. Classes can also call (use) variables or methods of other classes if those have been set to public. Constructors # Classes can also have a constructor which is a special type of method that has the same name (case sensitive) as the class file Constructors are always called when the class is loaded into the program for the first time. This is often the only time they are called. Constructors are called when trying to access the class in other files. They can be called again if the class is programmed to be unloaded (destroyed) and reloaded. Calls to methods, and assignment of values, within the constructor will run as soon as the class is called (loaded) in the code. The new operator creates an object of a type of class using a constructor Example classObject = new className(); Methods # Methods, also known as functions, can be thought of as subprograms or routines that run inside of your main program. Methods are used when you want to run the same code multiple times. Copying and pasting code is BAD! Use methods instead! Methods are also useful to access only certain parts or functions of another class. Methods can also have their own variables ( local ) or use variables available throughout the whole class ( global variables ), this will be explained more in the scope section . Methods can call (use) other methods, even multiple times. Example int value; void increment(){ value++; } Parameters # Parameters are variables that are passed (sent) to a method for it to use. You can pass more than one parameter but order matters when calling the method. Example // Example of a method with a parameter double half(int num1){ double multiplier = 0.5; return num1*multiplier; } int newNumber = half(12); // <---- Method being called (used) in code Variables # Variables are objects that contain data, they are characterized by data types Variables are assigned names and data types on creation Names can be anything with the exception of pre-existing keywords such as public or int Data types define what type of data is being stored in the variables: int - integers (whole numbers) double - double precision floating point (fractional/decimal values) boolean - true or false (true = 1 or false = 0) values. string - text values contained in parentheses Example: int sum; A variable that can hold whole number values Example: boolean isFull = true; A variable can either hold a true or false value and is being assigned a true value Constants # Most variables can have their values assigned or reassigned at any point elsewhere in your program. To avoid having a variable change its value during runtime you can make it a constant In Java you can create constants using the static final keywords together in front of the data type of the variable The static modifier causes the variable to be available without loading the class where it is defined. The final modifier causes the variable to be unchangeable. Java constants are normally declared in ALL CAPS. Words in Java constants are normally separated by underscores. Example: public static final double PI_VALUE = 3.14159; A variable that cannot be modified during code run time. Scope # When creating a variable, where you create it matters. This is known as the scope of a variable. The scope is where a variable can be seen within a class A variable created in a method can only be seen in that method. This is a local variable. A variable created outside a method can be seen in all methods of that class (file). This is a global variable. It is good practice to put them all at the top before your first method. Example of a Local Variable public int testMethod() { int example = 12; // Inside of method example = example + 1; return example } Example of a Global Variable int example = 12; // Outside of method public void testMethod() { example = example + 1; return example } Comments # Comments are a programmer-readable explanation or annotation in the source code of a program. Comments do not affect what the code does. Comments are often used to leave notes or explanations of what methods or classes are doing so that it is easier to understand the code. Example: Single Line Comments // This is what a single line comment looks like // You can also have multiple // single line comments in a row Example: Multi Line Comments /* This is what a multiline comment looks like */ Example: Doc Comments /** * This is a doc comment * *Flashing the firmware
Before we can deploy code to the robot, we must flash a software image on to the roboRIO and possibly update the firmware. This can be accomplished with the roboRIO imaging tool:
IMPORTANT NOTE
The FRC Game Tools (Windows Only) need to be installed to access the roboRIO imaging tool.
Following the instructions linked below will explain how to image/update the roboRIO.
For Windows ONLY:
There are other pieces of software necessary for programming a robot depending on your circumstances. If you are using Talon or Spark Max motor controllers, those have their own debugging tools that are necessary. If you plan on motion profiling for your drivetrain in autonomous, (check our [motion profiling tutorial] for more on that) you will need to download a pathing software as well.
See table of contents for a breakdown of this section.
If you are using Talons on your robot, the Pheonix tuner software is a must have. It allows you to deploy software updates, debug/test your talons, and name/organize your talons.
For Windows ONLY:
Download link for CTRE Framework (next to 'Installer')
If you are using Spark Max motor controllers on your robot, the Spark Max tuner software is a must have. It allows you to deploy software updates, debug/test your Spark maxes, and name/organize your Spark Maxes.
For Windows ONLY:
Download Spark Max Client (click 'Download Latest SPARK MAX Client)
In order to utilize motion profiling on a drivetrain, it is extremely helpful to have a tool such as Pathplanner. Pathplanner allows for seamless creation and deployment of motion profiles from your laptop to your robot, and has a nice interface for doing so. There are other available tools we may add in the future if pathplanner does not suit your needs, but we at 3255 found it comprehensive for our motion profiling needs (note, this software is only for driving in autonomous, it is likely not useful for other mechanisms).
For Windows ONLY:
Pathplanner Github (to install, click on the latest version under releases on the right)
Lets get started
Before we can start programing a robot we must install the necessary software for programming and driving the robot.
See table of contents for a breakdown of this section.
Tip
You can install both the Development Tools and the FRC Game Tools on the same computer or separate computers. However many teams (3255 included) have a development laptop (with both) and a dedicated driverstation laptop (with only the FRC Game Tools) that often stays disconnected from the internet.
If all you are doing is writing and deploying code to a robot, all you need are the development tools. Following the instructions linked below will get you set up with a development environment and get you setup with all the tools necessary to program a robot.
For Windows, macOS, or Linux:
Official FRC installation guide (Windows, macOS, or Linux)
IMPORTANT NOTE
These tools only allow you to program and deploy code to an already imaged roboRIO. They do not allow you to drive the robot or image/update the roboRIO. To accomplish those tasks you must install the FRC Game Tools.
If all you are doing is driving an already programmed robot or imaging/updating the roboRIO all you need is the FRC Game Tools. Following the instructions linked below will get you set up with the tools to drive the robot and image/update the roboRIO.
For Windows ONLY:
Official FRC installation guide (Windows only)
IMPORTANT NOTE
These tools only allow you to drive the robot and image/update a roboRIO. They do not allow you to program the robot. To accomplish those tasks you must install the Java Development Tools.
In order to enable wireless connectivity to the robot outside of FRC events or to allow connectivity to other network attached devices (i.e.Limelight Vision Camera), you must configure the robot's radio. Following the instructions linked below will get you set up with the Radio Configuration Utility and how to program the radio.
For Windows ONLY:
Official FRC Radio Configuration Utility and Use guide (Windows only)
This page is currently a work in progress. Check back later
What is software? Why should you care?