왕다방

인공지능 & 로봇 사용자들의 자유게시판입니다. 인공지능, 가정용로봇, 서비스로봇, 인공지능스피커 등 자유롭게 올려주세요. 질문과답변도 이곳에 올려주세요.

제목ROS와 비ROS 사이의 통신: roslibpy2022-01-25 01:24
작성자user icon Level 4

88x31.png


ROS2는 UDP를 기반으로 DDS-RTPS 프로토콜을 통해 통신합니다. 그러므로 웹브라우저같은 TCP를 기반으로 통신하는 어플리케이션은 원래 ROS와 커뮤니케이션이 불가합니다. 하지만 이를 가능하게 하는 모듈이 있는데 바로 rosbridge 패키지입니다. rosbridge는 ROS 환경에서 실행되는 노드로, 웹소켓을 생성하여 ROS와 비ROS 사이에 JSON 형식으로 통신함으로써 ROS의 범용성을 높여줍니다.


예제를 통해 확인해보도록 합시다. ROS2 버전은 foxy 이고, 파이썬에서 roslibpy 모듈을 통해 비ROS 환경에서 ROS와 통신해보겠습니다.


우선 다음 명령어를 통해 rosbridge 패키지를 설치합니다.

 $ sudo apt install ros-foxy-rosbridge-suite


pip를 통해 roslibpy 모듈도 설치합시다.

 $ sudo pip install roslibpy


다음으로 ros2의 launch 명령어를 통해 브릿지 서버를 실행합니다.

 $ ros2 launch rosbridge_server rosbridge_websocket_launch.xml

mb-file.php?path=2022%2F01%2F24%2FF4544_1.png
9090 포트를 통해 웹소켓이 생성되었습니다!



우선 발행자(Publisher) 모듈을 만들어 토픽을 발행해 보겠습니다.

 $ touch publisher.py && xed publisher.py

import time

import roslibpy


client = roslibpy.Ros(host='localhost', port=9090)

client.run()


publisher = roslibpy.Topic(client, 'topic', 'std_msgs/String')


while client.is_connected:

    publisher.publish(roslibpy.Message({'data': 'Hello World!'}))

    print('Sending message...')

    time.sleep(1)


publisher.unadvertise()


client.terminate()


mb-file.php?path=2022%2F01%2F25%2FF4547_2.png
 


타이머를 위한 time 모듈과 roslibpy 모듈을 import 합니다.

import time

import roslibpy


roslibpy 모듈의 Ros 함수를 통해 클라이언트를 생성하세요. 매개변수로 웹소켓 hostport를 넘겨줍니다. 클라이언트의 run 함수로 웹소켓에 연결합니다.

client = roslibpy.Ros(host='localhost', port=9090)

client.run()


roslibpy 모듈의 Topic 함수로 토픽에 연결합니다. 클라이언트 객체, 토픽 이름, 메시지 타입을 매개변수로 넘겨줍니다.

publisher = roslibpy.Topic(client, 'topic', 'std_msgs/String')


발행자 객체의 publish 메소드를 통해 토픽을 발행합니다. 'std_msgs/String' 타입 메시지는 string 타입의 'data' 필드를 가진다는 사실을 참고하세요.

while client.is_connected:

    publisher.publish(roslibpy.Message({'data': 'Hello World!'}))

    print('Sending message...')

    time.sleep(1)

이렇게 작성하면 'topic' 토픽으로 1초에 한번씩 메시지를 보냅니다.


웹소켓 연결이 끊어지면 발행자 등록을 취소하고 웹소켓을 닫습니다.

talker.unadvertise()


client.terminate()


저장하고 터미널을 새로 여세요. 예전에 만든 pubsub_py 패키지의 sub 노드를 실행하겠습니다. sub 노드는 'topic' 토픽을 구독하는 구독자 노드였습니다.

 $ overlay && ros2 run pubsub_py sub


다른 터미널을 열고 다음 명령어를 통해 publisher.py 모듈을 실행해보세요.

 $ python3 publisher.py


mb-file.php?path=2022%2F01%2F25%2FF4548_3.gif
 

결과만 보면 ROS2 환경에서 실행되는 발행자와 차이가 없어보이지만 roslibpy로 만든 발행자는 TCP를 통해 웹소켓으로 데이터를 보내고, 웹소켓을 통해 받은 데이터를 브릿지 노드가 UTP를 통해 토픽을 발행하는 과정을 거칩니다. 


rqt_graph를 통해 노드와 토픽을 확인해보면 발행자가 브릿지 노드라는 것을 확인할 수 있습니다.

mb-file.php?path=2022%2F01%2F25%2FF4549_3.png
 

구독자(Subscriber) 모듈은 발행자 모듈과 비슷한데 구독자 객체의 subscribe 메소드를 통해 토픽을 구독합니다. 매개변수로 콜백함수를 넘겨줍니다. 콜백함수는 매개변수로 메시지 객체를 받습니다. 아래 코드에서는 람다(lambda) 표현식을 통해 콜백함수를 작성했습니다.

 $ touch subscriber.py && xed subscriber.py

import roslibpy


client = roslibpy.Ros(host='localhost', port=9090)

client.run()


subscriber = roslibpy.Topic(client, 'topic', 'std_msgs/String')

subscriber.subscribe(

    lambda message: print('Heard talking: ' + message['data']))


try:

    while True:

        pass

except KeyboardInterrupt:

    client.terminate()

mb-file.php?path=2022%2F01%2F25%2FF4550_4.png
 

#ROS2# rosbridge# roslibpy# publisher# subscriber
댓글
자동등록방지
(자동등록방지 숫자를 입력해 주세요)