Skip to content

Latest commit

 

History

History
219 lines (174 loc) · 9.03 KB

File metadata and controls

219 lines (174 loc) · 9.03 KB

pointcloud_web_viewer

ROS2 PointCloud2 web viewer — a C++ node that serves a real-time 3D point cloud visualization in the browser using Boost.Beast (HTTP/WebSocket) and WebGL.

Demo

Overview

The pointcloud_web_viewer node subscribes to a sensor_msgs/msg/PointCloud2 topic, converts the point cloud into a compact binary format, and streams it to connected browsers via WebSocket. The board itself serves both the web page and the binary stream — no external server or dependencies required on the client side beyond a browser with WebGL support.

  • C++ server: Boost.Beast HTTP + WebSocket
  • Frontend: Single self-contained HTML file, raw WebGL 1.0 (no Three.js)
  • Binary protocol: 24-byte header + 20-byte-per-point structs
  • Thread-safe: Mutex-protected shared frame between ROS2 callback and WebSocket broadcast thread

Requirements

Dependency Purpose
ROS2 Humble (or compatible) Core framework
rclcpp ROS2 C++ client library
sensor_msgs PointCloud2 message type
Boost (system) Asio networking
Boost.Beast (header-only) HTTP/WebSocket server
C++17 compiler Build
Modern browser with WebGL Client

Build

cd ~/ros2_ws
colcon build --packages-select pointcloud_web_viewer
source install/setup.bash

Run

bash script/run_pointcloud_web_viewer.sh

The script (script/run_pointcloud_web_viewer.sh) sources the TROS Humble setup and launches the node with:

ros2 launch pointcloud_web_viewer \
  pointcloud_web_viewer.launch.py \
  pointcloud_topic:=/StereoNetNode/stereonet_pointcloud2 \
  server_port:=9999 \
  send_fps:=10.0 \
  downsample_step:=1 \
  max_points:=100000

Access the viewer

Open http://<board-ip>:<port> (e.g. http://192.168.1.100:8080) in a browser.

Parameters

All parameters can be set via the YAML config file (config/viewer.yaml), launch arguments, or command-line overrides.

Parameter Type Default Description
pointcloud_topic string /stereonet_pointcloud PointCloud2 topic to subscribe to
server_host string 0.0.0.0 HTTP/WebSocket bind address
server_port int 8080 HTTP/WebSocket listen port (1–65535)
send_fps double 10.0 Maximum frame rate for WebSocket streaming (min 0.1)
downsample_step int 2 Process every Nth point — higher values reduce CPU load (min 1)
max_points int 100000 Maximum number of points per frame (min 1)
min_distance double 0.1 Minimum distance filter in meters (min 0.0)
max_distance double 30.0 Maximum distance filter in meters (≥ min_distance)
intensity_field string intensity Name of the intensity field in the PointCloud2 message
qos_depth int 1 QoS keep_last depth for the subscription (min 1)

Config file

The default config file config/viewer.yaml provides preset values:

pointcloud_web_viewer:
  ros__parameters:
    pointcloud_topic: /StereoNetNode/stereonet_pointcloud2
    server_host: 0.0.0.0
    server_port: 8080
    send_fps: 10.0
    downsample_step: 2
    max_points: 100000
    min_distance: 0.1
    max_distance: 30.0
    intensity_field: intensity
    qos_depth: 1

Launch arguments

Argument Default Description
config_file <share>/config/viewer.yaml Path to YAML parameter file
pointcloud_topic /StereoNetNode/stereonet_pointcloud2 PointCloud2 topic
server_port 8080 HTTP/WebSocket port

Note: The launch file exposes only pointcloud_topic and server_port as CLI overrides. To change other parameters, edit config/viewer.yaml or pass them via the launch file's parameters dict.

Web Interface

The web viewer provides a real-time 3D point cloud display with the following features:

Controls

Control Action
Left-drag Rotate (orbit)
Right-drag or Shift+Left-drag Pan
Scroll Zoom in/out

UI Panel

  • Connection status: Green/red indicator showing WebSocket connection state
  • Point count: Number of points in the current frame
  • Receive FPS: Actual frame rate from the WebSocket stream
  • RGB status: Whether color data is available in the point cloud
  • Point size: Slider (1–10) to adjust rendered point size
  • Rotation sliders: Roll, Pitch, Yaw (−180° to 180°)
  • Reset View Rotation: Resets rotation to default orientation
  • Color mode: Select from:
    • RGB — Native point cloud colors
    • Forward Distance (X) — Heatmap based on X-axis distance
    • Height (Z) — Heatmap based on Z-axis elevation
    • Intensity — Heatmap based on the intensity field
    • White — Solid white rendering
  • XY Grid toggle: Reference grid at Z=0 with 1 m step, 5 m thick lines, color-coded ROS axes (red = X, green = Y)
  • Legend: ROS coordinate axes reference and mouse control hints

Coordinate System

ROS coordinates are mapped to the WebGL view as follows:

  • ROS X (forward) → WebGL −Z
  • ROS Y (left) → WebGL −X
  • ROS Z (up) → WebGL Y

This ensures Y is always up in the browser view.

Supported PointCloud2 Fields

Field Required Description
x, y, z Yes Point coordinates (any numeric type)
intensity No Configurable field name; any numeric type
rgb / rgba No Packed color as FLOAT32 or UINT32
r, g, b No Separate color channels (any numeric type, clamped to 0–255)

Both little-endian and big-endian messages are supported.

Binary Protocol

The WebSocket stream sends binary frames with the following layout:

PointCloudFrameHeader (24 bytes)
├── magic:        uint32  = 0x31444350 ("PCD1")
├── version:      uint16  = 2
├── point_format: uint16  = 1 (XYZI) or 2 (XYZI+RGB)
├── point_count:  uint32
├── point_stride: uint32  = 20
└── timestamp_ns: uint64  (ROS timestamp)

WebPoint[] (point_count × 20 bytes)
├── x, y, z:      float32
├── intensity:    float32  (normalized to [0, 1])
└── r, g, b:      uint8 × 3 + 1 reserved byte

HTTP Endpoints

Endpoint Method Description
/ or /index.html GET Serves the WebGL viewer page
/health GET JSON health check: {"ok":true,"frame_seq":<N>,"has_cloud":true/false}
/ws GET WebSocket upgrade for binary point cloud streaming
/favicon.ico GET Returns 204 No Content

Files

pointcloud_web_viewer/
├── CMakeLists.txt
├── package.xml
├── config/
│   └── viewer.yaml                  # Default parameter values
├── doc/
│   └── pointcloud_web_viewer.gif    # Demo animation
├── include/pointcloud_web_viewer/
│   ├── pointcloud_web_viewer.hpp    # ROS2 node header
│   ├── protocol.hpp                 # Binary protocol + SharedFrame
│   └── web_server.hpp               # HTTP/WebSocket server header
├── launch/
│   └── pointcloud_web_viewer.launch.py
├── script/
│   └── run_pointcloud_web_viewer.sh # Convenience startup script
├── src/
│   ├── main.cpp                     # Entry point
│   ├── pointcloud_web_viewer.cpp    # ROS2 node implementation
│   └── web_server.cpp               # Boost.Beast server implementation
└── web/
    └── index.html                   # WebGL viewer frontend