이번 포스팅부터는 ROS2를 공부해보도록 하자.
기본적인 ROS2의 정보는 여기를 참고해서 공부를 진행할 것이다.
https://cafe.naver.com/openrt/24070
ROS2의 기본적인 설치 및 개발 환경 세팅을 참고하도록 하자.
만약 그 이상으로 복잡하고 어려운 기능들이나 알고리즘을 다루게 된다면 별도의 링크, 깃헙 주소 등을 첨부하도록 하겠다.
그리고 본 ROS2 공부는 C++만으로 진행하도록 하겠다.
당초 파이썬 기반의 ROS2 프로젝트를 여럿 진행하였지만, 할수록 인터프리터 언어의 한계점을 느끼고(최소한 내 실력에선 파이썬을 가지고 더 높은 수준의 최적화를 못하기에) C++로 선회..
이번 포스팅의 목차는 다음과 같다.
📌 목차
1. ROS2란?
2. ROS2의 주요한 컨셉
3. ROS1과 ROS2의 차이
ROS2가 대체 무엇일까? ROS1과 유사한 것일까?
정답은 그렇다.
ROS2를 정확히 표현하면 다음과 같다.
💡 ROS2의 정의
- ROS2는 정확히 얘기하면 메타 운영체제(Meta OS) 혹은 소프트웨어 프레임워크(Software Framework) 혹은 미들웨어(Middleware)
이러한 ROS2는 다음과 같은 기능을 제공한다.
기존 운영체제를 활용해, 운영체제의 프로세스 관리 시스템 / 파일 시스템 / 유저 인터페이스 / 프로그래미 유틸리티를 이용해 다수의 이기종 하드웨어 간 데이터 송수신 / 프로세스 스케쥴링 / 에러 처리 등 로봇 응용 프로그램에 필요한 필수 기능들을 라이브러리 형태로 제공
이를 통해서 ROS는 다양한 목적의 응용 패키지들을 개발, 관리, 제공하고 있으며, 사용자들이 별도로 개발한 커스텀 패재키를 유통하는 로봇 생태계(ecosystem)을 갖추고 있다.
ROS2는 위와 같은 기능을 효과적으로 제공하기 위해서 약 400개의 공통 패키지(Common Package)들을 구성하여 지원하고 있다. 공통 패키지에는 다음 요소들이 포함된다.
- 빌드 시스템
- ROS 인터페이스 생성/관리/사용
- 토픽/서비스/액션 인터페이스 패키지
- 통신 미들웨어를 포함한 RMW 패키지
- 다양한 프로그래밍 언어 지원을 위한 클라이언트 라이브러리인 RCL 패키지
- 로보틱스 애플리케이션 프레임워크
- 로보틱스 애플리케이션 패키지
- 로봇 시뮬레이션 패키지
- 로봇 소프트웨어 개발 툴 패키지
등등...
ROS2의 공식 개발단체인 오픈 로보틱스에서는 Why ROS2? 라는 이름의 문서를 통해서 왜 ROS1에서 ROS2로 migration 해야하는지 설명하고 있다.
https://design.ros2.org/articles/why_ros2.html
정리해보면 다음과 같다.
- 빠른 개발 속도를 통한 시장 출시 기간 단축
- 산업계 피드백을 통한 생산에 최적화 된 설계
- 리눅스, 윈도우, Mac을 지원하는 멀티 플랫폼
- 다양한 산업 분야에서 사용 가능한 멀티 도메인
- 추상화된 라이브러리 및 응용프로그램을 통한 벤더 선택 기능
- 산업계 표준의 적극적 도입
- 오픈소스 라이센스 채택
- 강력한 글로벌 커뮤니티
- 산업계의 적극적인 지원
- ROS1과의 강력한 상호 운용성
https://cafe.naver.com/openrt/23965
이 문서에 표윤석 박사님께서 굉장히 잘 정리해놓았다.
여기를 기준으로, 극초보자인 본인이 ROS1과 ROS2를 모두 사용해서 개발을 해보면서 느낀 차이점을 정리하면 다음과 같다.
💡 ROS1은 아무리도 리눅스 위주로 사용되지만, ROS2는 윈도우를 제한적으로 지원하고 있다는 것이 크다고 생각한다. 다만 윈도우 사용자층이 강하지 않기 때문에 아무래도 ROS2도 무조건 리눅스로 가야하는 것이 맞다고 본다. 프로그래밍 및 개발을 지원하기에도 윈도우보다는 리눅스가 훨씬 유용하기 때문이다.
💡 이 점에 있어서는 ROS1 역시 많이 발전하였기에 실시간성이 중요한 플랫폼(예-자율주행 차량, 드론 등)에서 사용하는 것이 문제가 없다고 생각한다. 하지만 ROS1은 업데이트가 끝난 반면 ROS2는 활발히 개발이 이루어지고 있다는 차이점이 크다고 본다.
💡 ROS1은 아무래도 ROS Master가 모든 노드/토픽/서비스를 관리하다보니, Master만 탈취하게 되면 모든 시스템을 죽일 수 있다는 단점이 있었다. 반면 ROS2의 경우 거의 TCPROS로만 작동하던 ROS1과 다르게 산업계 표준인 DDS(Data Distribution System)을 적극 도입하였고, 산업계 표준에 해당하는 DDS Security를 통신 단계에서 도입하였다. 또한 SROS2와 RCL 라이브러리 단계에서의 보안성 강화도 적극 추진하였다.
💡 개인적인 생각으로는 ROS1과 ROS2의 가장 큰 차이점이 아닐까 싶다. ROS1에서는 TCP 통신을 ROS에 최적화 시킨 TCPROS를 적극 사용하였으며, ROS Master 등지에서도 사용하였다. 반면 ROS2의 경우 산업계 표준인 DDS의 도입으로 RTPS(Real Time Publish Subscribe)가 가능해졌다. 또한 산업 표준도 맞출 수 있었고, DDS의 자동 노드 감지 기능을 통해서 ROS Master를 생략 가능해졌다.
💡 그리고 통신의 QoS(Quality of Service)를 커스텀 설정이 가능해지면서, TCPROS로 거의 통일된 ROS1과 다르게 TCP와 UDP 등 다양한 통신 프로토콜 사이를 자유롭게 전전할 수 있게 되었다.
💡 이러한 DDS는 통신 미들웨어 형태로, RMW(ROS MiddleWare)라는 이름의 패키지로 다양한 벤더에서 제공하고 있다. 사용자는 이러한 점을 통해서 벤더를 선택할 수 있는 권한을 가진다.
💡 ROS1에서는
$ roscore
명령어를 통해서 실행되는 마스터(Master)가 파라미터 서버, 로깅 노드 등을 포함해서 모든 노드와 토픽, 서비스를 관리하고 탐색하였다. 따라서 마스터의 권한이 막강했고, 마스터가 중단되거나 하는 경우 해당 네트워크 도메인 내의 모든 시스템이 마비되는 경우가 발생하였다.
💡 반면 ROS2에서는
roscore도 없고, 마스터도 없다. 마스터는 완전히 삭제되어 DDS로 대체되었고, 파라미터 서버와 로깅 노드 모두 별도로 작동하게 되었다.
💡 개발 언어
ROS1과 마찬가지로 ROS2에서는 당연히 다양한 프로그래밍 언어를 지원한다. 파이썬 3과 C++14를 기초적인 베이스로 삼고 있다.
💡 빌드 시스템
ROS2에서는 ROS1의 catkin을 대체하는 새로운 빌드 시스템을 사용한다. ament라는 시스템인데, CMake 이외에 파이썬 패키지 관리도 가능해졌다. 이로 인해서 ROS2에서는 파이썬 패키지를 순수 파이썬 모듈과 동등한 수준으로 사용이 가능하다.
💡 빌드 툴
ROS1에서는 catkin_make, catkin build 등 다양한 빌드 툴을 지원하였다. ROS2의 경우 초창기에는 ament_tools가 사용되었지만, 현재는 colcon으로 교통 정리가 되었다.
📌 그 외 이야기들
- ROS1에서는 단일 워크스페이스에서 필요한 거의 모든 작업을 수행하였지만, ROS에서는 복수의 독립된 워크스페이스를 사용할 수 있게 되었다.
- ROS1에서는 CMakeLists.txt를 통해서 여러 개 패키지를 동시에 빌드하였지만, ROs2에서는 모든 패키지를 별도로 빌드해 설치용 폴더의 분리/병합이 가능해졌다.
- catkin은 빌드 후 devel 폴더에 코드를 저장했지만, ROS2에서는 패키지 빌드 후 설치를 통해 사용을 전제로 하고 있다. 따라서 devel 폴더가 필요하지 않다.
ROS1에서는 wstool을 사용하지만, ROS2에서는 vcstool로 통합하였다. 그리고 vcstool은 ROS1으로 재이식되었다.
💡 RCL
ROS에서 프로그래밍을 할 경우 유저 코드 영역(User Land)을 개발자가 다룬다는 것이고, 그 아래 RCL이 위치한다. RCL은 미들웨어를 사용하여, 각 프로그래밍 언어에 대한 클라이언트 라이브러리를 제공한다. 대표적으로 C++에는 rclcpp를, 파이썬에는 rclpy를 지원한다.
ROS2에서는 패키지의 각 노드들의 현재 상태를 모니터링 하고, 상태를 제어가 가능한 LifeCycle을 클라이언트 라이브러리에 포함시켜 ROS 시스템 상태를 효과적으로 제어할 수 있도록 하였다. ROS1에서는 불가능했던 다음 기능들을 지원한다.
- 노드 상태 모니터링
- 상태 천이(transition)
- 노드 재시작 / 교체
💡 컴포넌트
ROS1에서는 하나의 프로세스에 여러 노드 실행이 불가해, Nodelet 라이브러리를 통해 우회적으로 수행하였다. 반면 ROs2에서는 RCL에서 기본적으로 해당 기능을 제공하며, 이를 컴포넌트라고 부른다. 이를 통해 동일 실행 파일에서 복수의 노드 실행이 가능하다.
💡 ROS1에서는 단일 스레드와 다중 스레드 실행 중 하나만 선택이 가능했으나, ROS2에서는 더 세분화 된 실행 모델(Executor)을 C++과 파이썬에서 사용 가능하며, 사용자가 정의한 실행 모델도 RCL API를 통해 쉽게 구현 가능하다.
💡 ROS1의 메시지 통신과 ROS2
ROS1에서는 메시지 통신으로 자료형과 간단하 자료구조, 배열 등을 지원하였다. ROS2도 이와 마찬가지의 기능들을 지원하며, 커스텀 메시지 작성 기능도 지원한다. 여기에 ROS2에서는 IDL(Interface Description Language)를 사용해서 메시지 정의 및 직렬화를 더 쉽게, 더 포괄적으로 수해 가능하게 한다.
💡 launch
단일 노드만을 실행시키는 run과 다르게 launch는 복수 노드를 실행시킬 수 있다. 또한 사용자가 원하는 각종 설정을 기술하여 실행이 가능하다는 특징도 있다. 이러한 개념은 ROS1이나 ROS2나 별 차이가 없다. 하지만 ROS1에서는 launch 파일을 XML 형식만을 지원하였다. 반면 ROS2에서는 XML 이외에 파이썬을 통해서 복잡한 논리와 기능을 자유롭게 사용하도록 하였다.
💡 그래프 API
ROS1에서 rqt_graph를 사용해봤으면 알 것이다. ROS1에서는 실시간으로 변화하는 노드 그래프를 표현할 수 없었다. 반면 ROS2는 노드 실행 중 그래프 재매핑이 간으하며, 바로 그래프를 갱신할 수도 있는 기능을 지원한다.
💡 임베디드 시스템에 걸맞는 통신
ROS1에선 임베디드 시스템과 메시지를 주고받을 때 시리얼 통신을 사용하였따.
반면, ROS2의 경우
- 시리얼 통신
- 블루투스, 와이파이
- RTOS(Real-Time Operating System)
- XRCE-DDS (eXtremely Resource Constrained Environments - DDS)
- AWS ARCLM
- etc ..등
다양한 임베디드 시스템과의 통신 기능을 지원한다.