Live Streaming to PlotJuggler: WebSocket, MQTT, ZMQ and UDP

Files are for what already happened. Streaming is for what is happening now: a robot on the bench, a test running in the next room, a process emitting values you want to watch as curves rather than as scrolling numbers. PlotJuggler has streamed since the PJ3 era — its documented streamers cover WebSocket, MQTT, ZeroMQ (ZMQ) and UDP, plus ROS topics and Lab Streaming Layer — and PJ4 carries the same family forward and adds WebRTC. This tutorial explains the model, helps you choose a transport, and walks a complete streaming setup. The recorded-data counterpart workflows are in the bag and MCAP tutorial; the series index is the Tutorials hub.

The streaming model, in one paragraph

A streamer is the live twin of a file loader. Your program — the publisher — sends timestamped values over a network connection; PlotJuggler’s streamer for that transport receives them, decodes the messages, and the values appear as series you drag onto plots exactly as if they had come from a file, except the right edge of the plot keeps moving. Two choices define any setup: the transport (how the bytes travel: WebSocket, MQTT, ZMQ, UDP) and the encoding (how each message represents its values). PJ3 understands JSON, CBOR, BSON and MessagePack encodings; PJ4 widens that list (adding Protobuf and Apache Arrow, among others) and keeps the same transports, plus WebRTC for live video. Get transport and encoding to match on both ends and streaming is, honestly, the easy part.

Choosing a transport

TransportCharacterReach for it when
WebSocketA persistent connection over web-friendly plumbing; the natural output of anything that already speaks HTTP-era protocolsYour publisher is a web service, a script, or a tool that already offers a WebSocket endpoint; PJ3 even grew a WebSocket URL feature in its final release, 3.17.2
MQTTPublish/subscribe through a broker; publishers and subscribers never address each other directlyThe data already lives on an MQTT broker (IoT fleets, building and test-rig telemetry), or several consumers need the same stream
ZeroMQ (ZMQ)Lightweight socket patterns without a broker; common in research and robotics codebasesYour stack already uses ZMQ, or you want brokerless point-to-point streaming with minimal ceremony
UDPFire-and-forget datagrams: the lowest-overhead option, with no delivery guaranteeHigh-rate local telemetry where an occasional lost packet is acceptable and simplicity beats ceremony
ROS topics / LSLThe domain-native options: PJ3 subscribes to ROS 1/ROS 2 topics directly; Lab Streaming Layer serves lab and neuroscience rigsThe source is a running ROS system (see the ROS 2 install guide) or an LSL outlet

The message: a labelled example

Whatever the transport, the payload must tell PlotJuggler which values arrived and when. With JSON — the most readable encoding, and the right choice while you are setting up — one message typically carries a timestamp and a set of named values, like this illustrative example:

{
  "timestamp": 1712345678.42,
  "temperature": 24.6,
  "pressure_kpa": 101.3
}
# Illustrative example only — a generic JSON payload shape for explanation,
# not a captured message from a specific device.

Each named value becomes (or updates) a series; the timestamp places it on the timeline. Binary encodings — CBOR, BSON, MessagePack — express the same content more compactly, which is why high-rate streams prefer them once the setup is proven in JSON. The design rule on the publisher side is the same as for CSV files: stable value names and a consistent, honest timestamp on every message. Rename a value mid-stream and you have started a new series whether you meant to or not.

A complete streaming setup, step by step

  1. Start the publisher first. Streaming has two ends and only one of them is PlotJuggler; have your device, script or broker demonstrably emitting before debugging the receiving side. Most “PlotJuggler shows nothing” reports end here.
  2. Choose the matching streamer in PlotJuggler for your transport, and point it at the publisher (or broker) with the connection details your setup uses — host, port and topic or endpoint as applicable to that transport.
  3. Match the encoding. Tell the streamer which encoding the messages use (JSON while proving the link). A transport that connects and an encoding that mismatches produces silence, not errors — this is the second most common setup trap.
  4. Watch the series appear. As messages arrive, their named values show up as available series. Drag them onto a plot, as in Getting Started, and confirm the curves move and the values agree with a known reference (a sensor you can warm with a fingertip beats any amount of log staring).
  5. Then tune. Switch to a binary encoding if the rate demands it, add a derived series if the raw values need combining, and save the arrangement as a layout so the live view is rebuilt in one step next session.

Streaming in PJ4: what is added

PJ4’s live list — ROS 2, MQTT, ZeroMQ, UDP, WebSocket bridges, WebRTC and Lab Streaming Layer — keeps every PJ3-era transport that matters here and adds the piece PJ3 never had: WebRTC, for live camera streams that join your plots on the shared timeline (the multimodal picture is toured in PJ4 Video and 3D Visualisation). Its encoding list also grows to include ROS 1/2 messages, Protobuf and Apache Arrow alongside JSON, CBOR, BSON and MessagePack. The workflow in this tutorial — publisher first, match transport, match encoding, verify against reality — is unchanged by the generation; only the menu of options grows.

When nothing arrives: the short checklist

  • Is the publisher actually publishing? Verify at the source, with its own tools or a second consumer — never debug two ends at once.
  • Do the connection details match? Host, port, and topic/endpoint naming must agree exactly; “almost the same topic” is a different topic.
  • Do the encodings match? JSON sent to a MessagePack-configured streamer (or vice versa) fails quietly. Set both ends to JSON while diagnosing.
  • Is anything between the ends? Firewalls, broker authentication and containers that publish on a different network than you think are the classic in-between culprits — general networking checks, applied in that order.
  • Are the timestamps sane? Values arriving with a frozen or wildly wrong timestamp plot somewhere you are not looking; zoom out to the full timeline once before concluding nothing arrived.

Live data handled well becomes the best data: when a stream surprises you, the same session can be inspected with every tool in this series — offsets, XY views, transforms — because streamed series are ordinary series. And when the moment matters, record it and analyse the file with the recorded-data workflows. The full learning path is on the Tutorials hub; install files are on the Download page.

Similar Posts