Logo

الـTopics في ROS 2، وnodes النشر (Publisher) والاشتراك (Subscriber)

4 دقائق قراءة
شرائح الدرس
1 / 11

مواضيع ROS 2 (Topics) وعقد النشر والاشتراك

نموذج النشر والاشتراك (Pub/Sub) في التطبيق العملي

مقدمة: نموذج الـTopics وPub/Sub

في ROS 2، تتواصل الـnodes مع بعضها باستخدام نموذج النشر/الاشتراك (publish/subscribe أو pub/sub) عبر الـTopics. فالـPublisher يرسل رسائل إلى topic معين، والـSubscriber يستقبل الرسائل من ذلك الـtopic. هذا الأسلوب يفصل الـnodes عن بعضها البعض (decoupling) ويتيح تواصلاً مرناً بينها.


مثال كلاسيكي: nodes الـTalker والـListener

مثال "talker" و"listener" هو أبسط توضيح عملي لنموذج pub/sub.

1. شغّل node الـTalker

node الـtalker ينشر رسائل إلى topic باسم /chatter.

ros2 run demo_nodes_py talker

2. شغّل node الـListener

node الـlistener يشترك في topic باسم /chatter ويطبع الرسائل المستقبَلة.

ros2 run demo_nodes_py listener

3. افحص الـTopics

  • عرض قائمة الـtopics النشطة:
    ros2 topic list
  • عرض الرسائل الواردة على /chatter لحظيًا (echo):
    ros2 topic echo /chatter

Turtlesim: عرض مرئي للـTopics

turtlesim هي أداة رسومية لتصور الـtopics ونموذج pub/sub أثناء عمله فعليًا.

1. شغّل turtlesim_node

ros2 run turtlesim turtlesim_node

2. تحكّم بالسلحفاة عبر teleop

ros2 run turtlesim turtle_teleop_key
  • node التحكم عن بعد (teleop) ينشر أوامر السرعة إلى /turtle1/cmd_vel.
  • node الـturtlesim يشترك في /turtle1/cmd_vel ويحرّك السلحفاة بناءً عليها.

3. افحص topics الخاصة بـturtlesim

  • عرض قائمة الـtopics:
    ros2 topic list
  • عرض أوامر السرعة لحظيًا:
    ros2 topic echo /turtle1/cmd_vel

4. معلومات الـTopic ونوع الرسالة

للحصول على معلومات عن topic ونوع الرسالة الخاص به:

ros2 topic info /turtle1/cmd_vel

مثال على المخرجات:

Type: geometry_msgs/msg/Twist
Publisher count: 1
Subscription count: 1

لرؤية بنية نوع الرسالة:

ros2 interface show geometry_msgs/msg/Twist

وهذا يُعبّر عن السرعة في الفضاء الحر مقسّمة إلى جزئها الخطي (linear) وجزئها الزاوي (angular):

# This expresses velocity in free space broken into its linear and angular parts.
 
Vector3 linear
  float64 x
  float64 y
  float64 z
 
Vector3 angular
  float64 x
  float64 y
  float64 z

مثال: node ناشر (Publisher) لـturtlesim

لنشر أوامر السرعة إلى turtlesim، تحتاج إلى إضافة هذه الاعتماديات (dependencies) في ملف package.xml الخاص بحزمتك:

<depend>rclpy</depend>
<depend>geometry_msgs</depend>
<depend>turtlesim</depend>

إليك node ناشر بسيط يجعل السلحفاة تتحرك في مسار دائري عن طريق نشر رسائل من نوع Twist إلى /turtle1/cmd_vel:

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from geometry_msgs.msg import Twist
 
class DrawCircleNode(Node):
    def __init__(self):
        super().__init__("draw_circle")
        self.cmd_vel_pub = self.create_publisher(Twist, "/turtle1/cmd_vel", 10)
        self.timer = self.create_timer(0.5, self.send_velocity_command)
        self.get_logger().info("Draw circle node has been started")
 
    def send_velocity_command(self):
        msg = Twist()
        msg.linear.x = 2.0
        msg.angular.z = 1.0
        self.cmd_vel_pub.publish(msg)
 
def main(args=None):
    rclpy.init(args=args)
    node = DrawCircleNode()
    rclpy.spin(node)
    rclpy.shutdown()
 
if __name__ == "__main__":
    main()
  • يتم إنشاء الـPublisher لـtopic باسم /turtle1/cmd_vel باستخدام نوع الرسالة Twist.
  • المؤقّت (timer) يستدعي بشكل دوري الدالة send_velocity_command، والتي تنشر أمر سرعة يحرّك السلحفاة في مسار دائري.

مثال: node مشترك (Subscriber) لموضع (Pose) السلحفاة

للاشتراك في موضع (pose) السلحفاة، استخدم الاعتماديات التالية في ملف package.xml الخاص بك:

<depend>rclpy</depend>
<depend>turtlesim</depend>

الـtopic باسم /turtle1/pose يستخدم نوع الرسالة turtlesim/msg/Pose. يمكنك فحصه بالأمر:

ros2 topic info /turtle1/pose
ros2 interface show turtlesim/msg/Pose

بنية الرسالة:

float32 x
float32 y
float32 theta
float32 linear_velocity
float32 angular_velocity

إليك node مشترك بسيط لـ/turtle1/pose:

#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
from turtlesim.msg import Pose
 
class PoseSubscriberNode(Node):
    def __init__(self):
        super().__init__("pose_subscriber")
        self.subscription = self.create_subscription(
            Pose,
            "/turtle1/pose",
            self.pose_callback,
            10)
        self.subscription  # prevent unused variable warning
        self.get_logger().info("Pose subscriber node has been started")
 
    def pose_callback(self, msg):
        self.get_logger().info(
            f"x: {msg.x}, y: {msg.y}, theta: {msg.theta}, "
            f"linear_velocity: {msg.linear_velocity}, angular_velocity: {msg.angular_velocity}"
        )
 
def main(args=None):
    rclpy.init(args=args)
    node = PoseSubscriberNode()
    rclpy.spin(node)
    rclpy.shutdown()
 
if __name__ == "__main__":
    main()
  • الـSubscriber ينصت إلى /turtle1/pose ويطبع موضع السلحفاة وسرعتها.

تشغيل nodes الـPublisher والـSubscriber

###->>> لا تنسَ إضافة الـnodes كملفات تنفيذية (excutables) <<<-

  1. ابنِ مساحة العمل الخاصة بك:

    colcon build --symlink-install
    source install/setup.bash
  2. شغّل node الـPublisher:

    ros2 run my_first_py_pkg draw_circle
  3. شغّل node الـSubscriber (في نافذة طرفية (terminal) منفصلة):

    ros2 run my_first_py_pkg pose_subscriber

تصور (Visualizing) الـTopics

  • استخدم rqt_graph لتصور الـnodes والـtopics.
  • عرض قائمة الـtopics النشطة:
    ros2 topic list
  • عرض الرسائل على topic معين لحظيًا:
    ros2 topic echo /topic

مرجع

  • راجع 01/Readme.md للاطلاع على إعداد مساحة العمل والحزمة.

يشرح هذا الدليل كيفية استخدام الـtopics وإنشاء nodes للنشر (publisher) والاشتراك (subscriber) في ROS 2، بناءً على الأساسيات المذكورة في القسم 01. وهو يتضمن الآن مثالَي talker/listener الكلاسيكيين ومثال turtlesim، إضافةً إلى فحص معلومات الـtopic ونوع الرسالة، ونماذج عملية لـnodes النشر والاشتراك في turtlesim باستخدام geometry_msgs/msg/Twist وturtlesim/msg/Pose.