로봇/ROS

ROS2 Minimal Tutorial - Service

with-RL 2023. 7. 14. 00:50

이 포스트는 이전 포스트에 이어서 ROS2의 Service에 대한 간단한 설명입니다.

이 포스트는 다음 과정을 완료한 후에 참고하시길 바랍니다.

1. Service

  • Service는 Node들 간에 통신을 위한 다른 요소입니다.
  • Service는 call-and-response 방식으로 동작합니다. (vs Topic: publisher-subscriber)
  • Service-Server는 특정 Service-Client가 요청을 한 경우에만 데이터를 제공합니다.
  • 1:1 통신 방식으로 요청을 보내고 처리 결과를 확인하는 통신 방식입니다.

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

  • 첫 번째 터미널에서 아래 명령을 실행해서 'turtlesim.launch.py'를 실행합니다.
$ cd ~/Workspace/ros_ws
$ source install/setup.bash
$ ros2 launch ros_tutorial turtlesim.launch.py
  • 두 번째 터미널에서 아래 명령을 실행해서 '/turtle1/teleport_absolute' Service를 호출합니다. 아래 그림과 같이 Service를 호출하고 실행 결과를 수신한 것을 확인할 수 있습니다.
$ ros2 service call /turtle1/teleport_absolute turtlesim/srv/TeleportAbsolute "{x: 1.0, y: 1.0, theta: 0.0}"

  • 위 명령을 수신한 TurtleBot의 위치가 변경된 것을 확인할 수 있습니다.

  • 아래 명령을 실행해서 Service 목록을 확인합니다. 아래 그림과 같이 Service 목록을 확인할 수 있습니다.
$ ros2 service list

  • 아래 명령을 실행해서 '/turtle1/teleport_absolute' Service에 전달할 메시지를 확인합니다. 아래 그림과 같이 'turtlesim/srv/TeleportAbsolute'라는 메시지를 주고받는 것을 확인할 수 있습니다.
$ ros2 service type /turtle1/teleport_absolute

  • 아래 명령을 실행해서 'turtlesim/srv/TeleportAbsolute' 메시지를 사용하는 Service를 찾아봅니다. 아래 그림과 같이 '/turtle1/teleport_absolute' Service를 찾을 수 있습니다.
$ ros2 service find turtlesim/srv/TeleportAbsolute

  • 아래 명령을 실행해서 'turtlesim/srv/TeleportAbsolute' 메시지의 상세정보를 확인합니다. 아래 그림과 같이 'x', 'y', 'theta' 3가지 값으로 구성된 것을 확이할 수 있습니다.
$ ros2 interface show turtlesim/srv/TeleportAbsolute

2. Service - Client

  • TurtleBot을 위치를 변경했던 했던 '/turtle1/teleport_absolute' Service를 호출하는 Service Client를 python으로 구현해 보겠습니다.
  • 'src/ros_tutorial/package.xml' 파일의 'depend'에 아래 내용을 추가합니다. 아래 그림과 같이 Service Client가 사용할 dependency를 추가했습니다.
  <depend>turtlesim</depend>

  • 'src/ros_tutorial/setup.py'의 'console_scripts' 부분에 아래 내용을 추가합니다. 아래 그림과 같이 'turtlesim_abs_client'이라는 명령을 등록했습니다.
'turtlesim_abs_client = ros_tutorial.turtlesim_abs_client:main',

  • 'src/ros_tutorial/ros_tutorial/turtlesim_abs_client.py' 파일을 만들고 아래와 같이 편집합니다. TurtleBot에 x=10, y=10, theat=1 위치로 이동하도록  'turtlesim/srv/TeleportAbsolute' 메시지를 보내는 코드입니다.
#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
from turtlesim.srv import TeleportAbsolute


class TurtlesimAbsoluteClient(Node):
    def __init__(self):
        super().__init__('turtlesim_abs_client')

        self.client = self.create_client(TeleportAbsolute, '/turtle1/teleport_absolute')

        while not self.client.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('service not available, waiting again...')
        
        self.req = TeleportAbsolute.Request()
    
    def send_request(self, x, y, theta):
        self.req.x = x
        self.req.y = y
        self.req.theta = theta
        self.future = self.client.call_async(self.req)
        rclpy.spin_until_future_complete(self, self.future)
        return self.future.result()


def main(args=None):
    rclpy.init(args=args)

    client = TurtlesimAbsoluteClient()
    client.send_request(10.0, 10.0, 1.0)

    client.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

  • 첫 번째 터미널에서 아래 명령을 실행해서 컴파일, 환경설정 그리고 'turtlesim.launch.py'를 실행합니다.
$ cd ~/Workspace/ros_ws
$ colcon build --symlink-install
$ source install/setup.bash
$ ros2 launch ros_tutorial turtlesim.launch.py
  • 두 번째 터미널에서 아래 명령을 실행해서 'turtlesim_abs_client'을 실행합니다.
$ cd ~/Workspace/ros_ws
$ source install/setup.bash
$ ros2 run ros_tutorial turtlesim_abs_client
  • TurtleBot이 입력한 위치로 이동하면서 회전한 것을 확인할 수 있습니다.

3. Service - Server

  • '/turtle1/teleport_absolute' Service Server를 python으로 구현해 보겠습니다.
  • 'src/ros_tutorial/setup.py' 파일의 'console_scripts' 부분에 아래 내용을 추가합니다.
'turtlesim_abs_server = ros_tutorial.turtlesim_abs_server:main',

  • 'src/ros_tutorial/ros_tutorial/turtlesim_abs_server.py' 파일을 만들고 아래와같이 편집합니다.
#!/usr/bin/env python3

import rclpy
from rclpy.node import Node
from turtlesim.srv import TeleportAbsolute


class TurtlesimAbsoluteServer(Node):
    def __init__(self):
        super().__init__('turtlesim_abs_server')

        self.client = self.create_service(TeleportAbsolute,
                                          '/turtle1/teleport_absolute',
                                          self.service_callback)
    
    def service_callback(self, request, response):
        print('request:', request)
        print('response:', response)
        return response


def main(args=None):
    rclpy.init(args=args)

    service = TurtlesimAbsoluteServer()
    rclpy.spin(service)

    service.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

  • 첫 번째 터미널에서 아래 명령을 실행해서 컴파일, 환경설정 그리고 'turtlesim_abs_server'를 실행합니다.
$ cd ~/Workspace/ros_ws
$ colcon build --symlink-install
$ source install/setup.bash
$ ros2 run ros_tutorial turtlesim_abs_server
  • 두 번째 터미널에서 아래 명령을 실행해서 'turtlesim_abs_client'을 실행합니다
$ cd ~/Workspace/ros_ws
$ source install/setup.bash
$ ros2 run ros_tutorial turtlesim_abs_client
  • 'turtlesim_abs_server'가 실행중인 첫 번째 터미널에 'turtlesim_abs_client'가 보낸 메시지가 출력되는 것을 확인할 수 있습니다.