
# Logger
Logger는 “노드가 어떤 판단을 했는지”를 텍스트로 남깁니다. GUI가 강력하긴 하지만, 원인 추적의 시작점은 로그가 더 빠른 경우가 많습니다.
로그 레벨은 보통 아래처럼 쓰입니다.
- DEBUG: 개발 단계의 상세 상태(자주 찍힘)
- INFO: 정상 흐름에서 주요 이벤트
- WARN: 이상 징후(치명적이진 않음)
- ERROR: 실패/예외 상황
- FATAL: 계속 진행하기 어려운 실패
패키지 생성
간단한 Python 노드를 만들어 로깅 동작을 바로 확인할 때
무엇을 확인해야 하는지: rclpy 의존성이 포함되었는지
ros2 pkg create --build-type ament_python logger_test --dependencies rclpy
- --build-type ament_python: Python 패키지 형태로 생성
- --dependencies rclpy: rclpy를 종속성에 포함
노드 코드 작성 (log_demo.py)
언제 쓰는지: 각 레벨 로그가 실제로 출력되는지, 레벨 변경이 필터링에 반영되는지 확인할 때
무엇을 확인해야 하는지: 타이머 콜백이 주기적으로 돌고, 레벨별 메시지가 콘솔에 출력되는지
import rclpy
from rclpy.node import Node
class LogDemo(Node):
def __init__(self):
# call super() in the constructor in order to initialize the Node object
# the parameter we pass is the node name
super().__init__('logger_example')
# Logger level configuration
rclpy.logging.set_logger_level('logger_example', rclpy.logging.LoggingSeverity.DEBUG)
# create a timer sending two parameters:
# - the duration between 2 callbacks (0.2 seeconds)
# - the timer function (timer_callback)
self.create_timer(0.2, self.timer_callback)
def timer_callback(self):
# print a ROS2 log debugging
self.get_logger().debug("print a ROS2 log debugging")
# print a ROS2 log info
self.get_logger().info("print a ROS2 log info")
# print a ROS2 log warning
self.get_logger().warn("print a ROS2 log warning")
# print a ROS2 log error
self.get_logger().error("print a ROS2 log error")
# print a ROS2 log fatal
self.get_logger().fatal("print a ROS2 log fatal")
def main(args=None):
# initialize the ROS communication
rclpy.init(args=args)
# declare the node constructor
log_demo = LogDemo()
# pause the program execution, waits for a request to kill the node (ctrl+c)
rclpy.spin(log_demo)
# shutdown the ROS communication
rclpy.shutdown()
if __name__ == '__main__':
main()
- super().__init__('logger_example')
→ 이 노드의 이름이 logger_example가 됩니다. - set_logger_level('logger_example', LoggingSeverity.DEBUG)
→ 특정 로거 이름에 대해 최소 출력 레벨을 DEBUG로 맞춥니다. - create_timer(0.2, ...)
→ 0.2초마다 콜백이 돌아서, 로그가 계속 찍힙니다.
엔트리포인트 추가 (setup.py)
언제 쓰는지: ros2 run으로 Python 노드를 실행 가능하게 만들 때
무엇을 확인해야 하는지: 모듈 경로(logger_test.log_demo:main)가 실제 파일/함수와 일치하는지
entry_points={
'console_scripts': [
'log_demo = logger_test.log_demo:main',
],
},
빌드 및 환경 적용
언제 쓰는지: 새 패키지/노드를 워크스페이스에 반영할 때
무엇을 확인해야 하는지: 빌드 성공 여부, source가 반영됐는지
cd ~/ros2_ws
colcon build --symlink-install --packages-select logger_test
source install/local_setup.zsh # 환경에 따라 local_setup.bash
- --symlink-install: Python/리소스 수정 시 반영이 편해집니다.
- --packages-select logger_test: 해당 패키지만 빠르게 빌드합니다.
실행 및 레벨 변경 실험
언제 쓰는지: 로그가 레벨에 따라 필터링되는지 확인할 때
무엇을 확인해야 하는지: 레벨을 WARN으로 올리면 DEBUG/INFO 메시지가 사라지는지
ros2 run logger_test log_demo
그리고 코드에서 아래 부분을 바꿔서 확인합니다.
rclpy.logging.set_logger_level('logger_name', rclpy.logging.LoggingSeverity.<LOG_LEVEL>)
# RViz2

RViz2는 3D 시각화로 토픽/TF 기반 데이터를 직관적으로 보여줍니다. 특히 아래 범주가 자주 쓰입니다.
- 기본 표시: RobotModel, TF, Grid
- 센서 데이터: LaserScan, PointCloud2, Image
- 네비게이션: Map, Path, Odometry
# RQt

RQt는 Qt 기반 GUI 프레임워크이면서, 여러 디버깅 도구가 플러그인으로 묶여 있습니다. 한 창에서 노드 그래프, 토픽 모니터링, 플롯 등을 조합해 쓰는 형태입니다. (필요하면 플러그인 자체를 개발하는 것도 가능합니다.)
자료 기준으로 “자주 쓰는 플러그인 묶음”은 아래처럼 정리할 수 있습니다.
- Configuration: Dynamic Reconfigure
- Introspection: Node Graph
- Services: Service Caller
- Topics: Message Publisher, Topic Monitor
- Visualization: Image View, Plot, TF Tree
# rosbag2

rosbag2는 토픽 데이터를 기록하고(play) 다시 재생할 수 있습니다. 디버깅에서 제일 큰 장점은 같은 입력을 여러 번 반복할 수 있다는 점입니다.
- 기록(record) / 재생(play)
- 선택적 기록(토픽 지정)
- 녹화 중 파일 분할(크기/시간)
- 파일 내용 요약(info)
또한 ROS ↔ ROS 2 간 bag 파일은 기본 호환이 되지 않아 변환이 필요할 수 있습니다.
레코딩(Recording data)
(1) 모든 토픽 기록
언제 쓰는지: “전체 흐름”을 통째로 남겨 재현 가능성을 최대로 올릴 때
무엇을 확인해야 하는지: 저장 중 새 토픽이 자동으로 추가되는지, 디스크 사용량
ros2 bag record -a
- -a: 현재 사용 가능한 모든 토픽 기록
- 녹화 중 새 토픽이 나타나면 자동 추가
- 자동 발견 기능을 끄려면 --no-discovery
(2) 특정 토픽만 선택 기록
언제 쓰는지: 필요한 토픽만 골라 용량/분석 복잡도를 줄이고 싶을 때
무엇을 확인해야 하는지: 지정 토픽이 녹화 시작 시점에 없어도 나중에 등장하면 잡히는지(자동 발견)
ros2 bag record <topic 1> <topic 2> … <topic N>
- 지정한 토픽 중 하나가 나타나면 자동 인식(시작 시점에 없어도 됨)
- 이 자동 기능도 --no-discovery로 끌 수 있음
- 출력 폴더 이름은 -o, --output으로 지정 가능
(미지정 시 현재 타임스탬프 이름의 새 폴더 생성)
Simulation time (/clock) 기록 옵션
ROS 2에서 Simulation time은 “실시간” 대신 /clock 토픽 기반 시간을 쓰는 의미입니다. 녹화 시간축을 시뮬레이션 기준으로 맞춰야 할 때 아래 옵션을 씁니다.
- --use-sim-time: record 노드에서 sim time 사용
녹화 중 파일 분할(Splitting files during recording)
rosbag2는 파일이 너무 커지는 걸 막기 위해 크기/시간 기준으로 분할할 수 있습니다.
(1) 크기 기준 분할
언제 쓰는지: 단일 파일이 과도하게 커지는 걸 방지하고 싶을 때
무엇을 확인해야 하는지: 분할 임계치가 바이트 단위이며, 지정값이 조건을 만족하는지
ros2 bag record -a -b 100000
- -b: bag 파일이 지정 크기(바이트)보다 커지면 분할
- 기본값 0: 분할 없이 단일 파일
- 자료 기준: 배치 크기 단위는 바이트이며 86016보다 커야 함
(2) 시간 기준 분할
언제 쓰는지: 장시간 녹화에서 일정 시간 단위로 파일을 끊고 싶을 때
무엇을 확인해야 하는지: 분할 주기가 초 단위인지
ros2 bag record -a -d 9000
- -d: 지정 시간(초) 후 bag 파일 분할
- 기본값 0: 분할 없음
재생(Replaying data)
언제 쓰는지: 저장된 bag로 동일 입력을 반복 재생하며 디버깅할 때
무엇을 확인해야 하는지: 재생 속도/시작 오프셋/루프 여부가 의도대로인지
ros2 bag play <bag>
<bag>로 가능한 형태(자료 기준):
- metadata.yaml과 하나 이상의 bag 파일이 들어있는 디렉터리 이름
- *.mcap 또는 *.db3 같은 단일 저장 파일
재생 없이 정보 확인(Analyzing bag file)
언제 쓰는지: “뭐가 들어있는지”만 빠르게 확인하고 싶을 때
무엇을 확인해야 하는지: 토픽/타입/메시지 수/기간 등 핵심 요약
ros2 bag info <bag_file>
6-6. 저장 포맷(Storage format)
언제 쓰는지: 저장 포맷을 바꿔 I/O 성능이나 외부 도구 호환성을 맞출 때
무엇을 확인해야 하는지: 기본은 sqlite3이고, mcap은 외부 시각화 도구와 궁합이 좋을 수 있음
ros2 bag record -a -s mcap # MCAP 포맷 사용
- sqlite3(기본): 안정적이고 범용적
- mcap: 더 빠른 읽기/쓰기 성능, Foxglove Studio 등에서 직접 시각화 가능
ROS 2 Doctor

ros2 doctor는 ROS 2 환경의 여러 측면(네트워크, 플랫폼, QoS, RMW, ROS 2 정보, 토픽 등)을 점검해 “바닥이 정상인지”를 확인하는 데 쓰입니다. 로그/토픽만 보다가 막힐 때, 의외로 여기서 실마리가 나오는 경우가 있습니다.
'Side Project > ROS2 & LLM Autonomous Robot' 카테고리의 다른 글
| [최종 프로젝트] ROS2 기반 RGB-D 객체 탐지 VLM 서비스 로봇 (0) | 2026.03.10 |
|---|---|
| 모바일 로봇 구동 방식 (0) | 2026.01.29 |
| MentorPi 개발 환경 구성하기 (0) | 2026.01.29 |