마이크로컨트롤러와 컴퓨터간의 메시지 통신을 위해 변환 작업을 수행하는 패키지이다.
* 제어기 > 시리얼(rosserial 프로토콜) > PC(ROS 메시지로 재전송)
* 제어기 < 시리얼(rosserial 프로토콜) < PC(ROS 메시지를 시리얼로 변경)
일반적으로 마이크로컨트롤러는 ROS에서 기본 통신으로 사용하는 TCP/IP보다 시리얼 통신을 많이 사용해 rosserial과 같은 중계자 역할이 필요하다.
ROS가 구동되는 PC에서 rosserial protocol을 통해 중계자 역할을 하는 노드로 구현된 프로그래밍 언어에 따라 3가지 노드가 있다.
rosserial의 client 역할을 하는 라이브러리로 rosserial_client 라이브러리가 마이크로컨트롤러에서 사용되는 플랫폼에 포팅되었다.
rosserial server와 client는 시리얼 통신 기반의 패킷 형태로 데이터를 송/수신한다. rosserial protocol은 바이트 단위로 정의되어 있고 패킷의 동기화 및 데이터 검증을 위한 정보들이 포함되어 있다.
rosserial 패킷 구성
1st Byte | 2nd Byte | 3rd Byte | 4th Byte | 5th Byte | 6th Byte | 7th Byte | N Bytes | Byte N+8 |
---|---|---|---|---|---|---|---|---|
Sync Flag | Sync Flag/ Protocol version | Message Length(N) | Message Length(N) | Checksum over message length | Topic ID | Topic ID | Serialized Message Data | Checksum over Topic ID and Message Data |
각각의 Byte가 나타내는 바는 다음과 같다.
Checksum = 255 - ( (Message Length Low Byte + Message Length High Byte) %256)
ID_PUBLISHER=0, ID_SUBSCRIBER=1, ID_SERVICE_SERVER=2, ID_SERVICE_CLIENT=4, ID_PARAMETER_REQUEST=6, ID_LOG=7, ID_TIME=10, ID_TX_STOP=11
Checksum = 255 - ( (Topic ID Low Byte + Topic ID High Byte + data byte values) % 256)
임베디드에 사용되는 마이크로컨트롤러는 사용할 수 있는 메모리가 제한되어 있고 일반 PC에 비해서는 상당히 작은 용량을 가지고 있다. 송신, 수신 버퍼의 크기를 초과하는 메시지의 데이터는 송신, 수신할 수 없으므로 주의가 필요하다.
*MCU: 마이크로컨트롤러 유닛, 마이크로프로세서와 입출력 모듈을 하나의 칩으로 만들어 정해진 기능을 수행하는 컴퓨터를 말한다. 개인용 컴퓨터가 다양한 요구에 따라 동작하는 일반적인 일에 사용된다면, MCU는 기능을 설정하고 정해진 일을 수행하도록 프로그래밍되어 장치 등에 장착되어 동작한다.
rosserial client로 rosserial_auduino를 사용할 경우에 아두이노 보드에 사용된 MCU는 64비트 실수연산을 지원하지 않아 라이브러리를 생성할 때 자동으로 32비트형으로 변경한다. 만약 64비트 실수연산을 지원한다면 make_libraries.py에서 데이터 타입 변환 부분을 수정하면 된다.
마이크로컨트롤러의 메모리 제한으로 문자열 데이터를 String 메시지 안에 저장하지 않고 외부에서 정의한 문자열 데이터의 포인터값만 메시지에 저장한다. String 메시지를 사용하기 위해서는 다음과 같은 절차가 필요하다.
std_msgs::String str_msg; unsigned char hello[13] = "hello world!"; str_msg.data = hello;
string과 마찬가지로 메모리 제약사항으로 배열 데이터에 대한 포인터를 사용해서 배열의 끝을 알 수가 없다. 따라서 배열의 크기에 대한 정보를 추가하고 메시지를 송신, 수신할 때 사용한다.
UART 같은 경우 115200bps와 같은 속도로는 메시지의 개수가 많아지면 응답 및 처리속도가 느려질 수 있다. 하지만 OpenCR에서는 USB를 이용한 가상의 시리얼 통신을 적용하여 고속통신이 가능하다.
rosserial을 사용하기 위해서는 ROS의 필요한 패키지들을 설치하고 사용하고자 하는 디바이스의 플랫폼 client 라이브러리를 사용하도록 한다.
다음 명령어로 rosserial과 아두이노 계열 지원 패키지를 설치한다.
sudo apt-get install ros-melodic-rosserial ros-melodic-rosserial-server ros-melodic-rosserial-arduino
아두이노에서 사용하기 위해서는 아두이노용 rosserial 라이브러리를 생성해야 한다. 다음과 같이 아두이노 IDE의 개인 폴더의 라이브러리 폴더로 이동한 다음에 기존에 생성한 라이브러리가 있다면 삭제한다. rosserial_arduino 패키지의 make_libraries.py 파일을 실행하여 ros_lib를 생성한다.
cd ~/Arduino/libraries/ rm -rf ros_lib rosrun rosserial_arduino make_libraries.py .
아두이노 ROS 라이브러리를 생성한 경우에 기본으로 설정된 통신 포트를 사용하도록 되어 있다. 일반적인 아두이노 보드인 경우 HardwareSerial 클래스의 Serial 객체를 사용하도록 되어 있기 때문에 통신 포트를 변경하기 위해서는 생성된 라이브러리 소스를 수정해야 한다. 라이브러리 폴더의 ros.h 파일 내용을 보면 ArduinoHardware 클래스를 사용하여 NodeHandle을 정의 한다. 따라서 사용할 포트의 하드웨어 기능을 ArduinoHardware 클래스에서 변경하면 된다.
#include "ros/node_handle.h" #include "ArduinoHardware.h" namespace ros { /* Publishers, Subscribers, Buffer Sizes */ typedef Nodehandle_<ArduinoHardware, 25, 25, 1024, 1024> NodeHandle; }
#include <ros.h> #include <std_msgs/Empty.h> ros::NodeHandle nh; void messageCb( const std_msgs::Empty& toggle_msg){ digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level) delay(1000); // wait for a second digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW delay(1000); // wait for a second } ros::Subscriber<std_msgs::Empty> sub("toggle_led", &messageCb ); void setup() { pinMode(LED_BUILTIN, OUTPUT); nh.initNode(); nh.subscribe(sub); } void loop() { nh.spinOnce(); delay(1); }
roscore
rosrun rosserial_python serial_node.py __name:=arduino _port:=/dev/ttyACM0 _baud:=57600
rostopic pub /toggle_led std_msgs/Empty