-
Notifications
You must be signed in to change notification settings - Fork 79
Add a subscriber/publisher demo for typescript #1194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 1 commit
Commits
Show all changes
2 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,341 @@ | ||
| # rclnodejs TypeScript Topics Demo | ||
|
|
||
| This demo demonstrates how to use **rclnodejs** with TypeScript to create ROS2 publishers and subscribers. The demo includes a publisher that sends string messages to a topic called `ts_demo` and a subscriber that receives and displays those messages. | ||
|
|
||
| ## Features | ||
|
|
||
| - 🚀 **TypeScript Support**: Fully typed ROS2 node implementation using rclnodejs TypeScript interfaces | ||
| - 📤 **Publisher**: Sends timestamped string messages at regular intervals | ||
| - 📥 **Subscriber**: Receives and displays messages with timestamps | ||
| - 🛡️ **Type Safety**: Leverages TypeScript's type system for compile-time safety | ||
| - 🎯 **Error Handling**: Comprehensive error handling and graceful shutdown | ||
| - 📊 **Message Counting**: Tracks published and received message counts | ||
| - 🎨 **Console Output**: Colorful and informative console messages | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| Before running this demo, ensure you have: | ||
|
|
||
| 1. **Node.js** (>= 16.13.0) | ||
| 2. **ROS 2** installed and sourced | ||
| 3. **rclnodejs** built and available | ||
|
|
||
| ### ROS 2 Setup | ||
|
|
||
| Make sure your ROS 2 environment is properly sourced before running the demo: | ||
|
|
||
| ```bash | ||
| # For example, if using ROS 2 Jazzy | ||
| source /opt/ros/jazzy/setup.bash | ||
|
|
||
| # Or if you have a custom workspace | ||
| source /path/to/your/ros2_ws/install/setup.bash | ||
| ``` | ||
|
|
||
| ### Verify rclnodejs Installation | ||
|
|
||
| From the root of the rclnodejs project, ensure it's built: | ||
|
|
||
| ```bash | ||
| cd /path/to/rclnodejs | ||
| npm install | ||
| npm run build | ||
| ``` | ||
|
|
||
| ## Installation | ||
|
|
||
| Navigate to this demo directory and install dependencies: | ||
|
|
||
| ```bash | ||
| cd ts_demo/topics | ||
| npm install | ||
| ``` | ||
|
|
||
| ## Usage | ||
|
|
||
| ### Build and Run | ||
|
|
||
| 1. **Build the TypeScript code:** | ||
|
|
||
| ```bash | ||
| npm run build | ||
| ``` | ||
|
|
||
| 2. **Run the publisher (in one terminal):** | ||
|
|
||
| ```bash | ||
| npm run start:publisher | ||
| ``` | ||
|
|
||
| 3. **Run the subscriber (in another terminal):** | ||
|
|
||
| ```bash | ||
| npm run start:subscriber | ||
| ``` | ||
|
|
||
| 4. **Or run both simultaneously:** | ||
| ```bash | ||
| npm run start:both | ||
| ``` | ||
|
|
||
| ### Development Mode | ||
|
|
||
| For development, you can run TypeScript files directly with ts-node: | ||
|
|
||
| 1. **Run the publisher:** | ||
|
|
||
| ```bash | ||
| npm run dev:publisher | ||
| ``` | ||
|
|
||
| 2. **Run the subscriber:** | ||
|
|
||
| ```bash | ||
| npm run dev:subscriber | ||
| ``` | ||
|
|
||
| 3. **Type check only:** | ||
| ```bash | ||
| npm run check-types | ||
| ``` | ||
|
|
||
| ## TypeScript Setup | ||
|
|
||
| This demo includes a self-contained TypeScript configuration that allows compilation without requiring the full rclnodejs installation to be built first. The key components are: | ||
|
|
||
| ### Local Type Definitions | ||
|
|
||
| The `types/rclnodejs.d.ts` file provides basic TypeScript declarations for rclnodejs, enabling: | ||
|
|
||
| - ✅ TypeScript compilation without dependencies | ||
| - ✅ Type checking and IntelliSense support | ||
| - ✅ Proper interface definitions for common ROS2 operations | ||
|
|
||
| ### TypeScript Configuration | ||
|
|
||
| The `tsconfig.json` is configured to: | ||
|
|
||
| - Use local type definitions from the `types/` directory | ||
| - Compile TypeScript to JavaScript in the `dist/` directory | ||
| - Generate source maps and declaration files | ||
| - Enable strict type checking | ||
|
|
||
| ### Development vs Runtime | ||
|
|
||
| - **Compilation**: Uses local type definitions (no rclnodejs dependency) | ||
| - **Runtime**: Requires actual rclnodejs installation and ROS 2 environment | ||
|
|
||
| ## Expected Output | ||
|
|
||
| ### Publisher Output: | ||
|
|
||
| ``` | ||
| Starting TypeScript Publisher Demo... | ||
| ✓ rclnodejs initialized | ||
| ✓ Created node: /ts_publisher_demo | ||
| ✓ Created publisher on topic: ts_demo | ||
| ✓ Created timer with 1000ms interval | ||
| 🚀 Publisher is running. Press Ctrl+C to stop... | ||
|
|
||
| 📤 Published: "Hello from TypeScript publisher! Message #1 at 2025-07-16T10:30:00.123Z" | ||
| 📤 Published: "Hello from TypeScript publisher! Message #2 at 2025-07-16T10:30:01.125Z" | ||
| 📤 Published: "Hello from TypeScript publisher! Message #3 at 2025-07-16T10:30:02.127Z" | ||
| ... | ||
| ``` | ||
|
|
||
| ### Subscriber Output: | ||
|
|
||
| ``` | ||
| Starting TypeScript Subscriber Demo... | ||
| ✓ rclnodejs initialized | ||
| ✓ Created node: /ts_subscriber_demo | ||
| ✓ Created subscription on topic: ts_demo | ||
| 👂 Subscriber is listening. Press Ctrl+C to stop... | ||
|
|
||
| 📥 [1] Received: "Hello from TypeScript publisher! Message #1 at 2025-07-16T10:30:00.123Z" | ||
| Timestamp: 2025-07-16T10:30:00.124Z | ||
| 📥 [2] Received: "Hello from TypeScript publisher! Message #2 at 2025-07-16T10:30:01.125Z" | ||
| Timestamp: 2025-07-16T10:30:01.126Z | ||
| ... | ||
| ``` | ||
|
|
||
| ## Project Structure | ||
|
|
||
| ``` | ||
| ts_demo/topics/ | ||
| ├── package.json # Project dependencies and scripts | ||
| ├── tsconfig.json # TypeScript configuration | ||
| ├── README.md # This file | ||
| ├── src/ # TypeScript source files | ||
| │ ├── publisher.ts # Publisher implementation | ||
| │ └── subscriber.ts # Subscriber implementation | ||
| └── dist/ # Compiled JavaScript (after build) | ||
| ├── publisher.js | ||
| └── subscriber.js | ||
| ``` | ||
|
|
||
| ## Code Explanation | ||
|
|
||
| ### Publisher (`src/publisher.ts`) | ||
|
|
||
| The publisher demonstrates: | ||
|
|
||
| - **Node Creation**: Creates a ROS2 node using TypeScript | ||
| - **Publisher Setup**: Creates a publisher for `std_msgs/msg/String` messages | ||
| - **Timer Usage**: Uses `node.createTimer()` for periodic message publishing | ||
| - **Message Creation**: Uses `rclnodejs.createMessageObject()` with proper typing | ||
| - **Graceful Shutdown**: Handles SIGINT for clean shutdown | ||
|
|
||
| Key TypeScript features used: | ||
|
|
||
| ```typescript | ||
| import * as rclnodejs from 'rclnodejs'; | ||
|
|
||
| const node = new rclnodejs.Node('ts_publisher_demo'); | ||
| const publisher = node.createPublisher('std_msgs/msg/String', TOPIC_NAME); | ||
| const message = rclnodejs.createMessageObject('std_msgs/msg/String'); | ||
| ``` | ||
|
|
||
| ### Subscriber (`src/subscriber.ts`) | ||
|
|
||
| The subscriber demonstrates: | ||
|
|
||
| - **Subscription Creation**: Creates a typed subscription for string messages | ||
| - **Callback Handling**: Processes incoming messages with proper TypeScript typing | ||
| - **Message Processing**: Displays received messages with timestamps | ||
|
|
||
| Key TypeScript features used: | ||
|
|
||
| ```typescript | ||
| const subscription = node.createSubscription( | ||
| 'std_msgs/msg/String', | ||
| TOPIC_NAME, | ||
| (message: rclnodejs.std_msgs.msg.String) => { | ||
| console.log(`Received: "${message.data}"`); | ||
| } | ||
| ); | ||
| ``` | ||
|
|
||
| ## TypeScript Benefits | ||
|
|
||
| This demo showcases several TypeScript advantages: | ||
|
|
||
| 1. **Type Safety**: Compile-time checking prevents common errors | ||
| 2. **IntelliSense**: Better IDE support with autocompletion | ||
| 3. **Interface Definitions**: Clear contract definitions for ROS2 messages | ||
| 4. **Refactoring Safety**: Easier to maintain and modify code | ||
| 5. **Documentation**: Types serve as inline documentation | ||
|
|
||
| ## Troubleshooting | ||
|
|
||
| ### Common Issues | ||
|
|
||
| 1. **Module not found error for 'rclnodejs':** | ||
|
|
||
| ``` | ||
| Cannot find module 'rclnodejs' or its corresponding type declarations | ||
| ``` | ||
|
|
||
| **Solution**: Ensure you're in the correct directory and rclnodejs is properly linked: | ||
|
|
||
| ```bash | ||
| cd ts_demo/topics | ||
| npm install | ||
| ``` | ||
|
|
||
| 2. **ROS 2 environment not sourced:** | ||
|
|
||
| ``` | ||
| Error: Unable to find ROS 2 installation | ||
| ``` | ||
|
|
||
| **Solution**: Source your ROS 2 setup file: | ||
|
|
||
| ```bash | ||
| source /opt/ros/jazzy/setup.bash | ||
| ``` | ||
|
|
||
| 3. **Build errors:** | ||
| ``` | ||
| TypeScript compilation errors | ||
| ``` | ||
| **Solution**: Check TypeScript configuration and ensure all dependencies are installed: | ||
| ```bash | ||
| npm install | ||
| npm run clean | ||
| npm run build | ||
| ``` | ||
|
|
||
| ### Debugging Tips | ||
|
|
||
| 1. **Enable verbose logging:** | ||
|
|
||
| ```bash | ||
| export RCUTILS_LOGGING_SEVERITY=DEBUG | ||
| ``` | ||
|
|
||
| 2. **Check ROS 2 topic list:** | ||
|
|
||
| ```bash | ||
| ros2 topic list | ||
| ros2 topic echo /ts_demo | ||
| ``` | ||
|
|
||
| 3. **Monitor topic info:** | ||
| ```bash | ||
| ros2 topic info /ts_demo | ||
| ``` | ||
|
|
||
| ## Customization | ||
|
|
||
| You can easily customize this demo: | ||
|
|
||
| ### Change Topic Name | ||
|
|
||
| Edit the `TOPIC_NAME` constant in both files: | ||
|
|
||
| ```typescript | ||
| const TOPIC_NAME = 'your_custom_topic'; | ||
| ``` | ||
|
|
||
| ### Change Message Type | ||
|
|
||
| To use a different message type, update the type string and interface: | ||
|
|
||
| ```typescript | ||
| // For example, using geometry_msgs/msg/Twist | ||
| const publisher = node.createPublisher('geometry_msgs/msg/Twist', 'cmd_vel'); | ||
| const message = rclnodejs.createMessageObject('geometry_msgs/msg/Twist'); | ||
| ``` | ||
|
|
||
| ### Adjust Publishing Rate | ||
|
|
||
| Modify the `PUBLISH_INTERVAL` in the publisher: | ||
|
|
||
| ```typescript | ||
| const PUBLISH_INTERVAL = 500; // Publish every 500ms | ||
| ``` | ||
|
|
||
| ## Next Steps | ||
|
|
||
| After running this demo, you might want to explore: | ||
|
|
||
| 1. **Different Message Types**: Try using other ROS2 message types like `geometry_msgs/msg/Twist` | ||
| 2. **Services**: Implement ROS2 services with TypeScript | ||
| 3. **Actions**: Create action servers and clients | ||
| 4. **Parameters**: Use ROS2 parameters in your TypeScript nodes | ||
| 5. **Lifecycle Nodes**: Implement managed lifecycle nodes | ||
|
|
||
| ## Contributing | ||
|
|
||
| This demo is part of the rclnodejs project. To contribute: | ||
|
|
||
| 1. Fork the rclnodejs repository | ||
| 2. Create a feature branch | ||
| 3. Make your changes | ||
| 4. Add tests if applicable | ||
| 5. Submit a pull request | ||
|
|
||
| ## License | ||
|
|
||
| This demo is licensed under the Apache License 2.0, same as the rclnodejs project. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| { | ||
| "name": "rclnodejs-ts-topics-demo", | ||
| "version": "1.0.0", | ||
| "description": "TypeScript demo for rclnodejs topics (publisher and subscriber)", | ||
| "main": "index.js", | ||
| "scripts": { | ||
| "prebuild": "npm run clean", | ||
| "build": "tsc", | ||
| "start:publisher": "npm run build && node dist/publisher.js", | ||
| "start:subscriber": "npm run build && node dist/subscriber.js", | ||
| "start:both": "npm run build && concurrently \"node dist/publisher.js\" \"node dist/subscriber.js\"", | ||
| "clean": "rimraf dist", | ||
| "dev:publisher": "ts-node src/publisher.ts", | ||
| "dev:subscriber": "ts-node src/subscriber.ts", | ||
| "check-types": "tsc --noEmit" | ||
| }, | ||
| "keywords": [ | ||
| "rclnodejs", | ||
| "ros2", | ||
| "typescript", | ||
| "publisher", | ||
| "subscriber", | ||
| "demo" | ||
| ], | ||
| "author": "rclnodejs contributors", | ||
| "license": "Apache-2.0", | ||
| "devDependencies": { | ||
| "@types/node": "^22.16.4", | ||
| "concurrently": "^9.2.0", | ||
| "rimraf": "^6.0.1", | ||
| "ts-node": "^10.9.2", | ||
| "typescript": "^5.8.3" | ||
| }, | ||
| "dependencies": { | ||
| "rclnodejs": "file:../../" | ||
| } | ||
| } | ||
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[nitpick] The
mainfield points toindex.js, which doesn’t exist in this project. Update it to an existing entry (e.g.,dist/publisher.js) or remove it if unused.