githubEdit

databaseAdvantageKit Integration

YAMS integrates seamlessly with AdvantageKitarrow-up-right, Team 6328's logging and replay framework. This guide shows how to use YAMS mechanisms with AdvantageKit's IO layer pattern for deterministic log replay.

What is AdvantageKit?

AdvantageKitarrow-up-right is a logging framework that records all inputs to your robot code, enabling deterministic replay in simulation. Unlike traditional logging that captures specific values, AdvantageKit captures everything flowing into your code, allowing you to:

  • Replay matches exactly as they happened

  • Add new logged fields after the fact

  • Test code changes against real match data

  • Debug issues that only occurred on the real robot

circle-info

AdvantageKit is optional. YAMS works perfectly without it using its built-in telemetry system. Consider AdvantageKit if you want deterministic log replay capabilities.

Architecture Overview

AdvantageKit uses an IO interface patternarrow-up-right to separate hardware interaction from business logic. Traditionally, this requires separate IO implementations for real hardware and simulation:

β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚  Traditional AdvantageKit Pattern (without YAMS)            β”‚
β”‚                                                             β”‚
β”‚                      Subsystem                              β”‚
β”‚                          β”‚                                  β”‚
β”‚                    IO Interface                             β”‚
β”‚                    /           \                            β”‚
β”‚              IO Real           IO Sim                       β”‚
β”‚         (Real hardware)    (Physics sim)                    β”‚
β”‚          - Manual motor     - DCMotorSim                    β”‚
β”‚          - Manual encoders  - Manual state                  β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜

YAMS Simplification: One IO Class for Real and Sim

With YAMS, you don't need separate Real and Sim IO implementations. Every SmartMotorController wrapper (TalonFXWrapper, SparkWrapper, etc.) and every Mechanism class (Arm, Elevator, FlyWheel, SwerveModule, SwerveDrive, etc.) includes passive simulation that runs automatically when Robot.isSimulation() returns true.

This means:

  • One IO class handles both real robot and simulation

  • No duplicate code - configuration is written once

  • No SimWrapper needed - real hardware wrappers simulate themselves

  • Physics are automatic - based on your DCMotor, gearing, and mass/MOI configuration

circle-check

Step 1: Define the IO Interface

Create an interface that defines what inputs your subsystem reads and what outputs it sends. Following AdvantageKit conventions, inputs are grouped in an Inputs class.

Arm IO Interface

Elevator IO Interface

Shooter IO Interface

circle-info

The @AutoLog annotation from AdvantageKit generates a class (e.g., ArmIOInputsAutoLogged) that handles serialization for log replay. See AdvantageKit AutoLog documentationarrow-up-right for details.

Step 2: Implement the IO Class

With YAMS, you only need one IO implementation that works for both real hardware and simulation. The SmartMotorController automatically detects when it's running in simulation and uses physics simulation instead of real hardware.

Arm IO Implementation (Works for Real and Sim!)

Elevator IO Implementation (Works for Real and Sim!)

Shooter (FlyWheel) IO Implementation (Works for Real and Sim!)

circle-check

Step 3: Create the Subsystem

The subsystem uses the IO interface and doesn't know whether it's running on real hardware or in simulation.

circle-exclamation

Step 4: Wire It Up in RobotContainer

With YAMS's passive simulation, you don't need conditional logic for real vs sim - the same IO class works for both!

circle-info

Compare to Traditional AdvantageKit: Without YAMS, you'd need separate ArmIOReal and ArmIOSim classes with duplicate configuration. YAMS eliminates this duplication entirely.

Log Replay Mode

For log replayarrow-up-right, AdvantageKit provides a "replay" mode where inputs are read from a log file instead of hardware. This is the one case where you need a separate IO implementation - an empty one that does nothing:

In RobotContainer, only check for replay mode:

circle-check

Pattern Summary: Mechanism Classes with SmartMotorController Telemetry

The examples above demonstrate the recommended pattern for using YAMS with AdvantageKit:

  1. Create Mechanism classes (Arm, Elevator, FlyWheel, etc.) for high-level control

  2. Get the underlying SmartMotorController via mechanism.getSmartMotorController()

  3. Pull telemetry from SmartMotorController for AdvantageKit logging

  4. Use Mechanism methods like setMechanismPositionSetpoint() for control

  5. Optionally expose the Mechanism via a getter for command helpers like run() and runTo()

This pattern gives you the best of both worlds:

  • Mechanism classes provide convenient configuration and command helpers

  • SmartMotorController provides detailed telemetry for AdvantageKit logging

  • Passive simulation works automatically in both

circle-info

See the YAMS example codearrow-up-right for complete examples of using YAMS Mechanism classes with AdvantageKit's IO pattern.

Using WPILib's isNear() for Tolerance Checking

When checking if a mechanism is at its target, use the isNear() method from WPILib's unit classes (Angle, Distance, AngularVelocity):

This approach works with any unit type and handles conversions automatically.

Swerve Drive with AdvantageKit

YAMS swerve integrates seamlessly with AdvantageKit. Here's a complete example based on the official YAMS AdvantageKit swerve examplearrow-up-right:

Key Points for Swerve with AdvantageKit

  1. Create an @AutoLog inputs class with module states, positions, gyro, and pose

  2. Call updateTelemetry() BEFORE updateInputs() - the pose estimator and internal state updates in updateTelemetry()

  3. Log desired states and speeds using Logger.recordOutput() for replay debugging

  4. Call simIterate() in simulationPeriodic() for physics simulation

circle-exclamation

Alternative Pattern: Direct Subsystem (No IO Layer)

For simpler projects where replay isn't needed, you can use YAMS mechanisms directly as shown in the official examplesarrow-up-right:

This pattern is simpler and does support log replay, but with a key difference: during replay, the full YAMS simulation runs alongside the logged data. This means:

  • Pro: You get full simulation behavior during replay, which can help debug physics-related issues

  • Con: Replay requires more processing power since every SmartMotorController and Mechanism simulates its physics

Choose the IO layer pattern if you need lightweight replay; choose this direct pattern if you prefer simplicity and don't mind the extra processing during replay.

Benefits of YAMS + AdvantageKit

Feature
Benefit

No Duplicate IO Classes

Single IO class works for real robot AND simulation

Deterministic Replay

Debug issues from real matches using log replay

Automatic Physics

YAMS uses DCMotor, gearing, and mass/MOI for accurate sim

Less Boilerplate

2 IO classes instead of 3 per mechanism

Consistent Behavior

Same code paths execute in real and sim modes

Flexible Hardware

Swap vendors by changing one IO class

Further Reading

Last updated