1. 기본 세팅
- 이번에는 Python을 통해 ROS2를 다루는 방법에 대해 정리해보고자 한다.
- 우선 pip를 설치하자.
- 파이썬 관련 설명은 생략하도록 하겠다.
sudo apt install python3-pip
pip3 install --upgrade pip # 최신버전 유지
pip3 install jupyter ipywidgets pyyaml bqplot
- 모듈 설치가 끝났으면 재부팅해야 한다. 그리고 다음 명령을 통해 Jupyter notebook을 실행해 주자.
jupyter notebook
2. Python으로 토픽 구독하기
2.1 jupyter로 토픽을 구독하기 위한 준비
- 불필요한 혼선을 막기 위해 이전에 켜둔 터미널을 모두 끈 상태에서 다시 실행한다.
- 터미널을 분할하고 하나에는 주피터 노트북을, 하나는 turtlesim_node를 실행해 준다.
2.2 구독을 위해 필요한 모듈 import
- 이제 다음 코드를 입력해 보자
import rclpy as rp
from turtlesim.msg import Pose
나 as가 alias를 뜻한다는거 처음 알았다......
- 우리는 지금 turtlesim_node 토픽 중에서 /turtle1/pose라는 토픽을 구독해보려고 한다.
2.3 rclpy의 초기화 및 노드 생성
- 다음 명령은 Python에서 rclpy를 초기화하기 위한 코드이다.
rp.init()
- 그리고 sub_test라는 이름의 노드를 하나 만들기 위해 rclpy의 create_node를 사용한다.
test_node = rp.create_node('sub_test')
- rqt_graph 명령을 통해 확인해보면 sub_test라는 노드가 추가 된 것을 확인해 볼 수 있다.
2.4 토픽 Subscriber 만들기
구독에 대한 간단한 설명
까먹을수도 있으니 구독(Subscribe)에 대해 간단하게 설명하자면
- 구독은 발행자가 발행한 메시지를 특정 토픽에서 받는 것을 의미한다.
- 구독자(Subscriber) 노드는 해당 토픽을 구독하며, 이 과정에서 발행자(Publisher) 노드가 해당 토픽에 메시지를 발행하면, 해당 매시지를 받게 된다.
즉, 발행자는 메시지를 생성하여 특정 토픽에 발행하고, 구독자는 해당 토픽을 구독하여 메시지를 수신하는 역할을 한다.
이를 통해 여러 노드들이 서로 메시지를 주고 받으며, 로봇제어, 센싱 데이터 수집, 맵핑 등의 다양한 기능을 수행할 수 있다.
- subscriber를 생성하기 위해 다음 코드를 입력하면 된다.
생성한 노드.create_subscription(<data_type>, '<topic_name>', <callback>, <Qos History>)
test_node.create_subscription(Pose, '/turtle/pose', callback, 10)
def callback(data):
print("-->")
print("x: ", data.x)
print("y: ", data.y)
print("theta: ", data.theta)
- rqt_graph 명령을 통해 현재 플로우를 보면 다음과 같다.
- 그럼 토픽을 한번만 받아들여 보자. 토픽을 받아들이는 명령어는 rp.spin_once()이다.
rp.spin_once('test_node')
- 만약 토픽을 계속 무한히 구독하려면 spin()을 사용하면 된다.
- spin_once가 한 번 실행되면 토픽이 들어 올 때까지 기다렸다가, 토픽이 들어오면 지정된 callback함수가 위 사진 처럼 실행되는 것을 알 수 있다.
2.5 인터럽트
- spin()을 사용하게 되면 콜백함수에서 횟수 제한을 미리 정의하지 않는 이상 계속해서 메시지를 받아올 것이다.
- 그러한 경우 주피터 노트북의 인터럽트(interrupt) 버튼을 누르면 된다. (정사각형 정지 버튼)
- 만약 콜백함수에서 횟수를 미리 지정해 주고 싶다면 다음과 같이 하면 된다.
cnt = 0
def callback_cnt(data):
global cnt
cnt += 1
print(">", cnt, " -> X :", data.x, ", Y : ", data.y)
if cnt > 3:
raise Exception("Subscription Stop")
3. 토픽 발행하기
- 지금까지는 토픽을 구독했었다. 이번에는 토픽을 발행하는 방식에 대해 설명해 보겠다.
발행에 대한 간단한 설명
발행(Publish)
- 발행(Publish)은 메시지를 생성하고, 해당 메시지를 특정 토픽(Topic)에 발행하는 것을 의미한다.
- 발행자 노드는 해당 토픽에 메시지를 발행하며, 이 과정에서 다른 구독자 노드들이 해당 토픽을 구독하고 있다면, 발행한 메시지를 받게 된다.
- 이제 cmd_vel이라는 토픽을 발행해 보자.
- 전에 말했듯이 ros2 topic list -t 명령을 입력하면, 현재 사용 가능한 토픽들의 데이터 타입을 알 수 있다.
- cmd_vel의 경우 Twist라는 데이터 타입을 가지는 것을 알 수 있다.
from geometry_msgs.msg import Twist
- 그리고 'pub_test'라는 이름으로 발행자 노드를 하나 생성해 주자.
test_pub_node = rp.creat_node('pub_test')
msg = Twist()
print(msg)
- 위와 같이 Twist 데이터 형을 확인해 볼 수 있다.
3.2 cmd_vel 토픽 간단히 발행해보기
msg.linear.x = 2.0
- 위와 같이 linear의 x값을 수정할 수 있다.
pub = test_node.create_publisher(Twist, '/turtle1/cmd_vel', 10)
- 위 코드를 통해 Twist 메시지를 발행할 수 있는 'Publisher' 객체를 생성하는 코드이다.
- 그러면 pub는 Publisher 객체가 되며, 이제 토픽을 발행하는 것과 관련된 기능, 설정들을 지정할 수 있다.
- 여기서 msg를 발행하기 위해 다음과 같이 하면 된다.
pub.publish(msg)
- 실행한 상태에서 추가로 또 움직이게 하고 싶다면 msg를 변경하고 pub.publish()를 통해 다시 발행하면 된다
4. timer를 이용해서 토픽 발행하기
- 지금까지는 토픽을 한번만 발행했다.
- 이제는 주기적으로 토픽을 발행시켜 보자. 그러기 위해선 ROS의 타이머를 사용해야 한다.
- 주기적으로 토픽을 발행하기 위해선 일정 시간 유지할 필요가 있다.
노드이름.create_timer(timer_period, timer_callback)
- 그런 기능은 create_timer라는 기능을 사용한다.
- 타이머의 주기와(timer_period)와 해당 시간에 뭘 할 건지(timer_callback, 콜백 함수)를 지정해 주어야 한다.
5. 노드의 종료.
- 개발을 하다보면 방금 실행했던 노드를 이제는 사용하지 않는데 node list 명령의 결과에는 보이거나, 몇시간 전에 실행했던 노드나 토픽이 관찰될 때도 있다.
- 이런 경우 다음 명령을 통해 노드를 종료시키면 된다.
종료시킬 노트.destroy_node()
'Robot' 카테고리의 다른 글
ROS2 공부 - colcon (1) | 2023.05.02 |
---|---|
ROS2 공부 3일차 - ROS2 기본 명령 익히기 (0) | 2023.03.24 |
ROS2 공부 1일차-terminator (1) | 2023.03.23 |
ROS2 공부 2일차-ROS2 설치 (0) | 2023.03.23 |