학습 목표
- ROS가 운영체제가 아니라 로봇 응용을 위한 미들웨어·도구·생태계라는 점을 설명할 수 있다.
- Node, Topic, Service, Action, Parameter를 상황에 맞게 선택할 수 있다.
- ROS Graph, DDS, QoS가 데이터 전달에 어떤 역할을 하는지 큰 흐름을 이해할 수 있다.
- Package와 Workspace의 관계, Build와 실행 순서를 설명할 수 있다.
- TF2, URDF, RViz, rosbag이 로봇 개발에서 맡는 역할을 구분할 수 있다.
- 간단한 Publisher와 Subscriber를 실행하고 CLI로 통신 상태를 점검할 수 있다.
1. 한 문장으로 이해하는 ROS
ROS(Robot Operating System)는 Sensor, 판단 Algorithm, Motor Controller처럼 서로 다른 로봇 Software Component가 표준화된 방식으로 통신하고, 재사용되고, 관찰될 수 있게 하는 Open Source Software Framework입니다.
이름에 Operating System이 들어가지만 Windows나 Linux처럼 CPU, Memory, File System을 직접 관리하는 일반 목적 운영체제는 아닙니다. 보통 Ubuntu 같은 OS 위에서 실행되며 다음을 함께 제공합니다.
- Process 사이의 통신 규칙과 Client Library
- Code를 Package로 구성하고 Build하는 체계
- 실행 중인 System을 관찰하고 기록하는 도구
- Navigation, Manipulation, Perception 등에 재사용할 Package 생태계
쉽게 비유하면 Linux가 건물의 전기·수도·출입 설비라면, ROS는 여러 전문 작업자가 같은 도면과 무전 규칙을 사용하도록 만드는 로봇용 협업 기반입니다.
이 글에서 ROS는 현재 개발의 중심인 ROS 2를 뜻합니다. ROS 1이 필요한 부분에서는 이름을 따로 표시합니다.
2. ROS가 필요한 이유
이동 로봇 한 대에도 Camera Driver, LiDAR Driver, Wheel Odometry, Localization, Path Planner, 장애물 회피, Motor Control, UI가 필요합니다. 이를 하나의 거대한 Program으로 만들면 처음에는 간단해 보이지만 곧 문제가 생깁니다.
- Camera 처리 속도가 느려지면 Motor Control까지 영향을 받을 수 있습니다.
- Sensor나 Algorithm 하나를 교체할 때 전체 Program을 수정해야 합니다.
- C++ Driver와 Python AI Model을 자연스럽게 연결하기 어렵습니다.
- Robot Computer와 외부 Server에 기능을 나누기 어렵습니다.
- 중간 Data를 관찰하거나 특정 구간만 재현하기 어렵습니다.
ROS는 기능을 작은 실행 단위인 Node로 나누고, 정해진 Type의 Message로 연결합니다. 예를 들어 LiDAR Node가 /scan을 발행하면 SLAM Node와 장애물 회피 Node가 동시에 구독할 수 있습니다. 발행자는 구독자의 내부 구현을 알 필요가 없습니다.
[LiDAR Driver] ── /scan ──┬──> [SLAM]
└──> [Obstacle Avoidance]
[Navigation] ── /cmd_vel ──> [Base Controller] ──> Motor
이 구조의 핵심 가치는 분리, 교체, 재사용, 관찰입니다. 반면 직렬화, Network Delay, 설정 복잡도라는 비용도 생깁니다. 따라서 모든 함수를 무조건 Node로 쪼개는 것이 아니라, 독립 실행·교체·장애 격리가 필요한 경계를 Node로 정해야 합니다.
3. ROS가 해 주는 일과 해 주지 않는 일
| ROS가 제공하는 것 | 개발자가 결정하거나 구현할 것 |
|---|---|
| Node 검색과 Message 전달 | Robot이 달성할 임무와 동작 Logic |
| Message, Service, Action의 Type 체계 | 어떤 Data를 어느 주기로 보낼지 |
| Build, Package, Launch 도구 | Algorithm의 정확도와 안전성 |
| Logging, Visualization, Data 기록 | Sensor 보정과 Hardware 보호 회로 |
| 공개 Package를 연결하는 공통 Interface | 인증, 권한, Network 운영 정책 |
ROS를 설치했다고 Robot이 스스로 움직이지는 않습니다. ROS는 AI Model도, 완성된 자율주행 Algorithm도, Real-time OS도 아닙니다. 다만 Nav2, MoveIt 2, SLAM Toolbox 같은 공개 Software를 같은 Interface 위에서 조합할 수 있게 합니다.
특히 안전을 ROS 통신만으로 보장해서는 안 됩니다. Emergency Stop, Motor Enable, 과전류 차단처럼 사람과 장비를 보호하는 기능은 Hardware와 하위 제어기에도 독립적으로 있어야 합니다.
4. ROS 2 Software Stack
ROS 2는 하나의 Program이 아니라 여러 계층의 묶음입니다.
Application Navigation, Manipulation, Perception, 사용자 Node
Client Library rclcpp(C++), rclpy(Python)
Common Layer rcl, rosidl, launch, lifecycle
Middleware RMW 추상화
DDS Discovery, 전송, QoS
Platform Linux / Windows / macOS, Network, Hardware
Application Code는 보통 rclcpp 또는 rclpy API를 사용합니다. 그 아래 RMW(ROS Middleware) 계층이 DDS 구현의 차이를 감춥니다. 덕분에 같은 ROS API를 유지하면서 환경에 맞는 DDS 구현을 선택할 수 있습니다.
DDS는 분산된 Participant가 서로를 발견하고 Data를 전달하는 기반입니다. ROS 1의 중앙 Master와 달리 ROS 2의 기본 통신에는 반드시 실행해야 하는 중앙 roscore가 없습니다. 대신 Network의 Multicast, Firewall, Domain 설정이 Discovery에 영향을 줄 수 있습니다.
5. 가장 중요한 실행 단위: Node
Node는 하나의 명확한 책임을 가진 실행 단위입니다. 예를 들어 다음과 같이 나눌 수 있습니다.
camera_driver: Image를 읽어 발행object_detector: Image에서 Object를 검출localization: Sensor Data로 Robot Pose 추정planner: 목표까지의 Path 계산base_controller: 속도 명령을 Wheel 명령으로 변환
Node가 반드시 OS Process 하나와 일치하는 것은 아닙니다. 여러 Node를 한 Process에 넣는 Composition도 가능합니다. Process를 분리하면 장애 격리와 배포가 쉬워지고, 한 Process에 구성하면 복사와 통신 Overhead를 줄일 수 있습니다.
좋은 Node 경계는 다음 질문으로 판단합니다.
- 이 기능은 다른 주기로 동작하는가?
- 독립적으로 시작·종료·교체해야 하는가?
- 다른 Computer나 언어로 옮길 가능성이 있는가?
- 장애가 다른 기능으로 퍼지지 않아야 하는가?
6. ROS Graph
실행 중인 Node와 그 연결 전체를 ROS Graph라고 합니다. Graph에는 Topic뿐 아니라 Service, Action도 나타납니다. Graph는 고정 설계도가 아니라 Node가 켜지고 꺼질 때 변하는 실행 상태입니다.
ros2 node list
ros2 node info /talker
ros2 topic list -t
ros2 service list -t
ros2 action list -t
Node Name은 의미가 분명해야 하며 같은 Graph 안에서 충돌하지 않게 Namespace를 사용합니다. 예를 들어 여러 Robot을 운용할 때 /robot_01/camera와 /robot_02/camera로 분리할 수 있습니다.
7. 다섯 가지 핵심 Interface
7.1 Topic — 계속 흐르는 Data
Publisher가 Message를 발행하고 Subscriber가 구독하는 비동기 Streaming 방식입니다. Sensor Data, 상태, 속도 명령처럼 연속적으로 흐르는 값에 적합합니다.
Publisher ── Message ──> Topic ──> Subscriber 1
└──> Subscriber 2
발행자는 누가 듣는지 몰라도 됩니다. 응답을 기대하지 않으며 발행자와 구독자의 Message Type이 같아야 합니다.
대표 예: /scan, /camera/image_raw, /odom, /cmd_vel
7.2 Service — 짧은 요청과 한 번의 응답
Client가 Request를 보내고 Server가 Response를 돌려줍니다. 빠르게 끝나는 조회나 명령에 적합합니다.
대표 예: Sensor Reset, Map 저장 요청, 상태 조회
오래 걸리는 이동을 Service로 만들면 진행률을 알기 어렵고 취소도 곤란합니다. 그런 작업에는 Action을 사용합니다.
7.3 Action — 오래 걸리고 취소 가능한 작업
Action은 Goal, Feedback, Result의 흐름을 가집니다. Server는 Goal의 수락 여부를 정하고, 수행 중 Feedback을 보내며, 완료 후 Result를 반환합니다. Client는 도중에 Cancel을 요청할 수 있습니다.
대표 예: 목표 지점으로 이동, Robot Arm 궤적 실행, 자동 Docking
7.4 Parameter — Node의 설정값
Parameter는 Node가 소유하는 Runtime 설정입니다. 최대 속도, Frame 이름, Threshold처럼 비교적 천천히 바뀌는 값에 사용합니다. 대용량 Sensor Stream을 Parameter로 전달하면 안 됩니다.
7.5 Interface Type — Data 계약
Topic은 .msg, Service는 .srv, Action은 .action 정의로 Data 구조를 약속합니다. 같은 이름의 Topic이라도 Type이 다르면 연결되지 않습니다.
| 필요 | 선택 | 예 |
|---|---|---|
| 계속 흐르는 Data | Topic | Camera Image, Odometry |
| 짧은 요청과 응답 | Service | Reset, 설정 조회 |
| 긴 작업, Feedback, Cancel | Action | Navigation Goal |
| Node 설정 | Parameter | Update Rate, Max Speed |
8. Node, Topic, Service, Action 간단한 프로그램
다음 예제는 ROS 2 환경에서 Python Client Library인 rclpy를 사용합니다. 실행하기 전에 ROS 2 환경을 불러옵니다.
source /opt/ros/<distro>/setup.bash
<distro>는 설치한 ROS 2 배포판 이름으로 바꿉니다. 예제는 학습을 위해 한 파일로 단순화했습니다. 실제 Package에서는 package.xml, setup.py에 의존성과 실행 진입점을 선언하는 것이 표준입니다.
8.1 Node — 1초마다 Log 남기기
Node는 ROS Graph에 참여하는 기본 실행 단위입니다. 다음 hello_node.py는 1초마다 Timer Callback을 실행합니다.
import rclpy
from rclpy.node import Node
class HelloNode(Node):
def __init__(self):
super().__init__('hello_node')
self.count = 0
self.timer = self.create_timer(1.0, self.on_timer)
def on_timer(self):
self.get_logger().info(f'안녕하세요, ROS 2! count={self.count}')
self.count += 1
def main():
rclpy.init()
node = HelloNode()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
python3 hello_node.py
ros2 node list # 다른 Terminal에서 /hello_node 확인
rclpy.spin()은 Timer, Subscription 같은 Callback이 실행될 수 있도록 Node의 Event를 계속 처리합니다. Ctrl+C로 종료합니다.
8.2 Topic — Publisher와 Subscriber
다음 topic_demo.py는 Talker가 /chatter에 문자열을 발행하고 Listener가 같은 Topic을 구독합니다. 두 Node를 하나의 Executor에 넣었지만 서로는 Message Interface만 알고 있습니다.
import rclpy
from rclpy.executors import SingleThreadedExecutor
from rclpy.node import Node
from std_msgs.msg import String
class Talker(Node):
def __init__(self):
super().__init__('talker')
self.publisher = self.create_publisher(String, 'chatter', 10)
self.count = 0
self.timer = self.create_timer(1.0, self.publish_message)
def publish_message(self):
message = String()
message.data = f'메시지 {self.count}'
self.publisher.publish(message)
self.get_logger().info(f'발행: {message.data}')
self.count += 1
class Listener(Node):
def __init__(self):
super().__init__('listener')
self.subscription = self.create_subscription(
String, 'chatter', self.on_message, 10)
def on_message(self, message):
self.get_logger().info(f'수신: {message.data}')
def main():
rclpy.init()
talker = Talker()
listener = Listener()
executor = SingleThreadedExecutor()
executor.add_node(talker)
executor.add_node(listener)
try:
executor.spin()
except KeyboardInterrupt:
pass
finally:
executor.shutdown()
talker.destroy_node()
listener.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
python3 topic_demo.py
ros2 topic echo /chatter # 다른 Terminal에서 Message 관찰
10은 Queue Depth를 간단히 지정한 값입니다. 실제 Sensor 통신에서는 Data의 성격에 맞게 QoS를 명시적으로 설계해야 합니다.
8.3 Service — 두 정수를 더하는 Server
다음 add_service.py는 example_interfaces/srv/AddTwoInts Type으로 /add_two_ints Service를 제공합니다.
import rclpy
from example_interfaces.srv import AddTwoInts
from rclpy.node import Node
class AddService(Node):
def __init__(self):
super().__init__('add_service')
self.service = self.create_service(
AddTwoInts, 'add_two_ints', self.add)
def add(self, request, response):
response.sum = request.a + request.b
self.get_logger().info(
f'요청: {request.a} + {request.b} = {response.sum}')
return response
def main():
rclpy.init()
node = AddService()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Server를 실행한 뒤 다른 Terminal에서 CLI Client로 요청합니다.
python3 add_service.py
# 다른 Terminal
ros2 service call /add_two_ints example_interfaces/srv/AddTwoInts \
"{a: 7, b: 5}"
# response: example_interfaces.srv.AddTwoInts_Response(sum=12)
Service Callback은 짧게 끝나야 합니다. 내부에서 긴 계산이나 무기한 대기를 하면 다른 Callback 처리가 늦어질 수 있습니다.
8.4 Action — Fibonacci 수열 계산하기
다음 fibonacci_action.py는 Goal로 수열 길이를 받고, 계산할 때마다 Feedback을 보내며, 완료 후 전체 수열을 Result로 돌려줍니다. Cancel 요청도 확인합니다.
import time
import rclpy
from example_interfaces.action import Fibonacci
from rclpy.action import ActionServer, CancelResponse
from rclpy.node import Node
class FibonacciActionServer(Node):
def __init__(self):
super().__init__('fibonacci_action_server')
self.server = ActionServer(
self,
Fibonacci,
'fibonacci',
self.execute,
cancel_callback=self.accept_cancel)
def accept_cancel(self, _cancel_request):
self.get_logger().info('Cancel 요청을 수락합니다.')
return CancelResponse.ACCEPT
def execute(self, goal_handle):
order = goal_handle.request.order
feedback = Fibonacci.Feedback()
feedback.sequence = [0, 1]
for _ in range(2, order):
if goal_handle.is_cancel_requested:
goal_handle.canceled()
result = Fibonacci.Result()
result.sequence = feedback.sequence
return result
feedback.sequence.append(
feedback.sequence[-1] + feedback.sequence[-2])
goal_handle.publish_feedback(feedback)
time.sleep(0.5) # 동작을 보기 위한 학습용 지연
goal_handle.succeed()
result = Fibonacci.Result()
result.sequence = feedback.sequence[:order]
return result
def main():
rclpy.init()
node = FibonacciActionServer()
try:
rclpy.spin(node)
except KeyboardInterrupt:
pass
finally:
node.server.destroy()
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Server를 실행하고 다른 Terminal에서 Goal을 보냅니다.
python3 fibonacci_action.py
# 다른 Terminal: --feedback을 붙이면 중간 수열도 표시됩니다.
ros2 action send_goal --feedback \
/fibonacci example_interfaces/action/Fibonacci "{order: 8}"
이 예제의 time.sleep()은 Feedback을 보기 위한 학습용 코드입니다. 실제 Node에서 긴 Blocking 작업을 실행할 때는 Executor와 Callback Group을 설계하고, 다른 Callback과 안전 동작을 막지 않는지 확인해야 합니다.
9. QoS — Data 전달 방식을 정하는 계약
ROS 2의 QoS(Quality of Service)는 단순히 “통신 품질을 높이는 옵션”이 아니라 Publisher와 Subscriber가 어떤 전달 성질을 요구하는지 나타내는 정책입니다.
- Reliability: 가능한 재전송하는
reliable, 지연을 줄이고 유실을 허용하는best_effort - Durability: 늦게 참가한 Subscriber가 이전 Data를 받을 수 있는지 결정
- History / Depth: 최근 Message를 몇 개 보관할지 결정
- Deadline: 기대하는 Data 도착 주기
- Liveliness: Publisher가 살아 있음을 판단하는 방법
Camera나 LiDAR의 고주기 Data는 최신 값이 중요하므로 best_effort가 적합할 수 있습니다. 반드시 전달해야 하는 낮은 빈도의 상태는 reliable을 고려합니다. 양쪽 QoS가 호환되지 않으면 Topic 이름과 Type이 같아도 Data가 오지 않을 수 있습니다.
ros2 topic info /scan --verbose
ros2 topic hz /scan
ros2 topic bw /scan
10. Package, Workspace, Build
Package는 ROS Software를 배포하고 재사용하는 기본 단위입니다. Code, Interface, Launch File, 설정, 의존성 정보가 들어갑니다. package.xml은 Package의 이름과 의존성을 설명하고, C++ Package는 주로 CMake, Python Package는 주로 setuptools를 사용합니다.
Workspace는 여러 Package를 함께 개발하고 Build하는 작업 공간입니다.
my_ws/
├── src/ # Source Package
├── build/ # Build 중간 결과
├── install/ # 실행에 사용할 결과와 setup Script
└── log/ # Build Log
일반적인 흐름은 다음과 같습니다.
mkdir -p ~/my_ws/src
cd ~/my_ws
colcon build --symlink-install
source install/setup.bash
ros2 pkg list
새 Terminal에서는 source를 다시 해야 새 Package를 찾을 수 있습니다. 여러 Workspace를 겹쳐 쓸 때는 기반 ROS 환경을 먼저, 사용자 Workspace를 나중에 Source합니다.
11. Launch와 Lifecycle
실제 Robot은 Node 하나가 아니라 수십 개의 Node와 Parameter, Namespace, Remapping을 함께 실행합니다. Launch File은 이 실행 구성을 Code로 관리합니다.
- 어떤 Node를 실행할지
- 어느 Parameter File을 읽을지
- Topic 이름을 어떻게 Remap할지
- Namespace와 환경 변수를 어떻게 줄지
- 조건에 따라 무엇을 포함할지
Lifecycle Node는 unconfigured → inactive → active → finalized 같은 관리 상태를 가집니다. Sensor가 준비되기 전에 Controller가 명령을 보내는 일을 막고, 여러 Component의 시작 순서를 제어할 때 유용합니다.
12. TF2와 URDF
로봇 Data는 값뿐 아니라 어느 좌표계에서 언제 측정했는지가 중요합니다. TF2는 map, odom, base_link, camera_link 같은 Frame 사이의 시간에 따른 Transform을 관리합니다.
map → odom → base_link → laser_frame
└→ camera_link
URDF는 Robot의 Link, Joint, Geometry, 시각 형상, Collision 형상 등을 표현하는 Robot Model 형식입니다. robot_state_publisher는 URDF와 Joint State를 이용해 Robot의 Transform을 발행할 수 있습니다.
둘의 역할은 다릅니다.
- URDF: Robot이 어떻게 구성되었는지 기술
- TF2: 실행 중 Frame 관계를 시간과 함께 전달·조회
- RViz: Robot Model, Sensor Data, TF 등을 시각화
13. ROS 개발의 관찰 도구
ROS의 큰 장점은 내부 Data를 표준 도구로 관찰할 수 있다는 점입니다.
| 도구 | 역할 |
|---|---|
ros2 topic echo |
Message 내용 확인 |
ros2 topic hz, bw |
주기와 대역폭 확인 |
rqt_graph |
Node와 Topic 연결 시각화 |
| RViz | Sensor, Map, Path, TF, Robot Model 시각화 |
ros2 bag |
Topic Data 기록과 재생 |
tf2_tools |
TF Tree 점검 |
| Log | Node 상태와 오류 추적 |
ros2 bag으로 실제 Sensor Data를 기록하면 Hardware 없이 같은 입력을 반복 재생하여 Algorithm을 비교하고 회귀 Test를 만들 수 있습니다. 다만 Bag은 모든 Runtime 상태를 자동으로 보존하지 않으므로 필요한 Topic, Parameter, Version 정보도 함께 관리해야 합니다.
14. 가장 작은 실습
ROS 2 환경을 Source한 두 Terminal에서 Demo Node를 실행합니다.
Terminal 1: Publisher 실행
ros2 run demo_nodes_cpp talker
Terminal 2: Subscriber 실행
ros2 run demo_nodes_py listener
Terminal 3: Graph 관찰
ros2 node list
ros2 topic list -t
ros2 topic info /chatter --verbose
ros2 topic echo /chatter
ros2 topic hz /chatter
여기서 확인할 것은 다음과 같습니다.
- C++ Publisher와 Python Subscriber가 언어 차이 없이 통신합니다.
- 두 Node는
/chatter와std_msgs/msg/String이라는 Data 계약을 공유합니다. - 세 번째 Terminal이 기존 Code를 바꾸지 않고 Data를 관찰합니다.
Message를 한 번 직접 발행할 수도 있습니다.
ros2 topic pub --once /chatter std_msgs/msg/String "{data: '안녕하세요 ROS 2'}"
15. 실제 이동 로봇의 Data 흐름
LiDAR ─> Driver ─> /scan ─> Localization ─┐
Wheel Encoder ─> Odometry ─> /odom ───────┤
v
Goal ─> Nav2 Action ─> Planner ─> Controller ─> /cmd_vel ─> Base Controller ─> Motor
│ │
└─ /plan └─ 상태·Feedback
이 흐름에서 Topic, Action, TF가 함께 사용됩니다.
- Sensor와 상태는 Topic으로 계속 흐릅니다.
- “목표로 이동”은 오래 걸리고 취소 가능하므로 Action입니다.
- Localization 결과와 Sensor 위치는 TF Tree에서 같은 공간 관계로 연결됩니다.
- 속도 제한이나 Planner Option은 Parameter로 관리할 수 있습니다.
ROS가 각 Algorithm의 수학을 대신 계산하는 것은 아닙니다. 대신 각 Component가 명확한 Interface로 교체되고, Data 흐름이 도구로 보이게 만듭니다.
16. ROS 1과 ROS 2의 핵심 차이
| 항목 | ROS 1 | ROS 2 |
|---|---|---|
| 발견 방식 | 중앙 ROS Master 필요 | DDS 기반 분산 Discovery |
| 통신 설정 | 비교적 단순 | QoS로 전달 성질 조정 |
| 지원 환경 | Linux 중심 | 여러 OS와 Embedded 환경 고려 |
| 보안 | 기본 구조에 제한적 | DDS Security를 활용할 기반 |
| 실시간성 | 별도 설계가 많이 필요 | Real-time을 고려한 구조 개선 |
| Node 관리 | 일반 Node 중심 | Lifecycle, Composition 등 강화 |
ROS 2도 자동으로 Real-time이 되거나 안전해지는 것은 아닙니다. OS, Executor, Memory 할당, Network, Hardware까지 전체 경로를 목적에 맞게 설계해야 합니다. 새 프로젝트는 특별한 Legacy 제약이 없다면 ROS 2를 기준으로 판단하는 것이 일반적입니다.
17. 자주 생기는 오해와 문제
“Topic이 보이는데 Data가 안 옵니다”
Message Type, QoS 호환성, Namespace, Domain ID, Network Firewall, Publisher 수를 확인합니다.
ros2 topic info /topic_name --verbose
ros2 topic echo /topic_name
“다른 Computer의 Node가 보이지 않습니다”
두 장비가 같은 Network와 ROS Domain을 사용하는지, Multicast가 허용되는지, Host Firewall과 Container Network가 Discovery를 막지 않는지 확인합니다.
“Build했는데 Package를 찾지 못합니다”
Build 성공 여부와 install 결과를 확인하고 현재 Terminal에서 source install/setup.bash를 실행합니다.
“ROS면 모든 것이 분산되어야 합니다”
고주기 제어 Loop나 대용량 Image Pipeline은 한 Process의 Component, Intra-process Communication, MCU 내부 Control이 더 적합할 수 있습니다. 분산은 목적이 아니라 설계 수단입니다.
“Reliable이면 항상 더 좋습니다”
불안정한 Network에서 고주기 Sensor Data를 반드시 재전송하면 오래된 Data가 쌓이고 지연이 커질 수 있습니다. Data의 의미에 맞는 QoS가 더 중요합니다.
18. 좋은 ROS System을 위한 설계 원칙
- Topic 이름보다 먼저 Message의 의미, 단위, Frame, Timestamp를 정의합니다.
- 지속 Data는 Topic, 짧은 요청은 Service, 긴 작업은 Action으로 구분합니다.
- 안전 정지는 통신과 상위 Application 장애에 의존하지 않게 설계합니다.
- Node마다 책임, 입력, 출력, 주기, QoS, 실패 동작을 문서화합니다.
- Namespace와 Remapping을 활용해 Code에 Robot 이름을 박아 넣지 않습니다.
- 실제 장비 Test 전에 Simulation과 Bag Replay로 반복 검증합니다.
- “많이 쪼개기”보다 변경·배포·장애의 경계에 맞춰 Node를 나눕니다.
핵심 정리
- ROS는 운영체제가 아니라 로봇 Software를 연결하는 Middleware, 도구, Convention, Package 생태계입니다.
- Node는 책임 단위이며 ROS Graph에서 Topic, Service, Action으로 연결됩니다.
- Topic은 Stream, Service는 짧은 요청, Action은 긴 작업, Parameter는 설정에 적합합니다.
- DDS와 QoS는 ROS 2의 분산 Discovery와 Data 전달 특성을 담당합니다.
- Package를 Workspace에서
colcon으로 Build하고 환경을 Source한 뒤 실행합니다. - TF2는 좌표계 관계, URDF는 Robot 구조, RViz는 시각화, rosbag은 기록과 재생을 담당합니다.
- ROS의 진짜 가치는 Algorithm 하나가 아니라 서로 다른 Component를 교체하고 관찰하며 재사용할 수 있는 공통 기반에 있습니다.
- ROS로봇 소프트웨어 공통 기반
- 로봇 Software Component가 표준 방식으로 통신하고 재사용되도록 돕는 Open Source Middleware·도구·생태계입니다.
- Middleware미들웨어
- Operating System과 Application 사이에서 통신, Data 교환과 공통 기능을 제공하는 Software 계층입니다.
- Node기능별 실행 단위
- Sensor Driver, Localization이나 Controller처럼 하나의 명확한 책임을 수행하는 ROS 실행 단위입니다.
- ROS GraphROS 연결 구조
- 실행 중인 Node와 Topic, Service, Action의 관계를 나타내는 동적인 연결 Graph입니다.
- Topic비동기 Data 통로
- Publisher가 연속 Data를 발행하고 하나 이상의 Subscriber가 비동기로 구독하는 통신 방식입니다.
- Publisher발행자
- 정해진 Message Type의 Data를 Topic으로 보내는 Node의 통신 역할입니다.
- Subscriber구독자
- Topic에 발행된 정해진 Type의 Message를 받아 처리하는 Node의 통신 역할입니다.
- Service요청·응답 통신
- Client의 짧은 Request에 Server가 한 번의 Response를 반환하는 동기적 통신 방식입니다.
- Action장시간 작업 통신
- Goal을 받아 오래 수행하면서 Feedback과 Result를 제공하고 Cancel을 지원하는 통신 방식입니다.
- ParameterNode 설정값
- Update Rate, 최대 속도나 Frame 이름처럼 Node가 소유하고 실행 중 조회·변경할 수 있는 설정값입니다.
- DDS분산 Data 전달 기반
- ROS 2에서 Participant Discovery와 Message 전송, QoS 정책을 제공하는 Data Distribution Service 표준입니다.
- RMWROS Middleware 추상화
- ROS Client Library와 여러 DDS 구현 사이의 차이를 감추는 Middleware Interface 계층입니다.
- QoS통신 품질 정책
- Reliability, Durability, History 등 Publisher와 Subscriber가 요구하는 Data 전달 성질의 모음입니다.
- PackageROS 배포 단위
- Code, Interface, Launch, 설정과 의존성 정보를 함께 구성하고 배포하는 ROS의 기본 단위입니다.
- WorkspaceROS 작업 공간
- 여러 ROS Package를 함께 개발하고 Build하며 결과를 설치하는 Directory 구조입니다.
- colconROS Build 도구
- Workspace 안의 Package 의존성을 고려해 Build하고 install 결과를 만드는 명령행 도구입니다.
- Launch실행 구성
- 여러 Node와 Parameter, Namespace, Remapping을 하나의 재현 가능한 실행 구성으로 관리하는 기능입니다.
- Lifecycle Node상태 관리 Node
- 준비, 비활성, 활성과 종료 같은 명시적 상태 전환으로 시작 순서를 제어할 수 있는 Node입니다.
- URDFRobot 구조 기술 형식
- Robot의 Link, Joint, Geometry, 시각 형상과 Collision 형상을 표현하는 XML 기반 형식입니다.
- rosbagROS Data 기록·재생 도구
- 선택한 Topic Message를 시간과 함께 기록하고 다시 재생해 분석과 반복 Test에 사용하는 도구입니다.
연습 문제
- ROS가 일반 목적 Operating System이 아닌 이유를 설명해 보세요.
- Camera Image에는 Topic, Service, Action 중 무엇이 적합하며 그 이유는 무엇인가요?
- 30초 동안 수행되는 Navigation Goal을 Service로 만들면 어떤 문제가 생기나요?
- Topic 이름과 Message Type이 같아도 Data가 전달되지 않을 수 있는 ROS 2 설정은 무엇인가요?
- Package와 Workspace의 차이를 설명해 보세요.
- URDF와 TF2는 각각 무엇을 표현하나요?
- 고주기 Motor 전류 제어를 별도 Network Node로 분리하기 전에 무엇을 고려해야 하나요?
COMMUNITY
강의 댓글
질문과 학습 경험을 함께 나눠보세요.댓글을 불러오는 중입니다.