Skip to content

Commit a84742b

Browse files
committed
docs(web): tighten differentiation, drop forward-looking promises
- README 'Browser ↔ ROS 2' bullet leads with the three-word value prop (typed, allow-listed, curl-able) and substantiates each one inline. - tutorials/web.md §8 'How it compares' restructured around the decision: rclnodejs/web is the default for new code; rosbridge remains correct for graph introspection / Actions / fleet UIs. New keystone callout 'Why we don't try to hide the ROS graph' pre-empts the 'isn't this just modernised roslibjs?' pushback. Sibling-vs-competitor framing for rosocket made explicit. - Strip forward-looking promises ('on the roadmap', 'coming in a follow-up') from §5 reconnect note, §8 actions row, and §9 auth/actions bullets — replaced with present-tense facts.
1 parent 61cbf1a commit a84742b

2 files changed

Lines changed: 65 additions & 28 deletions

File tree

README.md

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -115,11 +115,12 @@ More runnable examples in [example/](https://github.com/RobotWebTools/rclnodejs/
115115
`rclnodejs` ships **two** browser ↔ ROS 2 bridges — pick one based on
116116
how much glue you want to write.
117117

118-
- **[`rclnodejs/web`](./tutorials/web.md)** — typed browser SDK +
119-
capability runtime. One string generic per call gives request,
120-
response, and message types; a `web.json` allow-list is the public
121-
API surface; the same capabilities are also reachable over plain
122-
HTTP for `curl`, Postman, and AI-agent tool-use. _New in `2.0.0-beta.0`._
118+
- **[`rclnodejs/web`](./tutorials/web.md)****typed, allow-listed,
119+
curl-able** browser ↔ ROS 2. A `web.json` file is your public API;
120+
the browser SDK types `call` / `publish` / `subscribe` end-to-end
121+
from rclnodejs's auto-generated message maps; and
122+
`curl -X POST .../capability/call/...` works for shell scripts,
123+
Postman, and AI-agent tool-use. _New in `2.0.0-beta.0`._
123124

124125
```ts
125126
import { connect } from 'rclnodejs/web';

tutorials/web.md

Lines changed: 59 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -142,8 +142,7 @@ await ros.close(); // cancels subscriptions, closes both transports
142142

143143
Today **`reconnect: true` is accepted but ignored** (the SDK warns
144144
once). If the server drops, the client is dead — `connect()` again
145-
and re-`subscribe()`. Auto-reconnect with resubscribe is on the
146-
roadmap.
145+
and re-`subscribe()`.
147146

148147
## 6. End-to-end
149148

@@ -203,37 +202,74 @@ curl -sS -X POST http://localhost:9001/capability/call/dangerous \
203202

204203
## 8. How it compares
205204

206-
`rclnodejs` ships **two** browser ↔ ROS 2 bridges, side-by-side
207-
with the upstream `rosbridge` + `roslibjs` stack:
208-
209-
| | `rosocket` | **`rclnodejs/web`** | `rosbridge` + `roslibjs` |
210-
| --------------------------- | --------------------------------------- | -------------------------------------------------------------------- | ---------------------------------------- |
211-
| **Browser API** | Hand-rolled `WebSocket + JSON` | `import { connect } from 'rclnodejs/web'` | `roslibjs` |
212-
| **URL shape** | `/topic/<name>`, `/service/<name>` | `/capability` (WS) + `POST /capability/{call,publish}/<name>` (HTTP) | rosbridge protocol over WS |
213-
| **Public surface** | All listed topics/services | **Required `web.json` allow-list** — a reviewable artifact | The whole ROS graph |
214-
| **TypeScript types** | `any`-shaped | Single string generic → request/response/message | `any`-shaped; bolt-on community packages |
215-
| **HTTP `call` / `publish`** || ✅ — `curl`, Postman, AI-agent tool-use just work ||
216-
| **Best for** | Quick prototypes, `roslibjs`-style apps | New apps, AI agents, typed UIs | Graph introspection, rqt-web, fleet UIs |
217-
218-
`rosocket` and `rclnodejs/web` are **siblings**, not layers — run as
219-
separate processes on separate ports. `rosbridge` remains the right
220-
choice when you genuinely need graph-shaped semantics (anything that
221-
has to enumerate the live graph rather than work against a fixed
222-
contract).
205+
The browser ↔ ROS 2 space already has `rosbridge` + `roslibjs`, and
206+
`rclnodejs` itself ships a second, lighter bridge called `rosocket`.
207+
All three speak to the same ROS graph — the differences live in **the
208+
contract you sign with the browser**, not in transport tricks.
209+
210+
> 💡 **Why we don't try to hide the ROS graph.** Robotics has no
211+
> stable equivalent to the web's URL/DOM/REST/SQL primitives, so any
212+
> attempt at a fully product-agnostic `robot.navigate(...)` style API
213+
> ends in unbounded capability explosion. All three options below
214+
> therefore keep the browser facing topics/services/actions
215+
> deliberately. The differentiator is the operational surface
216+
> _around_ the graph (allow-list, types, transports, governance), not
217+
> a new frontend abstraction. `robot.navigate()`-style verbs belong
218+
> in the integrator's product layer on top of these.
219+
220+
### Pick by the contract you want
221+
222+
| You want… | Use |
223+
| ------------------------------------------------------------------------------- | --------------------------------------------------------------------- |
224+
| **A reviewable allow-list, typed SDK, and curl-able HTTP** for new browser apps | **`rclnodejs/web`** _(this guide; default for new code)_ |
225+
| Live graph introspection / debug consoles / `rqt`-web / fleet topic discovery | `rosbridge` + `roslibjs` |
226+
| Hand-rolled `WebSocket + JSON` against a couple of named topics, no SDK at all | [`rosocket`](../rosocket/) |
227+
| You already have a working `roslibjs` codebase with no migration pressure | Stay on `rosbridge` + `roslibjs` |
228+
| You need ROS 2 Actions | `rosbridge` + `roslibjs` _(rclnodejs/web does not implement actions)_ |
229+
230+
### Detailed matrix
231+
232+
| | **`rclnodejs/web`** _(default)_ | [`rosocket`](../rosocket/) | `rosbridge` + `roslibjs` |
233+
| --------------------------- | -------------------------------------------------------------------- | --------------------------------------- | ---------------------------------------------------------------- |
234+
| **Public API surface** | **`web.json` allow-list — reviewable artifact** | All listed topics/services | The whole live ROS graph |
235+
| **Browser API** | `import { connect } from 'rclnodejs/web'` — typed, three verbs | Hand-rolled `WebSocket + JSON` | `roslibjs` |
236+
| **TypeScript types** | Single string generic → request/response/message from generated maps | `any`-shaped | `any`; bolt-on community packages |
237+
| **Wire shape** | `/capability` (WS) + `POST /capability/{call,publish}/<name>` (HTTP) | `/topic/<name>`, `/service/<name>` (WS) | rosbridge protocol over WS |
238+
| **HTTP `call` / `publish`** | ✅ — `curl`, Postman, AI-agent tool-use just work |||
239+
| **Setup** | `npx rclnodejs-web web.json` | `npx rosocket --topic …` | `apt install ros-<distro>-rosbridge-server` + Python launch file |
240+
| **Auth hooks** | `verifyClient` / `verifyRequest` per transport (today) | Connection-level | `securityglobs` plugin |
241+
| **Mature / battle-tested** | New (2.0) | New (2.0) | 10+ years in production |
242+
243+
### Sibling, not competitor: `rosocket`
244+
245+
`rosocket` and `rclnodejs/web` ship in the **same** rclnodejs package
246+
but are independent runtimes — different ports, different contracts,
247+
no shared state. Reach for `rosocket` when you genuinely just want
248+
"one named topic over a raw WebSocket"; reach for `rclnodejs/web`
249+
when you want a typed SDK and a reviewable allow-list. Neither
250+
replaces the other.
251+
252+
### Not a `rosbridge` replacement
253+
254+
`rosbridge` is still the right tool when the browser genuinely needs
255+
**graph-shaped semantics** — enumerating live topics, building
256+
`rqt`-style debug UIs, fleet dashboards that have to discover what's
257+
running. `rclnodejs/web` deliberately gives that up in exchange for a
258+
narrow, declarative contract.
223259

224260
## 9. Auth, HTTPS, Actions
225261

226262
- **HTTPS / `wss://`.** The runtime speaks plain `ws://` and
227263
`http://`. Put nginx, Caddy, or any TLS proxy in front of
228264
`rclnodejs-web`; clients then point at `wss://` / `https://`.
229-
- **Auth.** Today, gate at the connection level via the
265+
- **Auth.** Gate at the connection level via the
230266
`verifyClient(req)` / `verifyRequest(req)` hooks on
231267
`WebSocketTransport` / `HttpTransport` (return `false` to reject
232-
with a 401). Per-capability scopes are on the roadmap.
268+
with a 401).
233269
- **Browser ROS install?** No — the browser only ever speaks to the
234270
endpoint `rclnodejs-web` exposes.
235-
- **Actions.** Not yet — reserved as the `action` kind in the wire
236-
protocol; coming in a follow-up release.
271+
- **Actions.** Not implemented. Use `rosbridge` + `roslibjs` if you
272+
need ROS 2 Actions in the browser today.
237273

238274
## See also
239275

0 commit comments

Comments
 (0)