ROS2는 python을 공식 지원하며 Jupyter를 이용하여 python으로 Topic에 접근해 볼 것이다.
(Uubuntu Jupyter 설치의 경우 구글에 많이 나와있으니 찾아보길 바랍니다.)
Python으로 Topic 접근 코드 예제 결과
특정 범위 안에서 거북이가 random하게 움직이는 시뮬레이션
Topic
Topic 구독 코드 작성
터미널에서 turtlesim_node를 실행하고, ROS2를 실행한 후 VS-Code를 실행한다.
jupyter notebook을 통해 아래 코드를 입력하고 실행 시킨다.
import rclpy as rp
from turtlesim.msg import Pose
첫째 라인의 rclpy(ROS Client Library for Python)라는 ROS2를 Python에서 사용할 수 있게 해주는 Module을 rp라는 이름으로 import 한다.
둘째 라인은 Subscribe하고자 하는 Topic인 /turtle1/pose의 type을 참고하여 turtlesim/msg/Pose에서 Pose를 사용할 수 있도록 import 해준다.
rp.init()
test_node = rp.create_node('First')
rclpy 초기화 및 해당 라이브러리의 create_node() 메서드를 이용하여 'First'라는 이름의 노드를 생성하고 test_node로 객체화 한다.
position_x = 0.0
position_y = 0.0
def pose_callback(data) :
global position_x, position_y
position_x = data.x
position_y = data.y
print("X : ", data.x)
print("X : ", position_x)
print("Y : ", data.y)
print("Y : ", position_y)
print("Theta : ", data.theta)
Topic을 수신할 때 마다 실행하는 메서드는 callback()이다.
Topic 수신 시 처리할 내용은 callback() 메서드에 작성하여 사용한다.
위 코드는 파라미터로 넘어온 data의 x, y값을 position_x,y에 넣고, print를 통해 출력하는 함수에 해당한다.
test_node.create_subscription(Pose, '/turtle1/pose', pose_callback, 10)
Python 코드로 생성한 Node인 test_node에서 Subscription을 생성한다.
위 코드는 Subscription을 생성하는 코드이며 Subscription을 실행하는 코드는 아니다.
위와 같이 Topic과 Subscription을 생성하게 되면 rqt를 통해 GUI로 각 Node의 관계를 파악할 수 있다.
/turtlesim 노드에서 /turtle1/pose 토픽으로 message를 날리게 되면 /First_Day_try 노드에서 해당 message를 읽는 구조에 해당한다.
rp.spin_once(test_node)
///
rp.spin(test_node)
rp.spin_once를 통해 Topic을 한번만 구독할 수 있고, spin을 통해 계속해서 Topic을 구독할 수 있다.
Topic 발행 코드 작성
Twist의 형태를 가지는 msg 객체를 생성 후 내용을 출력한다.
msg에 linear, angular 데이터가 존재하고 다시 x, y, z값이 존재함을 확인할 수 있다.
msg 내부 데이터를 변경한 후 실행하게 되면 데이터가 변경된 것을 확인할 수 있다.
Topic을 발행하는 코드를 작성하고, 발행하게 되면 아래와 같이 거북이가 변경된 데이터에 따라 움직이는 것을 확인할 수 있다.
Topic 발행코드까지 작성하게 되면 위와 같은 관계를 가지는 것을 확인할 수 있다.
Service
Service Client 코드 작성
rclpy 초기화 및 해당 라이브러리의 create_node() 메서드를 이용하여 service_test라는 이름의 노드를 생성한다.
추가로 service 패키지에서 TeleportAbsolute 서비스 import한다.
/turtle1/teleport_absolute의 서비스를 이용할 것이기 때문에 변수에 저장하여 create_client() 메서드를 통해 Client를 생성하고 cli_T라는 객체를 생성한다.
Service Client가 Request에서 사용할 데이터 객체 생성 및 초기값을 확인한다.
Request의 값을 변경하고 값을 확인한다.
Service call을 실행하는 방법에는 아래와 같이 3가지가 있다.
cli_T.call_async(req)
rp.spin_once(test_node)
단순하게 실행하는 방법이다.
* 하지만 위 방법은 노드가 실행되어 있지 않은 상황에서도 실행되기 때문에 에러가 발생할 수 있다.
# while not cli.wait_for_service(timeout_sec=1.0) :
# print("Waiting for service...")
# cli_T.call_async(req)
# rp.spin_once(test_node)
두번째 방법은 Service Server가 실행될 때까지 기다렸다가 Service Server가 실행되는 것이 확인되면 실행하는 방법이다.
# future = cli_T.call_async(req)
# while not future.done() :
# rp.spin_once(test_node)
# print(future.done(), future.result())
세번째 방법은 요청한 Request에 대해 수행되었다는 Response가 도착할 때 까지 반복문을 계속해서 실행하게 된다.
Service Client 호출 후의 상황을 알려줄 때 사용한다.
Service에 의해 움직인 거북이 모습을 확인할 수 있다.
'Embedded > ROS' 카테고리의 다른 글
ROS2 (6) - Class, 상속을 이용한 그래프 그리기 (pyplot, numpy) (0) | 2024.09.30 |
---|---|
ROS2 - (4) Action, Parameter 이론 및 실습 (0) | 2024.09.23 |
ROS2 - (3) Topic, Service 이론 및 실습 (0) | 2024.09.23 |
ROS2 - (2) Message, DDS 이론 및 실습 (0) | 2024.09.23 |
ROS2 - (1) 설치 및 기본 동작 (Topic, Service, Action) (0) | 2024.09.09 |