ROS 시스템의 기본 통신 방식 (topic, service, action, parameter, interface)
책 ROS 2로 시작하는 로봇 프로그래밍 내용을 기반으로 정리함.
ROS의 메시지 통신
ROS 시스템이 어떻게 동작하는지 알아보자. 시스템이란, 각 구성요소들이 상호작용하거나 상호의존하여 복잡하게 얽혀 돌아가는 하나의 집합이다.
로봇의 시스템에서는 각 코드들이 구성요소가 되고, 코드끼리 통신하여 로봇이 맡은 일을 수행해 나간다. 이러한 통신을 ROS에서는 메시지 통신이라고 한다. 이 글에서는 이에 대한 몇 가지 용어와 정의, 기능들을 살펴볼 것이다. 각 통신에 대한 자세한 실습은 다른 글에서 다룰 것이다.
Node란?
로봇 시스템에서 프로그램의 재사용성을 높이기 위해 프로세서를 최소 단위로 작성한다. 쉽게 말하면 각 코드들이 특정 기능을 수행하도록 프로그래밍 되어 있다면, 메시지 통신을 통해 데이터를 주고 받고, 원하는 때에 각 코드를 실행할 수 있으니 시스템을 구성하기에 편리한 방식인 것이다. ROS에서는 이러한 실행 가능한 코드를 Node라고 부른다.
- Node: 최소 단위의 실행 가능한 프로세서
- Package: 하나 이상의 node 또는 node 실행을 위한 정보 등을 모아 놓은 것
- Metapackage: package의 집합
아래 사진처럼 각 노드들이 메시지로 유기적으로 연결되어 작동한다.
수많은 node들 사이에서 이뤄지는 통신에서 메시지로 가능한 것은 integer, floating point, boolean, string 와 같은 변수 형태이고, 메시지 안에 메시지를 품고 있는 간단한 데이터 구조 및 메시지들의 배열과 같은 구조도 가능하다.
다음 그림과 같이 메시지를 주고 받는 방식에 따라 topic, service, action, parameter로 구분된다.
Topic
topic은 비동기식 단방향 메시지 송수신 방식이다.
비동기식(Asynchronous) 작업의 완료 여부를 기다리지 않고 다른 작업(코드)을 실행할 수 있는 방식
동기식(Synchronous) 동시에 일어난다는 뜻. 요청과 그 결과가 동시에 일어남. 결과가 주어질 때까지 대기해야 함.
Publisher가 msg 메시지 형태의 메시지를 발간하고, Subscriber가 메시지를 구독하는 방식으로 통신한다. 아래 그림에서 node A -> node B, node A->node C 처럼, 중요한 것은 topic은 단방향이고, 1:1, 1:N, N:N 통신이 가능하다는 것이다.
Service
service는 동기식 양방향 메시지 송수신 방식이다.
Service client가 서비스 요청을 하고, Service server가 서비스 응답을 한다. 특정 요청을 하면 요청받은 일을 수행한 후에 결과로 응답하는 통신이다. topic에서 msg 메시지처럼 service에서의 요청과 응답을 srv 메시지라고 한다.
Action
action은 비동기식+동기식 양방향 메시지 송수신 방식이다.
Action client가 action goal을 지정하고, Action server는 이 액션 목표를 받아 특정 작업을 수행하면서 중간 결과값에 해당하는 action feedback와 최종 결과값인 action result를 전송하는 방식으로 통신이 이루어진다.
action은 topic과 service의 혼합이라고 볼 수 있다. 액션 목표와 결과를 전달하는 방식은 service, 피드백을 전달하는 방식은 topic과 같은 메시지 전송 방식이다. action goal, feedback, result 또한 위에서 언급한 msg 메시지의 변형으로 action 메시지라고 한다.
Parameter
parameter는 node에서 Parameter server를 실행시켜 외부의 Parameter client 간의 통신으로 매개변수를 변경하는 것이다. 방식 자체는 service와 동일하다고 볼 수 있지만 사용하는 입장에서 목적이 살짝 다르다. node 내 매개변수 또는 글로벌 매개변수를 node 또는 외부에서 지정(Set)하거나 변경할 수 있고, 가져와서(Get) 사용할 수 있다는 점에서 service와는 느낌이 다르다.
Interface
데이터 통신에서 사용되는 데이터의 형태를 interface라고 한다. ROS 인터페이스에는 OS 2에 새롭게 추가된 IDL(interface definition language)과 ROS 1부터 ROS 2까지 널리 사용 중인 msg, srv, action 이 있다. 위에서 언급했듯이 토픽, 서비스, 액션은 각각 msg, srv, action interface를 사용하고 있으며, 아래와 같은 구조로 쓰인다.
단순 자료형
- e.g. 정수(integer), 부동 소수점(floating point), 불(boolean)
메시지 안에 메시지를 품고 있는 간단한 데이터 구조
- e.g. geometry_msgs/msgs/Twist의
Vector3 linear
메시지들이 나열된 배열과 같은 구조
- e.g. sensor_msgs/msgs/LaserScan 의
float32[] ranges
메시지 안에 메시지를 품고 있는 간단한 데이터 구조, 메시지들이 나열된 배열과 같은 구조는 단순 자료형을 기반으로 한다. 이를 각 인터페이스 파일(msg, service, action)에서 정의할 때는 아래와 같이 기술한다. 여기서 fieldtype
이 메시지 자료형이고 fieldname
이 메시지 이름에 해당된다.
1
2
3
fieldtype1 fieldname1
fieldtype2 fieldname2
fieldtype3 fieldname3
예를 들어 Vector3.msg
은 아래와 같이 float64
자료형에 x
, y
, z
이라는 이름으로 선언되어 있다.
1
2
3
float64 x
float64 y
float64 z
ROS에서 사용 가능한 자료형은 위에서 언급한 단순 자료형이 사용되는데 더 자세하게 설명하자면 다음 표와 같다. 사용하는 언어별(C++, Python, DDS type)로 약간씩 차이가 있으니 참고하여 ROS 2 프로그래밍시에 문제가 없도록 하자.
Type name | C++ | Python | DDS type |
---|---|---|---|
bool | bool | builtins.bool | boolean |
byte | uint8_t | builtins.bytes* | octet |
char | char | builtins.str* | char |
float32 | float | builtins.float* | float |
float64 | double | builtins.float* | double |
int8 | int8_t | builtins.int* | octet |
uint8 | uint8_t | builtins.int* | octet |
int16 | int16_t | builtins.int* | short |
uint16 | uint16_t | builtins.int* | unsigned short |
int32 | int32_t | builtins.int* | long |
uint32 | uint32_t | builtins.int* | unsigned long |
int64 | int64_t | builtins.int* | long long |
uint64 | uint64_t | builtins.int* | unsigned long long |
string | std::string | builtins.str | string |
wstring | std::u16string | builtins.str | wstring |
static array | std::array<T, N> | builtins.list* | T[N] |
unbounded dynamic array | std::vector | builtins.list | sequence |
bounded dynamic array | custom_class<T, N> | builtins.list* | sequence<T, N> |
bounded string | std::string | builtins.str* | string |
여기까지 interfaec가 뭔지만 알아두고, interface에 대한 자세한 내용은 topic, service, action에 대한 실습에 대한 글에서 정리해두겠다.
토픽, 서비스, 액션 비교
Topic | Service | Action | |
---|---|---|---|
연속성 | 연속성 | 일회성 | 복합(토픽+서비스) |
방향성 | 단방향 | 양방향 | 양방향 |
동기성 | 비동기 | 동기 | 동기+비동기 |
다자간 연결 | 1:1, 1:N, N:1, N:N (Publisher: Subscriber) | 1:1 (Server: Client) | 1:1 (Server: Client) |
노드 역할 | Publisher, Subscriber | Server, Client | Server, Client |
동작 트리거 | Publisher | Client | Client |
인터페이스 | msg 인터페이스 | srv 인터페이스 | action 인터페이스 |
CLI 명령어 | ros2 topic, ros2 interface | ros2 service, ros2 interface | ros2 action, ros2 interface |
사용 예 | 센서 데이터, 로봇 상태, 로봇 좌표, 로봇 속도 명령 등 | LED 제어, 모터 토크 On/Off, IK/FK 계산, 이동 경로 계산 등 | 목적지로 이동, 물건 파지, 복합 태스크 등 |
마무리
이론적인 원리들을 파악했으면 실제로 확인하고 응용해보고 싶을 것이다. 다음 글에서는 Turtlesim을 통해 각 메시지 통신들이 이뤄지는 것을 모니터링 해보고, 가능하다면 각 통신들에 대한 프로그래밍에 대해서도 다뤄볼 예정이다.