Tiếp theo, chúng ta sẽ tạo một file tên là simple_publisher.py trong thư mục publisher_pkg ở trong package publisher_pkg mà chúng ta vừa tạo. Các bạn lưu ý là file này phải nằm trong thư mục cùng tên nhưng nằm trong package vừa tạo nhé. Cụ thể là đường dẫn tới file simple_publisher.py là ~/ros2_ws/src/publisher_pkg/publisher_pkg/simple_publisher.py
Tiếp theo, các bạn hãy copy những dòng code sau vào file simple_publisher.py
import rclpy
# import the ROS2 python libraries
from rclpy.node import Node
# import the Twist interface from the geometry_msgs package
from geometry_msgs.msg import Twist
class SimplePublisher(Node):
def __init__(self):
# Here you have the class constructor
# call super() in the constructor to initialize the Node object
# the parameter you pass is the node name
super().__init__('simple_publisher')
# create the publisher object
# in this case, the publisher will publish on /cmd_vel Topic with a queue size of 10 messages.
# use the Twist module for /cmd_vel Topic
self.publisher_ = self.create_publisher(Twist, 'cmd_vel', 10)
# define the timer period for 0.5 seconds
timer_period = 0.5
# create a timer sending two parameters:
# - the duration between 2 callbacks (0.5 seconds)
# - the timer function (timer_callback)
self.timer = self.create_timer(timer_period, self.timer_callback)
def timer_callback(self):
# Here you have the callback method
# create a Twist message
msg = Twist()
# define the linear x-axis velocity of /cmd_vel Topic parameter to 0.5
msg.linear.x = 0.5
# define the angular z-axis velocity of /cmd_vel Topic parameter to 0.5
msg.angular.z = 0.5
# Publish the message to the Topic
self.publisher_.publish(msg)
# Display the message on the console
self.get_logger().info('Publishing: "%s"' % msg)
def main(args=None):
# initialize the ROS communication
rclpy.init(args=args)
# declare the node constructor
simple_publisher = SimplePublisher()
# pause the program execution, waits for a request to kill the node (ctrl+c)
rclpy.spin(simple_publisher)
# Explicity destroys the node
simple_publisher.destroy_node()
# shutdown the ROS communication
rclpy.shutdown()
if __name__ == '__main__':
main()
File simple_publisher.py này chứa nội dung của một topic publisher cơ bản. Hiện tại thì các bạn chưa cần hiểu những dòng code này, mình sẽ giải thích ở phần sau. Chúng ta sẽ tiếp tục các bước tiếp theo để chạy thử code xem nó làm được gì trước nhé.
Tạo file launch
Đầu tiên, chúng ta sẽ tạo một thư mục launch ở trong package đang làm việc:
cd ~/ros2_ws/src/publisher_pkg
mkdir launch
Tiếp theo, ta sẽ tạo một file launch để chạy node publisher tên là publisher_pkg_launch_file.launch.py
cd ~/ros2_ws/src/publisher_pkg/launch
touch publisher_pkg_launch_file.launch.py
chmod +x publisher_pkg_launch_file.launch.py
Các bạn copy các dòng code sau vào trong file launch vừa mới tạo:
from launch import LaunchDescription
from launch_ros.actions import Node
def generate_launch_description():
return LaunchDescription([
Node(
package='publisher_pkg',
executable='simple_publisher',
output='screen'),
])
Chỉnh sửa file setup.py
Tiếp theo, các bạn hãy chỉnh sửa file setup.py để thiết lập các file vừa tạo với hệ thống package:
Trên Terminal sẽ hiển thị các nội dung message mà node mình vừa tạo đang publish lên topic /cmd_vel. Đồng thời robot cũng bắt đầu di chuyển thành vòng tròn.
Để kiểm tra thông tin đang ở trên topic /cmd_vel, các bạn chạy lệnh :
ros2 topic echo /cmd_vel
Giải thích code tạo publisher
Quy trình hoạt động
def main(args=None):
# initialize the ROS communication
rclpy.init(args=args)
# declare the node constructor
simple_publisher = SimplePublisher()
# pause the program execution, waits for a request to kill the node (ctrl+c)
rclpy.spin(simple_publisher)
# Explicity destroys the node
simple_publisher.destroy_node()
# shutdown the ROS communication
rclpy.shutdown()
Đầu tiên hệ thống sẽ khởi tạo giao tiếp ROS2 bằng lệnh
rclpy.init(args=args)
Khai báo và khởi tạo node publisher
simple_publisher = SimplePublisher()
Tạm dừng việc thực thi chương trình, chờ yêu cầu hủy node (ctrl+c)
rclpy.spin(simple_publisher)
Hủy node
simple_publisher.destroy_node()
Tắt hệ thống giao tiếp ROS2
rclpy.shutdown()
Tạo Class publisher
Phần code này cũng tương tự như khi tạo một class trong python thông thường với hàm khởi tạo __init__ và các hàm chức năng khác. Trong đó quan trọng nhất là các lệnh sau để thực hiện các chức năng liên quan tới ROS:
Khởi tạo một node có tên là 'simple_publisher':
super().__init__('simple_publisher')
Tạo một publisher cho topic /cmd_vel sử dụng Twist message với kích thước hàng đợi là 10:
ROS (Robot Operating System) se está convirtiendo en el “framework” estándar para programar robots. En este tutorial emplearemos los conceptos de tópicos y nodos para mover el robot “Turtlebot3” hacia múltiples posiciones deseadas. Hacemos uso de los mensajes del tópico /odom para conocer la posición estimada del robot y publicar en el tópico /cmd_vel para mover el robot a las posiciones deseadas. Todo esto es simulado en un mundo de Gazebo. Ten encuesta que se usará ROS2 Humble para este tutorial.
PASO 1: Abriendo el rosject
Para seguir este tutorial, necesitamos tener instalado ROS2 HUMBLE en nuestro sistema, y lo ideal sería tener un ros2_ws (Espacio de Trabajo ROS2). Para facilitarte la vida, ya hemos preparado un rosject para eso: https://app.theconstructsim.com/l/5fc977f5/.
Simplemente copiando el rosject (haciendo clic en el enlace de arriba), tendrás una configuración ya preparada para ti.
Después de haber copiado el rosject a tu propia área de trabajo, deberías ver el botón RUN. Haz clic en ese botón para lanzar el rosject (abajo tienes un ejemplo de rosject).
Tras pulsar el botón RUN, deberías tener cargado el rosject. Ahora, pasemos a la siguiente sección para ponernos manos a la obra.
El Turtlebot3 se moverá por una serie de posiciones en un orden específico, es decir, se moverá de su posición inicial a la 1ra posición deseada, una vez alcanzada, se moverá a la 2da posición y así sucesivamente. Para lograr esto, necesitamos de una estrategia.
Tengamos en cuenta que el robot conocerá las posiciones que debe alcanzar y su posición actual estimada gracias al tópico /odom, del cual aprovecharemos la posición en X, posición Y, y la rotación en Z.
Con ello, para alcanzar cada posición el Turtlebot3 realizará 2 movimientos: Primero, girar hasta que quede mirando a la posición deseada; Segundo, avanzar de manera recta hasta llegar a la posición.
Adicionalmente, debemos tener en cuenta el robot no se moverá en una línea recta de manera perfecta, por lo que se requiere compensar esa desviación conforme avanza. Esto se puede realizar añadiendo una velocidad angular cuando la orientación cambie demasiado.
Creación del paquete
Primero creamos un paquete en python para realizar un nodo-publicador-subscriptor que mueva al Turtlebot3 de la forma deseada. Necesitamos añadir las dependencias necesarias. Para ello ejecutamos en un terminal lo siguiente:
Debido a que en el tópico /odom la orientación es expresada en cuaterniones, el método euler_from_quaternion es necesario para convertir la orientación del robot de cuaterniones a la notación roll-pitch-yaw. Esto nos permite obtener la rotación del robot alrededor del eje z (yaw).
def euler_from_quaternion(self, quaternion):
"""
Converts quaternion (w in last place) to euler roll, pitch, yaw
quaternion = [x, y, z, w]
Below should be replaced when porting for ROS2 Python tf_conversions is done.
"""
x = quaternion[0]
y = quaternion[1]
z = quaternion[2]
w = quaternion[3]
sinr_cosp = 2 * (w * x + y * z)
cosr_cosp = 1 - 2 * (x * x + y * y)
roll = np.arctan2(sinr_cosp, cosr_cosp)
sinp = 2 * (w * y - z * x)
pitch = np.arcsin(sinp)
siny_cosp = 2 * (w * z + x * y)
cosy_cosp = 1 - 2 * (y * y + z * z)
yaw = np.arctan2(siny_cosp, cosy_cosp)
return roll, pitch, yaw
Este es el método definido en el timer y contiene la estrategia de control explicada anteriormente. Se ejecuta cada 0.1s y actualiza la velocidad del robot de acuerdo con la posición estimada.
Finalmente simularemos el comportamiento en gazebo, para ello primero iniciamos la simulación del Turtlebot3, cuyo paquete ya esta en este rosject. Esta se puede obtener desde este link.
Để hệ thống nhận diện được các câu lệnh của ROS2 thì chúng ta cần source file setup.bash của ROS2 trước.
Source file setup của ROS2 trên Terminal 1: source /opt/ros/humble/setup.bash
Để tạo package ROS2, chúng ta cần có một không gian làm việc ROS2.
Cùng tạo một không gian làm việc ROS2 tên là ros2_ws bằng cách tạo folder ros2_ws và một thư mục nguồn src chứacode của các package bằng các lệnh sau: mkdir ros_ws
cd ros_ws
mkdir src
Tạo một package tên là my_package ở trong thư mục src của không gian làm việc vừa tạo bằng trình tạo package tựđộng của ROS2: cd ~/ros_ws/src
ros2 pkg create --build-type ament_python my_package --dependencies rclpy
Một câu lệnh tạo package có cú pháp như sau: ros2 pkg create --build-type ament_python <package_name> --dependencies <package_dependency_1> <package_dependency_2>
Trong đó:
ros2: câu lệnh của ROS2
pkg: (package) thực hiện các hành động liên quan tới package
create: tạo một package mới
–build-type: truyền tham số về cách build package
ament_python: package sẽ được build dựa trên python
<package_name>: tên của package muốn tạo
–dependencies: truyền tham số tên các package mà package muốn tạo phụ thuộc
<package_dependency_1>: tên của package phụ thuộc
Compile package trong ROS2
Sau khi tạo xong package, bạn nên build package vừa tạo. Đây là cách nhanh nhất để xác định xem các package phụthuộc mà bạn đã liệt kê có hoạt động hay không và kiểm tra xem dữ liệu đã nhập có sai sót gì không. Thực hiện các lệnhsau để build các package trong không gian làm việc ros_ws: cd ~/ros_ws
colcon build
Để build từng package riêng lẻ thì ta dùng lệnh sau:
cd ~/ros_ws
colcon build --packages-select <package_name>
Sau mỗi lần build xong package, hãy tạo thói quen source file setup.bash từ thư mục install để ROS2 có thể tìm thấycác package trong không gian làm việc
source ~/ros_ws/install/setup.bash
Để xác nhận rằng package đã được tạo thành công và đã được tích hợp vào hệ thống ROS2, hãy liệt kê các package đãđược khai báo với ROS2. ros2 pkg list
Nếu package vừa tạo có tên trong danh sách thì chúng ta đã thành công.
Một cách nhanh hơn là ta có thể sử dụng lệnh grep trong Terminal để tìm nhanh tên package vừa tạo:
ROS (Mfumo wa Uendeshaji wa Roboti) unakuwa “mfumo” wa kawaida wa roboti za kutengeneza programu. Katika chapisho hili, hebu tujifunze jinsi ya kuunda kifurushi cha ROS2, muhimu kwa kutoa maagizo kwa roboti, kwa kutumia amri ya ros2.
Kutengeneza rosject
Ili kufuata mafunzo haya, tunahitaji kuwa na ROS2 iliyosakinishwa katika mfumo wetu, na kwa hakika ros2_ws (ROS2 Workspace). Ili kurahisisha maisha yako, tutaunda mpango wa kubofya kiungo hiki: https://app.theconstructsim.com/
Hii inakuleta kwenye ukurasa wa kutua wa kuunda, hapo tutaenda kwa myrosjects na kisha kuunda rosject mpya, hatua zimeangaziwa katika miraba ya bluu.
Baada ya kuunda rosject mpya, weka usambazaji ambao ungependa kutumia kwa kesi yetu Humble na jina la rosject na maelezo mafupi.
Baada ya kubonyeza kitufe cha Unda, unapaswa kuwa na rosject kwenye rosjects zangu Bonyeza na ubonyeze RUN.
Kuunda kifurushi cha ros2.
Ili kuunda kifurushi cha ROS2, tunahitaji kuwa na Nafasi ya Kazi ya ROS2, na kwa hiyo, tunahitaji terminal.
Wacha tufungue terminal kwa kubofya kitufe cha Fungua terminal mpya.
Mara tu ndani ya terminal tumia amri kuona vitu vilivyopo kwenye saraka ya sasa:
ls
Kisha nenda kwenye saraka ifuatayo ambapo tutaunda kifurushi:
Fungua kihariri cha msimbo kulia na uunde hati kwenye py_pubsub fille inayoitwa py_pubsub.py. Hii inafanywa kwa kubofya kulia kwenye py_pubsub na kubofya kuunda faili mpya
Nakili na ubandike yafuatayo na hati ya python ambayo ina mchapishaji na aliyejiandikisha kwenye hati yetu
Mehrere Nodes können gleichzeitig über ein gemeinsames Launch-File gestartet werden. Durch die Verwendung von Python für diesen Start können einfach komplexe Algorithmen implementiert werden.
Öffne das Rosject
Über RUN kann das rosject gestartet werden.
Als nächstes erstellen wir den Ordner „launch“ in dem Package „start“, in welchem wir unsere Launch Files speichern werden.
In diesem erstellen wir das Launch File „general_launch.py“.
Anschließend passen wir die setup.py an, damit das Launch File gestartet werden kann.
Als nächsten programmieren wir das eigentliche Launch File. In diesem wird die Funktion „generate_launch_description()“ verwendet, deshalb definieren wird diese und geben für einen ersten Test erstmal eine leere Liste zurück.
Anschließend starten wir das Launch File, indem wir erst in den Workspace gehen, dann den Bauprozess durchlaufen und danach mit „ros2 launch start general_launch.py“ das Ganze starten. Tipp: durch die Verwendung von TAB kann man sich viel Tipparbeit und Zeit sparen.
Das sollte erfolgreich keine Nodes starten, da unsere Launch Description aktuell leer ist.
Um dies zu ändern, füllen wir die Launch Description mit zwei Nodes und nehmen einen Prozess zum ROS-Bag aufnehmen auf.
Nun können wir das ganze erneut bauen und starten. Wir erhalten:
Wir haben nun mit einem ROS2 Launch File mehrere Nodes und Prozesse gestartet. Dies kann nun beliebig erweitert werden. Wir hoffen, dass dieser Post helfen konnte und Dir gefallen hat.