참고도서 1. ROS 2로 시작하는 로봇 프로그래밍. 표윤석 . 루비페이퍼 . 2021
참고도서 2. ROS2 혼자공부하는 로봇SW 직접 만들고 코딩하자 . 민형기 . 잇플 . 2022
참고자료 1. PinkWink(민형기)님의 ROS2 강의자료
참고자료 2. ROS2 humble documeation
ROS2를 복습하는 김에 제대로 다시 한 번 정리하고 넘어가고 싶어서 이 시리즈를 작성합니다.
이 글은 Turtlebot3 패키지를 제대로 이해하고, 다양한 센서를 부착하면서 활용하는 것을 목표로 합니다.
또한 글이 끝날 때 ROS와 관련된 문제를 하나 만들어서 직접 풀어보도록 합니다.
이번 장에서는 코드 레벨에서 확인하는 것이 아니라, ROS2에서 교육용으로 제공하는 패키지인 Turtlesim을 가지고 노는 것을 목표로 합니다.
ROS2의 Turtlesim
ROS2에서 튜토리얼로써 가장 많이 사용하는 패키지입니다. 이번 글에서는 이를 활용하여 ROS를 이해해볼 것입니다. 우선 ./bashrc에 다음이 추가되어 있어야 합니다.
alias humble="source /opt/ros/humble/setup.bash; ros_domain; echo \"ROS2 Humble is activated.\""
alias sb="source ~/.bashrc; echo \"bashrc is reloaded.\""
alias ros_domain="export ROS_DOMAIN_ID=33"
Turtlesim은 기본적으로 ROS2 개발환경 구축의 설치 방법대로 설치했다면, 이미 설치가 되어 있습니다. 그러나 설치는 다음과 같습니다.
sudo apt update
sudo apt install ros-humble-turtlesim
(혹시나 다른 버전을 사용하고 있다면 humble버전만 자신의 버전에 맞게 수정합니다.)
설치가 완료된 모습입니다.
ROS2에서의 통신
ROS2는 노드간의 통신이라고 볼 수 있으며, 노드간의 통신에 사용되는 것이 Topic, Service, Action, parameter입니다. turtlesim을 활용하면 이에 대해 쉽게 이해를 할 수 있습니다.
노드
실행가능한 최소한의 단위라고 합니다. 노드가 하나 이상 혹은 노드 실행을 위한 정보 등을 묶어 놓은 것을 패키지라고 합니다.
Documentation에서는 다음과 같이 설명합니다. ROS2 세상에서 각각의 노드들은 하나의 모듈의 목적을 수행할 수 있어야합니다. 예를 들어서 바퀴의 모터를 컨트롤할 때 하나의 노드가, 라이다 센서를 컨트롤해야할 때 하나의 노드가 사용됩니다.
Turtlesim 의 노드를 실행해보자.
우선 ROS환경을 불러와야합니다. 여기서 환경을 불러온다는 이야기는 시동을 건다는 이야기로 이해를 해도 좋습니다. 만약 환경을 불러오지 않는다면 ROS2에 관한 명령어를 입력할 수 없습니다.
source /opt/ros/humble/setup.bash
다음의 명령어를 터미널에 입력해서 환경을 불러올 수 있지만, 위에서 언급한대로 ./bashrc에 등록을 하는 경우에는 humble만 입력을 해주어도 됩니다.
alias humble="source /opt/ros/humble/setup.bash; ros_domain; echo \"ROS2 Humble is activated.\""
alias sb="source ~/.bashrc; echo \"bashrc is reloaded.\""
alias ros_domain="export ROS_DOMAIN_ID=33"
그러나 환경을 불러오지 않는다면 다음처럼 ros2명령어가 뭔지 모르는 상태가 됩니다.
그러면 이제 Turtlesim_node를 실행해봅시다.
ros2 run turtlesim turtlesim_node
다음처럼 TurtleSim창이 하나 뜨게 됩니다. 그러면 우리는 여기서 다양한 방법으로 Turtlesim에서 보내고 있는 통신정보들을 확인할 수 있습니다. node, topic, service, action 다음의 동작은 위의 스크린샷처럼 ros2 run turtlesim turtlesim_node의 터미널이 실행되고 있는 상태에서 새로운 터미널을 하나 열어서 진행해야합니다.
ros2 node list
현재 node는 turtlesim하나만 실행했기 때문에 turtlesim 노드 하나만 나오게 됩니다.
다음은 topic을 한 번 조회하도록 합니다. 아직까지 topic은 그냥 통신을 위한 한 방법이라고 생각하면됩니다. 그리고 지금부터 설명하는 것은 그냥 통신들의 한 방법들이라 생각합니다.
ros2 topic list
다음은 service를 한 번 조회하도록 합니다.
ros2 service list
다음은 Action을 한 번 조회하도록 합니다.
ros2 action list
그러면 이러한 통신 정보들은 어떤 노드에서 보내고 있는 걸까?
ROS 에서의 메시지 통신방법
ROS_Domain
그래서 turtlesim 노드를 실행하니 뭔가 통신을 하려고 많은 것들을 ROS 세상으로 보내고 있습니다. 그래서 그 통신을 하려는 방법들이 도대체 뭔가요?
우선 ROS 세상이라는 것을 한 번 이해해볼 필요가 있습니다. 저는 개인적으로 ROS세상이라는 용어를 사용하는데, ROS 세상은 ROS Domain 이라는 용어를 제가 이해하기 쉽게 부르는 용어같은 느낌입니다.
간단하게 말해서 여러분들의 공유기 혹은 컴퓨터 내부에 ROS를 위한 통신공간이 만들어집니다. 그리고 wifi를 같게하고, ROS Domain을 같게 설정한다면 누구든지 ROS상으로 통신이 가능합니다.
alias ros_domain="export ROS_DOMAIN_ID=33"
저는 33번을 사용하기로 했지만, 0~99까지의 주소중에서 하나를 선택하면 됩니다. 이 경우 같은 네트워크 상의 모든 기기에서 ROS2를 설치하고, ros_domain_ID를 맞추면 통신이 가능해집니다.
만약 Local (내 컴퓨터 내에서만 통신을 하고 싶다면) 다음과 같이 입력하면 됩니다. 보통 시뮬레이션 용도로 사용하는 경우에 해당합니다.
export ROS_LOCALHOST_ONLY=1
공유기를 사용하는 경우에 ROS의 통신 명령어들이 허공에 떠다닌다고 생각해보고, Local의 경우 컴퓨터 메모리에 ROS관련 통신 명령어들이 돌아다닌다고 생각해봅시다. 그러면 이 명령어를 누군가가 그냥 가져다 쓰면 됩니다. 이게 바로 ROS 세상(ROS_Domain)입니다.
여기서 ROS만의 장점이 나오게 됩니다. 예를 들어서 CCTV에서 영상을 ROS세상으로 보내는 노드가 있다고 생각을 해봅시다. 이 노드의 정보를 들여다 보는 여러 대의 컴퓨터 혹은 노드는 이 정보에서 사람을 탐지할지, 사람의 움직임을 읽어낼지 서로다른 일들을 할 수 있습니다.
노드는 무엇으로 통신하는가?
노드는 메시지를 통해 통신을 합니다. turtlesim에서 어떤 메시지를 주고받는지 한 번 알아봅시다. /turtle1/cmd_vel 해당 Topic의 메시지가 어떤식으로 생겼는지 확인을 해봅시다. (turtle1/cmd_vel 은 comend velocity의 줄임말로 거북이를 움직이는 토픽입니다.)
ros2 topic info /turtle1/cmd_vel
그러면 이 메시지의 타입은 geometry_msgs/msg/Twist 형태임을 알 수 있습니다. 어떤 메시지를 담고 있는지 확인을 해봅시다. 다음의 명령어는 현재 cmd_vel에 대한 topic을 들여다 보겠다는 뜻입니다.
ros2 topic echo /turtle1/cmd_vel
현재 거북이가 움직이고 있지 않으니, 당연히 topic 이 보이지도 않겠군요.. 그러면 거북이를 한 번 움직여봅시다.
ros2 run turtlesim turtle_teleop_key
해당 명령어를 새로운 터미널에서 입력합니다. 그러면 다음과 같은 상태가 되어야겠지요.
방향키로 거북이를 움직일 때마다, topic이 들어오는 것을 볼 수 있습니다. 직진을 하는 경우 2가 들어오고, 방향을 꺾으면 angular가 움직이게 됩니다. 그러면 이 메시지는 어떻게 생긴걸까요? 두 가지 방법이 있습니다. 파일을 직접 찾아서 뜯어보거나, 아니면 ros2에서 지원하는 명령어를 활용하거나
다음은 파일을 직접 뜯어본 경우입니다.
이렇게 생겼습니다. 그냥 별거 없죠
다음은 명령어를 통해서 확인을 해봅시다. 다음의 명령어를 입력하면 됩니다.
ros2 interface show geometry_msgs/msg/Twist
개인적으로는 위의 명령어는 외웠으면 합니다. 파일을 직접 뜯어보면 메시지도 이파일 저파일 서로 연관되어 있게 만들어져있기 때문에 위 명령어 하나를 몰라서 난관에 빠지는 경우가 많습니다.
그래서 요약하자면 ROS에서 노드간의 통신은 다음처럼 메시지를 통해 통신하게 됩니다.
Topic
Topic은 노드와 노드가 통신을 하는 방법 중 하나입니다. 넷플릭스를 생각해보면 넷플릭스는 서버로 다양한 드라마나 영화정보를 올리고, 소비자는 일정 비용을 지불하고 이를 구독하고, 영화나 드라마를 시청합니다.(ROS에서 Topic을 구독하는데 돈을 내지는 않습니다..) 이와 같은 원리입니다.
어떤 유저가 CCTV의 영상을 찍어서 ROS2 세상으로 영상을 메시지 형태로 topic으로 정보를 뿌린다고 생각합시다. 이 뿌린다는 내용도 topic에서는 publishing한다. 즉 발행한다라고 합니다. 그러면 이 영상을 구독해서 내가 원하는 대로 사용하면 됩니다. 이게 Topic의 모든 개념입니다.
ROS2 documentation에서는 다음과 같이 설명합니다. ROS2는 복잡한 시스템을 여러 모듈단위로 세분화하고 토픽은 노드가 메시지를 교환하는 데이터의 버스 역할을 합니다. topic을 발행하는 노드는 (publisher) 모터를 테스트하고 그 데이터를 발행했습니다. 다른 노드들은 이 모터에 대한 정보가 필요할때 publisher 노드의 모터 데이터를 구독하면 됩니다. (Subscriber)
그림처럼 해당 데이터를 한 명만 구독하는게 아니라 여러명이 구독할 수 있습니다. 비디오방에서 해리포터를 빌리면, 다른 사람은 해리포터를 볼 수 없지만, 넷플릭스에서는 그렇지 않은 것처럼 topic은 여러 노드가 구독을 하고 사용할 수 있습니다.
표윤석님의 책에 의하면 topic은 전체 ROS프로그래밍의 70%이상의 메시지 통신을 담당합니다. 그러면 아까 보았던 node info를 다시 살펴봅시다.
여기서 subscribers와 publishers가 해당 노드가 어떤 Topic을 구독했고, 어떤 topic을 발행하는지를 보여줍니다.
현재 ros세상에 떠다니는 토픽에 대한 정보는 앞서 설명한대로
ros2 topic list
다음의 명령어를 통해서 조회할 수 있습니다. 도메인만 일치한다면, 다양한 노드들이 topic을 발행하고 있다면 한 번에 조회가 되게 됩니다.
ros2 topic list -t
그리고 다음의 명령어를 추가하면 메시지 형태도 조회가 가능합니다.
ros2 topic list -t
일단 참고삼아서 rqt_graph라는 노드간의 통신상태를 확인할 수 있는 툴을 한 번 확인해봅시다.
아직 아무것도 하지 않았기 때문에 뜨지 않습니다.
ros2 run turtlesim turtle_teleop_key
놀고있는터미널에서 다음을 입력하고 rqt_graph를 확인해봅니다.
다음처럼 보이게 됩니다. 다음처럼 바꿔주면 이렇게도 볼 수 있습니다.
turtlesim은 cmd_vel topic 을 구독하고 있다는걸 알 수 있다. 이걸 보면 turtle1/cmd_vel을 구독하고 발행하는 노드는 각각 1개씩 있다.
ros2 topic info /turtle1/cmd_vel
맞다.
그리고 다음으로는 위에 있는 체크박스를 다 풀면 이런식으로 그림이 보여지는데, 여기서는 그냥 아 노드끼리 정보를 주고받는 것을 시각화해서 볼 수 있구나 정도만 이해하고 넘어갑니다.
Topic 을 직접 발행해보자.
위에서 살펴본 해당 명령어는 거북이를 움직이는 명령어였습니다. 이는 뒤에서 배우게되겠지만, 이 통신과정을 Action이라고 합니다. 이 Action을 뜯어보면 결국 cmd_vel topic을 발행하는 것이며, turtlesim이 이를 구독하여 움직이게 되는 것입니다.
새로운 터미널에서 다음을 입력하면 거북이가 회전을 하게됩니다.
ros2 topic pub --once /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
간단하게 코드를 설명하면 topic을 publishing합니다. 한 번만 토픽의 이름은 turtle1/cmd_vel로 메시지 타입은 geometry_msgs/msg/Twist입니다. 메시지의 내용은 다음과 같습니다.
계속 움직이게 하고 싶다면 다음과 같이 입력하며
ros2 topic pub --rate 1 /turtle1/cmd_vel geometry_msgs/msg/Twist "{linear: {x: 2.0, y: 0.0, z: 0.0}, angular: {x: 0.0, y: 0.0, z: 1.8}}"
rate 1은 1Hz주기로 토픽을 발행하라는 의미입니다.
다음처럼 움직이게 됩니다. 이 상태에서도 그냥 확인해봅시다. Topic을 어떤 식으로 쏘고 있는지 rqt_graph를 켜줍시다.
오른쪽은 잠시 신경쓰지 말고, cmd_vel을 쏘고 있는 것만 확인해봅니다. 그러면 한가지 실험을 해볼 수 있습니다. Turtlesim을 꺼버리면 어떻게 되는가?
그래도 cmd_vel topic은 지속적으로 발행되고 있습니다. 그러면 다시 turtlesim을 시작하면
시작하자마자, 거북이가 움직이는 모습을 볼 수 있죠. 즉 topic을 발행하는 쪽은 계속 발행을 하고, 이게 필요한 친구는 이 정보를 구독하면 되는 시스템입니다. 더 들어가볼까요? turtlesim을 여러개 켜면 어떻게 될까요?
다음처럼 cmd_vel topic을 구독하는 친구들은 Ros 세상에 돌아다니는 cmd_vel topic을 구독하고 움직이게 됩니다. 뭐 깊게 들어가면 그러면 각각의 거북이를 어떻게 컨트롤 해야할까? 이는 곳 로봇으로 생각하면 각각의 로봇을 서로 다른 토픽으로 컨트롤하는 방법이 뭘까?와 같은 고민으로 이어질 수도 있습니다. 이는 어려운 내용이될 수도 있으니 나중에 생각을 해보도록 합시다.
Service
ROS의 또다른 메시지 통신 방법으로는 Service 가 있습니다. ros documentation에서는 service를 다음과 같이 설명합니다.
서비스는 call-and-response model을 베이스로 하고 있으며, 데이터 스트림에 돌아다니는 토픽과 다르게 서비스는 오직 클라이언트에 의해 호출될 때만 데이터를 제공합니다.
표윤석님의 책에는 이렇게 언급되어 있습니다. 서비스에서 서비스를 요청하는 쪽은 Service Client, 요청 받은 서비스를 수행하고 서비스 응답하는 쪽을 Service Server라고 합니다. 서비스의 요청 및 응답은 msg 인터페이스를 변형한 srv인터페이스를 사용합니다.
서비스 응답은 서비스 요청이 있었던 서비스 클라이언트에 대해서만 응답하는 형태이다.
요청하면 정보를 제공해준다는 느낌이 아닙니다. 서비스를 요청하면 서비스에 대한 명령을 수행하고 이에 대한 결괏값을 다시 응답해주는 것으로 일해 -> 일함 -> 했어 와 같은 느낌입니다.
이를 이제 Turtlesim에서 한 번 확인해보도록 합시다.
parameter에 대한 서비스는 파라미터에 관련된 내용이므로 잠시 잊어도 됩니다. 서비스의 타입은 앞서 설명한 것처럼 -t를 붙이면 됩니다.
서비스에서는 거북이를 추가로 생성하는 것이나, 거북이의 이동괘적을 지울 수 있습니다. 다음의 명령어로 어떻게 서비스 메시지타입이 구성되어있는지 확인해볼 수 있다.
ros2 interface show turtlesim/srv/Spawn
ros2 interface show std_srvs/srv/Empty.srv
---을 경계로 위에는 request 아래는 response이다. Spawn의 경우에는 거북이를 소환하고, 소환을 완료하면 그의 이름으로 반응을 하는 것이다. 그러면 한 번 거북이를 소환해보자.
ros2 service call /spawn turtlesim/srv/Spawn "{x: 2, y: 2, theta: 0.2, name: ''}"
나 turtle2라는 이름으로 스폰해줬어 라고 나오는 모습
친구가 생겼다. 이 외에 다양한 서비스를 해볼 수 있으나, 딱히 중요한 내용은 아니니까 우선은 넘어가도록 하자.
turtlesim에서는 소환을 하면 자동을 Turtle2라는 이름의 topic 으로 바꿔주기 때문에 각각의 거북이들을 움직일 수 있다.
Action
Action은 ROS의 메시지통신의 방법 중 하나입니다. documentation에서는 다음과 같이 설명합니다.
장기적인 작업에 사용되며 goal, feedback, result 이렇게 총 3가지로 구성됩니다. Action은 topic과 service로 구성되며 액션은 서비스가 진행되는 동안 꾸준히 피드백을 제공합니다.
표윤석님의 책은 이렇게 설명합니다. 노드간 비동기식, 동기식 양방향 메시지 송수신 방식으로 액션 목표(Goal)를 지정하는 Action Client와 액션 목표를 받아 특정 태스크를 수행하면서 중간 결과값을 전송하는 액션 피드백 (Feedback) 그리고 최종 결과값을 담은 액션 결과(Result)를 전송하는 Action server간의 통신이다.
더 간단하게 이야기를 하자면, 자동차가 목적지까지 이동하는 상황에서 자동차를 지속적으로 움직이고, 피드백으로 남은 거리를 주는 느낌과 비슷하다고 생각하면 됩니다. 그래서 목적지까지 이동해라와 나 다 이동했어는 service를 사용하고, 피드백을 주는 과정은 Topic을 사용합니다. ROS1에서는 토픽만으로 처리를 했다고 하는데, ROS2부터 위와 같은 방식으로 변했다고 합니다.
turtlesim으로 볼 수 있는 액션은 다음의 명령어입니다.
ros2 run turtlesim turtle_teleop_key
여기서 G, B, V, C, D, E, R, T를 사용하는 것입니다. G를 누를경우에 다음과 같은 내용이 위에서 뜨게 됩니다.
[turtlesim]: Rotation goal completed successfully
G방향(오른쪽)으로 회전을 했다는 것을 나타냅니다.
그러나 돌고 있는 와중에 밑의 터미널에서 취소를 하게 되면
INFO] [1683372593.773450631] [turtlesim]: Rotation goal canceled
다음과 같은 내용이 뜨면서 거북이가 멈추게 됩니다.
ros2 node info /turtlesim
다음을 입력해봅니다.
여기서 Action Servers 를 주목해보면 됩니다.
ros2 node info /teleop_turtle
여기서 Action Clients를 주목하면 됩니다. 서비스에서 Server로 요청을 하고, 이를 client에서 다시 받아오는 일을 하는 것이 액션입니다.
근데, 이게 아니여도 다음으로 조회가 가능합니다.
ros2 action list
ros2 action info /turtle1/rotate_absolute
이런식으로 action의 clients와 servers가 누구인지 알려줍니다.
다음의 명령어로 action goal을 직접 보낼 수도 있습니다.
ros2 action send_goal /turtle1/rotate_absolute turtlesim/action/RotateAbsolute "{theta: 1.57}"
거북이가 위를 쳐다보게 하는 명령어였습니다.
참고로 Turtlesim에 등장하는 거북이들은 각 버전의 마스코트들입니다.
'공부#Robotics#자율주행 > (ROS2) 기초' 카테고리의 다른 글
(ROS2 기초)6. 코드 스타일, ROS2에서 파이썬으로 기초 코딩하기 (2) | 2023.05.09 |
---|---|
(ROS2 기초)5. ROS에서 코딩하기 전 알아야할 내용 (0) | 2023.05.08 |
(ROS2 기초)4. ROS에서 사용하는 도구 (1) | 2023.05.08 |
(ROS2 기초)3. ROS의 Turtlesim으로 ROS의 인터페이스와 파라미터 이해하기 (0) | 2023.05.06 |
(ROS2 기초)1. ROS의 정의와 ROS2 세팅하기 (0) | 2023.05.06 |