Files
ros-raspbot-v2/webui

Raspbot Web UI

Browser-based controller for the Raspbot V2. Displays a live WebRTC camera feed and provides keyboard / on-screen controls for robot movement and camera pan/tilt.

Architecture

Browser
  │
  ├─── WebSocket /ws ──────────► FastAPI backend (port 8080)
  │                                   │
  │                                   └─ rclpy node
  │                                       ├─ publishes /cmd_vel
  │                                       ├─ publishes /joint_command
  │                                       ├─ subscribes /joint_states
  │                                       └─ subscribes /ultrasonic/range
  │
  └─── WebSocket ws://<host>:8443 ──► GStreamer WebRTC server (separate container)

The FastAPI backend is the ROS 2 node — no rosbridge needed. The Vite/React frontend is built into static files and served directly by FastAPI in production.

ROS topics

Direction Topic Type
Publish /cmd_vel geometry_msgs/Twist
Publish /joint_command sensor_msgs/JointState (joints: pan, tilt)
Subscribe /joint_states sensor_msgs/JointState
Subscribe /ultrasonic/range sensor_msgs/Range

Controls

Input Action
W / ↑ Drive forward
S / ↓ Drive backward
A / ← Turn left
D / → Turn right
Pan slider Camera pan (±90°)
Tilt slider Camera tilt (30° to +55°)
Centre button Return camera to home position

The D-pad buttons on screen mirror the keyboard controls and work on touch devices.


Development (devcontainer)

Running locally in the devcontainer gives a fast edit → reload loop without needing to rebuild Docker images.

Prerequisites

Rebuild the devcontainer at least once after the Node.js addition to .devcontainer/Dockerfile was made — VS Code will prompt you, or run Dev Containers: Rebuild Container from the command palette.

Running

./webui/dev.sh

Then open http://localhost:5173.

The script will:

  • Create a Python venv at webui/backend/.venv (first run only)
  • Install backend and frontend dependencies
  • Start the FastAPI backend on port 8080
  • Start the Vite dev server on port 5173, proxying /ws to the backend

Both processes are stopped together with Ctrl+C.

ROS domain ID

The devcontainer uses ROS_DOMAIN_ID=42 by default, but the robot and lidar containers default to 0. Override when running the script to match whichever domain the robot is on:

ROS_DOMAIN_ID=0 ./webui/dev.sh

WebRTC camera

The camera feed connects to the GStreamer signaling server at ws://<hostname>:8443 by default. If your WebRTC container runs on a different host or port, set VITE_WEBRTC_WS_URL before starting the frontend (it is baked into the bundle at build time, but the dev server reads it from the shell):

VITE_WEBRTC_WS_URL=ws://raspbot-v2.local:8443 ./webui/dev.sh

Production (Docker Compose)

Build

docker compose build webui

To bake a specific WebRTC server URL into the bundle:

VITE_WEBRTC_WS_URL=ws://raspbot-v2.local:8443 docker compose build webui

Run

docker compose up webui

Or start everything together:

docker compose up

The web UI is served on port 8080 of the host.

Configuration

Variable Default Description
ROS_DOMAIN_ID 0 ROS 2 DDS domain — must match the robot container
VITE_WEBRTC_WS_URL ws://<page-hostname>:8443 WebRTC signaling server URL (baked in at build time)
CAMERA_DEVICE 0 (unused in production — camera is handled by the WebRTC container)