You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
**Live telemetry, health, and 3D pose for ROS 2 robot fleets — runnable with one command, no robot required.**
4
19
5
-
---
20
+
Ros Scope is a production-style observability platform for robot fleets. It bridges ROS 2 telemetry into a scalable time-series infrastructure and serves a live dashboard with 3D pose visualization, signal charts, per-topic health, session replay, and threshold, staleness, and anomaly alerting. The whole stack comes up with `docker compose up` and streams a synthetic fleet immediately — so you can try it without ROS installed and without hardware — then runs unchanged against a real robot via the ROS 2 bridge.
Ros Scope is a production-style observability platform for robot fleets. It bridges ROS 2 topics into a time-series database and serves a live dashboard with 3D pose, signal charts, per-topic health, and threshold + staleness alerts. The whole stack comes up with `docker compose up` and streams a synthetic fleet immediately — so you can try it without ROS installed and without hardware — then runs unchanged against a real robot via the ROS 2 bridge.
-**Live 3D pose** for the whole fleet with per-robot trajectory trails, fed by odometry over a WebSocket.
26
-
-**Streaming signal charts** (battery, CPU temperature, IMU) with history backed by TimescaleDB.
27
-
-**Topic health strip** showing the observed rate of each topic and flagging the moment one goes stale.
28
-
-**Alerting** on thresholds (battery low/critical, CPU overheat), on missing data (a sensor topic that stops arriving), and on **multivariate anomalies** — a rolling Mahalanobis-distance detector that flags unusual *combinations* of signals the fixed thresholds miss — all pushed live to the dashboard.
29
-
-**Session record & replay**: bookmark a time range, then scrub through it on a timeline (play/pause/seek/speed) with the whole dashboard — 3D trails, charts, alerts — replaying from stored data.
30
+
Modern robotic systems generate large volumes of telemetry across distributed sensors, actuators, and diagnostic channels. ROS 2 provides robust communication, but not a unified observability solution comparable to those used in cloud-native systems. Ros Scope closes that gap by applying observability principles from distributed systems to robotics: real-time fleet monitoring, historical telemetry storage, topic-health analysis, event-driven alerting, session record/replay, and hardware-independent reproducibility.
30
31
31
-
## Architecture
32
+
## 🏗 Architecture
32
33
33
34
```mermaid
34
35
flowchart LR
@@ -66,35 +67,58 @@ flowchart LR
66
67
67
68
The design decision worth calling out: **ingestion is separated from serving.** A Redis Stream absorbs sensor-rate bursts, a dedicated worker drains it with batched inserts, and the API only reads — so write throughput and the web tier scale independently. Full rationale in [`docs/architecture.md`](docs/architecture.md).
| Frontend | Three.js (3D pose), µPlot (charts), vanilla ES — no build step |
78
-
| Infra | Docker Compose, multi-service, health-gated startup |
72
+
-**Fleet monitoring** — real-time status across multiple robots, with online/offline detection and fleet-wide KPIs.
73
+
-**3D pose visualization** — live robot positions with historical trajectory trails in a shared scene.
74
+
-**Telemetry analytics** — battery, CPU temperature, and IMU signals with history backed by TimescaleDB and 1-second rollups.
75
+
-**Alert engine** — threshold rules, topic staleness/missing-data detection, and **multivariate anomaly detection** (rolling Mahalanobis distance) that flags unusual *combinations* of signals the thresholds miss.
76
+
-**Session record & replay** — bookmark a time range, then scrub through it on a timeline (play/pause/seek/speed) with the whole dashboard replaying from stored data.
77
+
-**Self-observable** — a Prometheus `/metrics` endpoint so Ros Scope can be scraped and graphed in Grafana like any production service.
79
78
80
-
## Quickstart
79
+
## 🔌 API
80
+
81
+
| Method | Path | Purpose |
82
+
|--------|------|---------|
83
+
| GET |`/api/summary`| Fleet KPIs: robots online, active alerts, lowest battery |
84
+
| GET |`/api/robots`| Known robots with first/last-seen timestamps |
85
+
| GET |`/api/topics?robot_id=`| Topics & metrics seen for a robot |
86
+
| GET |`/api/series?robot_id=&metric=&minutes=`| Metric history (raw, or 1s rollup for long windows) |
87
+
| GET |`/api/poses?robot_id=&seconds=`| Recent pose samples |
88
+
| GET |`/api/alerts?limit=`| Most recent alerts |
89
+
| GET |`/api/health`| Per-topic observed rate and last-seen |
90
+
| POST |`/api/sessions/start`| Begin recording (bookmarks a time range) |
91
+
| POST |`/api/sessions/{id}/stop`| End a recording |
92
+
| GET |`/api/sessions`| List recorded sessions |
93
+
| GET |`/api/sessions/{id}/data`| Replay payload (pose trails, series, alerts) |
Open **http://localhost:8000**. Within a few seconds you'll see three robots streaming, trails drawing in 3D, and the first alerts arriving as the simulated batteries drain and one robot's `/scan` topic drops out.
91
121
92
-
Run the unit tests for the alert engine (no containers needed):
The `ros` profile starts the rclpy bridge plus a small demo publisher so you can verify the ROS path end to end:
@@ -105,61 +129,48 @@ docker compose --profile ros up --build
105
129
106
130
The bridge subscribes to `/battery_state`, `/imu`, `/odom`, and `/diagnostics` and forwards them into the same pipeline. Point it at your own robot or a Gazebo bringup by replacing the demo publisher.
107
131
108
-
## API
109
-
110
-
| Method | Path | Purpose |
111
-
|--------|------|---------|
112
-
| GET |`/api/summary`| Fleet KPIs: robots online, active alerts, lowest battery |
113
-
| GET |`/api/robots`| Known robots with first/last-seen timestamps |
114
-
| GET |`/api/topics?robot_id=`| Topics & metrics seen for a robot |
115
-
| GET |`/api/series?robot_id=&metric=&minutes=`| Metric history (raw, or 1s rollup for long windows) |
116
-
| GET |`/api/poses?robot_id=&seconds=`| Recent pose samples |
117
-
| GET |`/api/alerts?limit=`| Most recent alerts |
118
-
| GET |`/api/health`| Per-topic observed rate and last-seen |
119
-
| POST |`/api/sessions/start`| Begin recording (bookmarks a time range) |
120
-
| POST |`/api/sessions/{id}/stop`| End a recording |
121
-
| GET |`/api/sessions`| List recorded sessions |
122
-
| GET |`/api/sessions/{id}/data`| Replay payload (pose trails, series, alerts) |
Lint and the full test suite run with no containers — the rule engine, schema, and
128
-
simulator logic are pure and infra-free, which is what keeps CI fast:
134
+
Lint and the full test suite run with no containers — the rule engine, schema, simulator, anomaly detector, and metrics formatter are pure and infra-free, which keeps CI fast:
129
135
130
136
```bash
131
137
pip install -r requirements-dev.txt
132
138
ruff check .
133
-
pytest -q #13 tests
139
+
pytest -q #22 tests
134
140
```
135
141
136
-
CI runs both as separate jobs on every push. See [`CONTRIBUTING.md`](CONTRIBUTING.md)
137
-
and [`CHANGELOG.md`](CHANGELOG.md).
142
+
CI runs lint and tests as separate jobs on every push. See [`CONTRIBUTING.md`](CONTRIBUTING.md) and [`CHANGELOG.md`](CHANGELOG.md).
138
143
139
-
## Engineering decisions
144
+
## 🛠 Engineering Decisions
140
145
141
146
A few choices that make this more than a toy, and what they buy:
142
147
143
148
-**Stream buffer, not direct DB writes.** Redis Streams decouple producers from storage and survive a worker restart via consumer groups, so no samples are lost during a redeploy.
144
-
-**Batched `COPY` ingestion.** The ingest worker accumulates samples and writes them with `copy_records_to_table`, which is dramatically cheaper than row-by-row inserts at sensor rates.
149
+
-**Batched `COPY` ingestion.** The ingest worker accumulates samples and writes them with `copy_records_to_table`, dramatically cheaper than row-by-row inserts at sensor rates.
145
150
-**Continuous aggregate for history.** Charts over long windows read a 1-second rollup instead of raw rows, keeping payloads small and queries fast; raw data has a 7-day retention policy.
146
-
-**Staleness as a first-class signal.** "No data" is often the most important alert in robotics. The engine tracks last-seen time per topic and fires when a stream goes quiet — not just on bad values.
147
-
-**Interchangeable producers.** A shared envelope means the synthetic publisher and the ROS 2 bridge are drop-in replacements, which is what lets the project demo with zero hardware.
151
+
-**Staleness as a first-class signal.** "No data" is often the most important alert in robotics — the engine tracks last-seen time per topic and fires when a stream goes quiet, not just on bad values.
152
+
-**Anomalies beyond thresholds.** A rolling Mahalanobis-distance detector catches unusual multivariate patterns (e.g. a CPU-temperature blip that never crosses the hard limit).
153
+
-**Interchangeable producers.** A shared envelope means the synthetic publisher and the ROS 2 bridge are drop-in replacements — which is what lets the project demo with zero hardware.
154
+
-**Self-observable.** A Prometheus `/metrics` endpoint exposes ingest rate, active alerts, anomalies, and fleet KPIs, so the observability platform is itself observable.
148
155
149
-
## Project layout
156
+
## 📁 Project Layout
150
157
151
158
```
152
159
common/ shared telemetry envelope + logging helper (used by every service)
153
160
sim/ synthetic fleet publisher (default data source)
tests/ unit tests: rules, schema, simulator, anomaly
167
+
tests/ unit tests: rules, schema, simulator, anomaly, metrics
161
168
```
162
169
170
+
## 🎯 Outcome
171
+
172
+
Ros Scope demonstrates how observability principles from modern distributed systems apply to robotic fleets: a reproducible environment for monitoring, analyzing, and diagnosing robot behavior, compatible with both simulated and real-world deployments. It serves as both a portfolio reference architecture and a practical starting point for telemetry-driven robotic observability.
0 commit comments