githubEdit

System Identification (SysId)

System Identification (SysId) is the process of determining feedforward constants for your mechanism through statistical analysis of its inputs and outputs.

What is System Identification?

System Identification is the process of determining a mathematical model for the behavior of a system through statistical analysis of its inputs and outputs. This model describes how input voltage affects the way your measurements (typically encoder data) evolve over time.

The WPILib SysId tool takes a model and dataset and attempts to fit parameters which would make your model most closely match the dataset. Even an imperfect model is usually "good enough" to give accurate feedforward control of the mechanism, and even to estimate optimal gains for feedback control.

circle-info

For a complete understanding of SysId theory, visit the WPILib System Identification Documentationarrow-up-right.

The Feedforward Equations

Different mechanisms use different feedforward equations:

Simple Motor (Flywheels, Turrets, Linear Sliders)

V=Kssgn(d˙)+Kvd˙+Kad¨V = K_s \cdot sgn(\dot{d}) + K_v \cdot \dot{d} + K_a \cdot \ddot{d}

Elevator

V=Kg+Kssgn(d˙)+Kvd˙+Kad¨V = K_g + K_s \cdot sgn(\dot{d}) + K_v \cdot \dot{d} + K_a \cdot \ddot{d}

The constant term (KgK_g) accounts for gravity.

Arm

V=Kgcos(θ)+Kssgn(θ˙)+Kvθ˙+Kaθ¨V = K_g \cdot cos(\theta) + K_s \cdot sgn(\dot{\theta}) + K_v \cdot \dot{\theta} + K_a \cdot \ddot{\theta}

The cosine term (KgK_g) accounts for the effect of gravity at different arm angles.

Types of Tests

A standard SysId routine consists of two types of tests, each run in both directions (forward and backward):

Test Type
Description

Quasistatic

The mechanism is gradually sped up such that the voltage corresponding to acceleration is negligible (hence, "as if static"). This helps determine KsK_s and KvK_v.

Dynamic

A constant "step voltage" is applied to the mechanism, so that the behavior while accelerating can be determined. This helps determine KaK_a.

circle-exclamation

Using YAMS Helper Functions

YAMS provides built-in sysId() methods on mechanism classes (Arm, Elevator, Shooter, etc.) that simplify the entire process.

triangle-exclamation

Prerequisites

Before running SysId:

  • Soft and hard limits are already configured

  • Gearing is correct

  • Mechanism circumference is set (for linear mechanisms)

Arm Example

Elevator Example

Binding to Controller Buttons

circle-info

Use whileTrue() so you can release the button to immediately stop the test if the mechanism exceeds safe limits!


Using WPILib SysIdRoutine Directly

If you need more control over the SysId process, or are working with a SmartMotorController directly without a mechanism class, you can use WPILib's SysIdRoutine directly.

Creating the SysIdRoutine

The SysIdRoutine requires two objects:

  1. Config - Test settings (ramp rate, step voltage, timeout)

  2. Mechanism - Callbacks for driving motors and logging data

circle-info

Why use duty cycle instead of voltage control?

Modern motor controllers (SparkMax, SparkFlex, TalonFX, etc.) have internal closed-loop voltage controllers. When you call a "set voltage" API, the motor controller actively adjusts output to maintain that voltage regardless of load or battery sag.

For SysId, we want raw, uncompensated motor behavior. By converting voltage to duty cycle (voltage / batteryVoltage) and using setDutyCycle(), we bypass the internal controller entirely. This produces cleaner data that more accurately represents the true motor and mechanism dynamics.

circle-info

Why use MutVoltage, MutAngle, and MutAngularVelocity?

The logging callback runs every robot loop iteration (typically 50Hz). Creating new Voltage, Angle, or AngularVelocity objects each iteration would allocate memory on the heap, increasing garbage collection (GC) pressure and potentially causing loop overruns.

The Mut* (mutable) variants allow you to reuse the same object and update its value in-place with mut_replace(). This eliminates per-iteration allocations and keeps your robot code running smoothly.

circle-exclamation

Reusable SysIdRoutine Factory Method

You can create a static helper method to generate SysIdRoutine instances for any SmartMotorController:

Then use it in your subsystem:

Binding All Four Tests

When using SysIdRoutine directly, you need to bind all four tests separately:

circle-exclamation

Running All Tests with One Command

You can combine all four tests into a single command sequence that runs automatically:

circle-exclamation

For mechanisms with limits (arms, elevators), you can add safety stops:


Running the Tests

  1. Deploy your code to the robot

  2. Ensure sufficient space - at least 10-20 feet for drivetrains, adequate range of motion for arms/elevators

  3. Run all four tests in sequence:

    • Quasistatic Forward

    • Quasistatic Reverse

    • Dynamic Forward

    • Dynamic Reverse

  4. Monitor carefully - stop tests early if the mechanism exceeds safe limits

triangle-exclamation

Analyzing Results

After running all tests:

  1. Retrieve the log file from the roboRIO using the DataLogTool

  2. Open SysId (included with WPILib)

  3. Load the log file in the Log Loader pane

  4. Drag entries to the Data Selector:

    • Find an entry containing "state" (type: string) → Test State slot

    • Find Position, Velocity, and Voltage entries → respective slots

  5. Select analysis type (Simple, Elevator, or Arm)

  6. Click Load and review diagnostics

Applying the Results

Once you have your feedforward constants (KsK_s, KvK_v, KaK_a, and KgK_g if applicable), apply them to your YAMS configuration:

circle-check

YAMS vs Manual: When to Use Each

Approach
Best For

YAMS mechanism.sysId()

Standard mechanisms (Arm, Elevator, Shooter) where you're already using YAMS mechanism classes. Simplest setup.

WPILib SysIdRoutine

Loosely coupled mechanisms, custom configurations, or when you need fine-grained control over the logging process.

Both approaches produce compatible log files that work with the WPILib SysId analysis tool.


REV SysId with Status Logger

When using REV motor controllers (SPARK MAX, SPARK Flex), YAMS leverages the REV Status Logger to capture high-quality CAN status frame data. This runs automatically in the background and can provide better data than the standard WPILib DataLog approach.

How Status Logger Works

Status Logger is enabled by default in REVLib 2026+ and requires no setup. When you run SysId tests with REV motor controllers:

  1. The standard WPILib .wpilog file is written to the roboRIO (usable directly in SysId)

  2. A separate .revlog file is also written, containing raw CAN status frames with higher fidelity

circle-info

Do I need the .revlog file?

The standard .wpilog file from your SysId routine may work fine for analysis. However, the .revlog file captures raw CAN data at a higher rate and avoids timing issues from the robot loop. For the best results, especially if you encounter issues with your initial analysis, extract and convert the .revlog file.

Log File Locations

Status Logger saves .revlog files to:

Storage
Path

roboRIO internal

/home/lvuser/logs/

USB drive (recommended)

/u/logs/

circle-exclamation

Retrieving .revlog Files

From roboRIO internal storage:

Use FTP to access files at /home/lvuser/logs/. See the WPILib FTP documentationarrow-up-right for details.

From USB drive:

Either access the /u/logs/ directory with the flash drive plugged into the roboRIO, or simply unplug the USB drive and insert it into your computer.

Converting .revlog to .wpilog

.revlog files must be converted before use in SysId. There are two methods:

  1. Open AdvantageScope

  2. Open your .revlog file directly

  3. AdvantageScope automatically converts it to .wpilog format

  4. Export as .wpilog if needed for SysId

circle-check

Method 2: revlog-converter CLI

Use the revlog-converter NPM package for command-line conversion:

Manual Logging Control

If you need precise control over when logging occurs (e.g., only during SysId tests), you can disable auto-logging:

circle-exclamation

CTRE SysId with Signal Logger

When using CTRE motor controllers (TalonFX, TalonFXS), YAMS leverages the Phoenix 6 Signal Logger instead of WPILib's DataLog. This provides several advantages:

  • Eliminates CAN latency issues

  • Supports signals faster than the 20ms main robot loop

  • Avoids Java garbage collection pauses affecting log quality

How YAMS Uses Signal Logger

When you call mechanism.sysId() with a CTRE motor controller, YAMS automatically:

  1. Configures the SysIdRoutine to log state using SignalLogger.writeString()

  2. Sets the log callback to null (Signal Logger captures all signals automatically)

  3. Uses VoltageOut control requests to apply voltage during tests

The resulting routine looks like this internally:

Running CTRE SysId Tests

You must manually start and stop the Signal Logger before and after running tests:

circle-exclamation

Extracting and Converting CTRE Logs

CTRE logs are saved in the .hoot format, which must be converted to .wpilog before analysis in SysId.

triangle-exclamation

Step 1: Locate the Log File

After running your tests, the .hoot log file is stored on the roboRIO at:

You can also find logs on a USB drive if one was connected during testing.

Step 2: Extract Using Phoenix Tuner X

  1. Open Phoenix Tuner X

  2. Connect to your robot

  3. Navigate to Tools → Extracting Signal Logs

  4. Select your .hoot log file

  5. Choose WPILOG as the export format

  6. Save the exported .wpilog file

Step 3: Alternative - Using owlet CLI

You can also use CTRE's owlet command-line tool:

Step 4: Load in SysId

  1. Open the SysId tool (included with WPILib)

  2. In the Log Loader pane, load your converted .wpilog file

  3. In the Data Selector, drag the following signals:

    • state (string) → Test State slot

    • TalonFX PositionPosition slot

    • TalonFX VelocityVelocity slot

    • TalonFX MotorVoltageVoltage slot

  4. Select your analysis type (Simple, Elevator, or Arm)

  5. Click Load and review the diagnostics

circle-info

The Signal Logger automatically captures Position, Velocity, and MotorVoltage signals from your TalonFX motors - you don't need to manually log these values like you would with REV motors.

CTRE vs REV: Key Differences

Aspect
CTRE (TalonFX)
REV (SparkMax/Flex)

Primary Logging

Phoenix Signal Logger (.hoot)

WPILib DataLog (.wpilog) + Status Logger (.revlog)

Log Callback

null (automatic)

Manual logging required

State Logging

SignalLogger.writeString()

Default WPILib logger

Conversion Required

Yes - Tuner X or owlet

Optional - .wpilog works, .revlog is better

Signal Quality

Higher (bypasses CAN latency)

Standard loop or higher with .revlog

Setup Required

Must start/stop SignalLogger

Status Logger runs automatically


Last updated