ROS2 DDS — 미들웨어 구조와 QoS 설정
ROS2는 노드 간 통신에 DDS(Data Distribution Service)를 사용한다. ROS1의 roscore 중앙 브로커 방식을 버리고, 분산 Discovery와 QoS 기반 통신을 도입한 것이다.
ROS1의 문제 — 왜 DDS인가
ROS1은 roscore가 모든 노드의 등록과 토픽 매칭을 담당한다. roscore가 죽으면 새 노드 등록이 불가능하고, 네트워크 분리 환경에서는 동작하지 않는다. 또한 통신 품질(손실 허용, 지연 제한 등)을 제어할 방법이 없다.
DDS는 이 세 가지를 해결한다:
- 중앙 브로커 없이 노드끼리 직접 Discovery
- QoS 정책으로 통신 품질 제어
- OMG 표준 기반으로 벤더 간 호환
ROS2 — DDS 통합 구조
Application (rclcpp / rclpy)
|
RCL (ROS Client Library)
|
RMW (ROS MiddleWare interface)
|
+-----------+-----------+
| | |
Fast DDS Cyclone DDS Connext DDS
RMW 레이어가 DDS 벤더를 추상화한다. 애플리케이션 코드를 바꾸지 않고 DDS 구현체를 교체할 수 있다.
# DDS 벤더 변경
export RMW_IMPLEMENTATION=rmw_fastrtps_cpp # Fast DDS (기본)
export RMW_IMPLEMENTATION=rmw_cyclonedds_cpp # Cyclone DDS
주요 DDS 벤더
| 벤더 | 패키지 | 특징 |
|---|---|---|
| eProsima Fast DDS | rmw_fastrtps_cpp | ROS2 기본값. Discovery Server 지원 |
| Eclipse Cyclone DDS | rmw_cyclonedds_cpp | 경량. 실시간 결정론적 통신에 최적화 |
| RTI Connext DDS | rmw_connextdds | 상용. 대규모 시스템, 보안 기능 |
Discovery — 노드를 어떻게 찾는가
Simple Discovery (기본)
모든 노드가 멀티캐스트로 자신을 알린다. 설정 없이 같은 네트워크의 모든 ROS2 노드가 서로를 찾는다.
Node A ---multicast---> 네트워크
Node B ---multicast---> 네트워크
Node C ---multicast---> 네트워크
(모두가 모두를 발견)
한계: 노드 수가 늘면 Discovery 패킷이 N²로 증가한다. WiFi 환경에서는 멀티캐스트가 불안정하다.
Discovery Server (Fast DDS 전용)
중앙 서버가 Discovery 정보를 관리한다. 노드는 서버에만 등록하고, 관련 토픽이 있는 노드 정보만 받는다.
# 서버 실행
fastdds discovery --server-id 0 --ip-address 192.168.1.100 --port 11811
# 클라이언트 노드
export ROS_DISCOVERY_SERVER=192.168.1.100:11811
ros2 run demo_nodes_cpp talker
Discovery Server v2는 같은 토픽을 구독하지 않는 노드 간에는 Discovery 데이터를 교환하지 않는다. 대규모 시스템(수십~수백 노드)에서 네트워크 부하가 크게 줄어든다.
Domain ID — 네트워크 격리
같은 네트워크에서 여러 로봇이나 팀이 ROS2를 사용할 때, Domain ID로 통신을 격리한다.
# 로봇 A 그룹
export ROS_DOMAIN_ID=1
ros2 run my_pkg node_a
# 로봇 B 그룹 — A와 통신 불가
export ROS_DOMAIN_ID=2
ros2 run my_pkg node_b
- 기본값:
0 - 안전 범위:
0 ~ 101 - Domain ID가 다르면 서로 Discovery 자체가 되지 않는다
Domain ID vs Namespace: Domain ID는 네트워크 수준에서 완전 격리한다. Namespace(/robot1/cmd_vel)는 같은 네트워크 안에서 토픽 이름만 분리한다.
QoS — 통신 품질 제어
DDS의 핵심 가치는 QoS(Quality of Service)다. Publisher와 Subscriber가 각각 QoS를 선언하고, 호환되는 경우에만 연결된다.
주요 QoS 정책
| 정책 | 옵션 | 설명 |
|---|---|---|
| Reliability | RELIABLE / BEST_EFFORT | 메시지 전달 보장 여부 |
| Durability | TRANSIENT_LOCAL / VOLATILE | 늦게 참여한 구독자에게 기존 데이터 전달 여부 |
| History | KEEP_LAST(N) / KEEP_ALL | 보관할 메시지 수 |
| Deadline | Duration | 메시지 간 최대 허용 간격 |
| Liveliness | AUTOMATIC / MANUAL_BY_TOPIC | 노드 생존 확인 방식 |
| Lifespan | Duration | 메시지 유효 기간 |
호환 규칙
QoS는 “Offered vs Requested” 모델이다. Publisher가 제공(Offer)하고, Subscriber가 요구(Request)한다. Subscriber의 요구가 Publisher의 제공보다 엄격하면 연결되지 않는다.
| Publisher (Offer) | Subscriber (Request) | 연결 |
|---|---|---|
| Reliable | Reliable | O |
| Reliable | Best Effort | O |
| Best Effort | Best Effort | O |
| Best Effort | Reliable | X |
| Transient Local | Transient Local | O |
| Transient Local | Volatile | O |
| Volatile | Volatile | O |
| Volatile | Transient Local | X |
규칙: Publisher가 더 높은 품질을 제공하면 낮은 요구에도 연결된다. 반대는 불가.
QoS 프리셋
// Sensor Data — 최신 값만 중요, 손실 허용
auto qos = rclcpp::SensorDataQoS();
// History: KEEP_LAST(5), Reliability: BEST_EFFORT, Durability: VOLATILE
// Default — 일반 토픽
auto qos = rclcpp::QoS(10);
// History: KEEP_LAST(10), Reliability: RELIABLE, Durability: VOLATILE
// 맵 데이터 — 늦게 참여해도 마지막 맵을 받아야 함
auto qos = rclcpp::QoS(rclcpp::KeepLast(1))
.reliable()
.transient_local();
실전 QoS 선택
| 상황 | Reliability | Durability | History |
|---|---|---|---|
| 센서 데이터 (IMU, LiDAR) | Best Effort | Volatile | Keep Last(5~10) |
| 제어 명령 (cmd_vel) | Reliable | Volatile | Keep Last(1) |
| 맵 (map, costmap) | Reliable | Transient Local | Keep Last(1) |
| TF | Reliable | Volatile | Keep Last(100) |
| 원격 조종 (teleop) | Best Effort | Volatile | Keep Last(1) |
QoS 불일치 디버깅
ros2 topic echo로 데이터가 안 보이면 QoS 불일치를 의심한다.
# 토픽의 QoS 확인
ros2 topic info /map --verbose
# Publisher와 Subscriber의 QoS 정책이 각각 표시된다
# QoS를 맞춰서 echo
ros2 topic echo /map --qos-reliability reliable --qos-durability transient_local
QoS가 불일치하면 에러 메시지 없이 데이터가 안 온다. ros2 topic info --verbose로 양쪽 QoS를 반드시 확인한다.
Zenoh — DDS 대안
ROS2 Kilted(2025)부터 Zenoh가 공식 대안 미들웨어로 추가되었다.
sudo apt install ros-jazzy-rmw-zenoh-cpp
export RMW_IMPLEMENTATION=rmw_zenoh_cpp
| 항목 | DDS | Zenoh |
|---|---|---|
| Discovery | 멀티캐스트 기반 | Router 기반 |
| 네트워크 | LAN 최적화 | WAN/클라우드 친화적 |
| 오버헤드 | 상대적으로 무거움 | 경량 와이어 프로토콜 |
| WiFi 환경 | 멀티캐스트 불안정 | 안정적 |
WiFi나 클라우드 연동이 필요한 환경에서 DDS 대신 고려할 수 있다.
메모
- QoS 불일치는 에러가 아니라 “무응답”으로 나타난다. 토픽이 보이는데 데이터가 안 오면 QoS부터 확인한다
ROS_DOMAIN_ID는 같은 물리 네트워크에서 ROS2 시스템을 격리하는 가장 간단한 방법이다. 별도 설정 없이 환경변수 하나로 동작한다- Discovery Server는 Fast DDS 전용이다. Cyclone DDS에서는 사용할 수 없다
- DDS 벤더를 바꿔도 애플리케이션 코드는 수정할 필요 없다. 단, 벤더별 성능 특성과 설정 방식은 다르다
- 센서 데이터에
RELIABLE을 쓰면 네트워크 지연 시 데이터가 쌓여서 지연이 누적된다. 최신 값만 필요하면BEST_EFFORT를 쓴다