ros2 topic list에 이름이 보여도 Publisher와 Subscriber가 메시지를 주고받는다는 뜻은 아닙니다. 먼저 토픽 타입과 실제 Publisher, QoS를 확인하세요. 센서의 Best Effort 발행자에 Reliable 수신자가 붙으면 이름은 보여도 연결되지 않을 수 있습니다.

개념 설명용 도해: 발행자 → Reliable 수신 → Best Effort 수신입니다.
1. 확인 순서를 좁히기
ros2 topic info /대상토픽 -v로 Publisher 수·노드·메시지 타입·QoS를 확인합니다. Publisher가 없다면 프로그램 실행이나 토픽 이름부터 보세요. Publisher가 있는데 수신이 없다면 Reliability와 Durability를 비교하세요. 그다음 시계·필터·콜백 문제를 살펴보면 원인을 한꺼번에 섞지 않을 수 있습니다.
2. 요청한 품질을 제공할 수 있어야 연결됩니다
Reliable Subscriber는 Reliable 전송을 요청합니다. Best Effort Publisher는 그 요청을 만족하지 못합니다. 반대로 Reliable Publisher와 Best Effort Subscriber는 Reliability 정책 기준으로 연결할 수 있습니다. 모든 정책이 함께 호환되어야 하므로 Reliability 하나만 맞췄다고 문제를 다 해결한 것으로 보지는 않습니다.
3. 도구 수신도 같은 조건으로 비교하기
센서가 Best Effort로 발행한다면 ros2 topic echo /대상토픽 --qos-reliability best_effort로 확인하세요. 기본 echo가 우연히 연결되는 경우도 있으므로 명령의 기본값을 추측하지 말고 실제 endpoint 설정을 함께 봅니다. 아래 예제는 한 Publisher에 두 Subscriber를 붙여 차이를 직접 보여줍니다. ROS 2 Jazzy에서 실행하며 실제 센서나 PX4 연결은 필요하지 않습니다.
직접 실행하기
다음 코드를 example.py로 저장한 뒤 ROS 2 Jazzy 환경에서 python3 example.py를 실행하세요.
import os
import time
os.environ.setdefault("ROS_DOMAIN_ID", "188")
import rclpy
from rclpy.node import Node
from rclpy.qos import QoSProfile, ReliabilityPolicy
from std_msgs.msg import String
rclpy.init()
node = Node("qos_receive_example")
counts = {"reliable": 0, "best_effort": 0}
def callback(name):
def receive(msg):
counts[name] += 1
return receive
best = QoSProfile(depth=10, reliability=ReliabilityPolicy.BEST_EFFORT)
reliable = QoSProfile(depth=10, reliability=ReliabilityPolicy.RELIABLE)
pub = node.create_publisher(String, "/qos_receive_example", best)
sub_a = node.create_subscription(String, "/qos_receive_example", callback("reliable"), reliable)
sub_b = node.create_subscription(String, "/qos_receive_example", callback("best_effort"), best)
timer = node.create_timer(0.05, lambda: pub.publish(String(data="hello")))
end = time.monotonic() + 3
while time.monotonic() < end:
rclpy.spin_once(node, timeout_sec=0.05)
print("Reliable 수신:", counts["reliable"])
print("Best Effort 수신:", counts["best_effort"])
assert counts["reliable"] == 0 and counts["best_effort"] > 0
node.destroy_node()
rclpy.shutdown()
실행 결과:
Reliable 수신: 0
Best Effort 수신: 59
터미널에는 incompatible QoS 경고도 표시됩니다. Best Effort 수신 개수는 발견 시간과 실행 환경에 따라 달라집니다. 여기서는 Reliable이 0이고 Best Effort가 양수인지 확인했습니다. 다음 편에서는 네 가지 Reliability 조합과 Durability를 표로 정리하겠습니다.
이어서 읽기
- ROS2 × PX4로 시작하는 자율비행 드론 제어 (3) Offboard Mode 기초
- ROS2 × PX4로 시작하는 자율비행 드론 제어 (2) PX4 + Ignition Gazebo + MAVROS2 연동 전체 형태 구성
참고 자료
'로봇 개발 실전' 카테고리의 다른 글
| 깊이 카메라는 거리를 어떻게 측정할까? Stereo와 ToF 이해하기 (0) | 2026.10.08 |
|---|---|
| ROS 2 QoS 이해하기: Publisher와 Subscriber가 연결되지 않을 때 (0) | 2026.10.08 |
| 객체 탐지와 세그멘테이션, 언제 무엇을 써야 할까? (0) | 2026.10.07 |
| 로봇 센서 선택 가이드: 카메라·깊이 카메라·LiDAR·IMU의 역할 (0) | 2026.10.07 |
| Jetson에서 AI를 실행하기 전 확인할 것: 운영체제와 라이브러리 호환성 (0) | 2026.10.07 |