Knowhow/ROS2

[ROS2 Foxy Tutorial 한글 번역] 5. Understanding services

침닦는수건 2023. 2. 1. 17:42
반응형

Link

https://docs.ros.org/en/foxy/Tutorials/Beginner-CLI-Tools/Understanding-ROS2-Services/Understanding-ROS2-Services.html

 

Understanding services — ROS 2 Documentation: Foxy documentation

Goal: Learn about services in ROS 2 using command line tools.

docs.ros.org

 

Background

서비스는 ROS graph에서 노드 간의 또 다른 소통 방식이다. 서비스는 기본적으로 call-and-response 모델 즉, 부르면 응답한다는 모델로 토픽 모델과는 차이가 있다. 토픽은 모든 노드들이 스트리밍되는 데이터를 지속적으로 subscribe하도록 해서 연속적인 업데이트를 기본으로 하는 반면, 서비스는 오로지 클라이언트 노드가 요청 했을 때만 데이터를 제공받아 업데이트하는 것을 기본으로 한다.

(참고로 서비스는 서버-클라이언트 관계를 1대1, 1대多만 지원한다. 多대1 혹은 多대多는 지원하지 않는다.)

 

Prerequisites

이전 튜토리얼에서 줄곧 소개했던 노드와 토픽에 대한 개념을 알고 있어야 한다. 

 

turtlesim 패키지를 계속 사용할 것이다. 

 

당연하게도, ROS2 sourcing을 잊지 말아라.

 

Tasks

1. Setup

/turtlesim 노드와 /teleop_turtle 노드로 시작하자. 각각 다른 터미널에 아래 커맨드를 입력한다.

 

ros2 run turtlesim turtlesim_node
ros2 run turtlesim turtle_teleop_key

 

2. ros2 service list

새로운 터미널을 또 열어 "ros2 service list" 커맨드를 입력해보면 다음과 같이 현재 활성화된 서비스들의 목록이 출력된다.

/clear
/kill
/reset
/spawn
/teleop_turtle/describe_parameters
/teleop_turtle/get_parameter_types
/teleop_turtle/get_parameters
/teleop_turtle/list_parameters
/teleop_turtle/set_parameters
/teleop_turtle/set_parameters_atomically
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
/turtlesim/describe_parameters
/turtlesim/get_parameter_types
/turtlesim/get_parameters
/turtlesim/list_parameters
/turtlesim/set_parameters
/turtlesim/set_parameters_atomically

현재 실행한 노드 2개 모두 각각 "parameters"가 포함된 이름으로 6개의 서비스를 갖고 있는 것을 볼 수 있다.. ROS2의 거의 모든 노드가 파라미터를 다루는 내부 서비스를 갖고 있다. 파라미터에 대한 내용은 다음 튜토리얼에서 다루어 보겠다. 이번 튜토리얼에서는 파라미터 관련 서비스는 생략하도록 하겠다.

 

지금은 turtlesim에 한정된 서비스에만 집중해볼 것인데, /clear, /kill, /reset, /spawn, /turtle1/set_pen, /turtle1/teleport_absolute, /turtle1/teloport_relative 가 있다. rqt를 사용해볼 당시 위 서비스가 있었던 것을 기억할지 모르겠다. 

 

3. ros2 service type

서비스는 request 데이터와 response 데이터가 어떤 구조인지 알려주는 타입이 있다. 서비스 타입은 토픽 타입과 거의 유사한데 서비스 타입은 request와 response 두 파트가 존재하는 차이가 있다. 

 

서비스 타입을 알아내기 위해 다음 커맨드를 입력하면 된다.

ros2 service type <service_name>

turtlesim의 /clear 서비스를 살펴보기 위해 새로운 터미널에 다음 명령어를 입력해보자.

ros2 service type /clear

다음과 같은 출력 결과를 얻을 수 있을 것이다.

std_srvs/srv/Empty

여기서 "Empty" 타입은 서비스 호출 때 request에 아무런 데이터도 보내지 않고, response로 아무런 데이터도 받지 않는다는 뜻이다. 

 

3.1 ros2 service list -t

활성환 모든 서비스의 타입을 동시에 보고 싶을 땐 list 커맨드에 --show-types 옵션을 추가하면 된다. 이전 튜토리얼에서도 줄곧 사용했던 -t 옵션이 이 --show-types의 축약형이다. 

ros2 service list -t

출력 결과는 다음과 같다.

/clear [std_srvs/srv/Empty]
/kill [turtlesim/srv/Kill]
/reset [std_srvs/srv/Empty]
/spawn [turtlesim/srv/Spawn]
...
/turtle1/set_pen [turtlesim/srv/SetPen]
/turtle1/teleport_absolute [turtlesim/srv/TeleportAbsolute]
/turtle1/teleport_relative [turtlesim/srv/TeleportRelative]
...

 

4. ros2 service find

만약 모든 서비스 중 구체적인 타입을 찾고 싶을 경우, 다음 커맨드를 입력하면 된다.

ros2 service find <type_name>

에를 들어, 아까 "Empty" 타입을 찾고 싶을 경우, 다음과 같이 입력하면 된다.

ros2 service find std_srvs/srv/Empty

출력 결과는 다음과 같다.

/clear
/reset

 

5. ros2 interface show

서비스를 직접 커맨드 라인에서 호출하는 방법을 배우기 전에, 입력 argument의 구조(서비스 타입의 내부 구조)를 먼저 알 필요가 있다.

ros2 interface show <type_name>.srv

예를 들어, /clear 서비스의 타입은 "Empty"였는데 이를 적용해보면,

ros2 interface show std_srvs/srv/Empty.srv

다음과 같은 결과를 얻게 된다.

---

"---" 의 의미는 원래 구분선이다. "---" 위에는 request structure가, 아래에는 response structure가 표시되는 식인데 지금 "Empty" 타입은 아무것도 보내지도, 받지도 않기 때문에 비어있는 것이다. 

 

이번엔 /spawn 서비스를 호출해보면 다음과 같다. "ros2 service list -t" 커맨드로부터 /spawn 서비스 타입은 turtlesim/srv/Spawn이라는 것을 알고 있다. 

ros2 interface show turtlesim/srv/Spawn

출력 결과는 다음과 같다.

float32 x
float32 y
float32 theta
string name # Optional.  A unique name will be created and returned if this is empty
---
string name

앞선 결과와 달리 "---" 위 request structure는 x,y,theta 라는 것과 아래 response structure는 name이라는 것을 알려준다. 

 

(다른 예시에 조금 더 돌려보면 다음과 같다. 이해에 도움이 되길.)

6. ros2 service call

이제 서비스 타입이 뭔지, 서비스 타입을 어떻게 찾는지, 그리고 해당 타입의 구조가 어떤지 알 것이다. 다음으로 service를 호출하는 하는 방법을 보자.

 

ros2 service call <service_name> <service_type> <arguments>

<argument> 파트는 필수가 아니다. 예를 들어, "Empty" 타입은 아무런 argument도 필요로 하지 않으니 말이다.

ros2 service call /clear std_srvs/srv/Empty

이 커맨드는 turtlesim 윈도우에서 거북이가 그렸던 궤적을 지운다.

이제 새로운 거북이를 /spawn과 입력 argument를 이용해 생성해보자. 입력 <arguments>를 적어줄 때는 YAML syntax를 지켜서 적어주어야 한다.

 

다음과 같이 커맨드를 입력해보자.

ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"

어떤 일이 벌어졌는지 method-style view(이게 뭔소린진 모르겠다.)와 함께 서비스 response를 얻게 된다.

 

turtlesim 윈도우로 가보면 새로운 거북이를 바로 볼 수 있을 것이다.

 

Summary

ROS2의 노드는 서비스를 통해 소통할 수 있다. 토픽과 다르게 서버가 1, 클라이언트는 1 혹은 多인 일방향성이 강한 소통 방식이다. 서비스 request-response 구조로 서비스를 제공하는 노드(서버)는 서비스를 원하는 노드(클라이언트)의 요청이 있을 때만 정보를 제공한다. 

 

일반적으로 서비스를 연속적으로 호출하는 것은 바람직 하지 않다. 토픽 혹은 앞으로 배울 액션이 더 적합한 형태다.

 

이번 튜토리얼에서는 서비스를 이해하고 사용하는 방법에 대해 배웠다. 

 

반응형