This documentation is your trusty sidekick for becoming an FRC programming legend! ๐ฆธโโ๏ธ Whether you're watching the video or going solo, we've got your back. Think of this as your programming training montage - but with fewer push-ups and more code!
Episode Overview
๐ Chapter 1: What is WPILib?
The Foundation of FRC Programming
WPILib (Worcester Polytechnic Institute Library) is the official software library provided by FIRST Robotics Competition. Think of it as your robot's Swiss Army knife, but instead of tiny scissors and a toothpick that nobody uses, it contains everything needed to:
- Control motors and actuators (make things go vroom! ๐๏ธ)
- Read sensors like encoders, gyroscopes, and cameras (give your robot superpowers! ๐ฆธโโ๏ธ)
- Handle controller input from joysticks and gamepads (turn button mashing into art! ๐จ)
- Manage autonomous routines during matches (teach your robot to think for itself! ๐ง )
- Communicate between robot components (make sure everyone's on the same page! ๐ข)
Think of WPILib like ordering pizza instead of making it from scratch. Sure, you COULD grow your own wheat, milk your own cows, and hunt wild pepperoni... but why would you when Pizza Hut exists? WPILib is the Pizza Hut of robot programming! ๐ (Just wanna let ya'll know Pizza Hut is not sponsering this segment)
Why WPILib Matters
Without WPILib, simple tasks like spinning a motor would require hundreds of lines of low-level code that would make your brain hurt and your keyboard cry. With WPILib, the same task takes just a few lines and leaves you time for important things like arguing about the best Star Wars movie:
// Without WPILib: 100+ lines of pure suffering ๐ตโ๐ซ
// With WPILib: Simple, clean, and your sanity intact! ๐
TalonFX motor = new TalonFX(1);
motor.set(0.5); // 50% speed - not too fast, not too slow, just right! ๐
What's in the WPILib Treasure Chest ๐ฆ
- Command-based framework for organizing robot behavior (like Marie Kondo, but for code!)
- Motor controller libraries (TalonFX, SparkMax, etc.) - the muscle of your operation ๐ช
- Sensor libraries for encoders, IMUs, and more (give your robot superhuman senses!)
- Controller support for Xbox, PlayStation, and custom controllers (because who doesn't love gaming?)
- Simulation tools for testing code without a robot (no robots were harmed in the making of this code!)
- Dashboard integration for real-time monitoring (like mission control, but cooler!)
โ๏ธ Chapter 2: Creating a Robot Project
Some teams use custom frameworks that are like WPILib's quirky cousin - slightly different but still part of the family! This guide covers the standard approach, but feel free to adapt it to your team's particular brand of organized chaos! ๐ช
๐ค Chapter 3: Naming Conventions
Java Naming Standards for FRC
๐ป Real Code Example: Naming in Action
Here's how these naming conventions look in actual robot code:
// Class name: PascalCase
public class ArmSubsystem extends SubsystemBase {
// Constants: UPPER_CASE
private static final int ARM_MOTOR_ID = 5;
private static final double MAX_ARM_SPEED = 0.8;
// Fields/Variables: camelCase
private final TalonFX armRotationMotor;
private double currentTargetAngle;
private boolean isArmAtTarget;
// Constructor: PascalCase (same as class)
public ArmSubsystem() {
armRotationMotor = new TalonFX(ARM_MOTOR_ID);
}
// Methods: camelCase
public void setArmSpeed(double speed) {
armRotationMotor.set(speed);
}
public boolean isAtTargetPosition() {
return isArmAtTarget;
}
// Enum values: UPPER_CASE
public enum ArmPosition {
STOWED,
INTAKE,
SCORING
}
}
Pro Tip: Notice how every name tells you exactly what it does! No guessing games, no mysteries, just clear, readable code that your teammates (and future you) will love! โค๏ธ
๐ Chapter 4: Controlling a Motor โ TalonFX Example
Understanding TalonFX Motors
A TalonFX Motor (Such as a Kraken X60 or Falcon 500) is one of the most popular motors in FRC. It's basically the Tesla of robot motors - brushless, smart, and comes with its own built-in encoder. It's like having a motor with a PhD! ๐
TalonFX motors use the CTRE Phoenix framework. Make sure you have the Phoenix vendordep installed in your project, or your motor will just sit there looking expensive and doing nothing! ๐ธ
Step 1: Basic Motor Setup
Creating Your First Subsystem
package frc.robot.subsystems;
import com.ctre.phoenix6.hardware.TalonFX;
import edu.wpi.first.wpilibj2.command.SubsystemBase;
import frc.robot.Constants.CANConstants;
public class ExampleMotorSubsystem extends SubsystemBase {
// Create the motor object
private final TalonFX exampleMotor;
public ExampleMotorSubsystem() {
// Initialize motor with CAN ID
exampleMotor = new TalonFX(CANConstants.EXAMPLE_MOTOR_ID);
}
// Method to set motor speed (-1.0 to 1.0)
public void setMotorSpeed(double speed) {
exampleMotor.set(speed);
}
// Method to stop the motor
public void stopMotor() {
exampleMotor.set(0);
}
@Override
public void periodic() {
// This runs every 20ms
// Add any periodic updates here
}
}
Step 2: Adding Motor Configuration
For more advanced control, you can configure the motor with specific settings:
import com.ctre.phoenix6.configs.TalonFXConfiguration;
import com.ctre.phoenix6.signals.NeutralModeValue;
public class ExampleMotorSubsystem extends SubsystemBase {
private final TalonFX exampleMotor;
public ExampleMotorSubsystem() {
exampleMotor = new TalonFX(CANConstants.EXAMPLE_MOTOR_ID);
// Configure the motor
TalonFXConfiguration config = new TalonFXConfiguration();
config.MotorOutput.NeutralMode = NeutralModeValue.Brake; // Brake when stopped
config.Voltage.PeakForwardVoltage = 12.0; // Max forward voltage
config.Voltage.PeakReverseVoltage = -12.0; // Max reverse voltage
exampleMotor.getConfigurator().apply(config);
}
// ...rest of the class
}
Step 3: Advanced Motor Control
Here's an example with PID control for precise positioning:
import com.ctre.phoenix6.controls.PositionVoltage;
import edu.wpi.first.wpilibj.smartdashboard.SmartDashboard;
public class AdvancedMotorSubsystem extends SubsystemBase {
private final TalonFX advancedMotor;
private final PositionVoltage positionControl = new PositionVoltage(0);
public AdvancedMotorSubsystem() {
advancedMotor = new TalonFX(CANConstants.ADVANCED_MOTOR_ID);
// Configure PID gains
TalonFXConfiguration config = new TalonFXConfiguration();
config.Slot0.kP = 0.1; // Proportional gain
config.Slot0.kI = 0.0; // Integral gain
config.Slot0.kD = 0.01; // Derivative gain
advancedMotor.getConfigurator().apply(config);
}
public void setTargetPosition(double rotations) {
advancedMotor.setControl(positionControl.withPosition(rotations));
}
public double getCurrentPosition() {
return advancedMotor.getPosition().getValueAsDouble();
}
@Override
public void periodic() {
// Display motor data on dashboard
SmartDashboard.putNumber("Motor Position", getCurrentPosition());
SmartDashboard.putNumber("Motor Velocity", advancedMotor.getVelocity().getValueAsDouble());
}
}
๐ฎ Chapter 5: Using a Controller to Control the Motor
Connecting Controllers to Motors
Now let's put the power in your hands! We'll connect an Xbox controller to control our motor directly. It's like giving your robot a remote control - because who doesn't want to feel like they're playing the world's most expensive video game? ๐ฎ๐ฐ
Step 1: Setting Up the Controller
First, add the controller to your RobotContainer.java
:
package frc.robot;
import edu.wpi.first.wpilibj2.command.button.CommandXboxController;
import frc.robot.subsystems.ExampleMotorSubsystem;
public class RobotContainer {
// Subsystems
private final ExampleMotorSubsystem motorSubsystem = new ExampleMotorSubsystem();
// Controllers
private final CommandXboxController driverController = new CommandXboxController(0);
public RobotContainer() {
configureBindings();
configureDefaultCommands();
}
private void configureBindings() {
// We'll add button bindings here
}
private void configureDefaultCommands() {
// Set default commands for subsystems
}
}
Step 2: Creating a Manual Control Command
package frc.robot.commands;
import edu.wpi.first.wpilibj2.command.Command;
import frc.robot.subsystems.ExampleMotorSubsystem;
import java.util.function.DoubleSupplier;
public class ManualMotorControl extends Command {
private final ExampleMotorSubsystem motorSubsystem;
private final DoubleSupplier speedSupplier;
public ManualMotorControl(ExampleMotorSubsystem subsystem, DoubleSupplier speed) {
motorSubsystem = subsystem;
speedSupplier = speed;
addRequirements(motorSubsystem);
}
@Override
public void execute() {
double speed = speedSupplier.getAsDouble();
// Apply deadband to avoid motor drift
if (Math.abs(speed) < 0.1) {
speed = 0;
}
motorSubsystem.setMotorSpeed(speed);
}
@Override
public void end(boolean interrupted) {
motorSubsystem.stopMotor();
}
}
Step 3: Binding Controller to Command
Back in RobotContainer.java
, set up the default command:
private void configureDefaultCommands() {
// Left Y-axis controls the motor speed
motorSubsystem.setDefaultCommand(
new ManualMotorControl(
motorSubsystem,
() -> -driverController.getLeftY() // Negative for intuitive control
)
);
}
Step 4: Adding Button Controls
For discrete motor actions, add button bindings:
private void configureBindings() {
// A button: Run motor forward at 50%
driverController.a().onTrue(
new InstantCommand(() -> motorSubsystem.setMotorSpeed(0.5), motorSubsystem)
);
// B button: Run motor backward at 50%
driverController.b().onTrue(
new InstantCommand(() -> motorSubsystem.setMotorSpeed(-0.5), motorSubsystem)
);
// X button: Stop motor
driverController.x().onTrue(
new InstantCommand(() -> motorSubsystem.stopMotor(), motorSubsystem)
);
// Y button: Position control (move to 10 rotations)
driverController.y().onTrue(
new InstantCommand(() -> {
if (motorSubsystem instanceof AdvancedMotorSubsystem) {
((AdvancedMotorSubsystem) motorSubsystem).setTargetPosition(10.0);
}
})
);
}
Step 5: Complete Controller Example
Here's a comprehensive example following Team 201's conventions:
public class RobotContainer {
// Subsystems
private final ExampleMotorSubsystem c_motorSubsystem = new ExampleMotorSubsystem();
// Controllers
private final CommandXboxController c_driverController = new CommandXboxController(0);
private final CommandXboxController c_operatorController = new CommandXboxController(1);
public RobotContainer() {
configureBindings();
configureDefaultCommands();
}
private void configureDefaultCommands() {
// Driver controls with left stick
c_motorSubsystem.setDefaultCommand(
new ManualMotorControl(
c_motorSubsystem,
() -> applyDeadband(-c_driverController.getLeftY(), 0.1)
)
);
}
private void configureBindings() {
// Operator precise controls
c_operatorController.a().whileTrue(
new InstantCommand(() -> c_motorSubsystem.setMotorSpeed(0.25))
);
c_operatorController.b().whileTrue(
new InstantCommand(() -> c_motorSubsystem.setMotorSpeed(-0.25))
);
}
// Utility method for deadband
private double applyDeadband(double value, double deadband) {
return Math.abs(value) < deadband ? 0 : value;
}
}
๐ง Chapter 6: Making It Work for Students
Creating a Learning Environment
Programming isn't just about writing codeโit's about building a team culture where everyone can learn, contribute, and grow together. Plus, it's way more fun when you're not the only one staying up until 3 AM debugging! ๐โ
Universal Programming Truth: We're not just building robotsโwe're building problem-solvers, critical thinkers, and people who can stay calm when everything is on fire (metaphorically... hopefully). Every line of code is an opportunity to learn something new! ๐ฅโก๏ธโ๏ธ
Best Practices for Team Programming
Code Quality Standards
Building Team Skills
๐ฏ What's Next?
๐ Congratulations, Robot Whisperer! ๐ You've completed Zero to Hero Episode 1 and officially leveled up from "What's a robot?" to "I can make robots do my bidding!" Here's what you've mastered:
Coming Up in Episode 2
Resources for Continued Learning
Practice Exercises
Remember: Programming is like learning to ride a bike, except the bike is on fire, you're on fire, everything is on fire, and you're in space. But hey, once you get the hang of it, it's the most fun you can have with a computer! Don't worry if everything doesn't click immediatelyโeven experienced programmers started by making motors spin in circles! ๐ฅ๐ดโโ๏ธ๐
๐ Need Help? We've Got Your Back!
- Email: feds.programming@gmail.com
Keep coding, keep learning, and remember: every expert was once a beginner who refused to give up! ๐
P.S. - If your robot starts talking back, that's either very advanced AI or you need more sleep. Probably more sleep. ๐ค๐ค
This documentation is part of the Zero to Hero programming series. For the complete learning experience, watch the accompanying video and practice with real robot code. Remember: the only way to get good at programming is to write lots of bad code first! ๐
Special Thanks: To all the students who asked "Why doesn't this work?" and inspired us to create better documentation. Your questions make us better teachers, and your curiosity drives innovation. You're the real MVPs! ๐
Remember: Every expert was once a beginner who refused to give up. Keep coding, keep learning, and most importantly - keep having fun! ๐