티스토리 뷰
ROS 패키지, 스택은 어떻게 구조화하는 것이 좋을까?
요약
mobilerobot 패키지를 만든다면,
- mobilerobot_ros (repo)
- mobilerobot (metapackage)
- mobilerobot_bringup
- mobilerobot_description
- mobilerobot__naviagation
- mobilerobot__slam
- mobilerobot__teleop
- mobilerobot_simulation (repo)
- mobilerobot_simlation (metapackage)
- mobilerobot_gazebo
- mobilerobot_msgs (repo)
이런 식으로 작성한다. -끝-
도입
로봇 구동 ROS 스택(패키지 묶음)을 제작할 때, 항상 고민인 부분이 ROS 패키지의 디렉터리들을 어떻게 구조화하냐는 것이다.
과거에 아무 생각 없이 '작동만 되는' 패키지 혹은 '나만 보는' 로봇 패키지를 만들었기 때문에, 대충 설계하고 빨리 제작했었다.
과거에 만든 레포를 다시 살펴보면 참... 남들한테 보여주기 좀 그렇다. 그래서 내 github 레포의 심해 속으로 빨리 가라앉았으면...
해당 글은 ROBOTIS, Hello Robot, Clearpath, Fetch Robotics의 레포지토리와 해외 블로그 RoboticsBackend의 글을 참고하여 작성하였다.
패키지와 스택
사람들은 패키지와 스택은 엄밀한 구분없이 혼용해서 사용한다.
그래도 패키지, 스택에 대해 짧게 설명해보자면
패키지는 빌드가 되는 ROS코드의 기본 단위이다. 어느 하나의 기능을 목적으로 만들어진다.
스택은 ROS 코드 배포의 기본단위이다. 주제상으로 동일한 목적을 가진 패키지들의 집합체를 말한다.
예로 터틀봇3을 구동하는 목적을 가진 구동, 네비게이션, 조종, 슬램 패키지들이 한 곳에 모여 터틀봇을 제어하는 터틀봇3 ROS 스택이 된다.
왜 패키지를 구조화하는 가?
패키지를 구조화하는 이유로 몇 가지를 들 수 있다. 객체 지향 프로그래밍이 추구하는 바와 유사하다.
1. 사용자가 해당 스택이 어떤 기능을 보유하고 있는지 한눈에 파악할 수 있도록 하기 위해.
2. 하나의 패키지가 하나의 목적과 기능을 수행하도록 하고 의존성의 관계를 명확하게 하기 위해서.
3. 다른 패키지와의 관계를 깨뜨리지 않게 않고 쉽게 패키지를 다른 패키지로 교체하거나 수정을 하기 위해
4. 순환 의존을 막기 위해
5. 예쁘게 보이게 함으로 있어보게 하기 위해
*나는 사실 5번이 주목적이다.
주로 패키지의 의존성 관리와 교체 가능성을 만들어 주고 싶어 하기 때문에 패키지를 구조화한다.
때에 따라서는 기본 패키지가 아닌 사용자가 원하는 다른 패키지로 바꿀 수 있어야하닌까. ex) SLAM(2D->3D)
구조화하는 법
Github 레포 이름 짓기
예) mobilerobot_ros, mobilerobot
패키지의 레포 이름은 어떻게 지었을까?
몇 레포를 보며 살펴보자.
로보티즈나 클리어패스처럼 '로봇이름' 자체로 짓는 경우도 있고 fetch나 hello robot처럼 '로봇이름_ros'를 붙이는 경우가 있다.
딱히 규정은 없으니 개인의 취향대로 하자.
나는 '로봇이름_ros'를 선호한다.
어떤 패키지를 넣어야하는가?
이제 ROS 스택의 레포 이름은 정해졌으니 그 이후는 구성될 패키지들를 정하는 것이다.
터틀봇3는 위 사진에서 볼 수 있는 것처럼 다양한 패키지를 담고 있다.
설명에 앞서 이름 규칙을 설명하자면, 일반적으로 '로봇이름_패키지기능' 으로 정한다.
ex) turtlebot3_bringup, strecth_core, fetch_teleop
meta package
예시) mobilerobot
레포를 살펴보면, 로봇 이름과 동일한 패키지가 있는 것을 확인할 수 있다. 이를 메타패키지라 말한다.
메타패키지 디렉터리 안에는
CHANGELOG.rst, CMakelists.txt, package.xml 파일 3가지밖에 없는 것을 확인할 수 있는데,
메타패키지는 아무런 기능은 없지만, 해당 스택에 포함된 패키지들 즉, ROS 스택을 구성하는 패키지들이 설치될 수 있도록 도와주는 역할을 한다.
해당 패키지의 package.xml을 보면 다음과 같은 <metapackage/> tag가 작성되어있는 것을 확인할 수 있다.
msgs
예시) mobilerobot_msgs
ROS를 사용하는 주 이유는 노드을 통해 기능을 쉽게 만들 수 있고 사용자가 노드간 통신을 신경 쓸 필요가 없도록 ROS라는 미들웨어가 관리해주기 때문이다.
하지만, 노드 간 통신을 하기 위해서는 msg 인터페이스에 대한 약속이 있어야 한다.
일반적으로 ROS 기본 메시지를 사용하여 노드간 통신을 하지만, 로봇을 제작하는 경우에는 어쩔수 없이 커스텀 된 메시지를 사용하는 경우가 생기게 된다.
이 때문에 로봇회사에서는 별도의 메시지 패키지를 만드는데, 이 경우 메시지 패키지를 별도의 레포로 분리하는 곳도 있다.
물론, ROS 스택에 함께 포함시키는 경우도 있다.
예시
약간의 Tip으로
웬만해서는 커스텀 msgs 패키지를 만들지 않는 것이 개발자 입장에서는 좋다.
할 수 있다면, 기본 msgs 타입만으로 작성하도록 하자
다른 패키지와 함께 사용할 경우, 커스텀 메시지를 일반 메시지로 변환시켜주는 브릿지 기능을 추가해야하는 귀찮음이 생길 수도 있기 때문이다.
driver
예시) mobilerobot_driver, mobilerobot_hw
driver 패키지는 하드웨어를 구동하는 패키지이다. 액추에이터, 센서 등 하드웨어 레벨을 직접 컨트롤하는 노드들이 포함된다.
로봇을 구성하는 패키지 중 가장 로우 레벨에 위치한다.
일반적으로 wrapper 패키지라 한다.
하드웨어 레벨의 비 ROS 프로그램을 ROS 상에서 사용할 수 있도록 ROS 인터페이스로 '감싼' 패키지이다.
예로는 RGB-D카메라인 Realsense ROS패키지, LiDAR인 벨로다인 ROS 패키지 등이 있다.
stretch의 경우 stetch_body라는 하드웨어 레벨 제어 패키지(비ROS)를 제작 후
이를 bringup(혹은 core) 패키지 내의 stretch_driver 노드가 wrapping 작업한 후 ROS 상에서 컨트롤 할 수 있도록 도와준다.
터틀봇3는 하드웨어레벨의 모터 제어를 OpenCR이 담당하는데,
OpenCR과 라즈베리파이를 시리얼 통신으로 연결해주는 ROS Serial 노드가 Wrapper 패키지 역할을 한다.
bringup
예시) mobilerobot_bringup, mobilerobot_core
bringup 혹은 core 패키지는 현실의 로봇을 동작시키는 launch파일들을 담은 패키지이다.
bringup 패키지는 하드웨어 레벨의 driver 패키지를 동작시키는 launch 파일과 로봇을 전체적으로 제어하는 laucnh 파일로 구성된다.
로봇 구동에 관련된 설정 파일은 해당 패키지의 config 디렉터리를 생성 후 yaml파일로 제작하면 파라미터 수정을 쉽게 할 수 있다.
Description
ex) mobilerobot_description
Description은 URDF(.xacro)와 meshes 디렉터리로 구성되며, 로봇의 외형을 묘사하는 패키지이다.
디렉터리 구조는 터틀봇3와 hello robot가 똑같지만, urdf 내에 담은 내용물에서는 약간의 차이점을 보인다.
터틀봇3의 경우 가제보가 사용할 수 있는 xacro를 포함한 반면,
stretch_ros는 가제보 관련 xacro는 별도의 stretch_gazebo/urdf로 분리해놓았다.
포함 여부는 개인의 기호에 따라 설정하자.
description 패키지에는 런치파일을 일반적으로 만들지는 않지만, rviz를 사용하여 로봇의 외형을 파악하는 launch 파일을 포함하기도 한다.
gazebo 실행 launch 파일은 넣지 말자. 해당 패키지의 로봇 외형 표현 목적에 맞지 않다.
simulation
예시) mobilerobot_gazebo, mobilerobot_simulations
실물 로봇이 아닌 시뮬레이션에서 로봇을 구동시켜볼 때 사용하는 패키지이다.
터틀봇3와 fetch는 독립적인 레포로 분리했지만
stretch는 메인 스택인 stretch_ros에 포함시켰다.
터틀봇3는 경우 launch 디렉터리에 여러 맵을 실행할 수 있도록 launch 파일들을 제작해놓았다.
개인적으로 시뮬레이션 레포는 분리하는 것을 선호한다.
예로 터틀봇3의 경우, 터틀봇3 스택을 라즈베리파이에서 실행시키게 되는데,
라즈베리파이에서 가제보를 돌릴 일이 없으니, 별도로 분리시키는게 낫다.
기타 모바일 로봇 패키지들
기타 모바일 로봇에 공통적으로 포함시키는 패키지로는 Navigation, SLAM 그리고 teleop 패키지가 있다.
slam 패키지의 경우, 터틀봇은 별도로 하나의 turtlebot3_slam으로 구성한 반면,
stretch와 fetchrobotics는 naviation 패키지 안에 launch로서 실행할 수 있도록 합쳐서 구성했다.
마찬가지로 개인의 취향에 따라 구성하자.
마무리
사실, ROS 패키지를 구성하는 것에는 정답이 없고, 규약도 딱히 정해진 것도 아니지만,
하나의 패키지에는 하나의 목적을 수행할 수 있도록 구성하고 최대한 의존성을 간단히 구성하는 게 좋다.
위에 서술한 내용으로 ROS 스택을 구성해보면
- mobilerobot_ros (repo)
- mobilerobot (metapackage)
- mobilerobot_bringup
- mobilerobot_description
- mobilerobot__naviagation
- mobilerobot__slam
- mobilerobot__teleop
- mobilerobot_simulation (repo)
- mobilerobot_simlation (metapackage)
- mobilerobot_gazebo
- mobilerobot_msgs (repo)
와 같이 구성할 수 있겠다.
1. ROS 아키텍트 구성에 관심이 있는 분은
How do you architect your robots?: state of the practice and guidelines for ROS-based systems
https://dl.acm.org/doi/10.1145/3377813.3381358
를 읽어보는 것을 추천하다.
2. Hello Robot의 도큐멘테이션이 작성이 잘 되어있다.
도큐테이션 사이트와 github 글을 읽어보는 것도 추천한다.
https://github.com/hello-robot
참고한 것
구조화하기
https://roboticsbackend.com/package-organization-for-a-ros-stack-best-practices/
https://dl.acm.org/doi/10.1145/3377813.3381358
https://github.com/ROBOTIS-GIT/turtlebot3
https://github.com/ROBOTIS-GIT/turtlebot3_simulations
https://github.com/hello-robot/stretch_ros
https://github.com/jackal/jackal
https://github.com/fetchrobotics/fetch_ros
'interactics > ROS' 카테고리의 다른 글
RTOS 개괄 (2) | 2020.09.14 |
---|