Phantom Bridge:一个基于WebRTC的ROS2远程可视化与遥操作工具

Phantom Bridge 是 Phantom Cybernetics 推出的一个 ROS2 远程可视化与遥操作工具。作者 mirek 在 2025-12-20 的 Open Robotics Discourse 发布帖中,把它描述为一种新的 ROS2 实时数据可视化、视频流、遥操作、远程/本地调试和 observability 方案:机器人端运行 C++ Bridge Client,浏览器端打开 Web UI,中间通过 WebRTC、Socket.io、Bridge Server 和 TURN/STUN 完成低延迟连接。

项目 环境
OS Ubuntu 22.04
ROS ROS 2 Humble

目录

  • [0. Phantom Bridge Features](#0. Phantom Bridge Features)
  • [1. 为什么用 WebRTC](#1. 为什么用 WebRTC)
  • [2. 系统结构](#2. 系统结构)
  • [3. 设置环境](#3. 设置环境)
  • [4. 实验](#4. 实验)
  • [5. 工具对比](#5. 工具对比)
  • [6. 编译问题备忘](#6. 编译问题备忘)
  • 参考

0. Phantom Bridge Features

  • ROS2 Node、Topic 和 Service 发现。
  • 二进制 ROS2 消息的快速流式传输(输入和输出)。
  • 快速 H.264 视频流式传输(预编码的 FFmpeg 帧)。
  • ImageCompressedImage 消息编码为 H.264 视频并进行流式传输(软件、CUDA 或 VAAPI 编码)。
  • Docker 容器发现和控制。
  • 通过 Socket.io 可靠调用 ROS2 Service。
  • ROS2 运行时参数读取/写入 API。
  • 可以轻松包含额外的 ROS2 package,以支持自定义消息和服务类型。
  • 机器人 Wi-Fi 信号监控、扫描和漫游(通过 Agent,需要主机上的 wpa_supplicant)。
  • 从任何正在运行的 Docker 容器中检索文件(例如通过 Agent 获取 URDF mesh)。
  • 系统负载和 Docker stats 监控(通过 Agent)。
  • P2P 连接;当无法建立 P2P 链路时,通过 TURN server 连接。
  • 多个 peer 可以连接到同一台机器,并且只产生很低的额外 CPU 开销。
  • 局域网约 5-10 ms RTT;通过 TURN server 远程操作时约 50 ms 以上 RTT。
  • 可与 Rosbag 以及 Gazebo、Webots 等仿真环境配合使用。
  • 支持 ROS2 Humble 及更新版本。

1. 为什么用 WebRTC

Reddit 讨论里有人问作者:设计时有没有考虑继续使用 DDS,而不是换成其他通信协议?作者的回答基本说明了 Phantom Bridge 的出发点。

他的判断是:如果两个端点经常在 NAT 后面、地址变化,或者希望公网自动建立连接,DDS-only 方案会很不实际。图像和视频本来就需要编码;浏览器又天然支持 WebRTC 和硬件加速视频解码。如果用 DDS 自己实现 NAT 穿透、媒体编码、浏览器解码、低延迟传输,最后很可能是在重新发明 WebRTC。

这个思路可以概括为:

text 复制代码
ROS2 / DDS
  适合机器人内部模块通信、局域网内 discovery、类型化消息传递。

WebRTC
  适合浏览器、NAT 穿透、P2P、TURN fallback、媒体流、低延迟 data channel。

Phantom Bridge
  在机器人端保留 ROS2 node,
  在传输层使用 WebRTC,
  在数据进入网络前按类型做压缩、转码、过滤和 UI 适配。

作者也提醒过,WebRTC RTT 不等于完整遥操作延迟。视觉遥操作还包括相机采集、编码、缓冲、解码和屏幕显示。作者给过一个非正式测试:多路相机、Pi 4/Pi 5、不同编码路径下,屏幕像素延迟约 104-116 ms,同时 WebRTC RTT 约 3-5 ms。

2. 系统结构

Phantom Bridge 的结构:

其中 phntm_bridge_client 是本文主要使用的部分, phntm_agent 则让 Web UI 可以看到 Docker、系统资源、Wi-Fi、文件等 ROS graph 以外的信息。

在线示例:https://docs.phntm.io/bridge/demos

3. 设置环境

本教程参考官方 PhantomCybernetics/phntm_bridge_client README 的 Install 流程,但把目标换成 Nav2 官方 TurtleBot3 Gazebo demo。

3.1 更新根证书

Bridge Client 需要访问 Bridge Server、容器镜像仓库和注册接口,先确认系统根证书是最新的:

bash 复制代码
sudo apt update
sudo apt install ca-certificates

3.2 安装 Docker、Buildx 和 Compose

如果系统还没有 Docker,先按 Docker 官方文档安装 Docker Engine、Buildx 和 Compose v2。安装完成后,把当前用户加入 docker 组,重新登录后即可不带 sudo 运行 docker compose

bash 复制代码
sudo usermod -aG docker ${USER}

重新登录后验证:

bash 复制代码
docker version
docker compose version

如果 docker compose 仍然不可用,优先检查 Compose v2 插件是否安装。在 Ubuntu 22.04 上,不同软件源里包名可能是 docker-compose-plugindocker-compose-v2

安装 Nav2 官方 demo 和 Phantom Bridge 推荐的 Cyclone DDS 依赖:

bash 复制代码
source /opt/ros/humble/setup.bash

sudo apt update
sudo apt install \
  ros-$ROS_DISTRO-navigation2 \
  ros-$ROS_DISTRO-nav2-bringup \
  ros-$ROS_DISTRO-gazebo-ros-pkgs \
  ros-$ROS_DISTRO-turtlebot3-gazebo \
  ros-$ROS_DISTRO-rviz2 \
  ros-$ROS_DISTRO-rmw-cyclonedds-cpp

额外安装 rmw_cyclonedds_cpp,是因为官方 README 推荐 Phantom Bridge 使用 Cyclone DDS。关键原则是:Nav2 这边和 Bridge 容器里要使用同一个 RMW 和同一个 ROS_DOMAIN_ID

3.4 准备 Bridge Client 镜像

官方 README 提供两种方式:直接使用预构建镜像,或者从源码构建本地镜像。本文示例使用本地镜像名 phntm/bridge:humble;如果你已经有可用的官方镜像,也可以在 Compose 中把 image 改成对应的 ghcr.io/phantomcybernetics/phntm_bridge_client 镜像。

从源码构建时:

bash 复制代码
cd ~
git clone git@github.com:PhantomCybernetics/phntm_bridge_client.git phntm_bridge_client
cd phntm_bridge_client

ROS_DISTRO=humble
docker build -f Dockerfile \
  -t phntm/bridge:$ROS_DISTRO \
  --build-arg ROS_DISTRO=$ROS_DISTRO \
  .

如果源码构建遇到 phntm_interfaces 接口不匹配,先看本文第 6 节的编译问题备忘;若只是体验本文 Nav2 可视化流程,优先使用官方预构建镜像会更省事。

3.5 注册 Phantom Bridge 机器人

向 Bridge Server 注册一个机器人,并生成默认配置。这个步骤会生成唯一的 id_robotkey

bash 复制代码
wget -O ~/phntm_bridge.yaml 'https://register.phntm.io/robot?yaml'

打开 ~/phntm_bridge.yaml,建议至少确认或修改:

yaml 复制代码
/**:
  ros__parameters:
    id_robot: '%ID_ROBOT%'
    key: '%SECRET_KEY%'
    name: 'Nav2 TurtleBot3 Demo'
    maintainer_email: 'robot.master@example.com'

注册接口生成的 id_robotkey 不要发布到公开网络。为了能在 Web UI 中处理 Nav2 action 类型,可以在 extra_packages 里补充 Nav2 消息包。官方 README 说明这里写 ROS 包名即可,不需要写完整 apt 包名:

yaml 复制代码
/**:
  ros__parameters:
    extra_packages:
      - turtlebot3-gazebo
      - turtlebot3-description
      - nav2-msgs
      - nav-msgs
      - sensor-msgs
      - map-msgs
      - bond

重启docker:

bash 复制代码
docker compose down
docker compose up -d --force-recreate

如果只看 /tf/scan/robot_description/odom 等常见消息类型,这一步通常不是必须的;如果要在 Web UI 的 Services & Actions 菜单里调用 /navigate_to_pose/navigate_through_poses 等 Nav2 action,Bridge Client 需要能找到对应 action 类型。

配置文件中还有几类常用字段可以按需确认:

字段 用途
bridge_server_address Bridge Server 地址,注册文件会自动生成。
discovery_period_sec ROS graph discovery 间隔。
stop_discovery_after_sec discovery 运行多久后停止;小于 0 表示持续发现。
/robot_description/tf_static 可设置 RELIABLETRANSIENT_LOCAL,便于 Web UI 后启动时仍能拿到静态信息。
wifi_interfaceenable_wifi_scanenable_wifi_roam Agent 的 Wi-Fi 监控和扫描能力;仿真 demo 通常可以保持默认或关闭。
docker_monitor_topicenable_docker_control Agent 的 Docker 容器监控和控制能力。
input_drivers Web UI 输入控制驱动,例如 TwistInputDriverJoyInputDriver

修改 ~/phntm_bridge.yaml 后先保存;Bridge Client 容器的启动和必要的重启放到第 4.3 节处理。

3.6 编写 Compose 服务

官方 README 建议把 Bridge Client 和 Agent 放在同一个 Docker Compose service 中运行。下面示例按 Humble 和本文的 ROS_DOMAIN_ID=22 整理:

yaml 复制代码
services:

  phntm_bridge:
    # 这里使用本地编译的 image
    # image: ghcr.io/phantomcybernetics/phntm_bridge_client:main-jazzy
    image: phntm/bridge:humble
    container_name: phntm-bridge
    hostname: phntm-bridge.local
    restart: unless-stopped
    privileged: true
    network_mode: host
    ipc: host
    environment:
     - RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
     - ROS_DOMAIN_ID=22
    volumes:
      - /home/jay/phntm_bridge.yaml:/ros2_ws/phntm_bridge_params.yaml:ro
      - /home/jay/phntm_bridge.yaml:/ros2_ws/phntm_agent_params.yaml:ro
      - /var/run:/host_run
      - /tmp:/tmp
    #devices:
    #  - /dev:/dev
    # logging:
    #   driver: local
    command:
      ros2 launch phntm_bridge client_agent_launch.py

/home/jay 改成你的实际用户目录。这里刻意使用绝对路径挂载参数文件,因为之前调试时遇到过 ~/phntm_bridge.yamlsudo docker compose 下被解析错、Docker 自动创建同名目录,最终导致 ROS 报 Parameter file path is not a file / Is a directory

4. 实验

环境设置完成后,再开始运行实验。实验顺序是:启动 Nav2/Gazebo,确认 ROS graph 和 TF,启动 Bridge Client,然后在浏览器里观察 Nav2 系统。

打开第一个终端,启动 Nav2/Gazebo:

bash 复制代码
source /opt/ros/humble/setup.bash

export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp
export ROS_DOMAIN_ID=22
export TURTLEBOT3_MODEL=waffle

ros2 launch nav2_bringup tb3_simulation_launch.py \
  use_rviz:=True \
  headless:=False

这个 launch 会启动:

  • TurtleBot3 Waffle Gazebo 仿真。
  • Nav2 getting started demo,包括 map server、AMCL、planner、controller、behavior server、BT navigator、waypoint follower、velocity smoother 等节点。
  • nav2_lifecycle_manager,负责把 Nav2 受管节点带到 active 状态。
  • robot_state_publisher 和 Gazebo 相关节点,用于发布机器人模型、TF、仿真时钟、里程计和激光数据。

启动后设置初始位姿。Nav2 需要 map -> odom -> base_link 这条 TF 链,AMCL 收到初始位姿后才会稳定发布 map -> odom

4.2 启动 Phantom Bridge 并打开 Web UI

如果你已经把当前用户加入 docker 组并重新登录,可以不使用 sudo

bash 复制代码
docker compose up phntm_bridge

如果首次运行时 Bridge Client 因为安装 extra_packages 后退出,重新执行一次:

bash 复制代码
docker compose up phntm_bridge

注册生成的 ~/phntm_bridge.yaml 顶部会包含机器人的 Web UI 地址,格式类似:

text 复制代码
https://bridge.phntm.io/%YOUR_ID_ROBOT%

浏览器打开这个地址后,应该能看到 Phantom Bridge UI 连接到本文启动的 Nav2/Gazebo 系统。

4.4 在 Web UI 中验证

打开 Web UI 后,可以按下面顺序验证。

Graph View:确认 Nav2 系统被发现

Nodes & Topics 菜单中打开 Graph View。左边应能看到 Nav2、Gazebo、robot_state_publisher 等节点,右边能看到 /tf/scan/odom/map、costmap、planner/controller 相关 topic。Graph View 的价值是快速确认两个问题:

  • Bridge Client 是否和 Nav2 处在同一个 ROS graph 中。
  • topic 的 publisher/subscriber 和 QoS 是否存在明显 mismatch。

World Model 3D:看机器人模型和激光

官方内置的 World Model 3D widget 会读取 /robot_description,再根据 /tf_static/tf 更新机器人姿态。它还支持 LaserScan overlay,可以把 /scan 映射到机器人模型对应 frame 上。

Nav2 service:观察和调用

Services 菜单中可以看到自动发现的 ROS service 和 action。Phantom Bridge 支持给复杂 service/action 定义 JSON payload,并保存成按钮。

对 Nav2 demo,可以关注:

  • /navigate_to_pose
  • /navigate_through_poses
  • /follow_waypoints
  • lifecycle manager 相关 service

Runtime Parameters:看 Nav2 参数

Graph View 中节点名旁边的参数图标可以打开 Runtime Parameter Inspector。对 Nav2 来说,这适合观察 planner、controller、costmap、bt_navigator、waypoint_follower 等节点的运行时参数。

这比在远程终端里反复运行 ros2 param list/get 更直接,尤其适合演示"远程调试和 observability"这一类能力。

5. 工具对比

Phantom Bridge 和几类已有工具有关系,但关注点不同。

工具/工作 重点 和 Phantom Bridge 的关系
RViz 本地 ROS 可视化和调试 Phantom Bridge 在远程浏览器场景下补充/部分替代 RViz,但不等于完整替代 RViz 插件生态。
rosbridge / Robot Web Tools WebSocket/JSON,把 ROS 带进浏览器 Phantom Bridge 继承"ROS to Web"的方向,但用 WebRTC/H.264/Socket.io 做更低延迟和媒体友好的方案。
Foxglove Bridge 高性能 WebSocket 数据观察链路 更偏数据可视化和 observability;Phantom Bridge 更强调遥操作、视频和运维一体化。

6. 编译问题备忘

本仓库前面验证 phntm_bridge_client 时遇到过一个接口漂移问题,可以作为从源码构建时的排查线索。

Dockerfile 会拉最新的 phntm_interfaces main,但最新接口仓库已经把旧的:

text 复制代码
phntm_interfaces/srv/FileRequest

删掉了,改成新的 message 接口:

text 复制代码
phntm_interfaces/msg/FileExtractionRequest
phntm_interfaces/msg/FileExtractionResult

而当时 phntm_bridge_client main 代码还在 include 旧头文件:

cpp 复制代码
#include "phntm_interfaces/srv/file_request.hpp"

所以编译时会报:

text 复制代码
fatal error: phntm_interfaces/srv/file_request.hpp: No such file or directory

当时的解决方法是直接用 dev 分支构建:

bash 复制代码
git fetch origin dev
git checkout dev

ROS_DISTRO=humble
docker build -f Dockerfile -t phntm/bridge:$ROS_DISTRO --build-arg ROS_DISTRO=$ROS_DISTRO .

如果之后再次复现,应优先检查 phntm_bridge_clientphntm_interfacesphntm_agent 三个仓库的接口版本是否匹配,而不是只看最后的编译错误。若只是按本文教程体验 Nav2 可视化,优先使用官方预构建镜像会更省事。

参考

相关推荐
换个昵称都难1 小时前
WebRTC QoS 实战:从原理到弱网优化
开发语言·php·webrtc
jinxindeep2 小时前
Dexterity-BEV:跨本体&跨相机&Action三维空间对齐,推动通用机器人策略学习
数码相机·学习·机器人
Linlingu3 小时前
OpenClaw接入钉钉企业内部机器人完整实操教程(Stream模式无公网部署)
人工智能·windows·机器人·钉钉·办公自动化·小龙虾
@Ma3 小时前
企业微信外部群机器人接入 AI:调用API接口自动回复 实战
人工智能·机器人·企业微信
中讯慧通3 小时前
微型无人机通信模块:低空链路核心,保障飞行与传输全程稳定
服务器·人工智能·机器人·无人机
kyle~3 小时前
工业机械臂---TCP标定验收
机器人·ros2·标定
Deepoch13 小时前
Deepoc VLA开发板:采摘机器人的环境鲁棒作业与不确定性应对
人工智能·机器人·采摘机器人·deepoc
WWZZ202513 小时前
宇树B2/W开发部署1:入门篇
机器人·具身智能·宇树·b2-w
换个昵称都难13 小时前
webrtc 视频传输Flexfec模块
音视频·webrtc