|
| 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. |
0 commit comments