Robot Data Closed-Loop Platform · Live Monitor · Data Replay · Parameter Management · Automated Testing
Quick Start · Architecture · Features · v3.0 Backend · API Reference · Setup · Structure
AimScope is a browser-based real-time debugging & data management dashboard for robotic aiming systems, built for the RoboMaster competition. It connects to ROS via rosbridge WebSocket and provides live visualization — plus an enterprise backend stack for data replay, parameter version control, and automated benchmark testing.
- Zero-install frontend — open a browser tab, connect, and you're live
- ROS1 + ROS2 dual support — one dashboard works with both, auto-detected
- Windows + WSL hybrid — camera on Windows, ROS & backend in WSL2
- v3.0 backend stack — Spring Boot + MariaDB + InfluxDB + Redis for data persistence and analysis
- Recording & playback —
.aimscope.jsonrecordings with frame-by-frame review - Dark/light theme — toggle with
T
No backend needed — just the real-time ROS dashboard.
Prerequisites: WSL2 with ROS + rosbridge, Python 3 on Windows with opencv-python.
Terminal 1 (WSL) — 一键启动 rosbridge + Web 服务器:
cd /mnt/d/AimScope
bash scripts/start_all.sh --ros1 # ROS1 模式
# bash scripts/start_all.sh --ros2 # ROS2 模式Terminal 2 (Windows PowerShell) — 数据源(三选一):
# 场景 1: 纯合成画面, 无需摄像头 (测 UI)
python D:\AimScope\tools\publishers\aimscope_demo_windows_rosbridge_camera.py --ros-version ros1 --no-camera
# 场景 2: 电脑摄像头 (测完整链路)
python D:\AimScope\tools\publishers\aimscope_demo_windows_rosbridge_camera.py --ros-version ros1
# 场景 3: 实际仿真 — 不需要运行此脚本, ROS 仿真环境会自行发送数据Open http://127.0.0.1:9006/index.html, set ROS type to match, address to ws://127.0.0.1:9090, click 连接.
场景说明:
场景 WSL 命令 PowerShell 命令 何时使用 合成测试 bash scripts/start_all.shpython ... --no-camera无摄像头, 测 UI 功能 摄像头测试 bash scripts/start_all.shpython ...有摄像头, 测完整链路 实际仿真 bash scripts/start_all.sh(无需运行) ROS/Gazebo 仿真, 真实数据
Includes backend for data replay, parameter management, and automated testing.
# Terminal 1 (WSL) — 一键启动 rosbridge + Web + Spring Boot 后端
cd /mnt/d/AimScope
bash scripts/start_all.sh --ros1 --backend
# Terminal 2 (WSL) — 启动数据库 (首次需安装)
bash /mnt/d/AimScope/scripts/wsl_install_dbs.sh
# 日常启动:
sudo service mariadb start && sudo service redis-server start && sudo service influxdb start
# Terminal 3 (PowerShell) — 数据源 (可选, 同 Option A)
python D:\AimScope\tools\publishers\aimscope_demo_windows_rosbridge_camera.py --ros-version ros1Open http://127.0.0.1:9006/index.html. The v3.0 tabs appear in the top navigation bar.
First-time database setup: After installing databases, run:
sudo mariadb -e "CREATE DATABASE IF NOT EXISTS aimscope CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;" sudo mariadb -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'aimscope'; FLUSH PRIVILEGES;" influx setup --username admin --password AimScope2024! --org aimscope --bucket aimscope --token aimscope-influx-token-dev-2024 --force
┌──────────────────────────────────────────────────────────────────────┐
│ Windows (Host) │
│ ┌─────────────────────┐ ┌──────────────────────────────────────┐ │
│ │ Browser │ │ Python: Camera Publisher │ │
│ │ Vue 3 SPA │ │ reads webcam → publishes via WS │ │
│ │ + roslib.js │ │ │ │
│ │ + Three.js (3D) │ └──────────────┬───────────────────────┘ │
│ │ + Canvas charts │ │ │
│ └──────┬───────┬───────┘ │ │
│ │ :9006 │ :8080 │ :9090 │
│ │ │ │ │
│ ┌──────┴───────┴──────────────────────────┴───────────────────────┐ │
│ │ WSL2 (Ubuntu 22.04) │ │
│ │ ┌──────────────────┐ ┌────────────────────────────────────┐ │ │
│ │ │ Static Server │ │ Spring Boot Backend (:8080) │ │ │
│ │ │ Python HTTP :9006 │ │ │ │ │
│ │ │ (or TinyWebServer)│ │ ┌──────────────────────────────┐ │ │ │
│ │ └──────────────────┘ │ │ JWT Auth · REST API │ │ │ │
│ │ │ │ WebSocket relay → rosbridge │ │ │ │
│ │ ┌──────────────────┐ │ │ @Async: rosbag parse, benchmark│ │ │ │
│ │ │ rosbridge (:9090) │ │ └──────────┬───────────────────┘ │ │ │
│ │ │ ROS ↔ WebSocket │ │ │ │ │ │
│ │ └────────┬─────────┘ │ ┌─────────┼─────────┐ │ │ │
│ │ │ │ │ │ │ │ │ │
│ │ ┌──────┴──────┐ │ ┌──┴──┐ ┌───┴───┐ ┌──┴──┐ │ │ │
│ │ │ ROS2 Nodes │ │ │MariaDB│ │InfluxDB│ │Redis │ │ │ │
│ │ │ (optional) │ │ │users, │ │ROS data│ │session│ │ │ │
│ │ └─────────────┘ │ │params,│ │(ns ts) │ │cache │ │ │ │
│ │ │ │replays│ │ │ │ │ │ │ │
│ │ │ └──────┘ └────────┘ └──────┘ │ │ │
│ │ │ │ │ │
│ │ │ ┌──────────────────────────────┐ │ │ │
│ │ │ │ Python Tools (subprocess) │ │ │ │
│ │ │ │ rosbag_converter.py │ │ │ │
│ │ │ │ rule_engine.py │ │ │ │
│ │ │ │ benchmark_runner.py │ │ │ │
│ │ │ └──────────────────────────────┘ │ │ │
│ │ └────────────────────────────────────┘ │ │
│ └─────────────────────────────────────────────────────────────────┘ │
└──────────────────────────────────────────────────────────────────────┘
Live mode: Camera/ROS → rosbridge :9090 → roslib.js (Browser)
rosbridge :9090 → Spring Boot WebSocket proxy :8080/ws/ros → Browser
Replay mode: Browser slider → REST API → InfluxDB query → JSON → Canvas charts
Params: Browser editor → REST API → write file → git commit → version history
Benchmark: Browser submit → @Async Python runner → metrics JSON → MySQL → report
- Two synchronized canvases: Raw and Result (reprojection overlay)
- JPEG decoded from rosbridge Base64 transport
- FPS counter and latency metrics per stream
- IMU attitude (Roll / Pitch / Yaw) — red, green, blue traces
- Aim angle (X / Y / Z) — yellow traces
- Debug values — orange traces
- Zoom (scroll), pan (drag), auto-range, lockable Y-axis
- Three.js scene with gimbal model + target sphere
- Orbit controls (mouse drag/wheel), driven by live IMU data
- Per-topic: Hz, latency, age, message size, state (ok/warn/alarm)
- Color-coded status dots, click to inspect full JSON payload
- Deduplicated event log with error/warn/info levels
- Alarm counter with summary display
- Record all ROS topic data to
.aimscope.json - Playback toolbar: play/pause, frame stepping, speed 0.25×–4×
- Timeline slider, markers, 5-second clip export
- Auto-generated Markdown test report
AimScope v3.0 adds a Java SpringBoot backend with databases for enterprise-grade robot data management. The v2.x live monitoring dashboard remains functional as the "实时监控" tab.
| Tab | Function | Auth |
|---|---|---|
| 实时监控 | Live ROS monitoring (v2.x UI, unchanged) | None |
| 数据回放 | Upload rosbag/JSON, query InfluxDB, timeline replay | TESTER+ |
| 参数管理 | YAML/JSON editor, Git version control, diff view, rollback | TESTER+ |
| 自动化测试 | A/B benchmark runs, comparison reports | ENGINEER |
| Component | Technology |
|---|---|
| Framework | Spring Boot 2.7.18 |
| Java | OpenJDK 11 |
| Database | MariaDB 10.6 (JPA/Hibernate) |
| Time-series | InfluxDB 2.7 |
| Cache | Redis 6.0 |
| Auth | JWT (io.jsonwebtoken 0.11.5) |
| Version control | JGit (org.eclipse.jgit 6.8.0) |
| Build | Maven 3.9+ |
| Python tools | rosbag converter, rule engine, benchmark runner |
- Upload — rosbag (.bag/.mcap) or AimScope recordings via browser drag-and-drop
- Parse — Python
rosbag_converter.pywrites to InfluxDB (@Async, non-blocking, progress via Redis) - Query —
GET /api/replay/{id}/data?topic=X&from=0&to=5000returns millisecond-precise data - Analyze — Rule engine detects:
- Vision loss (>500ms gap in tracking results)
- Overshoot (3+ consecutive frames exceeding threshold)
- IMU anomaly (30° jump in roll/pitch/yaw)
- Data dropout (>1s gap in any topic)
- Editor — In-browser YAML/JSON editor with syntax highlighting, line numbers, Tab/Ctrl+S support
- Git versioning — Every save =
git commitvia JGit. Full history, rollback to any version - Diff — LCS-based side-by-side comparison with add/remove highlighting, synchronized scroll
- Roles — ENGINEER (read/write), TESTER (read-only for sensitive params)
- A/B comparison — Compare two parameter sets against the same rosbag replay
- Metrics — detection_rate, reprojection_error, avg_latency_ms, fps, cpu_usage
- Report — Auto-generated Markdown comparison table with winner determination
| Method | Path | Body | Response | Auth |
|---|---|---|---|---|
| POST | /api/auth/register |
{username, password, role} |
{token, role} |
None |
| POST | /api/auth/login |
{username, password} |
{token, role} |
None |
| GET | /api/auth/me |
— | {id, username, role} |
JWT |
Roles: TESTER (default, can view replay/params), ENGINEER (full access including benchmark + param editing)
| Method | Path | Description | Auth |
|---|---|---|---|
| GET | /api/params/ |
List all configs | TESTER+ |
| POST | /api/params/ |
Create config | ENGINEER |
| GET | /api/params/{id} |
Get latest version | TESTER+ |
| PUT | /api/params/{id} |
Update (new git version) | ENGINEER |
| GET | /api/params/{id}/versions |
Version history | TESTER+ |
| GET | /api/params/{id}/versions/{vid} |
Get specific version | TESTER+ |
| POST | /api/params/{id}/rollback/{vid} |
Rollback to version | ENGINEER |
| GET | /api/params/{id}/diff?v1=&v2= |
Side-by-side diff | TESTER+ |
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /api/replay/upload |
Upload rosbag/JSON (multipart) | TESTER+ |
| GET | /api/replay/sessions |
List replay sessions | TESTER+ |
| GET | /api/replay/{id} |
Session detail + topic list | TESTER+ |
| GET | /api/replay/{id}/data?topic=&from=&to= |
Query time-series data | TESTER+ |
| GET | /api/replay/{id}/events?from=&to= |
Query analysis events | TESTER+ |
| GET | /api/replay/{id}/progress |
Parse progress | TESTER+ |
| DELETE | /api/replay/{id} |
Delete session + data | TESTER+ |
| Method | Path | Description | Auth |
|---|---|---|---|
| POST | /api/benchmark/ |
Create run {name, replayId, configAId, configBId} |
ENGINEER |
| GET | /api/benchmark/ |
List all runs | TESTER+ |
| GET | /api/benchmark/{id} |
Run detail + metrics | TESTER+ |
| GET | /api/benchmark/{id}/report |
Download Markdown report | TESTER+ |
| Method | Path | Description |
|---|---|---|
| WS | /ws/ros |
Browser connects here, backend relays to rosbridge :9090 |
| Component | Requirement |
|---|---|
| OS | Windows 10/11 + WSL2 |
| WSL | Ubuntu 22.04 |
| Java | OpenJDK 11 (for backend) |
| Databases | MariaDB 10.6, Redis 6.0, InfluxDB 2.7 |
| ROS | ROS2 Humble (recommended) or ROS1 Noetic |
| Python (Windows) | 3.8+ with opencv-python, numpy, websocket-client |
| Browser | Chrome/Edge (any modern browser) |
# All-in-one install script:
bash /mnt/d/AimScope/scripts/wsl_install_dbs.sh
# Or step-by-step:
sudo apt-get update
sudo apt-get install -y mariadb-server redis-server
# InfluxDB 2.x (via deb package if GPG key fails)
wget https://dl.influxdata.com/influxdb/releases/influxdb2_2.7.11-1_amd64.deb
sudo dpkg -i influxdb2_2.7.11-1_amd64.deb
# Setup databases
sudo mariadb -e "CREATE DATABASE IF NOT EXISTS aimscope CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;"
sudo mariadb -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'aimscope'; FLUSH PRIVILEGES;"
influx setup --username admin --password AimScope2024! --org aimscope --bucket aimscope --token aimscope-influx-token-dev-2024 --forcesudo apt install -y ros-humble-rosbridge-suite
# Or: bash /mnt/d/AimScope/scripts/ros2/install_ros2_rosbridge.shpython -m pip install opencv-python numpy websocket-client| Key | Action |
|---|---|
R |
Toggle recording |
Space |
Play / pause playback |
← / → |
Seek back/forward 5 seconds |
1 |
Raw camera view |
2 |
Result/reprojection view |
3 |
3D visualization |
T |
Toggle dark/light theme |
Escape |
Exit playback mode |
AimScope/
│
├── TinyWebServer-master/ # Static file server + frontend
│ ├── root/ # Vue 3 SPA root
│ │ ├── index.html # Main page — top tabs, panels, modals
│ │ ├── app.js # Core logic — ROS, tabs, auth, replay, params, benchmark
│ │ ├── roslib.min.js # Browser ↔ rosbridge WebSocket client
│ │ ├── favicon.ico
│ │ ├── assets/
│ │ │ ├── css/
│ │ │ │ └── aimscope.css # Full stylesheet (dark/light themes, tabs, panels)
│ │ │ └── js/
│ │ │ ├── api/ # REST API clients
│ │ │ │ ├── auth-api.js # JWT login/register/me
│ │ │ │ ├── param-api.js # Param CRUD + versions + diff
│ │ │ │ ├── replay-api.js # Replay upload + query
│ │ │ │ └── benchmark-api.js # Benchmark create + report
│ │ │ ├── ui/ # UI components
│ │ │ │ ├── interactive-chart.js # Canvas-based zoomable charts
│ │ │ │ ├── panel-resize.js # Drag-to-resize handles
│ │ │ │ ├── config-editor.js # YAML/JSON editor with syntax highlighting
│ │ │ │ └── diff-viewer.js # LCS-based side-by-side diff
│ │ │ └── core/
│ │ │ ├── namespace.js # Extension hooks & global namespace
│ │ │ └── ring-buffer.js # Fixed-length RingBuffer
│ │ └── vendor/
│ │ ├── vue.global.prod.js # Vue 3 production runtime
│ │ └── three.min.js # Three.js (lazy-loaded for 3D)
│ ├── server # Compiled binary
│ ├── webserver.cpp/.h # Core — epoll, thread pool, timer
│ ├── http/ # HTTP request/response
│ ├── threadpool/ # Thread pool
│ └── makefile # Build rules
│
├── backend/ # Spring Boot backend (v3.0)
│ ├── pom.xml
│ ├── src/main/resources/
│ │ └── application.yml # DB, JWT, InfluxDB, storage config
│ └── src/main/java/com/aimscope/
│ ├── AimScopeApplication.java
│ ├── model/entity/ # JPA entities
│ │ ├── User.java # id, username, passwordHash, role
│ │ ├── ParamConfig.java # id, name, fileType, currentContent
│ │ ├── ParamVersion.java # configId, versionNum, gitCommitHash
│ │ ├── ReplaySession.java # filename, fileHash, status, messageCount
│ │ └── BenchmarkRun.java # name, replayId, configA/B, metricsJSON
│ ├── repository/ # Spring Data JPA repositories (×5)
│ ├── security/ # JWT authentication
│ │ ├── JwtUtil.java # Token generation & validation
│ │ └── JwtFilter.java # Bearer token filter
│ ├── config/ # Spring configuration
│ │ ├── SecurityConfig.java # CORS, endpoints, JWT filter
│ │ ├── WebConfig.java # CORS whitelist
│ │ ├── InfluxDBConfig.java # InfluxDB client bean
│ │ └── WebSocketConfig.java# /ws/ros endpoint
│ ├── dto/ # Request/Response objects
│ │ ├── LoginRequest.java
│ │ ├── RegisterRequest.java
│ │ ├── ParamUpdateRequest.java
│ │ └── BenchmarkRequest.java
│ ├── service/ # Business logic
│ │ ├── AuthService.java # Register, login, BCrypt
│ │ ├── ParamService.java # CRUD + JGit versioning + diff
│ │ ├── ReplayService.java # Upload, InfluxDB query, rule engine
│ │ ├── BenchmarkService.java# @Async Python runner
│ │ └── RosRelayService.java# WebSocket proxy to rosbridge
│ └── controller/ # REST controllers
│ ├── AuthController.java
│ ├── ParamController.java
│ ├── ReplayController.java
│ └── BenchmarkController.java
│
├── scripts/
│ ├── ros2/ # ROS2 scripts
│ │ ├── install_ros2_rosbridge.sh
│ │ ├── start_ros2_rosbridge.sh
│ │ └── start_ros2_demo.sh
│ ├── windows/ # USB camera attach/detach
│ │ ├── attach_camera_to_wsl.ps1
│ │ └── detach_camera_from_wsl.ps1
│ ├── python/ # Python backend tools (v3.0)
│ │ ├── rosbag_converter.py # Rosbag → InfluxDB parser
│ │ ├── rule_engine.py # Anomaly detection rules
│ │ └── benchmark_runner.py # A/B config comparison
│ ├── start_backend.sh # Backend + DB startup
│ ├── start_tinywebserver.sh # TinyWebServer startup
│ └── wsl_install_dbs.sh # WSL database install script
│
├── tools/publishers/ # Python data publishers
│ ├── aimscope_demo_windows_rosbridge_camera.py # Windows camera → rosbridge
│ ├── aimscope_demo_ros2.py # ROS2 demo publisher
│ └── aimscope_demo.py # ROS1 demo publisher (legacy)
│
├── configs/ # Git-managed parameter files (v3.0)
│ ├── ekf_params_v1.yaml # Sample EKF parameters
│ └── pid_params_v1.yaml # Sample PID parameters
│
├── docs/ # Documentation (Chinese)
│ ├── AimScope最简启动手册.md
│ ├── AimScope使用手册.md
│ ├── AimScope环境配置文档.md
│ └── AimScope项目结构说明.md
│
├── data/recordings/ # Saved .aimscope.json files
├── .gitignore
└── README.md
.aimscope.json files use a flat time-series format:
{
"version": "2.2",
"format": "aimscope-recording",
"metadata": {
"startTime": "2026-06-10T02:57:04.577Z",
"duration": 5.1,
"includesImages": false,
"rosUrl": "ws://192.168.186.136:9090",
"recordedAt": "2026-06-10T02:57:09.678Z"
},
"topics": {
"/topic_name": [
{ "t": 0, "d": {} },
{ "t": 50, "d": {} }
]
},
"events": [],
"markers": [],
"report": {}
}AimScope provides extension points via AimScope.hooks:
// Custom topic display formatter
AimScope.registerTopicFormatter('/my_topic', function(data) {
return { title: 'My Topic', body: JSON.stringify(data, null, 2) };
});
// Custom log sink
AimScope.registerLogSink(function(entry) {
console.log('[Custom]', entry.level, entry.message);
});
// Custom panel
AimScope.registerPanel('my-panel', {
mount: function(container) { /* render */ },
unmount: function() { /* cleanup */ }
});| Layer | Technology |
|---|---|
| Frontend | Vue 3 (CDN, no build), Canvas API, WebSocket |
| ROS Bridge | roslib.js (browser ↔ rosbridge) |
| 3D | Three.js (lazy-loaded) |
| Web Server | TinyWebServer (C++17, epoll) / Python http.server |
| Backend | Spring Boot 2.7.18 + Java 11 |
| Auth | JWT (io.jsonwebtoken) + BCrypt |
| Relational DB | MariaDB 10.6 (JPA/Hibernate) |
| Time-series DB | InfluxDB 2.7 |
| Cache | Redis 6.0 |
| Version Control | JGit 6.8.0 |
| Build | Maven 3.9+, GNU Make |
| Data Sources | Python 3, OpenCV, NumPy |
| ROS | ROS2 Humble / ROS1 Noetic |
| Infrastructure | WSL2, Bash, PowerShell |
The frontend is intentionally a vanilla Vue 3 SPA — no Webpack, Vite, or npm. Vue and Three.js are vendored locally. Update app.js and refresh the browser. No build pipeline, no node_modules.
v3.0 — Robot Data Closed-Loop Platform
- v3.0 — Spring Boot backend (30 Java files), MariaDB/InfluxDB/Redis, JWT auth, 4-tab UI (实时监控/数据回放/参数管理/自动化测试), parameter management with Git version control, LCS-based diff viewer, YAML/JSON editor, rosbag upload & InfluxDB time-series replay, Python rule engine for anomaly detection, A/B benchmark comparison with auto-generated reports, WebSocket relay proxy
- v2.4 — Refined directory structure, cleaned up legacy TinyWebServer demo pages
- v2.3 — ROS1/ROS2 connection refactor, Windows camera publisher, topic status monitoring, image FPS/latency display, event log & alarms, recording/playback with frame-by-frame review, markers, segment export, test report export
- v2.2 — Image transfer bug fixes
- v2.1 — UI optimization, rqt-style plots, image recording
- v2.0 — Dashboard v2.0
- v1.0 — Initial auto-aim web debugger
AimScope is licensed under the MIT License.
The TinyWebServer component is based on qinguoyi/TinyWebServer, licensed under the Apache License, Version 2.0.
Third-party frontend libraries: Vue 3 (MIT), Three.js (MIT), roslib.js (BSD).