ROS2 Message Interfaces: Ano at Paano Gamitin ang mga Ito – ROS Filipino Tutorial

Written by Christian Anabeza

18/04/2024

This tutorial is created by Robotics Ambassador Christian



Unit 1 Introduksyon sa Kurso

– Buod –

Tinatayang Oras na Kakailanganin: 30 minuto

Mabuhay!

Sa maikling gabay na ito, ating dadaluban kung ano nga ba ang mga ROS2 Messages at paano natin magagamit ang mga ito sa ating paggawa ng mga robots.

Bilang gabay sa mga tatalakayin ng proyektong ito, sila ay nakalista bilang mga sumusunod:

1. Introduksyon sa Kurso
1.1 Mga Pangangailangan sa Kurso at mga Sanggunian
2. Pagpapahayag ng Konsepto ng ROS2 Messages
3. Praktikal na Halimbawa: Paggawa ng Sariling Message at Paggamit nito sa uganayang publisher-subscriber

– Dulo ng Buod –

Unit 1.1 Mga Pangangailangan sa Kurso at mga Sanggunian

Para sa kursong ito, tinataya ng may-akda na may kaalaman ka na sa pangunahing operasyong pang-terminal ng mga sistemang gumagana sa Ubuntu 22.04 LTS na OS at maging sa pangunahing nabigasyon and commands na ginagamit sa mga Linux terminals. Kung nais mo pang matuto ng mga programming fundamentals na kailangan para sa pag-aral ng ROS, mangyaring tumungo at tignan ang kursong Code Foundation for ROS Learning Path ng The Construct! Tiyak na matututunan mo ang lahat ng kailangan mong kaalaman upang masimulan mo na ang paggamit ng ROS!

Mga Akdang Kasama sa Code Foundation for ROS Learning Path:
* Linux for Robotics
* Python 3 for Robotics
*Examination

Iba pang mga Sanggunian:
* The Construct Blog
* Course Support of The Construct and Robot Ignite Academy
* The Official Rosbotics Ambassadors Channel

Kung nais mong matuto hinggil sa kung paano gumawa at mag-ayos ng workspace directories sa ROS1 at ROs2, maaari mong tignan ang aking nakarrang gabay na ito: How to Create and Organize Workspaces in ROS1 and ROS2

At kung interesado ka na rin sa kung paano gumawa ng mga packages at nodes sa ROS2, mangyaring tignan mo na rin ang gabay na ito: How to Create Packages and Nodes in ROS2

Sa tutorial na ito, Gagamitin natin ang ROSject platform na handog ng TheConstruct! Subalit, kung nais niyong gumamit ng sariling virtual machine o computer, mangyaring gawing gabay ang OS-to-Distribution compatibilities na siyang ibinahagi ng opisyal na dokumentasyon ng ros.org para sa ROS2 Humble Hawksbill

* ROS2 Humble Hawksbill: PC o Virtual Machine na may Ubuntu 22.04 LTS

Unit 2: ROS2 Messages – Ano nga ba sila?

Sa kasalukuyan ay dapat pamilyar na tayo sa konsepto ng mga topics sa ROS2. Kung ating babalikan ang naging halimbawa noong nakaraan, ang mga ROS2 topics ay siyang mga nagsisilbing lagusan ng impormasyon kung saan maaari itong gamitin ng mga subscriber para mapatakbo ang isang feature ng robot. Ngayon naman’y ating dadaluban ang isa sa mga mahalagang aspeto ng mga ito at ito ang mga messages!

Sa ROS2, may tatlong pangunahing uri ng interface — ang messages, services, at actions. Sa gabay na ito, ating tatalakayin ang mga messages. Sa madaling salita, ang mga dokumentong ito ang siyang naglalaman ng mga variables na gagamitin ng ating robot o program hinggil sa pagpapagana ng naturang feature. Isang magandang halimbawa na nito ay ang Twist() message na gamit natin upang bigyan ng velocities and ating turtlesim.

Kung ating sisiyasatin ang laman ng Twist() message type, ito ang ating masisilayan:
Vector3  linear
Vector3  angular

At sa loob ng bawat Vector, ito naman ang laman nila:

linear: 
x: 0.0 
y: 0.0 
z: 0.0
angular: 
x: 0.0 
y: 0.0 
z: 0.0

Ibigsabihin nito ay mayroong tatlong posibleng velocities na pwedeng ipublish gamit ang message na ito. Ang mga linear velocities ay siyang tumutkoy sa paharap at palikod, pagilid, at pataas na galaw ng robot; habang ang mga angular naman ay tinatawag na pitch, yaw, at roll. Para sa mga groundbot, ang madalas gamitin na angular velocity ay ang yaw; habang para sa mga robot na panghimpapawid ay ginagamit ang anim na yan dahil mas marami ang kanilang Degrees of Freedom (DoF).

Ngayon, kung ating papansinin ang pagsulat ng mga messages sa ROS2, masasabi nating napakasimple ng kanilang istruktura. Ang tanging kailangan lamang na ilagay ay yung klase ng variable at yung pangalan nito — at hinggil naman sa pagpapangalan, dapat ay masimulan lamang ito sa kapital ng letra at ang file extension ay ‘.msg’.

<variable type> <variable name>   

Ngayon at alam na natin kung ano sila, halina’t ating simulan ang paggawa at paggamit ng ating mga customized na ROS2 messages!

Unit 3: Paggawa ng Sariling Message at Paggamit nito sa Uganayang Publisher-Subscriber

Bilang panimula, tayo muna ay gumawa ng ating Workspaces folder na siyang maglalaman ng lahat ng ating workspace para sa ROS2.

# Sa Terminal 1
user:~$ mkdir Workspaces

Matapos niyan ay gumawa tayo ng workspace na ating papangalanang sample_ws. Mangyaring patakbuhin na rin ang ‘colcon build’ pagkatapos sa loob nito.

# Sa Terminal 1
user:~/Workspaces$ mkdir sample_ws
user:~/Workspaces$ colcon build

Para sa gabay na ito, gagawa tayo ng dalawang packages — una ay ating tatawaging ‘my_interface_pkg’ na siyang maglalaman ng ating custom message at ang isa naman ay ating tatawagin ‘use_custom_interface_pkg’ kung saan natin gagawin ang mga publisher at subscriber na gagamit ng ating nagawang interface.

Ngayon ay ating unahin muna ang ‘my_interface_pkg’

# Sa Terminal 1

user:~/Workspaces$ cd sample_ws
user:~/Workspaces/sample_ws$ mkdir src
user:~/Workspaces/sample_ws$ cd src
user:~/Workspaces/sample_ws/src$ ros2 pkg create my_interface_pkg --build-type ament_cmake --dependencies std_msgs rclcpp

Isang mahalagang konseptong alalahanin ay sa tuwing gagawa ng package para sa mga interfaces ay dapat na ament_cmake ang build type ng mga ito at nakadepende sa rclcpp. Subalit para sa paggawa ng nodes ay malaya tayong pumili kung nais nating gumamit ng python o cpp na environment.

Kasunod ng paggawa ng package ay gumawa tayo ng folder na ating papangalanang ‘msg’ sa loob ng my_interface_pkg. Mula rito ay gumawa na rin tayo ng ating message file na ating papangalanang ‘Numbers.msg’

# Sa Terminal 1

user:~/Workspaces/sample_ws/src$ cd my_interface_pkg
user:~/Workspaces/sample_ws/src/my_interface_pkg$ mkdir msg
user:~/Workspaces/sample_ws/src/my_interface_pkg$ cd msg
user:~/Workspaces/sample_ws/src/my_interface_pkg/msg$ touch Numbers.msg

Mangyaring kopyahin ang naturang code sa ilalim na siyang magiging laman ng Numbers.msg

int32 a
int32 b

Tumungo sa CMakeList.txt na file at idagdag ang sumusunod na mga linya:

find_package(rosidl_default_generators REQUIRED)

rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/num.msg"
)

Ganito ang kalalabasan ng iyong CMakeList.txt

cmake_minimum_required(VERSION 3.8)
project(my_interface_pkg)

if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
  add_compile_options(-Wall -Wextra -Wpedantic)
endif()

# find dependencies
find_package(ament_cmake REQUIRED)
find_package(std_msgs REQUIRED)
find_package(rclcpp REQUIRED)
find_package(rosidl_default_generators REQUIRED)

if(BUILD_TESTING)
  find_package(ament_lint_auto REQUIRED)
  # the following line skips the linter which checks for copyrights
  # comment the line when a copyright and license is added to all source files
  set(ament_cmake_copyright_FOUND TRUE)
  # the following line skips cpplint (only works in a git repo)
  # comment the line when this package is in a git repo and when
  # a copyright and license is added to all source files
  set(ament_cmake_cpplint_FOUND TRUE)
  ament_lint_auto_find_test_dependencies()
endif()

rosidl_generate_interfaces(${PROJECT_NAME}
  "msg/Numbers.msg"
)

ament_package()

Ngayon naman ay tumungo sa package.xml at idagdag ang mga sumusunod na sipi ng code:

<?xml version="1.0"?>
<?xml-model href="http://download.ros.org/schema/package_format3.xsd" schematypens="http://www.w3.org/2001/XMLSchema"?>
<package format="3">
  <name>my_interface_pkg</name>
  <version>0.0.0</version>
  <description>TODO: Package description</description>
  <maintainer email="user@todo.todo">user</maintainer>
  <license>TODO: License declaration</license>

  <buildtool_depend>ament_cmake</buildtool_depend>

  <depend>std_msgs</depend>
  <depend>rclcpp</depend>

  <build_depend>rosidl_default_generators</build_depend>
  <exec_depend>rosidl_default_runtime</exec_depend>
  <member_of_group>rosidl_interface_packages</member_of_group>

  <test_depend>ament_lint_auto</test_depend>
  <test_depend>ament_lint_common</test_depend>

  <export>
    <build_type>ament_cmake</build_type>
  </export>
</package>

Siguraduhing na-save ang lahat ng mga file at i-compile ang naturang package

# Terminal 1

user:~/Workspaces/sample_ws/src/my_interface_pkg/msg$ cd ../../../
user:~/Workspaces/sample_ws$ colcon build

Ngayon naman ay tumungo tayo sa paggawa ng publisher at subscriber na gagamit ng ating custom message.

Una, gumawa ng python package na ating papangalanang ‘use_custom_interface_pkg’

# Sa Terminal 1

user:~/Workspaces/sample_ws$ cd src
user:~/Workspaces/sample_ws/src$ ros2 pkg create use_custom_interface_pkg --build-type ament_python --dependencies rclpy std_msgs geometry_msgs my_interface_pkg

Para sa ating mga codes, atin itong ilalagay sa loob ng /use_custom_interface_pkg/use_custom_interface_pkg na directory at papangalanan natin ang publisher at subscriber bilang sumusunod:

Publisher: custom_publisher.py
Subscriber: custom_subscriber.py

# Sa Terminal 1

user:~/Workspaces/sample_ws/src$ cd use_custom_interface_pkg/cd use_custom_interface_pkg/
user:~/Workspaces/sample_ws/src/use_custom_interface_pkg/cd use_custom_interface_pkg$ touch custom_subscriber.py custom_publisher.py

Siguraduhing executable na rin ang mga ito.

# Sa Terminal 1

user:~/Workspaces/sample_ws/src/use_custom_interface_pkg/cd use_custom_interface_pkg$ chmod +x custom_subscriber.py custom_publisher.py

Ngayon ay simulan na natin silang i-program!

Code para sa custom_publisher.py

import rclpy
from rclpy.node import Node
from my_interface_pkg.msg import Numbers
import random
import time

class CustomPublisher(Node):
    def __init__(self):
        super().__init__('custom_publisher')
        self.custom_publisher_ = self.create_publisher(Numbers, 'custom_topic_sample', 10)
        self.msg = Numbers()
        self.timer = self.create_timer(1, self.timer_callback)
    
    def timer_callback(self):
        
        self.msg.a = random.randint(1,10)
        self.msg.b = random.randint(1,10)
        self.custom_publisher_.publish(self.msg)
        self.get_logger().info(f"Publishing numbers: a={self.msg.a}, b={self.msg.b}")

def main(args=None):
    rclpy.init(args=args)
    custom_publisher = CustomPublisher()
    rclpy.spin(custom_publisher)
    custom_publisher.destroy_node()
    rclpy.shutdown()

if __name__=='__main__':
    main()

Code para sa custom_subscriber.py

import rclpy
from rclpy.node import Node
from my_interface_pkg.msg import Numbers

class CustomSubscriber(Node):
    def __init__(self):
        super().__init__('custom_subscriber')
        self.subscription = self.create_subscription(
            Numbers,
            'custom_topic_sample',
            self.listener_callback,
            10)

    def listener_callback(self, msg):
        sum_numbers = msg.a + msg.b
        self.get_logger().info(f"Received numbers: a={msg.a}, b={msg.b}. Sum: {sum_numbers}")

def main(args=None):
    rclpy.init(args=args)
    custom_subscriber_node = CustomSubscriber()
    rclpy.spin(custom_subscriber_node)
    custom_subscriber_node.destroy_node()
    rclpy.shutdown()

if __name__ == '__main__':
    main()

Matapos nating maprogram ang mga ito, tumungo tayo sa ‘setup.py’ at idagdag ang mga sumusunod na linya:

from glob import glob
import os


(os.path.join('share', package_name), glob('launch/*.launch.py'))

Sa loob naman ng ‘console_scripts’ ay gawin natin ang ating mga node:

'custom_publisher = use_custom_interface_pkg.custom_publisher:main',
'custom_subscriber = use_custom_interface_pkg.custom_subscriber:main'

Sa kalaunan ay ganito dapat ang ating setup.py:

from setuptools import setup
from glob import glob
import os

package_name = 'use_custom_interface_pkg'

setup(
    name=package_name,
    version='0.0.0',
    packages=[package_name],
    data_files=[
        ('share/ament_index/resource_index/packages',
            ['resource/' + package_name]),
        ('share/' + package_name, ['package.xml']),
        (os.path.join('share', package_name), glob('launch/*.launch.py'))
    ],
    install_requires=['setuptools'],
    zip_safe=True,
    maintainer='user',
    maintainer_email='user@todo.todo',
    description='TODO: Package description',
    license='TODO: License declaration',
    tests_require=['pytest'],
    entry_points={
        'console_scripts': [
            'custom_publisher = use_custom_interface_pkg.custom_publisher:main',
            'custom_subscriber = use_custom_interface_pkg.custom_subscriber:main'
        ],
    },
)

Matapos i-code ang mga ito, mangyaring muling i-compile ang kabuuan ng ‘sample_ws’. At ngayon, atin nang patakbuhin ang ating mga nagawang node na gumagamit ng ating custom message!

# Sa Terminal 1

user:~/Workspaces/sample_ws/src/use_custom_interface_pkg/cd use_custom_interface_pkg$ cd ../../../
user:~/Workspaces/sample_ws$ colcon build

Para sa bahaging ito, i-source ang terminal 2 and 3 para sa sample_ws

# Sa Terminal 2 at 3

user:~$ cd Workspaces/sample_ws
user:~/Workspaces/sample_ws$ source install/setup.bash

Patakbuhin ang publisher at subscriber sa Terminal 2 at 3

# Sa Terminal 2
user:~/Workspaces/sample_ws$ ros2 run use_custom_interface_pkg custom_publisher
# Sa Terminal 3
user:~/Workspaces/sample_ws$ ros2 run use_custom_interface_pkg custom_subscriber

Ganito dapat ang lalabas sa iyong pagpapatakbo:

[INFO] [1711264604.204593355] [custom_subscriber]: Received Numbers: a=3, b=8, sum=11
[INFO] [1711264604.204593546] [custom_subscriber]: Received Numbers: a=3, b=5, sum=8
[INFO] [1711264604.187348953] [custom_subscriber]: Received Numbers: a=2, b=3, sum=5
[INFO] [1711264604.237378829] [custom_subscriber]: Received Numbers: a=4, b=4, sum=8
[INFO] [1711264604.142367827] [custom_subscriber]: Received Numbers: a=1, b=6, sum=7
...
[INFO] [1711264604.204593355] [custom_subscriber]: Received Numbers: a=7, b=9, sum=16
[INFO] [1711264604.204593355] [custom_subscriber]: Received Numbers: a=3, b=1, sum=4

At ayan!

Matagumpay nating nagawa ang ating custom message sa ROS2 at magamit ang mga ito sa publisher at subscriber! Kapag tapos ka nang magsiyasat, maaarin mong pindutin ang “ctrl + c” upang patayin na ang naturang node at maging ang simulation. At diyan nagtatapos ang ating maikling gabay hinggil sa paggawa ng custom messages! Nawa’y may natutunan kayong bago na makatutulong sa inyong pag-aaral ng ROS!

Para sa iba pang mga ROSject na tulad nito, mangyaring bisitahin ang The Construct. Nag-aalok sila ng napakaraming praktikal na mga gabay sa ROS mula sa mga payak hanggang sa mga konseptong pangbihasa na!

Hanggang sa muli! Ito si Christian C. Anabeza, ang inyong Filipino ROSbotics Ambassador!

Video Tutorial

Masterclass 2023 batch2 blog banner

Check Out These Related Posts

0 Comments

Submit a Comment

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Pin It on Pinterest

Share This