ROS(Robot Operating System) 개념과 활용

ROS(Robot Operating System) 개념과 활용 - 11. rosserial 알아보기

by 박정현 posted Mar 28, 2016
?

단축키

Prev이전 문서

Next다음 문서

ESC닫기

크게 작게 위로 아래로 댓글로 가기 인쇄

 ROS가 적용되는 시스템에선 연산을 위한 상위 제어기와 하드웨어 제어를 위한 하위 제어기가 각각의 역할을 수행하는 경우가 많습니다. 상위 제어기는 보통 PC나 OBC(One Board Computer)를 사용하게 되는데, 하위 제어기와 통신할 때 가장 흔하게 사용되는 프로토콜이 UART 같은 serial 통신이라고 할 수 있습니다. ROS 패키지 rosserial에서는 이러한 상위 제어기와 하위 제어기간에 ROS 기반의 데이터 전송을 가능하게 해 줍니다. rosserial은 상위 제어기, 즉 ROS 구동기 측에 적용되는 ROS-side interface와 하위 구동기에 적용되는 client-side library로 구성되어 있습니다. 상위 제어기는 ROS가 돌아갈 수 있는 플랫폼이면 어떤 것이든지 상관 없으며, 하위 구동기는 기본적으로 client library가 제공되는 아두이노, 임베디드리눅스, 윈도우, mbed, TI 런치패드 등을 제외하고는 사용자가 시리얼 인터페이스를 직접 정의하여 사용하게 됩니다. 통신 프로토콜은 기본적으로 serial 통신 중에서도 UART를 많이 사용하지만 사용자가 정의하기에 따라 다양한 통신 방법을 적용할 수 있습니다. Wi-Fi를 통한 TCP/IP socket 통신이나, Xbee를 이용해 mesh network를 구성하여 사용하는 것도 가능합니다. 이번에는 가장 기본적이며 손쉽게 사용할 수 있는 아두이노와 UART를 이용해 rosserial의 사용법을 알아 보도록 하겠습니다.


 우선 ROS 쪽에서 사용할 ROS-side interface로 rosserial_python 패키지를 설치합니다. rosserial_python은 파이썬 코드로 작성되어 있으며 간편하게 사용하기 좋습니다.


sudo apt-get install ros-indigo-rosserial-python


Client로 아두이노를 사용할 것이므로 rosserial-arduino 패키지도 설치합니다.


sudo apt-get install ros-indigo-rosserial-arduino
sudo apt-get install ros-indigo-rosserial


그 다음 Arduino IDE를 설치합니다. 여기서는 ROS가 구동되는 Ubuntu PC에 Linux버전 Arduino IDE를 설치하였습니다. 우분투 소프트웨어 센터에서 Arduino IDE를 검색하여 설치가 가능합니다. 아두이노 IDE를 설치하면 기본적으로 home/사용자명/ 경로(~/) 아래에 sketchbook 폴더가 생성되며, 그 하위 폴더인 'libraries'에 ROS-아두이노 라이브러리를 설치할 것입니다. 만약 이 경로에 기존에 설치한 ROS 라이브러리(ros_lib)가 있다면 에러 발생을 막기 위해 삭제하고 다시 설치하셔야 합니다.


  cd ~/sketchbook/libraries
  rm -rf ros_lib
  rosrun rosserial_arduino make_libraries.py .

rosrun rosserial_arduino make_libraries.py 뒤에 .을 빠트리지 않도록 합니다. 점은 현재 경로를 파이썬 스크립트의 output 위치, 즉 ros_lib을 만들 곳으로 사용한다는 뜻입니다.


저처럼 리눅스에서 아두이노 IDE를 사용하지 않고 다른 윈도우 PC에서 ROS-아두이노 라이브러리를 사용하고자 하는 경우, 위 과정을 통해 생성된 ros_lib 폴더를 윈도우에 있는 아두이노 IDE에 지정된 sketchbook/libraries 경로에 넣어 주시면 됩니다. 이 작업 후 아두이노 IDE를 여러 메뉴의 파일 -> 예제 -> ros_lib에서 라이브러리가 설치된 것을 확인 가능합니다.


 준비가 끝났다면 본격적으로 rosserial을 사용해 보도록 하겠습니다. 아두이노가 rosserial을 통해 "hello world!"를 보내도록 하여 publisher 노드로서 작동되게 하는 예제를 수행해 보겠습니다. 먼저 아두이노 IDE 메뉴의 예제 -> ros_lib -> HelloWorld를 선택하여 HelloWorld 예제 소스를 불러 옵니다.


/*
 * rosserial Publisher Example
 * Prints "hello world!"
 */

#include <ros.h>
#include <std_msgs/String.h>

ros::NodeHandle  nh;

std_msgs::String str_msg;
ros::Publisher chatter("chatter", &str_msg);

char hello[13] = "hello world!";

void setup()
{
  nh.initNode();
  nh.advertise(chatter);
}

void loop()
{
  str_msg.data = hello;
  chatter.publish( &str_msg );
  nh.spinOnce();
  delay(1000);
}


코드를 잘 보시면 예전에 해 보았던 발행자 노드 작성 예제(http://enssionaut.com/xe/board_robotics/942)와 거의 유사한 것을 확인할 수 있습니다. 플랫폼이 아두이노지만 ROS 라이브러리를 적용함으로써 ROS에서 사용하던 코드를 거의 그대로 사용할 수 있습니다. 물론 아두이노와 센서간 인터페이스나 전기적 입출력을 처리할 때에는 아두이노 명령어도 같이 사용이 가능합니다. 이번에도 내용을 하나씩 뜯어 보도록 하겠습니다.


#include <ros.h>
#include <std_msgs/String.h>

ROS 관련 헤더와 메시지 헤더를 포함시킵니다.


ros::NodeHandle  nh;

노드 핸들을 선언하여 publisher나 subscriber를 사용할 수 있도록 하며, 노드가 시리얼 통신을 다룰 수 있도록 합니다.


std_msgs::String str_msg;
ros::Publisher chatter("chatter", &str_msg);

메시지를 선언하고 토픽과 메시지 인스턴스에 대한 참조를 포함하는 발행자 객체를 만듭니다.


char hello[13] = "hello world!";

메시지 데이터로 집어 넣을 문자열을 만듭니다.


void setup()
{
  nh.initNode();
  nh.advertise(chatter);
}

아두이노의 setup() 함수 내에 들어가는 내용입니다. 노드 핸들을 초기화하고 chatter 토픽을 publish하도록 합니다. Publish 또는 subscribe할 다른 토픽이 있다면 전부 여기에 넣어 줍니다.


void loop()
{
  str_msg.data = hello;
  chatter.publish( &str_msg );
  nh.spinOnce();
  delay(1000);
}

아두이노의 loop() 함수 내에 들어가는 내용으로 계속 반복되어 실행됩니다. 메시지 데이터에 hello 문자열을 지정하고 chatter 발행자가 'chatter' 토픽으로 str_msg를 발행하도록 합니다. 딜레이는 ROS에서 쓰던 lop_rate() 대신 아두이노에서 사용하는 delay()를 사용합니다.


소스가 완성되면 아두이노 IDE를 통해 컴파일 후 아두이노에 프로그램을 업로드합니다. 아두이노가 어떤 USB 장치로 연결되어 있는지 확인하려면 예전에 direct serial 통신 예제에서 사용했던 방법을 이용합니다.


dmesg | grep tty


제 경우에는 아두이노가 ttyUSB0에 연결되어 있었으므로 이를 기준으로 진행하겠습니다. roscore를 실행시킨 다음, ROS 쪽 rosserial 인터페이스인 rosserial_python을 실행합니다. UART를 사용하는 경우 포트와 통신 속도 파라미터를 지정해야 합니다. 앞에서 포트는 ttyUSB0였고, 통신 속도(baudrate)는 57600을 사용하겠습니다. 다른 통신 속도를 사용하려고 했을 때 통신이 되지 않는 것으로 봐서 더 빠른 통신 속도를 적용하려면 아두이노쪽 라이브러리를 수정해야 할 것 같습니다.


roscore
rosrun rosserial_python serial_node.py _port:=/dev/ttyUSB0 _baud:=57600


연결이 성공한 경우 'Setup publisher on chatter [std_msgs/String]'이라는 내용이 터미널에 출력됩니다. 그 다음 토픽 내용을 화면으로 확인하기 위해 rostopic을 실행시킵니다.


rostopic echo chatter



jhpark@jhpark-901_ ~_004.png

1초마다 hello world!가 출력됩니다.



rqt_graph__RosGraph - rqt_006.png

chatter 토픽이 serial_node에서 rostopic node로 전달되는 것을 확인할 수 있습니다.


 지금까지 rosserial을 통해 아두이노와 ROS와 상호작용하는 과정을 살펴 보았습니다. rosserial은 아두이노 뿐만이 아닌 다양한 MCU들에게 적용될 수 있으며 ROS Wiki에서 일반적인 하드웨어에 rosserial client를 적용할 수 있는 튜토리얼을 제공하고 있습니다(http://wiki.ros.org/rosserial_client/Tutorials). 이를 활용해 ROS와 하위 제어기의 업무를 분리하여 모듈화된 시스템을 구성한다면 제어 성능과 개발 효율을 좀 더 향상시킬 수 있을 것입니다.