ROS2 humble 기준으로 코드를 작성하였습니다.

ROS2에서 실행가능한 최소 단위를 node라고 한다.(쉽게 말해 파이썬, c++파일 하나.) 위 그림과 같이 이 node들을 실행시킨 뒤 node들이 통신하는 형태로 소프트웨어가 구현된다. 사진 속에 나오는 다양한 형태의 통신 방식은 조금 뒤 소개한다.

작업공간인 workspace 속에 하나 이상의 node를 묶은 여러 package가 있다. package는 주로 하나의 기능을 담고 있다. 예를 들어 위 그림과 같이 motion planning package에는 path correction과 motion planning을 하는 node와, camera package에서는 img 수신을 위한 driver와 img processing node가 존재한다.
ros2 run을 통해 node 하나 혹은 ros2 launch를 통해 여러 기능적 단위를 함께 실행시킨다.
통신 방식은 아래 4가지가 있는데, 모두 로봇의 기능을 구현하는 데 용이하다.
하나씩 살펴보고 예제코드를 통해 이해해보자. 여기에 사용한 예제는 공식 문서에서도 확인해볼 수 있다.
https://docs.ros.org/en/crystal/Tutorials/Topics/Understanding-ROS2-Topics.html
비동기 단방향 소통 방식으로, publisher와 subscriber가 있다. 한 node에서 정해진 data type의 message를 만들어 node가 죽을 때까지 계속해서 publish하고, subscriber는 이를 구독한 뒤 message를 받아 가공하는 형식으로 이루어진다. 예를 들어 자율주행차에서 LiDAR의 정보를 publish하는 node와 이 정보를 받아 장애물을 인식하는 node를 생각해볼 수 있다.
1:1, N:1, N:N 소통 모두 가능하다. 다만 publisher가 여러 개이면 의도와 다르게 프로그램이 흘러갈 수 있으니 주의하자. 매순간 topic을 발행하므로 실시간 정보를 받아 사용할 때 이용된다. 가장 널리, 자주쓰이는 메세지 형식이고 필자가 보았을 땐 전체의 90%정도 차지하는 것 같다. 따라서 가벼운 개발이라면 topic만 이해하고 나머진 천천히 봐도 무방하다.
ROS 설치 확인에서 사용한 talker와 listener도 사실 topic으로 소통한다. 여기서는 가장 널리 쓰이는 예제인 turtlesim을 통해 topic의 사용에 대해 확인해 볼 것이다.
sudo apt update
sudo apt install ros-dashing-turtlesim #install
우선 turtlesim을 사용해본 적 없다면 위 코드를 이용하여 turtlesim을 설치한다.
sudo apt update
sudo apt install ros-dashing-rqt*
node visualization Tool인 rqt도 설치해본다.
이제 두 개의 node를 실행시키고, 이 node들이 topic을 publish하고 subscribe하는 과정을 살펴볼 것이다. node 실행은 다음과 같은 형태로 할 수 있다.
ros2 run <pkg_name> <executable_name>
여기서 executable은 node name을 의미하는데, 이는 사용자가 자유롭게 설정할 수 있으나 보통 파일 이름과 같게 만든다. 설정하는 방법은 package build 방법과 함께 설명하겠다.
첫 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtlesim_node
두 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtle_teleop_key

세 번째 터미널에 rqt_graph를 입력하면 위 그림과 node와 topic을 시각화해서 확인할 수 있다. 다른 것은 아직 확인하지 않아도 되고, /teleop_turtle node(두 번째로 실행한 노드)에서 /turtle1/cmd_vel이라는 topic을 publish하고 /turtlesim(첫 번째로 실행한 노드)에서 이를 subscribe 하는 것만 확인하면 된다.
명령어를 통해서도 확인해볼 수 있다.
ros2 topic list #현재 존재하는 모든 토픽 리스트
ros2 topic info <topic_name> #특정 토픽의 정보
ros2 interface show <msg_name> #토픽의 자료형이 구체적으로 무엇인지 확인
명령어를 입력하면 아래 터미널과 같은 화면을 확인할 수 있다.

geometry_msgs/msg/Twist는 ROS2에서 기본적으로 제공하는 자료형이다. 잘 보면 linear velocity와 angular velocity값을 담아 전달하는 걸 확인해볼 수 있다. 실제로 turtlesim을 켜놓고 방향키를 누르면 이동하는 것을 확인할 수 있다. 즉, 이 topic을 통해 robot의 이동속도를 입력해주는 것이다. 이렇듯 ROS는 robot의 통신에서 입력해주어야 하는 값들의 자료형을 직접 정의하여 통신 표준을 제공하고 있다.
동기 양방향 소통 방식으로, client와 server가 있다. client가 필요할 때(필요할 때만 작동한다.) request를 보내면 server가 특정 행동을 한 뒤 response를 보내는 형식이다. 예를 들어 얼굴 인식 시스템의 경우 사람이 앞에 왔을 때만 사람의 사진을 보낸 뒤 그 사람이 누구인지에 대한 응답을 받을 수 있다.
service에서 전달되는 메세지 형식 service를 줄여 srv라고 한다(topic은 그냥 message). 계속해서 발행되는 topic과 달리 필요할 때 요청을 보내고 응답하는 방식으로 이루어져 computer source의 낭비를 막는다. 1:1, 1:N(server가 여러명)만 가능하다.
마찬가지로 turtlesim에서 사용되는 service를 확인해보자.
첫 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtlesim_node
두 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtle_teleop_key
세 번째 터미널에서 명령어를 통해 service를 확인해보자.
ros2 service list
ros2 service type <srv_name>
ros2 interface show <srv_type>
명령어를 입력하면 아래와 같은 터미널을 확인할 수 있다.

자료형이 비어있는 걸 확인할 수 있는데 왜냐하면 clear는 turtlesim의 화면을 깨끗하게 만드는 작업을 수행할 뿐이기 때문이다. 이 외에도 kill, reset 등이 이름에서 알 수 있는 역할을 수행한다.
turtlesim을 화면에서 자유롭게 움직이다가 세 번째 터미널에 아래 코드를 입력하면 화면이 깨끗해지는 것을 확인할 수 있을 것이다. 원래는 type 뒤에 argument를 입력하는데 자료형이 비어있으므로 그냥 전달해도 무방하다.
ros2 service call /clear std_srvs/srv/Empty
request를 보냈으므로 response까지 받아볼 수 있다.
service와 약간 비슷한데, feedback이 있다는 것과 중간에 멈출 수 있다는 점이 다르다. 마찬가지로 client와 server가 있고, client는 goal을 보낸다. server는 중간중간 feedback을 보낸 뒤(topic처럼) 완료되면 result를 보낸다. client는 feedback을 받으며 중간에 멈추고 싶을 때 action을 멈출 수 있다. 예를 들어 navigation에서 목표 지점까지 가며 feedback을 보내고, 그 중간에 멈출 수 있게 만들고 싶은 경우 action을 사용한다.
마찬가지로 turtlesim에서 사용되는 action를 확인해보자.
첫 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtlesim_node
두 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtle_teleop_key
두 번째 터미널에서 아래와 같은 메세지를 확인할 수 있을 것이다.
Use G|B|V|C|D|E|R|T keys to rotate to absolute orientations. 'F' to cancel a rotation.
이에 따라 key를 입력하면 turtle이 회전하는 것을 확인할 수 있다. 또, 한 key를 누른 뒤 이 action이 모두 실행되기 전에 F를 누르면 취소되는 것을 확인할 수 있다.

이를 수행하면 첫번째 터미널에는 위 그림과 같은 INFO들을 확인할 수 있다.
Parameter란 이름에서 예측할 수 있듯 node에서 사용되는 변수를 의미한다. 외부에서 이 node(server)의 parameter를 get, set을 통해 얻고, 수정할 수 있다. 로봇이 작동하는 환경의 지도나 목표 위치 등을 파라미터로 설정하며, 필요할 때 수정하는 방식으로 사용할 수 있다.
마찬가지로 turtlesim에서 사용되는 parameter를 확인해보자.
첫 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtlesim_node
두 번째 터미널에 아래 코드를 입력한다.
ros2 run turtlesim turtle_teleop_key
세 번째 터미널에서 명령어를 통해 parameter를 확인해보자.
ros2 param list
ros2 param get <node_name> <parameter_name>
ros2 param set <node_name> <parameter_name> <value>
명령어를 입력하면 아래와 같은 터미널을 확인할 수 있다.

똑같이 입력하면 turtlesim의 화면이 초록색으로 변하는 것을 확인할 수 있다.
ROS2의 통신 방식인 토픽, 서비스, 액션, 파라미터에 대해 살펴봤다. 토픽은 매 순간 발행되고 구독자가 이를 받아 사용하는 형태이다. 서비스는 필요할 때만 발행되고 응답을 받는다. 액션은 필요할 때만 발행되고 응답을 받는데, 중간중간 피드백을 받고 원할 때 멈출 수 있다. 파라미터는 노드에 필요한 변수로 외부에서 수정이 가능하다.
로봇에서 사용자, 또는 환경과 실시간으로 interaction할 때는 대부분 토픽을 이용한다. 서비스, 액션, 파라미터는 살펴보았듯 필요할 때 관련 설정을 수정하거나, 항상 쓰이지 않는 기능을 구현하기 위해 이용된다.
그렇다면 이들을 어떻게 코드로 구현할 수 있을까? 그 방법은 추후 package build와 함께 소개하도록 하겠다.
첫번째 사진: https://docs.ros.org/en/crystal/Tutorials/Understanding-ROS2-Nodes.html
두번째 사진: https://roboticsbackend.com/what-is-a-ros-node/