my_robot_controller Node 만들기
저작권: 쿼드(QUAD) 드론연구소 https://smartstore.naver.com/maponarooo
자 이제 실제 ROS2 프로그램에서 작업의 주체인 노드를 만들어 보겠습니다.
이 샘플 노드는 노드를 실행 시키면 "Hello time: <넘버 증가>" 를 출력하는 샘플 노드 입니다.
노드 파일과 권한 부여하기
우선, my_robot_controller 노드 디렉토리로 이동 합니다.
~/ros2_ws/src/my_robot_controller$ cd my_robot_controller/
~/ros2_ws/src/my_robot_controller/my_robot_controller$
my_first_node.py 라는 이름으로 노드 파일을 만들고 실행 권한을 부여 합니다.
$ touch my_first_node.py
$ chmod +x my_first_node.py
코드 작성
자 이제 ~/ros2_ws 작업공간으로 이동한후 vs code를 실행 합니다. (현재 디렉토리를 의미하는 "." 을 반드시 붙여주세요)
vscode에서 my_first_node.py 파일을 열고 코드를 작성 합니다.
#!/usr/bin/env python3
import rclpy
from rclpy.node import Node
class MyNode(Node):
def __init__(self):
super().__init__("first_node")
self.counter_ = 0
self.create_timer(1.0, self.timer_callback)
def timer_callback(self):
self.get_logger().info("Hello times: " + str(self.counter_))
self.counter_ += 1
def main(args=None):
rclpy.init(args=args)
node = MyNode()
rclpy.spin(node)
rclpy.shutdown()
if __name__ == '__main__':
main()
코드 분석
프로그램의 가장 상단에 ROS2 Python을 사용하기 위한 rclpy 패키지와 노드를 사용하기 위한 Node 패키지를 import 합니다.
import rclpy
from rclpy.node import Node
main() 함수는 rclpy 클래스를 초기화 하고 노드를 생성하고 실행(spin) 시키며 종료 시그널을 받으면 노드를 종료 시키는 역할을 수행 합니다. 따라서, main() 함수는 보통 아래와 같은 구조를 가집니다.
def main(args=None):
rclpy.init(args=args)
node = MyNode()
rclpy.spin(node)
rclpy.shutdown()
if __name__ == '__main__':
main
제일 아래에 if __name__ == '__main__': 코드는 main 함수가 모듈로 실행되는 경우가 아닌 독립적으로 실행할 때에만 실행 되도록 합니다.
main() 함수가 만들어 졌으니 이제 실제 기능을 수행할노드 클래스를 작성 하여야 합니다.
일반적인 노드 클래스의 구조는 아래와 같습니다.
class MyNode(Node):
// 노드 클래스 초기화
def __init__(self):
super().__init__("노드 이름")
# 콜백 타이머 생성
self.counter_ = 0
self.create_timer(1.0, self.timer_callback)
# 콜백 함수
def timer_callback(self):
self.get_logger().info("Hello times: " + str(self.counter_))
self.counter_ += 1
위에서 처럼 노드 클래스는 일반적으로 콜백 함수라는 수동적(passive) 함수를 사용하며 이 함수는 스스로 실행하는 것이 아닌, 타이머에 의해 피동적으로 동작하게 됩니다.
self.get_logger().info("Hello times: " + str(self.counter_))
get_logger() 메쏘드는 print 문과 같이 화면에 문자열과 데이터를 출력하는 노드 클래스의 메쏘드 입니다.
setup.py 수정하기
다음은 setup.py 파일을 열어 우리가 만든 실행 노드인 my_first_node.py를 실행할 수 있도록 등록해 줍니다.
ros2 run 커멘드를 이용하여 노드를 실행하기 위해서는 setup.py 파일 안에 entry_points 필드에 우리가 작성한 프로그램 스크립트를 등록해 줍니다.
from setuptools import setup
package_name = 'my_robot_controller'
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']),
],
install_requires=['setuptools'],
zip_safe=True,
maintainer='quad',
maintainer_email='quad@todo.todo',
description='TODO: Package description',
license='TODO: License declaration',
tests_require=['pytest'],
entry_points={
'console_scripts': [
"test_node = my_robot_controller.my_first_node:main"
],
},
)
여기에서 중요한 것은 console_scripts 필드 항목의 의미를정확히 이해하는 것입니다.
일반적으로 혼란을 방지하기 위하여노드 이름과 파일명은 일치 시키는 것이 일반적이지만 이번에는 정확한 의미 파악을 위하여 test_node 라는 노드 이름으로 작성해 보았습니다.
"<노드 이름> = <패키지 이름>.<파일명>:main"
"test_node = my_robot_controller.my_first_node:main"
실행
자 이제 빌드하고 실행해 봅시다.
$ cd ~/ros2_ws
$ colcon build --symlink-install # 또는 cb
Starting >>> my_robot_controller
Finished <<< my_robot_controller [1.08s]
Summary: 1 packages finished [1.08s]
정상적으로 빌드가 되었으면 이제 실행해 봅니다.
~/ros2_ws$ ros2 run my_robot_controller test_node
[INFO] [1686303448.844482120] [first_node]: Hello times: 0
[INFO] [1686303449.837809953] [first_node]: Hello times: 1
[INFO] [1686303450.837563358] [first_node]: Hello times: 2
[INFO] [1686303451.837769318] [first_node]: Hello times: 3
[INFO] [1686303452.838259485] [first_node]: Hello times: 4
[INFO] [1686303453.838148123] [first_node]: Hello times: 5
[INFO] [1686303454.837859217] [first_node]: Hello times: 6
[INFO] [1686303455.837947410] [first_node]: Hello times: 7
[INFO] [1686303456.838174925] [first_node]: Hello times: 8
Hello times: 와 함께 타이머에 의해 증가된 숫자가 출력 되는 것을 볼 수 있습니다.
Last updated