rclpy로 파이썬을 활용하여 Topic, Publisher, Subscriber 작성하기
사용자 작업 폴더에 패키지를 생성한다.
$ ros2 pkg create [패키지이름] --build-type [빌드 타입] --dependencies [의존하는패키지1] [의존하는패키지n]
$ cd ~/ros2_dashing/src/
$ ros2 pkg create my_first_ros_rclpy_pkg --build-type ament_python --dependencies rclpy std_msgs
해당 패키지 생성에 앞서 미리 설치해야 하는 의존 패키지들. 패키지 생성 시 위와 같이 지정할 수도 있지만, 생성한 다음 package.xml에서 직접 입력해도 된다.
.
├── my_first_ros_rclpy_pkg
│ └── __init__.py
├── resource
│ └── my_first_ros_rclpy_pkg
├── test
│ ├── test_copyright.py
│ ├── test_flake8.py
│ └── test_pep257.py
├── package.xml
├── setup.cfg
└── setup.py
3 directories, 8 files
ament_cmake 인지, ament_python 인지에 따라 구성 파일 시스템이 달라짐.
package.xml, setup.cfg, setup.py는 패키지 생성 시 자동으로 생성된다.
패키지 설정 파일. 사용할 RCL (ROS2 Client Libraries)에 따라 달라짐.
<?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_first_ros_rclpy_pkg</name>
<version>0.0.2</version>
<description>ROS 2 rclpy basic package for the ROS 2 seminar</description>
<maintainer email="pyo@robotis.com">Pyo</maintainer>
<license>Apache License 2.0</license>
<author email="mikael@osrfoundation.org">Mikael Arguedas</author>
<author email="pyo@robotis.com">Pyo</author>
<depend>rclpy</depend>
<depend>std_msgs</depend>
<test_depend>ament_copyright</test_depend>
<test_depend>ament_flake8</test_depend>
<test_depend>ament_pep257</test_depend>
<test_depend>python3-pytest</test_depend>
<export>
<build_type>ament_python</build_type>
</export>
</package>
파이썬 패키지 설정 파일.
entry_points 옵션의 console_scripts 키를 사용한 실행 파일 설정함. (각각의 콘솔 스크립트는 각 모듈의 main 함수를 호출함.)
from setuptools import find_packages
from setuptools import setup
package_name = 'my_first_ros_rclpy_pkg'
setup(
name=package_name,
version='0.0.2',
packages=find_packages(exclude=['test']),
data_files=[
('share/ament_index/resource_index/packages',
['resource/' + package_name]),
('share/' + package_name, ['package.xml']),
],
install_requires=['setuptools'],
zip_safe=True,
author='Mikael Arguedas, Pyo',
author_email='mikael@osrfoundation.org, pyo@robotis.com',
maintainer='Pyo',
maintainer_email='pyo@robotis.com',
keywords=['ROS'],
classifiers=[
'Intended Audience :: Developers',
'License :: OSI Approved :: Apache Software License',
'Programming Language :: Python',
'Topic :: Software Development',
],
description='ROS 2 rclpy basic package for the ROS 2 seminar',
license='Apache License, Version 2.0',
tests_require=['pytest'],
entry_points={
'console_scripts': [
'helloworld_publisher = my_first_ros_rclpy_pkg.helloworld_publisher:main',
'helloworld_subscriber = my_first_ros_rclpy_pkg.helloworld_subscriber:main',
],
},
)
/home/[user]/ros2_dashing/install/my_first_ros_rclpy_pkg/lib/my_first_ros_rclpy_pkg
와 같은 지정 폴더에 실행 파일이 생성됨[develop]
script-dir=$base/lib/my_first_ros_rclpy_pkg
[install]
install-scripts=$base/lib/my_first_ros_rclpy_pkg
~/ros2_dashing/src/my_first_ros_rclpy_pkg/my_first_ros_rclpy_pkg/
import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile # 퍼블리셔의 QoS 설정
from std_msgs.msg import String # 퍼블리시 메시지 타입
class HelloworldPublisher(Node): # Node 클래스 상속
def __init__(self):
super().__init__('helloworld_publisher') # 노드 이름 지정
qos_profile = QoSProfile(depth=10) # 퍼블리시할 데이터를 버퍼에 10개까지 저장
self.helloworld_publisher = self.create_publisher(String, 'helloworld', qos_profile)
# 퍼블리셔 설정 : 토픽 메시지 타입, 이름, QoS 설정
self.timer = self.create_timer(1, self.publish_helloworld_msg)
# 콜백함수 : n초마다 지정한 콜백함수 실행
self.count = 0
def publish_helloworld_msg(self):
msg = String() # 퍼블리시할 메시지
msg.data = 'Hello World: {0}'.format(self.count) # 메시지 저장
self.helloworld_publisher.publish(msg) # 메시지 퍼블리시
self.get_logger().info('Published message: {0}'.format(msg.data)) # 콘솔창에 출력 (==print함수)
# logger 종류 : debug, info, warning, error, fatal
self.count += 1
def main(args=None):
rclpy.init(args=args) # 초기화
node = HelloworldPublisher()
try:
rclpy.spin(node) # 콜백함수 실행
except KeyboardInterrupt: # 'Ctrl+c'와 같은 인터럽트 시그널 예외 상황
node.get_logger().info('Keyboard Interrupt (SIGINT)')
finally:
node.destroy_node() # 노드 소멸
rclpy.shutdown() # 함수 종료
if __name__ == '__main__':
main()
~/ros2_dashing/src/my_first_ros_rclpy_pkg/my_first_ros_rclpy_pkg/
import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile
from std_msgs.msg import String
class HelloworldSubscriber(Node):
def __init__(self):
super().__init__('Helloworld_subscriber') # Node 클래스 생성자 호출
qos_profile = QoSProfile(depth=10) # 서브스크라이브 데이터를 버퍼에 10개까지 저장
self.helloworld_subscriber = self.create_subscription(
String, # 토픽 메시지 타입
'helloworld', # 토픽 이름
self.subscribe_topic_message, # 콜백함수
qos_profile) # QoS 설정
# 받은 메시지는 msg.data에 저장
def subscribe_topic_message(self, msg):
self.get_logger().info('Received message: {0}'.format(msg.data))
def main(args=None):
rclpy.init(args=args)
node = HelloworldSubscriber()
try:
rclpy.spin(node)
except KeyboardInterrupt:
node.get_logger().info('Keyboard Interrupt (SIGINT)')
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
(워크스페이스내의 모든 패키지 빌드하는 방법)
$ cd ~/robot_ws && colcon build --symlink-install
(특정 패키지만 빌드하는 방법)
$ cd ~/robot_ws && colcon build --symlink-install --packages-select [패키지 이름1] [패키지 이름2] [패키지 이름N]
(특정 패키지 및 의존성 패키지를 함께 빌드하는 방법)
$ cd ~/robot_ws && colcon build --symlink-install --packages-up-to [패키지 이름]
$ cd ~/robot_ws
$ colcon build --symlink-install --packages-select my_first_ros_rclpy_pkg
Starting >>> my_first_ros_rclpy_pkg
Finished <<< my_first_ros_rclpy_pkg [0.66s]
Summary: 1 package finished [0.87s]
. ~/robot_ws/install/local_setup.bash
각 터미널 창에서 아래 코드 실행
$ ros2 run my_first_ros_rclpy_pkg helloworld_subscriber
$ ros2 run my_first_ros_rclpy_pkg helloworld_publisher