Skip to content

Commit 506e0b6

Browse files
committed
Add a client/service demo for typescript (#1195)
This PR adds a comprehensive TypeScript demo for rclnodejs, demonstrating how to create ROS2 service servers and clients using TypeScript. The demo includes a complete project structure with proper TypeScript configuration, build scripts, and detailed documentation. Key changes: - Adds a complete TypeScript service demo with client and server implementations - Implements AddTwoInts service with proper type handling and error management - Updates main README to include reference to the new TypeScript demo Fix: #1193
1 parent ed74249 commit 506e0b6

File tree

7 files changed

+562
-1
lines changed

7 files changed

+562
-1
lines changed

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,3 +30,4 @@ scripts/cpplint.js
3030
scripts/npm-pack.sh
3131
scripts/npmjs-readme.md
3232
scripts/run_test.js
33+
ts_demo/

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,8 @@ rclnodejs.init().then(() => {
3434
- [Using TypeScript](#using-rclnodejs-with-typescript)
3535
- [ROS2 Interface Message Generation](#ros2-interface-message-generation-important)
3636
- [Examples](https://github.com/RobotWebTools/rclnodejs/tree/develop/example)
37-
- [Electron demo](https://github.com/RobotWebTools/rclnodejs/tree/develop/electron_demo)
37+
- [Electron Demo](https://github.com/RobotWebTools/rclnodejs/tree/develop/electron_demo)
38+
- [TypeScript Demo](https://github.com/RobotWebTools/rclnodejs/tree/develop/ts_demo)
3839
- [Efficient Usage Tips](./docs/EFFICIENCY.md)
3940
- [FAQ and Known Issues](./docs/FAQ.md)
4041
- [Building from Scratch](./docs/BUILDING.md)

ts_demo/services/README.md

Lines changed: 287 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,287 @@
1+
# rclnodejs TypeScript Services Demo
2+
3+
This demo demonstrates how to use **rclnodejs** with TypeScript to create ROS2 service servers and clients. The demo includes a service server that provides an `AddTwoInts` service and a client that calls the service with random numbers.
4+
5+
## Features
6+
7+
- 🚀 **TypeScript Support**: Fully typed ROS2 service implementation using rclnodejs TypeScript interfaces
8+
- 🔢 **Service Server**: Provides an AddTwoInts service that adds two integers
9+
- 📞 **Service Client**: Calls the AddTwoInts service with random numbers at regular intervals
10+
- 🛡️ **Type Safety**: Leverages TypeScript's type system for compile-time safety
11+
- 🎯 **Error Handling**: Comprehensive error handling and graceful shutdown
12+
- 📊 **Request Counting**: Tracks service requests and responses
13+
- 🎨 **Console Output**: Colorful and informative console messages
14+
- ⏱️ **Service Discovery**: Client waits for service availability before making requests
15+
16+
## Prerequisites
17+
18+
Before running this demo, ensure you have:
19+
20+
1. **Node.js** (>= 16.13.0)
21+
2. **ROS 2** installed and sourced
22+
3. **rclnodejs** built and available
23+
24+
### ROS 2 Setup
25+
26+
Make sure your ROS 2 environment is properly sourced before running the demo:
27+
28+
```bash
29+
# For example, if using ROS 2 Jazzy
30+
source /opt/ros/jazzy/setup.bash
31+
32+
# Or if you have a custom workspace
33+
source /path/to/your/ros2_ws/install/setup.bash
34+
```
35+
36+
### Verify rclnodejs Installation
37+
38+
From the root of the rclnodejs project, ensure it's built:
39+
40+
```bash
41+
cd /path/to/rclnodejs
42+
npm install
43+
npm run build
44+
```
45+
46+
## Installation
47+
48+
Navigate to this demo directory and install dependencies:
49+
50+
```bash
51+
cd ts_demo/services
52+
npm install
53+
```
54+
55+
## Usage
56+
57+
### Build and Run
58+
59+
1. **Build the TypeScript code:**
60+
61+
```bash
62+
npm run build
63+
```
64+
65+
2. **Run the service server (in one terminal):**
66+
67+
```bash
68+
npm run start:server
69+
```
70+
71+
3. **Run the service client (in another terminal):**
72+
73+
```bash
74+
npm run start:client
75+
```
76+
77+
4. **Or run both simultaneously:**
78+
```bash
79+
npm run start:both
80+
```
81+
82+
### Development Mode
83+
84+
For development, you can run TypeScript files directly with ts-node:
85+
86+
1. **Run the service server:**
87+
88+
```bash
89+
npm run dev:server
90+
```
91+
92+
2. **Run the service client:**
93+
94+
```bash
95+
npm run dev:client
96+
```
97+
98+
3. **Type check only:**
99+
```bash
100+
npm run check-types
101+
```
102+
103+
## How It Works
104+
105+
### Service Server (`server.ts`)
106+
107+
The service server:
108+
109+
- Creates a ROS2 node named `ts_server_demo`
110+
- Provides an `AddTwoInts` service at `/add_two_ints`
111+
- Receives requests with two integers (`a` and `b`)
112+
- Calculates the sum and returns it in the response
113+
- Logs each request and response with timestamps
114+
115+
### Service Client (`client.ts`)
116+
117+
The service client:
118+
119+
- Creates a ROS2 node named `ts_client_demo`
120+
- Waits for the `AddTwoInts` service to become available
121+
- Sends requests every 3 seconds with random integers
122+
- Displays the results and verifies the calculations
123+
- Handles service availability and error cases
124+
125+
### Example Output
126+
127+
**Service Server:**
128+
129+
```
130+
Starting TypeScript Service Server Demo...
131+
✓ rclnodejs initialized
132+
✓ Created node: /mock_namespace/ts_server_demo
133+
✓ Created service server: add_two_ints
134+
🚀 Service server is running. Press Ctrl+C to stop...
135+
136+
🔢 [1] Received request: a=42, b=17
137+
📤 [1] Sending response: sum=59
138+
Calculation: 42 + 17 = 59
139+
Timestamp: 2025-07-16T02:30:15.123Z
140+
```
141+
142+
**Service Client:**
143+
144+
```
145+
Starting TypeScript Service Client Demo...
146+
✓ rclnodejs initialized
147+
✓ Created node: /mock_namespace/ts_client_demo
148+
✓ Created service client: add_two_ints
149+
⏳ Waiting for service to be available...
150+
✓ Service is available
151+
🚀 Starting to send requests. Press Ctrl+C to stop...
152+
153+
📞 [1] Sending request: a=42, b=17
154+
Timestamp: 2025-07-16T02:30:15.120Z
155+
📨 [1] Received response: sum=59
156+
Verification: 42 + 17 = 59 ✓
157+
Response time: 2025-07-16T02:30:15.125Z
158+
```
159+
160+
## TypeScript Configuration
161+
162+
This demo includes:
163+
164+
- **Local Type Definitions**: Custom TypeScript definitions for rclnodejs in `types/rclnodejs.d.ts`
165+
- **Service Types**: Type definitions for `example_interfaces/srv/AddTwoInts`
166+
- **Strict Type Checking**: Full TypeScript strict mode enabled
167+
- **Build Pipeline**: Automated compilation with shebang fixing for executable JavaScript
168+
169+
## Service Interface
170+
171+
The `AddTwoInts` service interface:
172+
173+
```typescript
174+
export interface AddTwoInts {
175+
Request: {
176+
a: number; // First integer
177+
b: number; // Second integer
178+
};
179+
Response: {
180+
sum: number; // Sum of a and b
181+
};
182+
}
183+
```
184+
185+
## Customization
186+
187+
You can easily customize this demo:
188+
189+
### Change Service Name
190+
191+
Edit the `SERVICE_NAME` constant in both files:
192+
193+
```typescript
194+
const SERVICE_NAME = 'your_custom_service';
195+
```
196+
197+
### Change Request Interval
198+
199+
Modify the `REQUEST_INTERVAL` in the client:
200+
201+
```typescript
202+
const REQUEST_INTERVAL = 1000; // Send requests every 1 second
203+
```
204+
205+
### Use Different Service Types
206+
207+
To use a different service type, update the type string and interface:
208+
209+
```typescript
210+
// For example, using a custom service
211+
const service = node.createService(
212+
'your_package/srv/YourService',
213+
'service_name',
214+
callback
215+
);
216+
```
217+
218+
### Add Custom Logic
219+
220+
Modify the service callback to implement your own business logic:
221+
222+
```typescript
223+
(request, response) => {
224+
// Your custom service logic here
225+
response.result = processRequest(request);
226+
};
227+
```
228+
229+
## Troubleshooting
230+
231+
### Common Issues
232+
233+
1. **Service not available:**
234+
235+
```
236+
Service not available after 5 seconds
237+
```
238+
239+
**Solution**: Make sure the service server is running before starting the client.
240+
241+
2. **Module not found error:**
242+
243+
```
244+
Cannot find module 'rclnodejs'
245+
```
246+
247+
**Solution**: Ensure rclnodejs is properly linked and you're in the correct directory.
248+
249+
3. **TypeScript compilation errors:**
250+
```
251+
Type errors in service definitions
252+
```
253+
**Solution**: Check the type definitions in `types/rclnodejs.d.ts` match your usage.
254+
255+
### Debugging Tips
256+
257+
1. **Check service list:**
258+
259+
```bash
260+
ros2 service list
261+
ros2 service type /add_two_ints
262+
```
263+
264+
2. **Call service manually:**
265+
266+
```bash
267+
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts "{a: 1, b: 2}"
268+
```
269+
270+
3. **Monitor service info:**
271+
```bash
272+
ros2 service info /add_two_ints
273+
```
274+
275+
## Next Steps
276+
277+
After running this demo, you might want to explore:
278+
279+
1. **Custom Service Types**: Create your own service definitions
280+
2. **Asynchronous Services**: Implement long-running service operations
281+
3. **Service Parameters**: Use ROS2 parameters in your services
282+
4. **Service Discovery**: Implement dynamic service discovery
283+
5. **Lifecycle Services**: Create managed lifecycle service nodes
284+
285+
## License
286+
287+
This demo is licensed under the Apache License 2.0, same as the rclnodejs project.

ts_demo/services/package.json

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
{
2+
"name": "rclnodejs-ts-services-demo",
3+
"version": "1.0.0",
4+
"description": "TypeScript demo for rclnodejs services (client and server)",
5+
"main": "dist/client.js",
6+
"scripts": {
7+
"prebuild": "npm run clean",
8+
"build": "tsc",
9+
"start:server": "npm run build && node dist/server.js",
10+
"start:client": "npm run build && node dist/client.js",
11+
"start:both": "npm run build && concurrently \"node dist/server.js\" \"node dist/client.js\"",
12+
"clean": "rimraf dist",
13+
"dev:server": "ts-node src/server.ts",
14+
"dev:client": "ts-node src/client.ts",
15+
"check-types": "tsc --noEmit"
16+
},
17+
"keywords": [
18+
"rclnodejs",
19+
"ros2",
20+
"typescript",
21+
"client",
22+
"server",
23+
"service",
24+
"demo"
25+
],
26+
"author": "rclnodejs contributors",
27+
"license": "Apache-2.0",
28+
"devDependencies": {
29+
"@types/node": "^22.16.4",
30+
"concurrently": "^9.2.0",
31+
"rimraf": "^6.0.1",
32+
"ts-node": "^10.9.2",
33+
"typescript": "^5.8.3"
34+
},
35+
"dependencies": {
36+
"rclnodejs": "file:../../"
37+
}
38+
}

0 commit comments

Comments
 (0)