A high-performance bridge server that forwards middleware topic content over WebSocket to PlotJuggler clients. Three backends share a common core:
- ROS2 (
pj_bridge_ros2) — ROS2 Humble / Jazzy / Kilted viarclcpp - FastDDS (
pj_bridge_fastdds) — eProsima Fast DDS 3.4 (standalone, no ROS2 required) - RTI (
pj_bridge_rti) — RTI Connext DDS (build disabled, code preserved)
Even if primarily created for PlotJuggler, this can be considered a general purpose DDS-to-Websocket bridge and be used independently.
pj_bridge enables clients to subscribe to topics and receive aggregated messages at 50 Hz without needing a full middleware installation. This is useful for visualization tools like PlotJuggler, remote monitoring, and lightweight clients.
- No ROS required: if you have PlotJuggler 3.16+ installed on your computer, you don't need ROS installed on it.
- No DDS Communication: Clients connect via WebSocket (single port) without needing ROS2/DDS installed
- High Performance: 50 Hz message aggregation with ZSTD compression. The original message timestamp is preserved, and less bandwidth is used.
- Multi-Client Support: Multiple clients can connect simultaneously with shared subscriptions
- Runtime Schema Discovery: Automatic extraction of message schemas from installed ROS2 packages on the server side.
- Large Message Stripping: Automatic stripping of large array fields (Image, PointCloud2, LaserScan, OccupancyGrid) to reduce bandwidth while preserving metadata
| Humble | Jazzy | Kilted | |
|---|---|---|---|
| Pixi | |||
| colcon |
| Parameter | Type | Default | Description |
|---|---|---|---|
port |
int | 9090 | WebSocket server port |
publish_rate |
double | 50.0 | Aggregation publish rate in Hz |
session_timeout |
double | 10.0 | Client timeout duration in seconds |
strip_large_messages |
bool | true | Strip large arrays from Image, PointCloud2, LaserScan, OccupancyGrid messages |
Install the pre-built package from the PlotJuggler conda channel — no build step required.
# Install (change humble to jazzy or kilted as needed)
pixi global install pj-bridge-ros2-humble \
-c https://prefix.dev/plotjuggler -c robostack-humble -c conda-forge
# Run (add arguments if different from default)
pj_bridge_ros2 --ros-args -p port:=9090Pre-built AppImages are available from GitHub Releases.
Example for ROS2 Humble:
# Do once after downloading the file
chmod +x pj_bridge_ros2-humble-x86_64.AppImage
# Run (add arguments if different from default)
./pj_bridge_ros2-humble-x86_64.AppImage --ros-args -p port:=9090All dependencies (spdlog, nlohmann_json, ZSTD) are provided by the dependency manager. IXWebSocket is resolved via find_package first, with a FetchContent fallback for colcon builds. Only tl::expected is vendored.
Pixi manages the full toolchain including ROS2 via RoboStack.
From the cloned plotjuggler_bridge directory:
# Build and test (change humble to jazzy or kilted as needed)
pixi run -e humble build
pixi run -e humble test
# Run
pixi shell -e humble
ros2 run pj_bridge pj_bridge_ros2Standard ROS2 build using colcon. Dependencies are installed via rosdep; only IXWebSocket is fetched automatically via CMake FetchContent.
# Set up workspace
mkdir -p ~/ws_plotjuggler/src && cd ~/ws_plotjuggler/src
git clone https://github.com/PlotJuggler/plotjuggler_bridge && cd plotjuggler_bridge
# Install dependencies
source /opt/ros/${ROS_DISTRO}/setup.bash
rosdep install --from-paths pj_bridge --ignore-src -y
# Build and test
cd ~/ws_plotjuggler
colcon build --packages-select pj_bridge --cmake-args -DCMAKE_BUILD_TYPE=Release
colcon test --packages-select pj_bridge && colcon test-result --verbose
# Run
source install/setup.bash
ros2 run pj_bridge pj_bridge_ros2Standalone build using eProsima Fast DDS (no ROS2 required).
From the cloned plotjuggler_bridge directory:
# Build
conan install . --output-folder=build_fastdds --build=missing -s build_type=Release
cd build_fastdds
cmake .. -DCMAKE_BUILD_TYPE=Release -DENABLE_FASTDDS=ON \
-DCMAKE_TOOLCHAIN_FILE=conan_toolchain.cmake
make -j$(nproc)
# Run
./pj_bridge_fastdds --domains 0 1- For detailed architecture documentation, see docs/ARCHITECTURE.md.
For the full API protocol documentation (commands, responses, binary wire format), see docs/API.md.
Another process is using the port. Either kill the conflicting process or use a custom port:
ros2 run pj_bridge pj_bridge_ros2 --ros-args -p port:=9090- Verify server is running:
ps aux | grep pj_bridge - Check topics are being published:
ros2 topic list - Verify heartbeat is being sent (required every 1 second)
- Check server logs:
ros2 run pj_bridge pj_bridge_ros2 --ros-args --log-level debug
The message type's .msg file was not found. Ensure the ROS2 package containing the message type is installed and sourced:
ros2 interface show <package_name>/msg/<MessageType>The client stopped sending heartbeats. Ensure the client sends a heartbeat every 1 second. The default timeout is 10 seconds. Increase if needed:
ros2 run pj_bridge pj_bridge_ros2 --ros-args -p session_timeout:=20.0pj_bridge is licensed under the GNU Affero General Public License v3.0 (AGPL-3.0).
Copyright (C) 2026 Davide Faconti
This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
See the LICENSE file for the full license text.
Yes, absolutely. The AGPL does not restrict commercial use. You can:
- Use pj_bridge in commercial products and services
- Deploy it in production environments for profit
No, it does not. Because pj_bridge is a standalone application that communicates via inter-process communication (WebSocket), it does not impose license restrictions on:
- Your ROS2 nodes and packages
- Client applications connecting to the bridge
- Other software running on the same system
- Proprietary code that publishes to or subscribes from ROS2 topics
You must share modifications to pj_bridge only if you:
- Distribute modified versions to others (e.g., shipping a modified binary), OR
- Provide the modified software as a network service to external users
You do NOT need to share code if you:
- Use pj_bridge unmodified (even commercially)
- Modify it for internal use only within your organization
- Connect proprietary clients or ROS2 nodes to the bridge
The AGPL's network provision states that users who interact with the software over a network should have access to the source code. However, this only applies if you:
- Modify the software, AND
- Provide it as a service to external users
If you're using pj_bridge unmodified, you have nothing to worry about - there are zero licensing obligations. If still concerned, contact me for alternative licensing options.
