Skip to content

Repository files navigation

Eurobot Web

A web dashboard built for Eurobot robot competitions, focused on robot status monitoring and strategy selection.

GitHub starsLicense: MITEurobot

Robot Status
Robot Status
ROS status, startup groups, battery, SIMA, parameters
Playmat
Playmat
Mission buttons, sequence planning, live score
Control Panel
Control Panel
Layout, theme, SIMA names, backup, assets

FeaturesROS Bridge InterfacesAPI And Config FilesGetting StartedDeploymentDevelopment


Features

Eurobot 2026 Web is a React dashboard for the robot-side screen, laptop, iPad, or dual-monitor pit setup. It connects to ROS 2 through rosbridge, persists competition parameters in /home/share/data, and keeps local UI assets such as robot GLB files and sponsor logos in browser storage.

The app has three primary panels:

PanelCurrent functionality
Robot StatusROS bridge connection state, battery voltage, USB device status, startup plug signal, startup group state, game time, game score, SIMA online status, game ready/service call controls, game start publisher, on-take test publisher, rival/dock/nav/SIMA/robot-config parameter editing, sponsor fullscreen overlay, robot 3D preview.
Playmat2026 field visualization, 18 mission buttons, click order sequence, plan import, saved plans in browser storage, live estimated score from ROS, selected plan service server for the robot startup flow.
Control PanelHalf-screen layout toggle, active panel selection, theme accent, BMS hostname, playmat background selection, SIMA instance-name whitelist editing, browser backup/restore ZIP, factory reset for browser data, IndexedDB manager for GLB models and sponsor logos.

ROS Bridge Interfaces

The frontend loads roslibjs as a static script (index.html/lib/roslib.min.js), which exposes window.ROSLIB. React code uses that global through src/utils/useRosConnection.ts (and a few components that read window.ROSLIB directly). The bridge URL is fixed in code as:

ws://localhost:9090

roslib bundle (maintenance)

  • *.min.js: minified build (smaller download; same runtime behavior as the non-minified bundle for a given release).

  • Stay on roslib 1.x for this app. The checked-in file matches the classic browser bundle (global ROSLIB, Ros / Topic / Service APIs). On npm, the latest tag is roslib 2.x, which ships as ES modules for bundlers and is not a drop-in replacement for a single script tag; migrating would mean importing from roslib in Vite, removing the global, and re-testing every bridge call.

  • Stability: Prefer pinning to a known 1.x release (for example 1.4.1) rather than chasing latest on npm. Optional refresh from CDN (run at repo root):

    curl -fsSL -o public/lib/roslib.min.js 'https://unpkg.com/roslib@1.4.1/build/roslib.min.js'

    To follow the newest 1.x line without editing the URL on each patch release, you can use roslib@1 instead of 1.4.1 in that path.

Use this section as the rosbridge whitelist reference.

Whitelist Summary

Topics:

/robot_status/battery_voltage
/robot_status/usb/chassis
/robot_status/usb/mission
/robot_status/usb/lidar
/robot_status/usb/esp
/robot_status/usb/imu
/robot/startup/plug
/robot/startup/groups_state
/robot/startup/game_time
/game_score
/score
/robot/startup/ideal_score
/<sima_name>/status
/robot/on_put

Services:

/robot/startup/ready_signal
/robot/startup/web_plan

Replace /<sima_name>/status with the exact SIMA names configured in Control Panel, for example /sima_01/status.

Subscribed Topics

TopicTypeUsed byContent / behavior
/robot_status/battery_voltagestd_msgs/msg/Float32Robot StatusBattery voltage. Display is smoothed and considered stale after 8 seconds without messages.
/robot_status/usb/chassisstd_msgs/msg/BoolRobot StatusChassis STM32 USB/device connectivity.
/robot_status/usb/missionstd_msgs/msg/BoolRobot StatusMission STM32 USB/device connectivity.
/robot_status/usb/lidarstd_msgs/msg/BoolRobot StatusLiDAR connectivity.
/robot_status/usb/espstd_msgs/msg/BoolRobot StatusESP32 connectivity.
/robot_status/usb/imustd_msgs/msg/BoolRobot StatusIMU connectivity.
/robot/startup/plugstd_msgs/msg/BoolRobot StatusStartup plug/ready signal. true marks connected and expires after 5 seconds without another true; false clears immediately.
/robot/startup/groups_statestd_msgs/msg/Int32MultiArrayRobot StatusStartup group states in order: MAIN, VISION, NAVIGATION, LOCALIZATION. UI maps 0 to yellow, 3 to green, missing/other values to red.
/robot/startup/game_timestd_msgs/msg/Float32Robot StatusCurrent match/game time value.
/game_scorestd_msgs/msg/Int32Robot Status, PlaymatCurrent game score. Also drives Playmat estimated score.
/scorestd_msgs/msg/Int32PlaymatPrimary live score source. If no recent message is seen, Playmat falls back to startup ideal score.
/robot/startup/ideal_scorestd_msgs/msg/Int32PlaymatFallback estimated score from the main startup process.
/<sima_name>/statusstd_msgs/msg/BoolRobot StatusDynamic SIMA online status. Names come from Control Panel localStorage key sima-instance-names; defaults are sima_01 through sima_08. A SIMA is considered stale after 1.3 seconds.

Published Topics

TopicTypePublished byPayload
/robot/startup/plugstd_msgs/msg/BoolRobot StatusPublishes { data: true } when Game Start is triggered.
/robot/on_putstd_msgs/msg/Int16Robot StatusHW Test publishes four messages at 400 ms intervals with data in 03.

Service Clients

ServiceTypeCalled byRequest / response handling
/robot/startup/ready_signalbtcpp_ros2_interfaces/srv/StartUpSrvRobot StatusCalled four times for groups 1 to 4 with { group: gid, state: 1 }. Response is expected to include { group, success }; the UI logs a warning if the response group differs or success=false, then continues to the next group.

Service Servers Advertised By The Web UI

ServiceTypeAdvertised byResponse
/robot/startup/web_planstd_srvs/srv/TriggerPlaymatReturns success=true; message is the selected plan id as a string, or "0" if no plan is selected.

API And Config Files

The Express API lives in src/api/index.js and is mounted under /api by src/server.js. Data is stored in /home/share/data; production Compose mounts that directory from the host.

REST API

MethodPathBacking filePurpose
GET/api/rival-radiusrival_params.yamlRead nav_rival_parameters.rival_inscribed_radius in meters. Frontend displays centimeters.
POST/api/rival-radiusrival_params.yamlUpdate rival radius, clamped to 0.0 to 0.5 m. Body: { "radius": number }.
GET/api/dock-rival-paramsrival_params.yamlRead dock_rival_radius and dock_rival_degree.
POST/api/dock-rival-paramsrival_params.yamlUpdate dock rival radius and degree. Radius is clamped to 0.0 to 0.5 m; degree to 0 to 360.
GET/api/nav-params?profile=<name>nav_<profile>_params.yamlRead navigation max linear/angular velocity for didilong, fast, slow, linearBoost, or angularBoost.
POST/api/nav-paramsnav_<profile>_params.yamlUpdate navigation profile. Body: { "profile": string, "linearVelocity": number, "angularVelocity": number }. Linear is clamped to 0.1 to 1.6; angular to 1.0 to 15.0.
GET/api/sima-paramssima.jsonRead sima_start_time and plan_code.
POST/api/sima-paramssima.jsonUpdate SIMA start time and plan code. Body: { "sima_start_time": number, "plan_code": number }.
GET/api/button-statesbutton.jsonRead playmat button states, flat sequence, and derived pantry_sequence / collection_sequence.
POST/api/button-statesbutton.jsonUpdate playmat button states and sequence. Mission arrays are derived from the flat sequence.
GET/api/robot-configrobot_config.yamlRead supported ROS parameter fields from /**.ros__parameters. Falls back to legacy robot_config_black.yaml if present.
POST/api/robot-configrobot_config.yamlUpdate supported robot config parameters and remove robot_name from the YAML.
GET/api/mission-sequencebutton.jsonRead pantry/collection sequence. Legacy mission_sequence.json or mission_sequence_black.json is migrated into button.json when needed.
POST/api/mission-sequencebutton.jsonStore manual pantry/collection sequence in button.json.
POST/api/reset-to-defaultsall server-side config filesReset rival, nav, SIMA, robot config, and playmat/mission state to defaults.

YAML / JSON Files

rival_params.yaml

nav_rival_parameters:
rival_inscribed_radius: 0.22dock_rival_parameters:
dock_rival_radius: 0.46dock_rival_degree: 120

Navigation profiles:

Filemax_linear_velocitymax_angular_velocity
nav_didilong_params.yaml1.51.0
nav_fast_params.yaml1.112.0
nav_slow_params.yaml0.82.0
nav_linearBoost_params.yaml1.12.0
nav_angularBoost_params.yaml0.512.0

robot_config.yaml

/**:
ros__parameters:
pantry_aggressiveness: 0.0pantry_sensitivity: 2.0pantry_rival_sigma: 0.3pantry_rival_distance_threshold: 0.3collection_aggressiveness: 0.0collection_sensitivity: 2.0collection_rival_sigma: 0.3collection_rival_distance_threshold: 0.3flip_distance_threshold: 0.1cursor_tolerance: 0.18

sima.json

{
"sima_start_time": 85,
"plan_code": 1
}

button.json

{
"states": {
"0": false,
"1": false
},
"sequence": [],
"pantry_sequence": [],
"collection_sequence": []
}

Getting Started

Prerequisites

  • Docker and Docker Compose
  • ROS 2 with rosbridge_server
  • A rosbridge websocket available at ws://localhost:9090

Run With Docker

  1. Clone and enter the repo:

    git clone -b Eurobot-2026 https://github.com/DIT-ROBOTICS/Eurobot-Web.git
    cd Eurobot-Web
  2. Start the development container:

    docker compose -f docker-compose.dev.yml up -d
  3. Open the app:

    ServiceURL
    Frontend dev serverhttp://localhost:5173
    Express APIhttp://localhost:3001/api
    ROS bridge websocketws://localhost:9090

Start ROS Bridge

sudo apt install ros-<distro>-rosbridge-server
ros2 launch rosbridge_server rosbridge_websocket_launch.xml

Deployment

Development

docker compose -f docker-compose.dev.yml up -d
docker compose -f docker-compose.dev.yml logs -f app-dev
docker compose -f docker-compose.dev.yml down

The dev Compose file uses host networking and starts both the Express API and Vite dev server:

bun install && node src/server.js & bun run dev -- --host 0.0.0.0

Production

Images are published to GHCR by .github/workflows/docker-build-and-push.yml on pushes to eurobot-YYYY / Eurobot-YYYY (for example Eurobot-2026). The image tag is only the year (:2026, not latest). Match that on the machine that runs Compose, for example:

export EUROBOT_IMAGE_TAG=2026 # optional; default in compose is 2026 for this branch
docker compose pull && docker compose up -d
docker compose logs -f eurobot-2026-web
docker compose down

Production runs a built React app behind Nginx, keeps the API server available, uses host networking, and persists server-side config through:

/home/share/data:/home/share/data

Development

Stack

AreaTechnology
FrontendReact 19, TypeScript, Vite
StylingTailwind CSS 4, Radix UI, Lucide React, React Icons
ROS bridgeroslib 1.x browser bundle (public/lib/roslib.min.js, window.ROSLIB) over WebSocket
API serverExpress, js-yaml
3D assetsmodel-viewer, Three.js / React Three Fiber dependencies
Browser storagelocalStorage, IndexedDB, JSZip backup/restore
DeploymentDocker, Docker Compose, Nginx

Useful Commands

npm run dev
npm run build
npm run lint
npm run server

Browser-Side Data

The Control Panel can export and restore browser-local data as eurobot-web-backup_YYYYMMDD.zip. The backup includes selected localStorage keys, custom robot GLB files, and sponsor logos. Server-side /home/share/data YAML/JSON files are not included in that browser backup.

Important localStorage keys include:

KeyPurpose
sima-instance-namesDynamic SIMA topic names used for /<name>/status.
bms-hostnameBMS/ESP hostname shown in the UI.
playmat-background-idActive playmat background.
savedPlansPlaymat plan presets.
activePanel, verticalPanel, isHalfScreenLayout state.

License

License: MIT

This project is licensed under the MIT License.

About

Web dashboard for Eurobot competitions: robot status monitoring, playmat & mission planning.

Topics

Resources

Stars

7 stars

Watchers

0 watching

Forks

Releases

Packages

Used by

Contributors

Languages