A Robot Debugging Workflow with PlotJuggler: From Rosbag to Root Cause

Most robot bugs are not found by staring at code. They are found by watching what the robot actually did — which means a recording, a timeline, and a disciplined way of moving from “it behaved strangely” to the minute, then the second, then the signal where behaviour diverged. This workflow uses PlotJuggler as the investigation desk: record the run, load the recording, align the signals in time, derive the quantities that are not logged directly, and save the whole view as a layout you can reuse on the next run and hand to a colleague.

Step 1: Record with debugging in mind

A debugging session starts before PlotJuggler opens. Record the run in the format your stack already produces — a ROS bag or an MCAP recording are the common cases — and record the topics you would want if something went wrong, not only the topics for the feature you are testing. Note the wall-clock time of anything you observe in the room: a bump, a pause, a missed grasp. That single note is often the difference between a ten-minute investigation and an afternoon of scrubbing. Our guide to reading rosbag and MCAP files in PlotJuggler covers loading both formats, including what to check when a recording does not open as expected.

Step 2: Load, orient, and narrow the window

Load the recording and first read it at the widest level: when did the robot start moving, when did the task end, and where does the observed problem sit? Plot a small set of high-level signals — commanded versus actual motion is the classic pair — and zoom into the window around your noted timestamp. Resist adding more series until the window is right. Debugging fails by drowning: fifty plotted topics will always contain something that looks odd, somewhere.

Step 3: Align signals with time offset

Signals recorded by different parts of a system rarely share a perfect clock, and a cause can appear to follow its effect if two series are offset. PlotJuggler’s per-curve time offset exists for exactly this: shift one series until events that happened together line up together, then judge the relationship. The dedicated walkthrough is PlotJuggler time offset: aligning signals that do not line up. Alignment is also the step that makes sensor-versus-command comparisons honest — a “lag” that disappears after a small offset was never a control problem; it was a timestamp problem, which is a different bug and a different fix.

Step 4: Derive what was not logged

The signal that proves a root cause is often not in the recording at all — it is a combination of signals that are. PlotJuggler’s transform tools cover the common cases two ways. Built-in transforms give you derivatives, integrals, moving averages and scaling without code. For anything bespoke, custom functions do the job: Lua has been the scripting route on the established line, and PlotJuggler 4 adds Python alongside it, as our PlotJuggler 4 Python scripting guide explains. Typical derived series in a debugging session include an error signal (command minus actual), a rate (the derivative of a position), and a combined condition that only matters when two states coincide. Build the derived series, plot it in the narrowed window, and the question usually answers itself.

Step 5: Save the investigation as a layout

When the view finally shows the problem clearly, save it as a layout before you touch anything else. A saved layout preserves which series are plotted, where, and — on PlotJuggler 4’s layout format — the viewport and offsets as well, so the same investigation can be reopened on tomorrow’s recording in one step. The how-to is saving and sharing PlotJuggler layouts. Treat good layouts like good tests: one per recurring question (“why did navigation pause?”, “why did the arm overshoot?”), named for the question, and shared with the team so root-cause analysis stops depending on who holds the mouse.

The workflow in one pass

  1. Record generously, and note the wall-clock time of anything you see go wrong.
  2. Load the bag or MCAP file and narrow to the window around that note.
  3. Align series with time offset before judging cause and effect.
  4. Derive the missing quantity with a built-in transform or a Lua/Python custom function.
  5. Confirm the pattern in the window, then check whether it appears elsewhere in the run.
  6. Save the layout, named for the question it answers, and reuse it on the next recording.

Followed in order, that sequence turns debugging from folklore into a repeatable method — and each step leaves an artefact (the recording, the offsets, the derived series, the layout) that someone else can check.

Similar Posts