Ubuntu 18.04 LTS / ROS Melodic / RPLIDAR A3
용어를 번역하자면 동시적 위치추정 및 지도작성이다. SLAM은 자동차, 로봇 등이 미지의 환경(공간)에서 이동함과 동시에 주변을 탐색하며, 그 공간의 지도를 그리고 현 위치를 추정하는 개념이다.
rplidar는 RPLIDAR의 제조사인 Slamtec에서 관리하는 ROS 패키지로, 2D 레이저 스캐너 RPLIDAR A1, A3, A3 모델의 기본적 디바이스 핸들링을 지원한다. GitHub에서 소스를 다운받을 수 있다. 본인 ROS의 버전을 잘 살펴서 다운받자.
드라이버는 senser_msgs/LaserScan 데이터를 퍼블리시한다. 해당 내용은 아래서 자세히 다룬다.
rplidarNode는 RPLIDAR의 드라이버로, RPLIDAR의 SDK에서 raw scan 결과를 읽어 ROS LaserScan 메시지로 바꾸어준다.
SDK(Software Development Kit)는 소프트웨어 개발 키트로, 하드웨어 플랫폼이나 운영체제(Operating System, OS), 프로그래밍 언어 제작사가 제공하는 도구이다. 기본적으로는 컴파일러, 디버거, API(Application Programming Interface) 등이 포함된다. 개발자는 SDK를 이용하여 특정 플랫폼이나, 시스템, 프로그래밍 언어에 따라 애플리케이션을 개발할 수 있다.
노드는 레이저로부터 토픽 /scan
을 퍼블리시하며, 메시지 형태는 sensor_msgs/LaserScan이다. 하이퍼링크를 따라가 직접 살펴보아도 좋다.
해당 메시지 파일을 자세히 살펴보자. 아래 내용은 sensor_msgs/LaserScan.msg의 Raw Message Definition
을 그대로 가져온 것이다.
# Single scan from a planar laser range-finder
#
# If you have another ranging device with different behavior (e.g. a sonar
# array), please find or create a different message, since applications
# will make fairly laser-specific assumptions about this data
Header header # timestamp in the header is the acquisition time of
# the first ray in the scan.
#
# in frame frame_id, angles are measured around
# the positive Z axis (counterclockwise, if Z is up)
# with zero angle being forward along the x axis
float32 angle_min # start angle of the scan [rad]
float32 angle_max # end angle of the scan [rad]
float32 angle_increment # angular distance between measurements [rad]
float32 time_increment # time between measurements [seconds] - if your scanner
# is moving, this will be used in interpolating position
# of 3d points
float32 scan_time # time between scans [seconds]
float32 range_min # minimum range value [m]
float32 range_max # maximum range value [m]
float32[] ranges # range data [m] (Note: values < range_min or > range_max should be discarded)
float32[] intensities # intensity data [device-specific units]. If your
# device does not provide intensities, please leave
# the array empty.
header
seq
, time stamp
, string frame_id
로 구성되어 있다.time
: 스캔하여 데이터를 획득한 시간angle_min
[rad] : 스캔의 시작 각도angle_max
[rad] : 스캔의 끝 각도angle_increment
[rad] : 측정되는 각의 단위이다. 0.01이라면 0.01라디안 마다 측정이 이루어지는 것이다.scan_time
[sec] : 측정되는 시간 간격range_min
[m] : 최소 range(거리) 값range_max
[m] : 최대 거리 값ranges
[m]
range_min
) 이상, 최대 거리(range_max
) 이하의 거리 값들을 말한다.angle_min
)부터 최대 각도(angle_max
)까지 단위 각도(angle_increment
)씩 분할한 하나하나를 요소로 하는 리스트이다.inf
로 표시된다.intensities
: 레이저가 부딪혀 돌아오는 강도를 담고 있다. 지원하는 기기에서만 표시되고, 그 외에서는 빈 배열이다.위 사진은 RPLIDAR A3를 연결해 /scan
데이터를 rostopic echo
명령을 통해 출력한 결과이다. 주요 값의 예는 아래와 같다.
data | value |
---|---|
angle_min | -3.14159274101 |
angle_max | 3.14159274101 |
angle_increment | 0.00322876940481 |
range_min | 0.15000000596 |
range_max | 25.0 |
라이다 작동에 필요한 파라미터는 아래와 같다. 해당 파라미터들은 rplidar.launch
파일에 <param>
태그로 나타나 있다.
파라미터 | 자료형 | default 값 | 설명 |
---|---|---|---|
serial_port | string | /dev/ttyUSB0 | 라이다가 연결된 시리얼 포트 |
serial_baudrate | int | 115200 | 시리얼 포트의 보 레이트. 통신 속도 |
frame_id | string | laser_frame | 기기의 프레임 ID |
inverted | bool | false | 라이다가 inverted되어 마운드 되었는가 (뒤집어졌는가) |
angle_compensate | bool | false | 기기가 시야각 보상(angle compensation)이 필요한가 |
scan_mode | string | std::string() | 스캔 모드 |
보 레이트(Baud Rate)는 초당 전송 신호 요소 개수로, 심볼(Symbol, 의미 있는 데이터 묶음)을 얼마나 전송할 수 있는가를 나타낸다. 하나의 심볼을 쉽게 하나의 ‘데이터 묶음’이라고 표현하자. 시리얼 통신에서는 8bit를 데이터 묶음이라 한다. 그렇다면 100 baud rate라면 1초에 100개의 데이터 묶음, 즉 8*100=800bit를 전송한다는 이야기이다.
[1] GitHub에서 패키지를 /catkin_ws/src
에 내려받고 빌드를 해준다.
$ git clone https://github.com/Slamtec/rplidar_ros
$ catkin_make 또는 cm
[2] USB 포트에 라이다를 연결한다. [3] 터미널에서 USB 포트를 확인하고, 권한을 허용한다.
$ ls -l /dev | grep ttyUSB
$ sudo chmod 666 /dev/ttyUSB0
[4] .launch
파일을 실행시켜 라이다를 작동시킨다.
실행 전, 실행할 파일에 기기 모델에 따라 파라미터 baudrate
를 수정해주어야 한다. A1, A2 모델은 기본값으로 되어 있는 115200
를, A3는 256000
으로 변경해야 한다.
모든 .launch
파일은 /rplidar_ros/launch
에 있다. 모델에 따라 나뉘어 파일 엄청 많다.
[4-1] Rviz가 함께 실행되는 버전: launch 파일을 실행함과 동시에 Rviz 창이 자동으로 켜진다. 필자가 사용하는 모델은 A3이므로 view_rplidar_a3.launch
파일을 실행시켰다.
$ roslaunch rplidar_ros view_rplidar_a3.launch
[4-2] 라이다 작동만 하는 버전: 가장 기본적 launch 파일이다.
$ roslaunch rplidar_ros rplidar.launch
[5] 추가적으로 라이다가 센싱한 값을 터미널에서 확인하고 싶다면 다른 터미널에서 아래 명령을 실행해보자.
# (1) 패키지에 포함된 스크립트를 실행함. 라이다가 받는 ranges[] 데이터를 나타냄
$ rosrun rplidar_ros rplidarNodeClient
# (2) rostopic echo로 /scan 메시지를 직접 출력함. rostopic list로 토픽 목록 확인 후 실행해보자.
$ rostopic echo /scan
위 우측 사진은 rplidarNodeClient
를 작동시켰을 때의 터미널 출력이다. -180°(-3.14rad)부터 180°(3.14rad)까지에서의 인덱스 값과 거리값을 담고 있음을 알 수 있다.
USB 허브를 이용하는 등 복수 개의 센서를 연결할 경우 매번 ttyUSB*의 번호가 바뀐다. 매번 이 번호를 확인하고 lauch 파일에서 바꿔주기에는 매우 번거롭다. 때문에 이를 이름으로 고정하면 매우 편리하다.
자세한 이론적 내용은 [Linux] USB 장치 이름 고정하기: udev 설정, Symbolic Link(심볼릭 링크) 만들기에 설명해두었다.
간단히 하자면, /rplidar_ros/script
에 있는 rplidar.rules
파일을 /etc/udev/rules.d
로 복사하여, ttyUSB*
로 표시되던 라이다의 이름을 rplidar
로 변경하며 권한을 777
으로 한다는 뜻이다.
$ cd /catkin_ws/src/rplidar_ros
$ ./scripts/create_udev_rules.sh
결과적으로 이름이 바뀌었는지 확인하자.
$ ls -l /dev | grep rplidar
결과를 확인하면 rplidar
라는 이름이 생성되었고, ttyUSB0
로 연결이 되어 있다고 한다. 만약 연결 포트가 바뀌어 ttyUSB1
로 변경되었대도 라이다는 여전히 rplidar
로 뜰 것이다.
만약 rplidar
라고 나오지 않는다면 컴퓨터를 재부팅해보자.
라이다의 이름이 바뀌었으니 rplidar.launch
에서 파라미터의 값을 /dev/ttyUSB0
에서 /dev/rplidar
로 바꾸어주어야 한다.
<param name="serial_port" type="string" value="/dev/rplidar"/>
이름을 바꾸어주었으니 launch파일을 다시 실행해도 문제가 없을 것이다.
위에서 view_rplidar_a3.launch
를 실행시켰을 때 rviz가 동시에 실행되었었다. 스캔 결과가 점으로 표시되므로 어디가 어디인지 판별하기 힘들 때가 있으니, 축을 표시해보자.
좌측 하단의 Add
버튼을 클릭한 뒤, 나타나는 창에서 Axis
를 선택하고 OK
를 클릭해 추가한다.
화면 상에 축이 보이고, 마우스를 이용해 뷰를 조절할 수 있다.
X축은 빨강, Y축은 초록, Z축은 파랑색이다.