How to Import and Plot CSV Files in PlotJuggler

CSV is where most PlotJuggler journeys begin: it is the format every logger, spreadsheet and test rig can produce, and both PlotJuggler lines read it — CSV is a core loader in PJ3 and stays on the supported file list in PJ4 alongside MCAP, Parquet and PX4 ULog. This tutorial covers the one concept that decides whether a CSV plots correctly — the timestamp column — plus a complete import workflow and the fixes for the CSV problems everyone hits once. It assumes the basics from Getting Started with PlotJuggler; all the guides live on the Tutorials hub.

What a PlotJuggler-ready CSV looks like

PlotJuggler plots values against time, so a usable CSV needs three things: a header row naming the columns, one column that carries time, and numeric columns to plot. The illustrative example below shows the shape — a time column first, then one column per signal, one row per sample:

time,voltage,current,temperature
0.00,12.61,1.82,24.5
0.10,12.58,1.85,24.6
0.20,12.55,1.91,24.6
# Illustrative example only — a generic CSV shape, not output from a specific tool.
  • The timestamp column is the column PlotJuggler uses as the horizontal axis. It can hold elapsed seconds, epoch time or another consistent time representation — what matters is that it increases monotonically down the file and that PlotJuggler can identify it as the time column during import.
  • One column per signal. Each numeric column becomes a series you can drag onto a plot. Name columns meaningfully in the header — those names are what you will see in the signal list.
  • Consistent rows. Keep the column count the same on every row, and keep units consistent within a column. Mixed text annotations inside a numeric column are the classic cause of a series that loads partially or not at all.

Step 1 — Prepare the file

Before importing, open the CSV in a text editor or spreadsheet and spend sixty seconds as a sceptic. Confirm the header row exists and names every column. Confirm the time column really is time — sorted, increasing, and in units you can state out loud (seconds? milliseconds?). If your export wrote timestamps as formatted date-time text, consider whether your exporter can emit a numeric epoch or elapsed-seconds column instead; a plain numeric time column is the least ambiguous input you can give any plotting tool. Save a copy rather than editing your only original.

Step 2 — Load the file

The documented workflow is drag-and-drop: drag the CSV file into the PlotJuggler window. The CSV loader reads the file and the import step asks you, in effect, the defining question of this tutorial: which column is time? Designate your timestamp column there. Every other numeric column is then offered as a plottable series, sampled at the times that column provides. Get this choice right and everything downstream — overlays, transforms, XY plots — behaves; get it wrong and the data plots against row index or against one of your signals, which looks bizarre and wastes debugging time.

Step 3 — Choose and plot series

With the file loaded, the signal list shows your columns. Drag the series you care about onto the plotting area, exactly as in the getting started walkthrough: overlay signals that share a story, give unrelated signals their own plots. Two CSV-specific checks are worth doing on first plot:

  1. Check the time span. The plot’s horizontal extent should match your recording’s real duration. A span of thousands of “seconds” for a one-minute test usually means the time column was in milliseconds — the data is fine, the unit assumption is not.
  2. Check a known value. Pick a moment you know (a switch flipped, a motor started) and confirm the curve does what the real system did at that time. This catches swapped columns and off-by-one header mistakes in seconds.

Working with the imported data

Once plotted, a CSV series is a first-class PlotJuggler series. Apply built-in transforms such as a moving average or derivative to it, combine columns with a Lua custom function (total power from the voltage and current columns, in the example above, is the textbook case), plot one column against another in an XY plot, and capture the whole arrangement as a layout so the next CSV from the same rig opens into the same view. If you import several CSVs from repeated runs, the multiple-recording comparison workflow applies to them just as it does to bag files.

Common CSV problems, and fixes

SymptomLikely causeFix
Data plots against row numberNo column was designated as time, or the time column was not recognisedRe-import and designate the timestamp column explicitly
Timeline spans absurd durationsTime values are in milliseconds (or microseconds) while the plot reads them as secondsConvert the column in your exporter, or rescale the series with a scale transform after import
A series is missing or stops earlyNon-numeric text inside that column, or rows with missing fieldsClean the column in the source export; keep one consistent value format per column
Signals from two files do not line upThe recordings started at different timesThat is a time-alignment problem, not a CSV problem — see the time offset tutorial
The file will not load at allThe file is not really CSV (wrong delimiter saved under a .csv name, or an Excel workbook renamed)Export a genuine comma-separated text file from the source tool

CSV in PJ4: one extra worth knowing

PJ4 keeps CSV import and adds an export direction: the 3.999.9 preview introduced an export tool to CSV and Arrow-Parquet, which shipped in the 4.0 line. That makes CSV a two-way street in PJ4 — bring data in as CSV, and send selected data back out as CSV for a spreadsheet or a colleague. The CSV workflow itself, timestamp column and all, is unchanged between the lines, which is why this tutorial can honestly cover both. For the files themselves and every other format, see the Download page and the Tutorials hub.

Similar Posts