본문 바로가기
ros2_python/Ros2 msg,srv,action,parm

ros2_srv 토픽 simple example

by 알 수 없는 사용자 2022. 4. 27.

참고

https://docs.ros.org/en/foxy/Tutorials/Writing-A-Simple-Py-Service-And-Client.html

 

 


패키지 생성 및 코드 data 저장

~/워크스페이스/src 에 드가서 이거 치삼

srv는 기본예제 weget으로 안받고 패키지 만들고 직접 editor로 작성해서 진행 할거임.!

ros2 pkg create --build-type ament_python py_srvcli --dependencies rclpy example_interfaces

 

저거 세개 수정해줄 거 해주고 (이름 이메일 파일설명 라이센스)


코드

~/ws_2/src/py_srvcli/py_srvcli$ 안에 들어가서 직접 editor 로 작성

 

service_member_function.py

from example_interfaces.srv import AddTwoInts

import rclpy
from rclpy.node import Node


class MinimalService(Node):

    def __init__(self):
        super().__init__('minimal_service')
        self.srv = self.create_service(AddTwoInts, 'add_two_ints', self.add_two_ints_callback)

    def add_two_ints_callback(self, request, response):
        response.sum = request.a + request.b
        self.get_logger().info('Incoming request\na: %d b: %d' % (request.a, request.b))

        return response


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

    minimal_service = MinimalService()

    rclpy.spin(minimal_service)

    rclpy.shutdown()


if __name__ == '__main__':
    main()

 

 

~/ws_2/src/py_srvcli/py_srvcli$ 안에 들어가서 직접 editor 로 작성

 

client_member_function.py

import sys

from example_interfaces.srv import AddTwoInts
import rclpy
from rclpy.node import Node


class MinimalClientAsync(Node):

    def __init__(self):
        super().__init__('minimal_client_async')
        self.cli = self.create_client(AddTwoInts, 'add_two_ints')
        while not self.cli.wait_for_service(timeout_sec=1.0):
            self.get_logger().info('service not available, waiting again...')
        self.req = AddTwoInts.Request()

    def send_request(self):
        self.req.a = int(sys.argv[1])
        self.req.b = int(sys.argv[2])
        self.future = self.cli.call_async(self.req)


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

    minimal_client = MinimalClientAsync()
    minimal_client.send_request()

    while rclpy.ok():
        rclpy.spin_once(minimal_client)
        if minimal_client.future.done():
            try:
                response = minimal_client.future.result()
            except Exception as e:
                minimal_client.get_logger().info(
                    'Service call failed %r' % (e,))
            else:
                minimal_client.get_logger().info(
                    'Result of add_two_ints: for %d + %d = %d' %
                    (minimal_client.req.a, minimal_client.req.b, response.sum))
            break

    minimal_client.destroy_node()
    rclpy.shutdown()


if __name__ == '__main__':
    main()

코드설명

코드설명 전에 알아 둬야 하는 내용들

- 1

클라이언트의 메인에서 유일하게 중요한 차이점은 while 루프입니다. 루프는 시스템이 실행되는 동안 서비스로부터 응답이 있는지 확인하기 위해 future 를 확인합니다. 서비스에서 응답을 보낸 경우 결과가 로그 메시지에 기록됩니다.

- 2

클라이언트 노드에서 call_async() API를 사용하여 서비스를 호출했고, 서비스를 호출할 다양한 방법(API)가 있습니다.

- 3

https://docs.ros2.org/latest/api/rclpy/api/services.html

client <--------> server 간의 data 전송 방식에 대한 설명이 나온 사이트 참고해라

 

 

순서도

server -> dds 네이밍올림

client -> dds 네이밍올림 -> 대기상태( wait_for_service )

dds -> client -- server -네이밍 맞춰서 연결

client.request -> server 

( 클라이언트노드객체명.future.XXX   future 클래스가 중요함.  클라이언트.future.done() 함수로 통신양호한지 확인도 하고, 클라이언트.future.result() 함수로 server로부터 받는 response도 가져오기도  하고 함. )

server.response -> client 

client.destroy_node() 

 

 

내용정리

------------------------------------------메시지 타입 정의 부분 --------------------------------------------------

service 와 client 가 사용한 메시지 타입은 String 이다.

메시지 타입을 사용하려면 방법이 2개 있다.

1. 직접 만드는방법

2. ros2 깔면서 자동으로 받아지는 lib 쓰기

 

여기서 쓴 방법은 2번이다.

하는방법 

1_1.

ros2 pkg create --build-type ament_python py_srvcli --dependencies rclpy example_interfaces

생성할 때 디펜던시 의존성을 넣어 주든가

1_2.

package.xml 에 의존성 명시 해줘야한다.

밑에 그림 3번 부분 처럼 <depend>example_interfaces</depend>

1_3

python 코드짤 때, 위에 그림에 1,2 번처럼

from example_interfaces.srv import AddTwoInts

 

 

------------------------------------------순서도 설명 --------------------------------------------------

1~4 까지는 네이밍 부분이라 누가 먼저 실행하냐 얘기임 그래서 동일하게 1~4 했고

그리고 어느부분에서 순서도 동작을 하는지 정리해봄

 

server -> dds 네이밍올림

3 (네임)

client -> dds 네이밍올림 -> 대기상태( wait_for_service )

3 (네임)

dds -> client -- server -네이밍 맞춰서 연결

4 , 4 (토픽,메시지타입)

client.request -> server 

9 ( call_async(self.req) )

server.response -> client 

12 ( return respone )

client.destroy_node() 

16 관련노드 제거


~/ws_2/src/py_srvcli 에 드가서

새로 작성한 python 코드들 명시 해주고

entry_points={
    'console_scripts': [
        'service = py_srvcli.service_member_function:main',
        'client = py_srvcli.client_member_function:main',
    ],
},

 

종속성 맞춰서 깔아주공

rosdep install -i --from-path src --rosdistro foxy -y

 

이거 아니면 걍 colcon build 로 전부 해줘도 ㄱㅊ

colcon build --packages-select py_srvcli

colcon build --packages-select "콜콘할 패키지명"

 

. install/setup.bash

 

service 노드 실행

ros2 run py_srvcli service

 

client 노드 실행 (인자 2개 넘겨줘야함 , 서비스에서 더해서 프린팅해중꼐)

ros2 run py_srvcli client 2 3

 

츨력값

[INFO] [minimal_client_async]: Result of add_two_ints: for 2 + 3 = 5

 

 

 

 

 

댓글