-
Notifications
You must be signed in to change notification settings - Fork 79
Provide tutorial about basic concepts of ROS2 #1243
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,399 @@ | ||||||||||||||||||||||||
| # ROS 2 Basic Concepts Tutorial | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| This tutorial introduces the fundamental communication patterns in ROS 2: **Topics** (publish/subscribe) and **Services** (request/response). These are essential building blocks for any ROS 2 application. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## Table of Contents | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - [What are ROS 2 Communication Patterns?](#what-are-ros-2-communication-patterns) | ||||||||||||||||||||||||
| - [Topics (Publish/Subscribe)](#topics-publishsubscribe) | ||||||||||||||||||||||||
| - [Services (Request/Response)](#services-requestresponse) | ||||||||||||||||||||||||
| - [When to Use Topics vs Services](#when-to-use-topics-vs-services) | ||||||||||||||||||||||||
| - [Running the Examples](#running-the-examples) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## What are ROS 2 Communication Patterns? | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ROS 2 provides three primary communication patterns: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - **📡 Topics** - Continuous data streams (pub/sub) | ||||||||||||||||||||||||
| - **🔧 Services** - Remote procedure calls (request/response) | ||||||||||||||||||||||||
| - **⚡ Actions** - Long-running tasks with feedback (covered in separate tutorial) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| These patterns enable **distributed communication** between nodes in a robotics system, allowing for flexible, modular architectures. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ## Topics (Publish/Subscribe) | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### Concept Overview | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| **Topics** implement a **publish/subscribe** communication pattern where: | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| - **Publishers** produce data and send it to a named topic | ||||||||||||||||||||||||
| - **Subscribers** consume data from the same named topic | ||||||||||||||||||||||||
| - **Anonymous** - Subscribers don't know which publisher sent the data | ||||||||||||||||||||||||
| - **Many-to-many** - Multiple publishers and subscribers per topic | ||||||||||||||||||||||||
| - **Asynchronous** - Publishers don't wait for subscribers | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| Topics are ideal for **continuous data streams** like sensor readings, robot state, or camera images. | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### Basic Publisher Example | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```javascript | ||||||||||||||||||||||||
| const rclnodejs = require('rclnodejs'); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| async function createPublisher() { | ||||||||||||||||||||||||
| await rclnodejs.init(); | ||||||||||||||||||||||||
| const node = rclnodejs.createNode('publisher_example_node'); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Create a publisher for String messages on 'topic' | ||||||||||||||||||||||||
| const publisher = node.createPublisher('std_msgs/msg/String', 'topic'); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| let counter = 0; | ||||||||||||||||||||||||
| setInterval(() => { | ||||||||||||||||||||||||
| const message = `Hello ROS ${counter}`; | ||||||||||||||||||||||||
| console.log(`Publishing message: ${message}`); | ||||||||||||||||||||||||
| publisher.publish(message); | ||||||||||||||||||||||||
| counter++; | ||||||||||||||||||||||||
| }, 1000); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| rclnodejs.spin(node); | ||||||||||||||||||||||||
| } | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| createPublisher().catch(console.error); | ||||||||||||||||||||||||
| ``` | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ### Basic Subscriber Example | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| ```javascript | ||||||||||||||||||||||||
| const rclnodejs = require('rclnodejs'); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| async function createSubscriber() { | ||||||||||||||||||||||||
| await rclnodejs.init(); | ||||||||||||||||||||||||
| const node = rclnodejs.createNode('subscriber_example_node'); | ||||||||||||||||||||||||
|
|
||||||||||||||||||||||||
| // Create a subscriber for String messages on 'topic' | ||||||||||||||||||||||||
| node.createSubscription('std_msgs/msg/String', 'topic', (msg) => { | ||||||||||||||||||||||||
| console.log(`Received message: ${typeof msg}`, msg); | ||||||||||||||||||||||||
|
||||||||||||||||||||||||
| console.log(`Received message: ${typeof msg}`, msg); | |
| console.log(`Received message: ${msg.data}`); |
Copilot
AI
Aug 28, 2025
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.
The use of BigInt for integer values in ROS 2 service requests may not be necessary or correct. Standard JavaScript numbers should typically work for AddTwoInts service. The documentation should clarify when BigInt is required.
| a: BigInt(10), | |
| b: BigInt(15), | |
| a: 10, | |
| b: 15, |
Copilot
AI
Aug 28, 2025
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.
The expected output shows 'string Hello ROS 0' but with the correct message structure (msg.data), it should display just 'Hello ROS 0' without the type information.
| Received message: string Hello ROS 0 | |
| Received message: string Hello ROS 1 | |
| Received message: string Hello ROS 2 | |
| Received message: Hello ROS 0 | |
| Received message: Hello ROS 1 | |
| Received message: Hello ROS 2 |
Copilot
AI
Aug 28, 2025
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.
The expected output shows BigInt values (45n, 67n) but the actual example code uses BigInt(10) and BigInt(15). The expected output should match the input values from the example code.
| Incoming request: object { a: 45n, b: 67n } | |
| Sending response: object { sum: 112n } | |
| ``` | |
| **Service client terminal:** | |
| ``` | |
| Sending: object { a: 45n, b: 67n } | |
| Result: object { sum: 112n } | |
| Incoming request: object { a: 10n, b: 15n } | |
| Sending response: object { sum: 25n } |
Service client terminal:
Sending: object { a: 10n, b: 15n }
Result: object { sum: 25n }
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.
The publish method expects a message object with the correct structure for std_msgs/msg/String, but a plain string is being passed. It should be
publisher.publish({data: message});to match the String message type structure.