From f02fdd99c455cad8cba2f6f289a224e32708d7bc Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Wed, 6 May 2026 13:43:18 +0800 Subject: [PATCH 1/2] Consolidate all demos under demo/ + add rosocket demo --- .npmignore | 1 + README.md | 8 +- {electron_demo => demo/electron}/README.md | 0 .../electron}/car/README.md | 0 .../electron}/car/car-control-electron.gif | Bin .../electron}/car/index.html | 0 {electron_demo => demo/electron}/car/main.js | 0 .../electron}/car/package.json | 0 .../electron}/car/renderer.js | 0 .../electron}/manipulator/README.md | 2 +- .../electron}/manipulator/index.html | 0 .../electron}/manipulator/main.js | 0 .../manipulator/manipulator-demo.gif | Bin .../manipulator/manipulator-demo.png | Bin .../electron}/manipulator/package.json | 0 .../electron}/manipulator/renderer.js | 0 .../electron}/topics/README.md | 2 +- .../electron}/topics/electron-demo.gif | Bin .../electron}/topics/index.html | 0 .../electron}/topics/main.js | 0 .../electron}/topics/package.json | 0 .../electron}/topics/renderer.js | 0 .../electron}/turtle_tf2/README.md | 2 +- .../electron}/turtle_tf2/index.html | 0 .../electron}/turtle_tf2/main.js | 0 .../electron}/turtle_tf2/orbit-controls.js | 0 .../electron}/turtle_tf2/package.json | 0 .../electron}/turtle_tf2/renderer.js | 0 .../electron}/turtle_tf2/turtle-tf2-demo.gif | Bin .../electron}/turtle_tf2/turtle-tf2-demo.png | Bin demo/rosocket/README.md | 93 ++++++++ demo/rosocket/index.html | 212 ++++++++++++++++++ demo/rosocket/server.js | 76 +++++++ {ts_demo => demo/typescript}/README.md | 4 +- .../typescript}/actions/README.md | 4 +- .../typescript}/actions/package.json | 0 .../typescript}/actions/src/client.ts | 0 .../typescript}/actions/src/server.ts | 0 .../typescript}/actions/tsconfig.json | 0 .../typescript}/services/README.md | 2 +- .../typescript}/services/package.json | 0 .../typescript}/services/src/client.ts | 0 .../typescript}/services/src/server.ts | 0 .../typescript}/services/tsconfig.json | 0 {ts_demo => demo/typescript}/topics/README.md | 6 +- .../typescript}/topics/package.json | 0 .../typescript}/topics/src/publisher.ts | 0 .../typescript}/topics/src/subscriber.ts | 0 .../typescript}/topics/tsconfig.json | 0 eslint.config.mjs | 2 +- scripts/npmjs-readme.md | 5 +- 51 files changed, 401 insertions(+), 18 deletions(-) rename {electron_demo => demo/electron}/README.md (100%) rename {electron_demo => demo/electron}/car/README.md (100%) rename {electron_demo => demo/electron}/car/car-control-electron.gif (100%) rename {electron_demo => demo/electron}/car/index.html (100%) rename {electron_demo => demo/electron}/car/main.js (100%) rename {electron_demo => demo/electron}/car/package.json (100%) rename {electron_demo => demo/electron}/car/renderer.js (100%) rename {electron_demo => demo/electron}/manipulator/README.md (99%) rename {electron_demo => demo/electron}/manipulator/index.html (100%) rename {electron_demo => demo/electron}/manipulator/main.js (100%) rename {electron_demo => demo/electron}/manipulator/manipulator-demo.gif (100%) rename {electron_demo => demo/electron}/manipulator/manipulator-demo.png (100%) rename {electron_demo => demo/electron}/manipulator/package.json (100%) rename {electron_demo => demo/electron}/manipulator/renderer.js (100%) rename {electron_demo => demo/electron}/topics/README.md (99%) rename {electron_demo => demo/electron}/topics/electron-demo.gif (100%) rename {electron_demo => demo/electron}/topics/index.html (100%) rename {electron_demo => demo/electron}/topics/main.js (100%) rename {electron_demo => demo/electron}/topics/package.json (100%) rename {electron_demo => demo/electron}/topics/renderer.js (100%) rename {electron_demo => demo/electron}/turtle_tf2/README.md (99%) rename {electron_demo => demo/electron}/turtle_tf2/index.html (100%) rename {electron_demo => demo/electron}/turtle_tf2/main.js (100%) rename {electron_demo => demo/electron}/turtle_tf2/orbit-controls.js (100%) rename {electron_demo => demo/electron}/turtle_tf2/package.json (100%) rename {electron_demo => demo/electron}/turtle_tf2/renderer.js (100%) rename {electron_demo => demo/electron}/turtle_tf2/turtle-tf2-demo.gif (100%) rename {electron_demo => demo/electron}/turtle_tf2/turtle-tf2-demo.png (100%) create mode 100644 demo/rosocket/README.md create mode 100644 demo/rosocket/index.html create mode 100644 demo/rosocket/server.js rename {ts_demo => demo/typescript}/README.md (94%) rename {ts_demo => demo/typescript}/actions/README.md (99%) rename {ts_demo => demo/typescript}/actions/package.json (100%) rename {ts_demo => demo/typescript}/actions/src/client.ts (100%) rename {ts_demo => demo/typescript}/actions/src/server.ts (100%) rename {ts_demo => demo/typescript}/actions/tsconfig.json (100%) rename {ts_demo => demo/typescript}/services/README.md (99%) rename {ts_demo => demo/typescript}/services/package.json (100%) rename {ts_demo => demo/typescript}/services/src/client.ts (100%) rename {ts_demo => demo/typescript}/services/src/server.ts (100%) rename {ts_demo => demo/typescript}/services/tsconfig.json (100%) rename {ts_demo => demo/typescript}/topics/README.md (99%) rename {ts_demo => demo/typescript}/topics/package.json (100%) rename {ts_demo => demo/typescript}/topics/src/publisher.ts (100%) rename {ts_demo => demo/typescript}/topics/src/subscriber.ts (100%) rename {ts_demo => demo/typescript}/topics/tsconfig.json (100%) diff --git a/.npmignore b/.npmignore index 947bfcd51..d24e04c8f 100644 --- a/.npmignore +++ b/.npmignore @@ -26,6 +26,7 @@ tutorials/ electron_demo/ ts_demo/ tools/ +demo/ .github/ .nyc_output/ .vscode/ diff --git a/README.md b/README.md index 6dc9f07ad..8735f0621 100644 --- a/README.md +++ b/README.md @@ -144,10 +144,10 @@ Create rich, interactive desktop applications using Electron and web technologie | Demo | Description | Screenshot | | :-----------------------------------------------: | :-----------------------------------------------------------------------------------------------------------------------------------: | :--------------------------------------------------------------: | -| **🐢 [turtle_tf2](./electron_demo/turtle_tf2)** | Real-time coordinate frame visualization with turtle control. Features TF2 transforms, keyboard control, and dynamic frame updates. | ![turtle_tf2](./electron_demo/turtle_tf2/turtle-tf2-demo.png) | -| **🦾 [manipulator](./electron_demo/manipulator)** | Interactive two-joint robotic arm simulation. Features 3D joint visualization, manual/automatic control, and visual movement markers. | ![manipulator](./electron_demo/manipulator/manipulator-demo.png) | +| **🐢 [turtle_tf2](./demo/electron/turtle_tf2)** | Real-time coordinate frame visualization with turtle control. Features TF2 transforms, keyboard control, and dynamic frame updates. | ![turtle_tf2](./demo/electron/turtle_tf2/turtle-tf2-demo.png) | +| **🦾 [manipulator](./demo/electron/manipulator)** | Interactive two-joint robotic arm simulation. Features 3D joint visualization, manual/automatic control, and visual movement markers. | ![manipulator](./demo/electron/manipulator/manipulator-demo.png) | -Explore more examples in [electron_demo](https://github.com/RobotWebTools/rclnodejs/tree/develop/electron_demo). +Explore more examples in [demo/electron](https://github.com/RobotWebTools/rclnodejs/tree/develop/demo/electron). ## Using rclnodejs with TypeScript @@ -175,7 +175,7 @@ rclnodejs.init().then(() => { }); ``` -See [TypeScript demos](https://github.com/RobotWebTools/rclnodejs/tree/develop/ts_demo) for more examples. +See [TypeScript demos](https://github.com/RobotWebTools/rclnodejs/tree/develop/demo/typescript) for more examples. ## Observable Subscriptions diff --git a/electron_demo/README.md b/demo/electron/README.md similarity index 100% rename from electron_demo/README.md rename to demo/electron/README.md diff --git a/electron_demo/car/README.md b/demo/electron/car/README.md similarity index 100% rename from electron_demo/car/README.md rename to demo/electron/car/README.md diff --git a/electron_demo/car/car-control-electron.gif b/demo/electron/car/car-control-electron.gif similarity index 100% rename from electron_demo/car/car-control-electron.gif rename to demo/electron/car/car-control-electron.gif diff --git a/electron_demo/car/index.html b/demo/electron/car/index.html similarity index 100% rename from electron_demo/car/index.html rename to demo/electron/car/index.html diff --git a/electron_demo/car/main.js b/demo/electron/car/main.js similarity index 100% rename from electron_demo/car/main.js rename to demo/electron/car/main.js diff --git a/electron_demo/car/package.json b/demo/electron/car/package.json similarity index 100% rename from electron_demo/car/package.json rename to demo/electron/car/package.json diff --git a/electron_demo/car/renderer.js b/demo/electron/car/renderer.js similarity index 100% rename from electron_demo/car/renderer.js rename to demo/electron/car/renderer.js diff --git a/electron_demo/manipulator/README.md b/demo/electron/manipulator/README.md similarity index 99% rename from electron_demo/manipulator/README.md rename to demo/electron/manipulator/README.md index 76c3497d5..616769367 100644 --- a/electron_demo/manipulator/README.md +++ b/demo/electron/manipulator/README.md @@ -25,7 +25,7 @@ An interactive Electron application demonstrating a two-joint robotic manipulato 1. **Navigate to the demo directory**: ```bash - cd rclnodejs/electron_demo/manipulator + cd rclnodejs/demo/electron/manipulator ``` 2. **Install dependencies**: diff --git a/electron_demo/manipulator/index.html b/demo/electron/manipulator/index.html similarity index 100% rename from electron_demo/manipulator/index.html rename to demo/electron/manipulator/index.html diff --git a/electron_demo/manipulator/main.js b/demo/electron/manipulator/main.js similarity index 100% rename from electron_demo/manipulator/main.js rename to demo/electron/manipulator/main.js diff --git a/electron_demo/manipulator/manipulator-demo.gif b/demo/electron/manipulator/manipulator-demo.gif similarity index 100% rename from electron_demo/manipulator/manipulator-demo.gif rename to demo/electron/manipulator/manipulator-demo.gif diff --git a/electron_demo/manipulator/manipulator-demo.png b/demo/electron/manipulator/manipulator-demo.png similarity index 100% rename from electron_demo/manipulator/manipulator-demo.png rename to demo/electron/manipulator/manipulator-demo.png diff --git a/electron_demo/manipulator/package.json b/demo/electron/manipulator/package.json similarity index 100% rename from electron_demo/manipulator/package.json rename to demo/electron/manipulator/package.json diff --git a/electron_demo/manipulator/renderer.js b/demo/electron/manipulator/renderer.js similarity index 100% rename from electron_demo/manipulator/renderer.js rename to demo/electron/manipulator/renderer.js diff --git a/electron_demo/topics/README.md b/demo/electron/topics/README.md similarity index 99% rename from electron_demo/topics/README.md rename to demo/electron/topics/README.md index e06a3a03b..20f2f504e 100644 --- a/electron_demo/topics/README.md +++ b/demo/electron/topics/README.md @@ -30,7 +30,7 @@ A minimal Electron application demonstrating basic ROS2 topic communication usin 1. **Navigate to the demo directory**: ```bash - cd rclnodejs/electron_demo/topics + cd rclnodejs/demo/electron/topics ``` 2. **Source your ROS 2 environment**: diff --git a/electron_demo/topics/electron-demo.gif b/demo/electron/topics/electron-demo.gif similarity index 100% rename from electron_demo/topics/electron-demo.gif rename to demo/electron/topics/electron-demo.gif diff --git a/electron_demo/topics/index.html b/demo/electron/topics/index.html similarity index 100% rename from electron_demo/topics/index.html rename to demo/electron/topics/index.html diff --git a/electron_demo/topics/main.js b/demo/electron/topics/main.js similarity index 100% rename from electron_demo/topics/main.js rename to demo/electron/topics/main.js diff --git a/electron_demo/topics/package.json b/demo/electron/topics/package.json similarity index 100% rename from electron_demo/topics/package.json rename to demo/electron/topics/package.json diff --git a/electron_demo/topics/renderer.js b/demo/electron/topics/renderer.js similarity index 100% rename from electron_demo/topics/renderer.js rename to demo/electron/topics/renderer.js diff --git a/electron_demo/turtle_tf2/README.md b/demo/electron/turtle_tf2/README.md similarity index 99% rename from electron_demo/turtle_tf2/README.md rename to demo/electron/turtle_tf2/README.md index 89ad595ed..33ae9a002 100644 --- a/electron_demo/turtle_tf2/README.md +++ b/demo/electron/turtle_tf2/README.md @@ -77,7 +77,7 @@ The demo uses the following key dependencies: 1. **Navigate to the demo directory**: ```bash - cd electron_demo/turtle_tf2 + cd demo/electron/turtle_tf2 ``` 2. **Install dependencies**: diff --git a/electron_demo/turtle_tf2/index.html b/demo/electron/turtle_tf2/index.html similarity index 100% rename from electron_demo/turtle_tf2/index.html rename to demo/electron/turtle_tf2/index.html diff --git a/electron_demo/turtle_tf2/main.js b/demo/electron/turtle_tf2/main.js similarity index 100% rename from electron_demo/turtle_tf2/main.js rename to demo/electron/turtle_tf2/main.js diff --git a/electron_demo/turtle_tf2/orbit-controls.js b/demo/electron/turtle_tf2/orbit-controls.js similarity index 100% rename from electron_demo/turtle_tf2/orbit-controls.js rename to demo/electron/turtle_tf2/orbit-controls.js diff --git a/electron_demo/turtle_tf2/package.json b/demo/electron/turtle_tf2/package.json similarity index 100% rename from electron_demo/turtle_tf2/package.json rename to demo/electron/turtle_tf2/package.json diff --git a/electron_demo/turtle_tf2/renderer.js b/demo/electron/turtle_tf2/renderer.js similarity index 100% rename from electron_demo/turtle_tf2/renderer.js rename to demo/electron/turtle_tf2/renderer.js diff --git a/electron_demo/turtle_tf2/turtle-tf2-demo.gif b/demo/electron/turtle_tf2/turtle-tf2-demo.gif similarity index 100% rename from electron_demo/turtle_tf2/turtle-tf2-demo.gif rename to demo/electron/turtle_tf2/turtle-tf2-demo.gif diff --git a/electron_demo/turtle_tf2/turtle-tf2-demo.png b/demo/electron/turtle_tf2/turtle-tf2-demo.png similarity index 100% rename from electron_demo/turtle_tf2/turtle-tf2-demo.png rename to demo/electron/turtle_tf2/turtle-tf2-demo.png diff --git a/demo/rosocket/README.md b/demo/rosocket/README.md new file mode 100644 index 000000000..830d5cd44 --- /dev/null +++ b/demo/rosocket/README.md @@ -0,0 +1,93 @@ +# rosocket demo (browser ↔ ROS 2) + +A minimal end-to-end example of the +[`rosocket`](../../rosocket/README.md) WebSocket bridge added in +commit `3176aca`. The Node server runs anywhere ROS 2 is sourced; +the HTML page runs in any modern browser and talks to it over plain +`WebSocket` — no client library required. + +## What it shows + +- Subscribe to and publish on `/chatter` (`std_msgs/msg/String`). +- Call `/add_two_ints` (`example_interfaces/srv/AddTwoInts`) — the + service implementation lives in + [`example/services/service/service-example.js`](../../example/services/service/service-example.js) + and is launched in a second terminal. + +## Layout + +- `server.js` — `rclnodejs` node + `startRosocket` bridge only. +- `index.html` — single-file browser client using only built-in + `WebSocket` and `JSON`. + +## Run the bridge + +```bash +# 1. Source your ROS 2 distro (humble / jazzy / kilted / lyrical / rolling) +source /opt/ros/$ROS_DISTRO/setup.bash + +# 2. Terminal A — start the WebSocket bridge +node demo/rosocket/server.js +# [rosocket-demo] listening on ws://localhost:9000 (bind=0.0.0.0) + +# 3. Terminal B — start the AddTwoInts service so the browser has +# something to call +node example/services/service/service-example.js +``` + +The server binds to `0.0.0.0:9000` so it is reachable from any host +that can route to the machine running it. + +## Open the page + +Open `demo/rosocket/index.html` in any modern browser (double-click, +or `File > Open`). Leave the bridge field as `ws://localhost:9000` +when the browser and the bridge run on the same machine, and click +**Subscribe**, then **Publish**, then **Call**. + +If the browser is on a different machine than the bridge (remote ROS +box, container, VM, WSL → host browser, etc.), change the bridge +field to point at the bridge host, e.g. `ws://192.0.2.10:9000` or +`ws://my-ros-host.local:9000`, and reconnect. + +> WSL note: WSL2 normally forwards `localhost` to Windows, so +> `ws://localhost:9000` works as-is. On WSL1 or with custom/mirrored +> networking, use the WSL IP (`hostname -I | awk '{print $1}'`) +> instead. + +### Verify from the ROS 2 side (optional) + +```bash +# Always works (explicit type), even before any browser tab is connected: +ros2 topic echo /chatter std_msgs/msg/String + +# Auto-discovery form — only works after a browser tab is connected to +# ws://.../topic/chatter (the bridge creates the subscription on demand) +# and after a publisher exists on the topic (browser Publish, or the +# `ros2 topic pub` command below): +ros2 topic echo /chatter + +ros2 topic pub /chatter std_msgs/msg/String "{data: 'hi from ros2'}" +ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 7, b: 5}" +``` + +> If you see `WARNING: topic [/chatter] does not appear to be published yet +> / Could not determine the type for the passed topic`, it just means no +> publisher exists on `/chatter` yet — use the explicit-type form above, +> or click **Subscribe** + **Publish** in the browser first. + +Anything you publish from the browser shows up in `ros2 topic echo`, +and any `ros2 topic pub` to `/chatter` shows up in the browser +subscription log. + +## URL scheme reminder + +``` +ws://:/topic/?type=/msg/ +ws://:/service/?type=/srv/ +``` + +This demo pre-declares both types server-side via `topicTypes` / +`serviceTypes`, so the browser can omit `?type=`. See +[`rosocket/README.md`](../../rosocket/README.md) for the full +protocol reference. diff --git a/demo/rosocket/index.html b/demo/rosocket/index.html new file mode 100644 index 000000000..89e4aa872 --- /dev/null +++ b/demo/rosocket/index.html @@ -0,0 +1,212 @@ + + + + + + rosocket demo + + + +

rosocket demo

+

+ Browser ↔ ROS 2 over plain WebSocket. Adjust the bridge URL if your WSL + IP differs from localhost. +

+

+ Bridge: + +

+ +

Topic: /chatter (std_msgs/msg/String)

+
+
+

+ + +

+

+ + +

+

+      
+
// Subscribe — every published message arrives as onmessage.
+const sub = new WebSocket('ws://localhost:9000/topic/chatter');
+sub.onmessage = (ev) => console.log('recv:', ev.data);
+// e.g. {"data":"hi"}
+
+// Publish — open, send JSON, close.
+const ws = new WebSocket('ws://localhost:9000/topic/chatter');
+ws.onopen = () => {
+  ws.send(JSON.stringify({ data: 'hello from browser' }));
+  setTimeout(() => ws.close(), 200); // let it flush
+};
+
+ +

Service: /add_two_ints (example_interfaces/srv/AddTwoInts)

+
+
+

+ a: b: + + +

+

+      
+
// Service call — send {id, request}, await one response, close.
+const ws = new WebSocket('ws://localhost:9000/service/add_two_ints');
+ws.onopen = () => ws.send(JSON.stringify({
+  id: 1,
+  request: { a: '2n', b: '3n' }, // int64 → "Nn" string
+}));
+ws.onmessage = (ev) => {
+  console.log('resp:', ev.data);
+  // {"id":1,"response":{"sum":"5n"}}
+  ws.close();
+};
+
+ + + + diff --git a/demo/rosocket/server.js b/demo/rosocket/server.js new file mode 100644 index 000000000..8e1d7061f --- /dev/null +++ b/demo/rosocket/server.js @@ -0,0 +1,76 @@ +// Copyright (c) 2026 RobotWebTools Contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 + +'use strict'; + +// rosocket demo server. +// +// Bridges two ROS 2 endpoints to plain WebSocket URLs so a browser can +// drive them with built-in `WebSocket` + `JSON`, no client library: +// +// ws://:9000/topic/chatter std_msgs/msg/String +// ws://:9000/service/add_two_ints example_interfaces/srv/AddTwoInts +// +// Run inside WSL (where ROS 2 is sourced): +// node demo/rosocket/server.js +// +// To exercise the service, start the existing AddTwoInts example in a +// second terminal (it implements `/add_two_ints`): +// node example/services/service/service-example.js +// +// Then open demo/rosocket/index.html on the Windows host browser. WSL2 +// forwards localhost so `ws://localhost:9000` works as-is. See README.md +// for fallback instructions. + +const rclnodejs = require('../../index.js'); +const { startRosocket } = require('../../rosocket'); + +const PORT = Number(process.env.PORT) || 9000; +const HOST = process.env.HOST || '0.0.0.0'; + +async function main() { + await rclnodejs.init(); + const node = rclnodejs.createNode('rosocket_demo_node'); + rclnodejs.spin(node); + + const bridge = await startRosocket({ + node, + port: PORT, + host: HOST, + topicTypes: { + '/chatter': 'std_msgs/msg/String', + }, + serviceTypes: { + '/add_two_ints': 'example_interfaces/srv/AddTwoInts', + }, + }); + + console.log( + `[rosocket-demo] listening on ws://localhost:${bridge.port} (bind=${HOST})` + ); + console.log('[rosocket-demo] endpoints:'); + console.log(' ws://localhost:9000/topic/chatter'); + console.log(' ws://localhost:9000/service/add_two_ints'); + console.log('Open demo/rosocket/index.html in the host browser to try it.'); + + const shutdown = () => { + bridge.close().finally(() => { + try { + rclnodejs.shutdown(); + } catch (_) {} + process.exit(0); + }); + }; + process.on('SIGINT', shutdown); + process.on('SIGTERM', shutdown); +} + +main().catch((e) => { + console.error(e.stack || e.message); + process.exit(1); +}); diff --git a/ts_demo/README.md b/demo/typescript/README.md similarity index 94% rename from ts_demo/README.md rename to demo/typescript/README.md index 9619ade74..3ce710873 100644 --- a/ts_demo/README.md +++ b/demo/typescript/README.md @@ -59,7 +59,7 @@ Asynchronous actions with progress feedback and cancellation ## 🔗 Related Resources -- [rclnodejs Tutorials](../tutorials/) - Comprehensive API documentation -- [Electron Demos](../electron_demo/) - GUI applications with rclnodejs +- [rclnodejs Tutorials](../../tutorials/) - Comprehensive API documentation +- [Electron Demos](../electron/) - GUI applications with rclnodejs - [TypeScript Handbook](https://www.typescriptlang.org/docs/) - Language reference - [ROS2 Documentation](https://docs.ros.org/) - Official ROS2 concepts diff --git a/ts_demo/actions/README.md b/demo/typescript/actions/README.md similarity index 99% rename from ts_demo/actions/README.md rename to demo/typescript/actions/README.md index 015d9f3c9..447e28b94 100644 --- a/ts_demo/actions/README.md +++ b/demo/typescript/actions/README.md @@ -32,7 +32,7 @@ This demo implements a Fibonacci sequence calculator using ROS2 actions: ## Project Structure ``` -ts_demo/actions/ +demo/typescript/actions/ ├── src/ │ ├── client.ts # Action client implementation │ └── server.ts # Action server implementation @@ -74,7 +74,7 @@ Before running this demo, ensure you have: 3. **Navigate to the demo directory**: ```bash - cd ts_demo/actions + cd demo/typescript/actions ``` 4. **Install dependencies**: diff --git a/ts_demo/actions/package.json b/demo/typescript/actions/package.json similarity index 100% rename from ts_demo/actions/package.json rename to demo/typescript/actions/package.json diff --git a/ts_demo/actions/src/client.ts b/demo/typescript/actions/src/client.ts similarity index 100% rename from ts_demo/actions/src/client.ts rename to demo/typescript/actions/src/client.ts diff --git a/ts_demo/actions/src/server.ts b/demo/typescript/actions/src/server.ts similarity index 100% rename from ts_demo/actions/src/server.ts rename to demo/typescript/actions/src/server.ts diff --git a/ts_demo/actions/tsconfig.json b/demo/typescript/actions/tsconfig.json similarity index 100% rename from ts_demo/actions/tsconfig.json rename to demo/typescript/actions/tsconfig.json diff --git a/ts_demo/services/README.md b/demo/typescript/services/README.md similarity index 99% rename from ts_demo/services/README.md rename to demo/typescript/services/README.md index df754bba8..26280c126 100644 --- a/ts_demo/services/README.md +++ b/demo/typescript/services/README.md @@ -48,7 +48,7 @@ npm run build Navigate to this demo directory and install dependencies: ```bash -cd ts_demo/services +cd demo/typescript/services npm install ``` diff --git a/ts_demo/services/package.json b/demo/typescript/services/package.json similarity index 100% rename from ts_demo/services/package.json rename to demo/typescript/services/package.json diff --git a/ts_demo/services/src/client.ts b/demo/typescript/services/src/client.ts similarity index 100% rename from ts_demo/services/src/client.ts rename to demo/typescript/services/src/client.ts diff --git a/ts_demo/services/src/server.ts b/demo/typescript/services/src/server.ts similarity index 100% rename from ts_demo/services/src/server.ts rename to demo/typescript/services/src/server.ts diff --git a/ts_demo/services/tsconfig.json b/demo/typescript/services/tsconfig.json similarity index 100% rename from ts_demo/services/tsconfig.json rename to demo/typescript/services/tsconfig.json diff --git a/ts_demo/topics/README.md b/demo/typescript/topics/README.md similarity index 99% rename from ts_demo/topics/README.md rename to demo/typescript/topics/README.md index ee158beb9..928ec2f98 100644 --- a/ts_demo/topics/README.md +++ b/demo/typescript/topics/README.md @@ -47,7 +47,7 @@ npm run build Navigate to this demo directory and install dependencies: ```bash -cd ts_demo/topics +cd demo/typescript/topics npm install ``` @@ -162,7 +162,7 @@ Starting TypeScript Subscriber Demo... ## Project Structure ``` -ts_demo/topics/ +demo/typescript/topics/ ├── package.json # Project dependencies and scripts ├── tsconfig.json # TypeScript configuration ├── README.md # This file @@ -239,7 +239,7 @@ This demo showcases several TypeScript advantages: **Solution**: Ensure you're in the correct directory and rclnodejs is properly linked: ```bash - cd ts_demo/topics + cd demo/typescript/topics npm install ``` diff --git a/ts_demo/topics/package.json b/demo/typescript/topics/package.json similarity index 100% rename from ts_demo/topics/package.json rename to demo/typescript/topics/package.json diff --git a/ts_demo/topics/src/publisher.ts b/demo/typescript/topics/src/publisher.ts similarity index 100% rename from ts_demo/topics/src/publisher.ts rename to demo/typescript/topics/src/publisher.ts diff --git a/ts_demo/topics/src/subscriber.ts b/demo/typescript/topics/src/subscriber.ts similarity index 100% rename from ts_demo/topics/src/subscriber.ts rename to demo/typescript/topics/src/subscriber.ts diff --git a/ts_demo/topics/tsconfig.json b/demo/typescript/topics/tsconfig.json similarity index 100% rename from ts_demo/topics/tsconfig.json rename to demo/typescript/topics/tsconfig.json diff --git a/eslint.config.mjs b/eslint.config.mjs index a40fdcaab..75f596d21 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -15,7 +15,7 @@ export default [ "**/scripts/", "**/benchmark/", "**/docs/", - "**/electron_demo/", + "**/demo/electron/", ], }, { diff --git a/scripts/npmjs-readme.md b/scripts/npmjs-readme.md index 5d1cca269..73fc37543 100644 --- a/scripts/npmjs-readme.md +++ b/scripts/npmjs-readme.md @@ -68,8 +68,9 @@ npm install rclnodejs - API documentation: [robotwebtools.github.io/rclnodejs/docs](https://robotwebtools.github.io/rclnodejs/docs/index.html) - Tutorials: [tutorials/](https://github.com/RobotWebTools/rclnodejs/tree/develop/tutorials) - JavaScript examples: [example/](https://github.com/RobotWebTools/rclnodejs/tree/develop/example) -- TypeScript demos: [ts_demo/](https://github.com/RobotWebTools/rclnodejs/tree/develop/ts_demo) -- Electron demos: [electron_demo/](https://github.com/RobotWebTools/rclnodejs/tree/develop/electron_demo) +- TypeScript demos: [demo/typescript/](https://github.com/RobotWebTools/rclnodejs/tree/develop/demo/typescript) +- Electron demos: [demo/electron/](https://github.com/RobotWebTools/rclnodejs/tree/develop/demo/electron) +- WebSocket bridge demo: [demo/rosocket/](https://github.com/RobotWebTools/rclnodejs/tree/develop/demo/rosocket) - Companion CLI: [rclnodejs-cli](https://github.com/RobotWebTools/rclnodejs-cli/) ## Message Generation From 459a0f71debb50aff7d01c8bf0910937881a9133 Mon Sep 17 00:00:00 2001 From: Minggang Wang Date: Wed, 6 May 2026 18:05:15 +0800 Subject: [PATCH 2/2] Address comments --- demo/rosocket/README.md | 8 ++++---- demo/rosocket/index.html | 12 ++++++++++-- demo/rosocket/server.js | 8 +++++--- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/demo/rosocket/README.md b/demo/rosocket/README.md index 830d5cd44..6e35b96ae 100644 --- a/demo/rosocket/README.md +++ b/demo/rosocket/README.md @@ -1,10 +1,10 @@ # rosocket demo (browser ↔ ROS 2) A minimal end-to-end example of the -[`rosocket`](../../rosocket/README.md) WebSocket bridge added in -commit `3176aca`. The Node server runs anywhere ROS 2 is sourced; -the HTML page runs in any modern browser and talks to it over plain -`WebSocket` — no client library required. +[`rosocket`](../../rosocket/README.md) WebSocket bridge. The Node +server runs anywhere ROS 2 is sourced; the HTML page runs in any +modern browser and talks to it over plain `WebSocket` — no client +library required. ## What it shows diff --git a/demo/rosocket/index.html b/demo/rosocket/index.html index 89e4aa872..aba379cc4 100644 --- a/demo/rosocket/index.html +++ b/demo/rosocket/index.html @@ -37,6 +37,14 @@ overflow: auto; white-space: pre-wrap; } + .log { + background: #f4f4f4; + padding: 0.5em; + max-height: 12em; + overflow: auto; + font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace; + font-size: 0.9em; + } .demo { display: grid; grid-template-columns: 1fr 1fr; @@ -102,7 +110,7 @@

Topic: /chatter (std_msgs/msg/String)

-

+        
// Subscribe — every published message arrives as onmessage.
 const sub = new WebSocket('ws://localhost:9000/topic/chatter');
@@ -125,7 +133,7 @@ 

Service: /add_two_ints (example_interfaces/srv/AddTwoInts)

-

+        
// Service call — send {id, request}, await one response, close.
 const ws = new WebSocket('ws://localhost:9000/service/add_two_ints');
diff --git a/demo/rosocket/server.js b/demo/rosocket/server.js
index 8e1d7061f..5f5898d1f 100644
--- a/demo/rosocket/server.js
+++ b/demo/rosocket/server.js
@@ -50,12 +50,14 @@ async function main() {
     },
   });
 
+  const displayHost = HOST === '0.0.0.0' || HOST === '::' ? 'localhost' : HOST;
+  const baseUrl = `ws://${displayHost}:${bridge.port}`;
   console.log(
-    `[rosocket-demo] listening on ws://localhost:${bridge.port} (bind=${HOST})`
+    `[rosocket-demo] listening on ${baseUrl} (bind=${HOST}:${bridge.port})`
   );
   console.log('[rosocket-demo] endpoints:');
-  console.log('  ws://localhost:9000/topic/chatter');
-  console.log('  ws://localhost:9000/service/add_two_ints');
+  console.log(`  ${baseUrl}/topic/chatter`);
+  console.log(`  ${baseUrl}/service/add_two_ints`);
   console.log('Open demo/rosocket/index.html in the host browser to try it.');
 
   const shutdown = () => {