[Dashing][CLI Tools] 5. Understanding ROS 2 services
이 글은 아래의 자료를 참고로 만들어졌습니다.
docs.ros.org/en/dashing/Tutorials/Services/Understanding-ROS2-Services.html
Understanding ROS 2 services
Goal: Learn about services in ROS 2 using command line tools.
Tutorial level: Beginner
Background
services는 ROS graph에서 nodes와 통신할 수 있는 또 다른 방법입니다.
topics은 publisher-subscriber 모델인데 반해, services는 call-and-response 모델을 기반으로 합니다.
topics은 nodes에 data streams을 subscribe하고 지속적으로 업데이트하는 반면에,
services는 client에게 호출(called)받을 경우에만 data를 제공합니다.
Prerequisites
이 튜토리얼에서 언급되는 몇 가지의 개념(nodes나 topics)은 이전 튜토리얼에서 다루고 있습니다.
turtlesim package가 필요합니다.
또한, 항상 새로운 터미널에 설정파일을 소싱하는 것을 잊지 마세요.
Tasks
1 Setup
turtlesim의 2개의 노드들(/turtlesim, /teleop_turtle)을 실행합니다.
새로운 터미널을 열고 아래와 같이 실행합니다.
$ ros2 run turtlesim turtlesim_node
또 다른 터미널을 열고 아래와 같이 실행합니다.
$ ros2 run turtlesim turtle_teleop_key
2 ros2 service list
ros2 service list 명령을 새로운 터미널에 실행하여, 현재 활성 가능한 모든 services의 리스트를 확인합니다.
$ 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
두 nodes가 parameters를 포함하는 services가 6개 있음을 확인할 수 있습니다. ROS 2에서 거의 모든 node에는 parameters가 기본 제공되는 인프라 services를 가지고 있습니다. 다음 tutorial에서 parameters에 집중하여 다루기 때문에, 이번 tutorial에서는 생략하겠습니다.
따라서 아래의 turtlesim의 servies에 대해 집중하겠습니다.
이에 대해서 2. Introducing turtlesim and rqt에 대해 rqt를 이용하여 이러한 몇 개의 services를 다루어 보았었습니다.
/clear
/kill
/reset
/spawn
/turtle1/set_pen
/turtle1/teleport_absolute
/turtle1/teleport_relative
3 ros2 service type
services의 type은 service가 어떻게 data를 request하고, response하는지에 대한 설명으로 구성되어있습니다.
service types은 topic types과 유사하지만, 2가지 면에서 다릅니다: 한 message는 request를 위한 것이며, 다른 것은 response를 위한 것입니다.
service type을 알고 싶다면, 아래의 명령어를 실행합니다.
$ 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]
...
여기에서 /clear, /reset의 type은 [std_srvs/srv/Empty]입니다.
Empty의 의미는
service가 request로 인해 call할 때, 어떠한 데이터도 보내지 않고,
service가 response를 receive할 때, 어떠한 데이터도 받지 않는다는 의미입니다.
4 ros2 interface show
command line으로 services를 call하기 전에
input arguments의 구조를 알 수 있는 명령은 아래와 같습니다.
$ ros2 srv show <type_name>
/clear service's type인 Empty에 대해서 아래의 명령을 실행합니다.
$ ros2 srv show std_srvs/srv/Empty
---
---는 위에는 request, 아래에는 response로 구분해줍니다.
이전에 Empty에 대해 배웠던 것처럼, 아무 데이터도 보내거나 받지 않기 때문에 아무 것도 써 있지 않습니다.
같은 방법으로 /spawn service에 대해 알아봅시다.
ros2 service list -t 명령어를 통해 /spawn의 type이 turtlesim/srv/Spawn인 것을 알 수 있습니다.
/spawn의 arguments를 알아보기 위해 아래의 명령어를 실행합니다.
$ ros2 srv 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
/spawn을 call하기 위해서는
--- 위의 x, y, theta의 spawned turtle의 위치를 결정해주면 되며,
name은 optional(입력해도 되고 안해도 되는 것)입니다.
이 경우에는 --- 밑에는 꼭 알 필요가 없는 정보이지만,
call로부터 어떠한 data type을 response하는지 이해하는데 도움이 됩니다.
5 ros2 service call
이제
service type은 무엇인지,
service's type은 어떻게 찾는지,
그리고 type's arguments를 어떻게 찾는지 알 수 있으므로,
아래의 명령을 사용하여 service를 call할 수 있습니다.
$ ros2 service call <service_name> <service_type> <arguments>
<arguments>는 optional입니다.
예를 들어, Empty typed services는 어떠한 arguments도 필요하지 않습니다.
이 명령어를 통해 turtle이 그린 모든 선을 clear합니다.
$ ros2 service call /clear std_srvs/srv/Empty
waiting for service to become available...
requester: making request: std_srvs.srv.Empty_Request()
response:
std_srvs.srv.Empty_Response()
이제 /spawn명령어와 arguments를 사용하여 새로운 turtle을 spawn해봅시다.
command-line에 input <arguments>로 YAML syntax를 이용하여 service를 call하기 위해 아래의 명령을 실행합니다.
$ ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
waiting for service to become available...
requester: making request: turtlesim.srv.Spawn_Request(x=2.0, y=2.0, theta=0.2, name='None')
response:
turtlesim.srv.Spawn_Response(name='turtle2')