**Team 2890 Usage:** Primary swerve drive library on Mothman
## What It Is
YAGSL (Yet Another Generic Swerve Library) is an open-source FRC library that lets you configure an entire swerve drivetrain through JSON files instead of writing custom Java code for each module. You describe your hardware in a few config files, and YAGSL generates the `SwerveDrive` object that handles kinematics, odometry, path following, and more.
The core idea: **one line of Java, a directory of JSON, and you have a working swerve drive.**
## Why We Use It
Team 2890 runs YAGSL on Mothman with SDS MK4i modules, NEO Vortex drive motors, SPARK Flex controllers, and CANcoders. YAGSL lets us swap hardware (different motors, different encoders, different gyros) by editing JSON instead of rewriting Java code.
**Advantages over rolling your own swerve code:**
- JSON config means hardware changes are data, not code changes
- Built-in support for PathPlanner autonomous integration
- Vision odometry integration (works with PhotonVision out of the box)
- Brushed motors with external encoders (SparkMAX only)
## JSON Configuration Structure
YAGSL reads configuration from the `deploy/swerve/` directory in your WPILib project:
```
src/main/deploy/swerve/
swervedrive.json <- Main config (IMU, module list)
frontleft.json <- Module 1
frontright.json <- Module 2
backleft.json <- Module 3
backright.json <- Module 4
```
### swervedrive.json (Main Config)
```json
{
"imu": {
"type": "pigeon2",
"id": 13,
"canbus": "canivore"
},
"invertedIMU": true,
"modules": [
"frontleft.json",
"frontright.json",
"backleft.json",
"backright.json"
]
}
```
Key fields:
-`imu.type` — Your gyro model (pigeon2, navX, etc.)
-`imu.id` — CAN device ID
-`imu.canbus` — CAN bus name ("canivore" or null for rio bus)
-`invertedIMU` — Flip the gyro heading if your IMU is mounted upside down
-`modules` — List of module config files, clockwise from front-left
### Module JSON (e.g., frontleft.json)
```json
{
"drive": {
"type": "sparkflex",
"id": 2,
"canbus": null
},
"angle": {
"type": "sparkflex",
"id": 1,
"canbus": null
},
"encoder": {
"type": "cancoder",
"id": 10,
"canbus": null
},
"inverted": {
"drive": false,
"angle": false
},
"absoluteEncoderInverted": false,
"absoluteEncoderOffset": -50.977,
"location": {
"front": 12,
"left": -12
}
}
```
Key fields:
-`drive` / `angle` — Motor controller type and CAN ID
-`encoder` — Absolute encoder type and CAN ID
-`inverted` — Motor direction inversion (separate for drive and angle)
-`absoluteEncoderOffset` — CRITICAL: the angular offset to align the wheel forward (see below)
-`location` — Physical position of the module relative to robot center (inches)
## The Eight Steps of Bringing Up Swerve
YAGSL's docs recommend a specific order for first-time configuration. Follow these in sequence — do not skip steps:
1.**Install dependencies** — All vendor libraries (CTRE, REV, etc.)
2.**Check your gyroscope** — Verify it reads heading correctly
3.**Check your motors** — Verify CAN IDs and direction
4.**Create your configuration** — JSON files with correct device IDs
5.**Verify module locations** — Physical position matches config
6.**Tune drive PID** — Drive motor velocity PID
7.**Tune angle PID** — Steering motor angle PID
8.**Verify odometry** — Robot position tracks correctly
**Common mistake:** Trying to tune PID before verifying CAN IDs. Every wrong CAN ID causes cascading failures that look like PID problems but are actually configuration problems.
## Code Setup
### Dependency Installation (vendordep URLs for 2026)
Install these via WPILib's "Install vendor libraries" in VS Code:
public class SwerveSubsystem extends SubsystemBase {
private final SwerveDrive swerveDrive;
public SwerveSubsystem() {
swerveDrive = new SwerveDrive(
new File(Filesystem.getDeployDirectory(), "swerve")
);
}
public SwerveDrive getSwerveDrive() {
return swerveDrive;
}
}
```
That's it. The JSON config files do the heavy lifting.
### Driving the Robot
```java
// In your RobotContainer:
new Joystick(driverJoystick, 0); // Xbox or flight stick
// Map joystick axes to drive commands:
swerveSubsystem.setDefaultCommand(
new RunCommand(
() -> swerveDrive.drive(
// X, Y, rotation — WPILib ChassisSpeeds or raw values
joystick.getLeftY(), // Forward/back
joystick.getLeftX(), // Left/right
joystick.getRightX(), // Rotation
true // Field-relative?
),
swerveSubsystem
)
);
```
## Encoder Offsets — The Most Important Number
The `absoluteEncoderOffset` in each module JSON is the single most critical configuration value. It tells the steering motor where "forward" is for that wheel.
### How to Find Your Offset
1.**Align all wheels physically forward** — Point every wheel straight ahead
2.**Read the raw encoder value** from SmartDashboard or ShuffleBoard
3.**Negate that value** — That's your offset
4.**Put it in the module JSON** as `absoluteEncoderOffset`
Example: If the raw encoder reads `149.06`, the offset is `-149.06`.
**Pitfall:** Offsets change if you physically move the encoder gear or swap modules. Re-verify after any hardware change.
**2026 Note:** The `pushOffsetsToEncoders` and `restoreInternalOffset` methods are deprecated in YAGSL 2026+. Offsets should be set in the JSON config and left alone.
## PID Tuning
YAGSL has two PID loops per module: one for drive velocity, one for steering angle.
### Angle (Steering) PID
- Start with just P gain
- The steering motor wraps at 180°/-180°, so test with lateral (left/right) translation, not just forward
- Typical starting P: 0.5-2.0 depending on module
- If the wheel oscillates around target, P is too high
- Add D if the wheel overshoots and rings
### Drive PID
- Tune for velocity, not position
- Start with just P (try 0.1)
- Use ShuffleBoard or FRC Web Components to see actual vs commanded velocity
- Feedforward is important here — YAGSL supports kS, kV, kA
**Test order:** Always tune angle PID before drive PID. A mis-steered module gives garbage drive data.
## Inversion — When to Invert
The most common YAGSL problem is wrong motor inversion. The docs have a dedicated flowchart (see "When to Invert?"), but the rules are:
-`drive` inversion: Flip if the wheel spins backward when commanded forward
-`angle` inversion: Flip if the steering turns the wrong direction
-`absoluteEncoderInverted`: Flip if the encoder reads backwards
-`invertedIMU`: Flip if the gyro reads heading opposite to expected
**Test method:** Drive forward with ShuffleBoard open. If any wheel spins backward, flip its drive inversion. If any wheel turns the wrong way, flip its angle inversion.
## PathPlanner Integration
YAGSL integrates with PathPlanner for autonomous path following:
```java
// Create auto builder from SwerveDrive
AutoBuilder.configure(
swerveDrive::getPose, // Robot pose supplier
swerveDrive::resetOdometry, // Reset pose
swerveDrive::getRobotVelocity, // Robot velocity
swerveDrive::drive, // Drive consumption
new PPHolonomicDriveController( // Holonomic path follower
new PIDConstants(5.0, 0.0, 0.0), // Translation PID
YAGSL can fuse vision measurements into odometry. This is how PhotonVision AprilTag data improves your robot's field position:
```java
// Add a vision measurement (from PhotonVision, Limelight, etc.)
swerveDrive.addVisionMeasurement(
new Pose2d(3, 3, Rotation2d.fromDegrees(65)),
Timer.getFPGATimestamp()
);
```
See [[photonvision]] for the full AprilTag pipeline.
## Debugging Tools
- **FRC Web Components** — Real-time swerve visualization widget. Connects to SmartDashboard/swerve. Blue lines = measured, shows each module's velocity and position
- **AdvantageScope** — Log viewer and swerve visualization
- **YAGSL Config Generator** — <https://github.com/BroncBotz3481/YAGSL-Example> includes example configs for common hardware combos
- **ShuffleBoard** — Standard WPILib dashboard, shows raw encoder values