Implementing Logging
Setting Up DataLogManager
We log with WPILib's built-in DataLogManager. No vendordep, no LoggedRobot, no replay layer. Two lines in Robot's constructor turn it on; after that, anything published to NetworkTables (your telemetry plus the Driver-Station and joystick data) is captured to a .wpilog file you open in AdvantageScope.
Turn it on in Robot's constructor, then publish what you care about to NetworkTables. DataLogManager records every NT change to disk.
Turning on logging
DataLogManageris part of WPILib, so there's nothing to install. Start it in Robot's constructor before anything else, and add the Driver-Station data feed:
Where the logs go
- Simulation: a
.wpilogunder./logsin your project. - On SystemCore: a USB drive if one is plugged in, otherwise
/home/systemcore/logs. - Phoenix 6 devices additionally log to a
.hootfile (high-rate signal data) that you can open in Tuner X or AdvantageScope, so you get that extra detail for free.
What you get automatically
The moment DataLogManager.start() runs, these are captured with no further code:
Captured for free
- Every NetworkTables value change, including everything your telemetry publishes (more below)
- Console output: anything printed to stdout/stderr
- Driver-Station data (via
startDataLog): alliance, mode, match time, and full joystick axes/buttons - Phoenix 6 signals in the
.hootfile: motor positions, velocities, currents, temperatures
Logging your own values
To log something specific, publish it to NetworkTables; DataLogManager records the change to the .wpilog automatically. For a quick number, SmartDashboard.putNumber("Arm/Position", pos) works. For structured types like Pose2d or ChassisVelocities, use a NetworkTables struct publisher so AdvantageScope can render them natively.
πΊοΈ The drivetrain telemetry surface (struct publishers)
The template's Telemetryclass is the project's logging surface. It publishes the swerve state to NetworkTables with type-aware struct publishers; CTRE calls it from the odometry thread (register with drivetrain.registerTelemetry(telemetry::telemeterize)). Because it's on NetworkTables, DataLogManager writes it to the .wpilog too.
π Logging from a mechanism (there's no periodic() in v3)
v3 mechanisms don't have a periodic()method, so "publish my state every loop" needs a different home. The simple pattern is a runRepeatedly(...) default command that publishes each tick whenever nothing else is using the mechanism:
You can also publish from inside a command body, right next to the setpoint that produced the value β handy for logging target-vs-actual during a move.
Performance Considerations
- Use hierarchical keys (e.g.
"Arm/Position") so the log stays organized. - Prefer struct types: publish one
Pose2drather than three separate numbers. - Avoid high-frequency strings. They're expensive; log numbers and booleans.
- Don't over-publish. Too much NT traffic can affect loop timing.
Workshop Code Implementation
Robot.java β starting DataLogManager
Loading file...
π§ Drivetrain telemetry
The drivetrain is the canonical example: it publishes Pose2d, velocity, and per-module states to NetworkTables through its telemetry helper, and DataLogManager records all of it.
Loading file...
AdvantageScope
AdvantageScope is the natural viewer for the logs you're producing. It reads .wpilog files for post-match analysis and connects to your robot over NetworkTables for live monitoring. (Glass and Tuner X can also read these; Tuner X opens the .hoot files.)
π‘ Real-Time Data Viewing
Everything you publish to NetworkTables is visible live.
- Open AdvantageScope on your driver station
- Select "Connect to Robot" from the menu
- Enter your team number or robot address
- Browse the NetworkTables tree β your keys land under their table (e.g.
Drivetrain/Pose) - Add graphs, the 3D field view, or swerve module visualizations
π₯ Post-Match Log Analysis
Pull .wpilog files off the USB drive or download them from the robot with AdvantageScope.
- Open Preferences and set the robot address / log folder
- Click "File" > "Download Logs..."
- Select the logs to download (newest at top)
- Open the downloaded
.wpilogfile - Add line graphs or use the 3D field view for analysis
Where the data lives in NetworkTables
Your published values land under whatever table you chose, and the auto-captured data sits alongside it:
Drivetrain/Pose,Drivetrain/Velocity, β¦: your telemetry struct publishersSmartDashboard/...: anything you sent viaSmartDashboard.put*- Driver-Station and joystick data captured by
startDataLog
AdvantageScope Pro Tips
- Overlay multiple signals: compare target vs actual on the same graph
- Video sync: line log data up with match video
- Save layouts: reusable dashboards for quick analysis
- Drag struct types in: drop a logged
Pose2donto the 2D/3D field view directly
Logging Best Practices
β Do
- Log sensor inputs, motor outputs, and target setpoints together
- Use hierarchical keys (
Subsystem/Parameter) - Prefer struct types (
Pose2d,SwerveModuleVelocity[]) over flattened number arrays - Start DataLogManager first thing in Robot's constructor
- Download logs after every match and review between matches
β Donβt
- Log high-frequency strings (use numbers or booleans)
- Publish so much that NetworkTables traffic hurts loop timing
- Forget a USB drive on the robot if you want the log off the controller easily
- Ignore loop-overrun warnings from excessive publishing
Additional Resources
What's Next?
Up Next: Drive to Point