This is the top-level folder for the DevilBotz robot code
The code uses Java WPILib and the WPILib command-based programming paradigm
- Extensibility and Reusability
- One code base, multiple robots
- Debuggability
- Logging
- Simulation
- Vision Based Odometry
- Odometry-based Path Following
- WPILib Documentation
- DevilBotz 2876 Standard Laptop Configuration
- FRC Programming in WPILib
- Git Tutorial
- Java Tutorial
- Install WPILib
- Install Git
- Windows
- MacOS
- Get Code from GitHub
- Create GitHub Account (if you don't already have one)
- Start WPILib VSCode
- Clone Repository
- Login to GitHub Account (if prompted)
- Repo: https://github.com/DevilBotz2876/XxxYYYY (where Xxx is the name of the FRC game and YYYY is the year E.g. "Reefscape2025"
- Note: The initial compilation will take a while because of all the dependencies that need to be downloaded. If all works well, in the Terminal view at the bottom, you should see:
- Simulating the Code
- Starting a Simulation
- "F5" starts the simulation
- Alternate Steps:
- "Ctrl-Shift-P" or "Command-Shift-P"
- "Simulate Robot Code"
- Alternate Steps:
- Enable: "Sim GUI"
- If you get the following error: "cannot find frc.robot.main", then:
- "Ctrl-Shift-P" --> "Clean Language Server Workspace"
- If you get the following error: "cannot find frc.robot.main", then:
- Optional: Enable DriverStation to better mimic real world usage
- "F5" starts the simulation
- Robot Simulation (aka Sim GUI) Overview
- Configure XBox Controller
- Make sure joystick is in "X-Box Mode". Plug in Joystick.
- Verify Joystick is Detected in "System Joysticks" window
- On Mac OS: You must connect via a bluetooth wireless enabled controller
- Drag controller from "System Joysticks" to "Joysticks" (Joystick[0])
- Make sure to "Map Gamepad" is checked
- Open 2D Field View
- NetworkTables --> "SmartDashboard" --> "Field"
- To Hide Swerve Modules:
- Click on the "Hamburger Button"
- Goto "XModules"
- Box/Image --> Hidden
- Arrow Size --> 10% (slider)
- Set Robot State
- Set Mode to "Teleoperated"
- Thumb Controls should now move the robot
- Configure XBox Controller
- 2D Mechanism Simulation
- NetworkTables --> "SmartDashboard" --> "Robot 2D Simulation"
- Vision Field
- NetworkTables --> "SmartDashboard" --> "VisionSystemSim-main" --> Sim Field
- Alliance Selection
- Autonomous
- AdvantageScope
- Starting a Simulation
.github/workflows: Contains various GitHub automation scripts that are run automatically at various stages of the code development/ integration process.vendordeps: Contains the various external libraries and versions that the code base utilizes.src/main: All of the robot code and config files are heredeploy: Config files, resources, etc that need to be stored directly on the actual robot. These can be read using standard Java File I/O callsjava/frc/robot: This is the root of all of the actual Java code for the robotcommands/: All commands are stored in this foldercommon/: Common commands are ones that operate on the Subsystem interface, so doesn't rely on any game specific implementations/APIs.motorMotorBringUpCommand.java: TODO
gizmoGizmoCommand.java
arm/drive/DriveCommand.java- ...
- ...
config/: The config directory is used to support multiple robot versions using the same code base.game/(src/main/java/frc/robot/config/game/): Each game will generally have it's own robot configuration.reefscape2025/: game-specific robot configurations are stored here.RobotConfig.java: Defines all of the subsystems and controls required for a "robot". Each robot variant extends RobotConfig and instantiates the subsystems and overrides constants as needed. Implements simulation stubs for all subsystems.RobotConfigPhoenix..java: Robot config for the "Phoenix" robot that instantiates specific subsystems (e.g. drivetrain and vision) using specific hardware IO instances. Everything else not explicitly overrideen will use the default _stub _versions.- ...
io/: generic low-level hardware IO (e.g. Motors, Limit Switches, Sensors, etc)interfaces/: hardware interfaces that are common for all possible implementations. E.g. a MotorIO would generally have a way to at leastsetVoltageand get status such asvoltageapplied and actualamperageused.MotorIO.java: Defines the minimum expected interface (settings, control, and status) for a generic motor.setVoltage(double volts)setVelocity(double velocityRadPerSec, double ffVolts)setPosition(double positionRad, double ffVolts)getPid()
GizmoIO.javaArmIO.javaClimberIO.java- ...
implementations/: Hardware specific implementations of the hardware IO interfaces. Each interface may have one or more implementations depending on manufacturer, model, etc. Each interface must have a simulation stub implementationmotor/MotorIOBase.java: The base abstract implementation of the Motor interface. All motor implementations should extend this base class. It implements the following functionality:- generates status in other units (e.g. from radians to degrees, RPMs, etc)
- implements software based velocity and position PID control
- Stub Implementations - for software bring-up in simulation. Each implements the physics of different types of mechanisms
MotorIOStub.java: Generic DC Motor based Mechanism (uses DCMotorSim)MotorIOArmStub.java: Motor connected to an Arm Mechanism (uses SingleJointedArmSim)MotorIOFlywheelStub.java: Motor connected to a Flywheel/Roller Mechanism (uses FlywheelSim)MotorIOElevatorStub.java: Motor connected to an Elevator Mechanism (uses ElevatorSim)
- Real Implementations
MotorIOSparkMax.java: SparkMax Motor Controller implementationMotorIOTalonFx.java: TalonFx Motor Controller implementation
gizmo/GizmoIOStub.java: Dummy/Stub implementation of a "Gizmo"GizmoIOAcme.java: Implementation of the Acme brand/model of a "Gizmo"
arm/ArmIOStub.javaArmIOSparkMax.java- ...
climber/- ...
subsystems/: subsystems are implemented using one or more Hardware IO instances. E.g. an Arm may contains an instance of a MotorIO connected to gears (to move the Arm up/down) and an AbsoluteEncoderIO (to measure the actual current angle).interfaces/: subsystem interfaces that are common for all possible implementationsMotor.java: TODOArmV2.java: TODOFlywheel.java: TODOElevatorV2.java: TODOGizmo.javaArm.javaClimber.java- ...
controls/: All controls including driver, debug, pit, and sysid are defined here. This includes both joystick and GUI-based controls. Contains the logic to connect specific user interfaces (e.g. ShuffleBoard, XBox Controllers, etc) to subsystem functionality. Ideally, the controls should be operating on the subsystem's interface and not the actual implementation.gizmoGizmoControls.java
driveDriveControls.java
visionVisionControls.java
implementations/: Subsystem specific implementations that use one or more hardware IO instances. May need to be configured differently depending on the Robot Configuration. E.g. for an Arm, the absolute encoder offset will likely be different in different implementations of the Arm. The subsystem should provide a mechanism to configure it accordingly.motorMotorSubsystem.java: TODOArmMotorSubsystem.java: TODOFlywheelMotorSubsystem.java: TODOElevatorMotorSubsystem.java: TODO
gizmo/GizmoSubsystem.java
arm/ArmSubsystem.java
climber/ClimberSubsystem.java
- ...
We had 3 different robots with different capabilities for dev/testing purposes:
- Sherman: Tank Drive + Initial Arm Prototype
- Phoenix: Initial Swerve Drive + Vision Prototype
- Inferno: Final Robot
| Robot | Drive | Shooter | Intake | Arm | Auto | Climber | Vision | LED |
|---|---|---|---|---|---|---|---|---|
| Sherman | Differential | SparkMax(2) | SparkMax(1) | TalonSRX(3) | No (stub) | No (stub) | No (stub) | No (stub) |
| Phoenix | Swerve(yagsl) | No (stub) | No (stub) | No (stub) | Yes | No (stub) | Shooter | No (stub) |
| Inferno | Swerve(yagsl) | SparkMax(2) | SparkMax(3) | SparkMax(4) | Yes | SparkMax(7) SparkMax(6) | Shooter Intake Right Left | Yes |
Subsystem and IO interfaces and implementations
Subsystems utilize the AdvantageKit IO Layer paradigm.
Each subsystem is implemented using the following breakdown. Here, assume we have a mechanism called a "Gizmo":
- Hardware IO
- Simple Interface (defines the desired hardware functionality)
- GizmoIO.java
public static class GizmoIOInputs { public double velocityRadPerSec = 0.0; public double appliedVolts = 0.0; public double current; } void updateInputs(GizmoIOInputs inputs); ← gets current sensor readings void setVoltage(double volts); ← sets desired voltage
- GizmoIO.java
- One or more Implementation(s)
- GizmoIOStub.java ← Simulated implementation
public class GizmoIOStub implements GizmoIO { - GizmoIOSparkMax.java ← SparkMax motor based implementation
- GizmoIOEtc.java
- GizmoIOStub.java ← Simulated implementation
- Simple Interface (defines the desired hardware functionality)
- Subsystem (utilizes one or more Hardware IO implementation)
- Single Interface (defines the desired subsystem functionality)
- GizmoSubsystem.java
- Low Level/Debug Controls
void runVoltage(double volts); double getCurrentVoltage(); void add2dSim(Mechanism2d mech2d); - High Level Controls
Command getTurnOffCommand(); Command getTurnOnCommand();
- Low Level/Debug Controls
- GizmoSubsystem.java
- One or more Implementation(s)
- GizmoSubsystemSimple.java
public class GizmoSubsystemSimple implements Gizmo { GizmoSubsystemSimple(GizmoIO io); ← an IO instance is passed into the GizmoSubsystemSimple void periodic() { IO.updateInputs(inputs); Logger.processInputs("Intake", inputs) } ... } - GizmoSubsystemAdvanced.java
public class GizmoSubsystemAdvanced implements Gizmo { ... } - GizmoSubsystemEtc.java
- GizmoSubsystemSimple.java
- Single Interface (defines the desired subsystem functionality)
It is important to note that the same Hardware IO can be shared by completely different subsystems. E.g. we may just want a Hardware IO layer abstraction for basic functionality E.g.
- MotorIO
- MotorIOSparkMax
- MotorIOTalonSRX
- LimitSwitchIO
And then a subsystem can consist of 1 or more MotorIO instances and 1 or more LimitSwitchIO instances.
- Main.java --> Robot.java --> RobotContainer.java
- Setup Robot Config
- A persistent preference with the key "Robot Name" is hard-coded onto the RoboRio flash memory
- The "Robot Name" key is read from the RoboRio at start and determines which robot config to load.
- Setup Controls (Bindings)
- Setup Autonomous
- Setup Robot Config
Path and Auto routine configuration files generated by the PathPlanner App
YAGSL swerve configuration files for each robot
- YAGSL
- Crescendo 2024 Swerve Bring-Up Checklist - Phoenix
- Crescendo 2024 Swerve Bring-Up Checklist - Inferno
- Initial Setup
- For each camera
- On the PhotonVision co-processor (e.g.. Raspberry Pi)
- Assign a unique camera name
- 2D AprilTag tracking will work out of the box
- You can get camera relative yaw, pitch, and roll information for each visible/detected AprilTag w/o calibrating the camera
- 3D AprilTag tracking requires calibration for each resolution:
- Calibrate FOV
- Measure location of camera relative to the center of the robot (See Transform3D VisionCamera.VisionCamera)
- Measure translation (x,y,z)
- Measure rotation (roll, pitch, yaw)
- On the PhotonVision co-processor (e.g.. Raspberry Pi)
- For each field
- Load the AprilTag map layout into PhotonVision (See AprilTagFields.class)
- For each camera
- Periodically at runtime
- For each camera
- If estimated robot pose is available (i.e. AprilTag is visible and 3D tracking is enabled)
- addVisionMeasurement to drivetrain odometry (See Drive.addVisionMeasurement())
- If estimated robot pose is available (i.e. AprilTag is visible and 3D tracking is enabled)
- For each camera