1261.73 행동 제어 디버깅 기법과 도구

1. 행동 제어 디버깅의 고유한 난제

행동 제어 시스템(behavior control system)의 디버깅(debugging)은 범용 소프트웨어의 디버깅과 근본적으로 상이한 난제를 수반한다. 행동 제어 시스템은 물리적 환경과 실시간(real-time)으로 상호작용하는 사이버-물리 시스템(cyber-physical system)의 일부이므로, 전통적인 중단점(breakpoint) 기반 대화형 디버깅은 실시간 제약 조건(real-time constraint)을 위반하여 로봇의 제어 불능 상태, 하드웨어 손상, 또는 안전 사고를 초래할 수 있다(Zeller, 2009).

행동 제어 시스템에서 결함(fault)이 발현되는 양상은 단일 코드 라인의 논리 오류에 국한되지 않는다. 복수의 행동 모듈 간 상호작용, 센서 노이즈(sensor noise), 통신 지연(communication latency), 운영체제의 스레드 스케줄링(thread scheduling) 비결정성, 그리고 환경 조건의 동적 변화가 복합적으로 결합하여 결함이 간헐적으로(intermittently) 발현된다. 이러한 비결정적 결함(non-deterministic fault)은 재현(reproduction)이 극히 곤란하며, 하이젠버그(Heisenbug)의 전형적 특성을 나타낸다.

분산 ROS2 시스템에서는 다수의 노드가 독립된 프로세스로 동시 실행되므로, 결함의 근본 원인(root cause)이 위치한 노드를 식별하는 것 자체가 디버깅의 첫 번째 과제이다. 노드 간 통신의 비동기성(asynchrony), DDS(Data Distribution Service) 미들웨어의 QoS(Quality of Service) 정책 차이, 그리고 콜백(callback) 실행 순서의 비결정성이 결함의 인과 관계(causal relationship) 추적을 복잡하게 만든다.

또한 행동 제어 시스템은 행동 선택(behavior selection), 행동 전이(behavior transition), 행동 실행(behavior execution)의 세 단계가 밀접하게 결합되어 있으므로, 결함이 어느 단계에서 기인하였는지를 구분하기 위해서는 행동 제어 아키텍처(유한 상태 머신, 행동 트리, 포섭 아키텍처 등)에 대한 심층적 이해가 선행되어야 한다.

2. 디버깅 기법의 분류

행동 제어 디버깅 기법은 시스템 실행에 대한 개입(intervention) 정도와 분석 시점(analysis timing)에 따라 다음과 같이 분류할 수 있다.

2.1 관찰 기반 디버깅

관찰 기반 디버깅(observation-based debugging)은 행동 제어 시스템의 실행 흐름을 중단하지 않고, 실행 중의 상태 정보를 수동적으로(passively) 관찰하여 결함을 진단하는 접근법이다. 이 기법은 실시간 제약을 유지하면서 시스템 내부 상태를 파악할 수 있으므로, 행동 제어 디버깅의 기본 패러다임으로 간주된다.

관찰 기반 디버깅의 구체적 방법은 다음과 같다.

실시간 토픽 모니터링: ROS2의 ros2 topic echo 명령을 사용하여 행동 제어 관련 토픽(행동 상태 토픽, 피드백 토픽, 센서 데이터 토픽 등)에 발행되는 메시지를 실시간으로 관찰한다. ros2 topic hz 명령으로 메시지 발행 주기(frequency)를 측정하여, 기대 주기와의 편차가 행동 제어 루프의 타이밍 위반을 야기하는지 확인한다. ros2 topic bw 명령으로 대역폭(bandwidth) 소비를 측정하여 통신 병목(bottleneck) 여부를 진단한다.

서비스 호출을 통한 상태 조회: 행동 제어 노드에 상태 조회 서비스(state query service)를 구현하고, ros2 service call 명령으로 실행 중 노드의 내부 상태를 외부에서 질의한다. 이 방법은 행동 제어의 현재 상태(현 행동 명칭, 활성 목표, 블랙보드 변수 값 등)를 비침습적(non-invasive)으로 확인할 수 있다.

행동 트리 실시간 시각화: BehaviorTree.CPP 프레임워크를 사용하는 행동 트리 기반 시스템에서는, Groot2 도구를 통해 행동 트리 각 노드의 실행 상태(SUCCESS, FAILURE, RUNNING)를 색상으로 구분하여 실시간 그래프로 시각화한다. 이를 통해 행동 흐름의 이상(anomaly)을 시각적으로 즉시 식별할 수 있다.

유한 상태 머신 상태 추적: SMACH(Bohren and Cousins, 2010)나 FlexBE(Schillinger et al., 2016) 프레임워크를 사용하는 유한 상태 머신(FSM) 기반 시스템에서는, 상태 전이(state transition)를 토픽에 발행하도록 구성하여 현재 활성 상태와 전이 이력을 외부에서 모니터링한다. SMACH의 smach_viewer는 상태 전이 다이어그램을 실시간으로 시각화하는 도구이다.

2.2 사후 분석 기반 디버깅

사후 분석 기반 디버깅(post-mortem debugging)은 시스템 실행 중에 기록된 로그(log)와 데이터를 실행 종료 후에 분석하여 결함의 원인을 추적하는 방법이다. 실시간 제약에 영향을 주지 않으며, 시간적 제한 없이 반복적이고 심층적인 분석이 가능하다는 장점을 갖는다.

rosbag2 기반 데이터 재생: rosbag2는 ROS2의 공식 데이터 기록·재생 도구이다. 행동 제어 관련 토픽의 메시지를 시간 동기화(time-synchronized) 방식으로 기록하고, 기록된 데이터를 동일한 시간 순서로 재생함으로써 행동 제어 로직의 입력-출력 관계를 시간적으로 재구성한다. --clock 옵션을 사용하면 시뮬레이션 시간을 기록 당시의 시간으로 복원하여 시간 의존적 행동 로직의 검증이 가능하다.

구조화된 로그 분석: ROS2의 rclcpp::Logger 또는 rcutils 로깅 인프라를 통해 생성된 타임스탬프(timestamp) 포함 로그를 분석한다. 행동 전이, 목표 수신, 결과 반환, 오류 발생 등의 시간적 시퀀스를 재구성하여 인과 관계를 추적한다. 로그의 심각도(severity) 수준(DEBUG, INFO, WARN, ERROR, FATAL)을 활용하여, 이상 이벤트를 시간적·공간적으로 교차 필터링한다.

코어 덤프 분석: 분할 오류(segmentation fault), 미처리 예외(unhandled exception), 스택 오버플로우(stack overflow) 등에 의한 비정상 종료 시 생성되는 코어 덤프(core dump) 파일을 GDB(GNU Debugger)로 분석한다. 코어 덤프로부터 종료 시점의 콜 스택(call stack), 지역 변수(local variable), 레지스터(register) 상태를 복원하여 비정상 종료의 직접적 원인을 파악한다. 디버그 심볼(debug symbol)이 포함된 빌드(-DCMAKE_BUILD_TYPE=RelWithDebInfo 또는 Debug)를 사용하면 소스 코드 수준의 분석이 가능하다.

2.3 시뮬레이션 기반 디버깅

시뮬레이션(simulation) 환경은 행동 제어 디버깅에 있어 불가결한 기반을 제공한다. 시뮬레이션에서는 환경 조건(장애물 배치, 조명, 지형 등)을 정밀하게 제어할 수 있으므로, 결함 발현 조건을 체계적으로 재현(reproduce)할 수 있다.

Gazebo 시뮬레이터에서는 gz sim --pause 옵션으로 시뮬레이션을 일시 정지(pause) 상태에서 시작하거나, 실행 중에 일시 정지와 재개를 반복하면서 행동 제어 루프의 매 주기(tick)를 개별적으로 관찰할 수 있다. 시뮬레이션 시간의 배속(time factor)을 조절하여 실시간보다 느리게 실행하면, 빠른 행동 전이의 세부 과정을 관찰할 수 있다.

시뮬레이션 기반 디버깅의 핵심 이점은 결정적 재현(deterministic reproduction)의 가능성이다. 동일한 시뮬레이션 시드(seed)와 초기 조건을 설정하면 물리 엔진의 결정적 모드(deterministic mode)에서 동일한 실행 경로를 재현할 수 있으며, 이로써 간헐적 결함의 원인을 체계적으로 추적할 수 있다.

2.4 단위 격리 디버깅

단위 격리(unit isolation) 디버깅은 복잡한 행동 제어 시스템에서 결함이 의심되는 개별 행동 모듈을 독립적으로 실행하여 결함을 격리(isolate)하는 접근법이다. 외부 의존성(센서 입력, 타 행동 모듈, 통신 채널 등)을 모의 객체(mock object)로 대체하고, 사전 정의된 테스트 데이터를 입력하여 개별 행동의 정확성을 검증한다.

ROS2 환경에서는 rclcpp::Node를 상속한 테스트 노드를 작성하여 모의 발행자(mock publisher)와 모의 구독자(mock subscriber)를 구성한다. launch_testing 프레임워크를 사용하면 테스트 노드와 행동 제어 노드를 격리된 환경에서 자동으로 구동하고, 행동 결과를 자동화된 어서션(assertion)으로 검증할 수 있다. Google Test(GTest)와 결합하여, 행동 모듈의 개별 함수 수준 단위 테스트(unit test)도 수행한다.

2.5 주입 기반 디버깅

결함 주입(fault injection) 디버깅은 행동 제어 시스템의 강건성(robustness)을 검증하기 위해, 의도적으로 이상 조건을 주입하여 시스템의 반응을 관찰하는 기법이다. 주입 가능한 결함 유형에는 센서 데이터 손실, 통신 지연 증가, 메시지 순서 역전, 노드 비정상 종료, 파라미터 범위 초과 등이 포함된다.

ROS2에서는 DDS QoS 정책을 의도적으로 불일치(mismatch)시키거나, 토픽 메시지에 노이즈를 주입하는 중간 노드(interceptor node)를 삽입하여 결함 주입을 수행할 수 있다. 이 기법은 행동 제어의 예외 처리 로직과 폴백(fallback) 메커니즘의 정상 작동 여부를 검증하는 데 필수적이다.

3. 주요 디버깅 도구

3.1 ROS2 명령줄 도구

ROS2는 행동 제어 시스템의 런타임 상태를 탐색하기 위한 포괄적인 명령줄 인터페이스(CLI)를 제공한다.

도구기능
ros2 topic list현재 활성 토픽 목록 조회
ros2 topic echo <topic>특정 토픽의 메시지를 실시간 출력
ros2 topic hz <topic>토픽 메시지의 발행 주기 측정
ros2 topic bw <topic>토픽 대역폭 소비량 측정
ros2 topic info <topic>토픽의 발행자·구독자 수 및 메시지 타입 조회
ros2 service list활성 서비스 목록 조회
ros2 service call서비스 요청을 수동 전송
ros2 action list활성 액션 서버 목록 조회
ros2 action send_goal액션 목표를 수동으로 전송하고 피드백·결과 수신
ros2 action info <action>액션의 서버·클라이언트 연결 정보 조회
ros2 node list활성 노드 목록 조회
ros2 node info <node>특정 노드의 토픽, 서비스, 액션 연결 정보 조회
ros2 param get <node> <param>노드 파라미터 값 조회
ros2 param set <node> <param> <value>노드 파라미터 값을 런타임에 변경
ros2 doctorROS2 시스템 전반의 건전성(health) 진단
ros2 lifecycle get <node>관리형 노드(managed node)의 생명주기 상태 조회

이 도구들은 행동 제어 시스템의 통신 구조를 탐색하고, 개별 토픽·서비스·액션 인터페이스의 정상 동작 여부를 확인하며, 파라미터 조정을 통한 결함 재현에 활용된다.

3.2 Groot2

Groot2는 BehaviorTree.CPP 프레임워크(Faconti, 2019)의 공식 시각화 및 디버깅 도구이다. 행동 트리의 구조를 그래픽 에디터에서 시각적으로 설계·편집하고, 실행 시점에 각 노드의 상태 변화를 실시간으로 트리 그래프 위에 시각화한다.

Groot2는 ZeroMQ(ZMQ) 기반 소켓 통신을 통해 BehaviorTree.CPP 엔진과 양방향으로 연동한다. 엔진 측에서 BT::PublisherZMQ를 등록하면, Groot2 클라이언트가 원격으로 접속하여 다음의 디버깅 기능을 수행할 수 있다.

  • 실시간 실행 모니터링: 행동 트리의 틱(tick) 순서에 따라 각 노드의 반환 상태(SUCCESS, FAILURE, RUNNING)를 색상으로 구분하여 실시간 갱신한다.
  • 중단점 설정: 특정 노드에 중단점을 설정하여, 해당 노드의 실행 직전에 트리의 틱을 일시 정지시킬 수 있다. 이를 통해 특정 행동 분기(branch)의 진입 조건을 상세히 관찰한다.
  • 블랙보드 변수 조회·수정: 블랙보드(blackboard)에 저장된 변수 값을 실시간으로 조회하거나 수동으로 변경하여, 행동 전이 조건의 변화를 즉시 관찰할 수 있다.
  • 실행 이력 기록·재생: 행동 트리의 실행 이력(execution log)을 파일로 기록하고, 사후에 재생하여 행동 흐름의 시계열적 변화를 분석한다.

3.3 rqt 도구군

rqt는 ROS2의 Qt 기반 GUI 프레임워크로서, 플러그인 아키텍처를 통해 다양한 디버깅 기능을 제공한다.

rqt_graph: 전체 ROS2 시스템의 노드 간 토픽·서비스·액션 연결 구조를 방향 그래프(directed graph)로 시각화한다. 행동 제어 시스템의 통신 토폴로지를 일목요연하게 파악할 수 있으므로, 누락된 연결(missing connection), 의도하지 않은 데이터 흐름, 또는 토픽 이름의 오탈자(typo)를 신속히 식별하는 데 유용하다.

rqt_console: 모든 노드에서 발생하는 로그 메시지를 통합적으로 수집하고, 심각도(DEBUG, INFO, WARN, ERROR, FATAL), 노드 이름, 키워드, 시간 범위 등의 조건으로 필터링하여 표시한다. 행동 제어 시스템에서 발생하는 경고 및 오류 메시지의 패턴을 파악하는 데 활용된다.

rqt_plot: 토픽 메시지의 수치형 필드를 실시간 시계열 그래프(time-series plot)로 표시한다. 행동 제어 루프의 주기적 데이터(센서 측정값, 제어 명령, 오차 신호, 행동 지속 시간 등)를 시각적으로 모니터링하고, 이상값(outlier)이나 추세(trend)를 탐지하는 데 유용하다.

rqt_reconfigure: 노드의 동적 재구성 가능(dynamically reconfigurable) 파라미터를 실행 중에 GUI를 통해 변경할 수 있다. 행동 제어의 임계값(threshold), 타임아웃(timeout), 제어 게인(gain) 등을 실행 중에 조정하면서 결함 발현 조건을 탐색하는 데 적합하다.

3.4 GDB와 Valgrind

C++ 기반 행동 제어 코드에서 발생하는 저수준 결함(메모리 오류, 비정상 종료, 교착 상태 등)의 진단에는 GDB(GNU Debugger)와 Valgrind를 활용한다.

GDB를 ROS2 노드에 부착(attach)하기 위해서는 ros2 run <pkg> <exec> --prefix 'gdb -ex run --args' 형식으로 실행하거나, launch 파일에서 prefix 인자를 설정한다. 시뮬레이션 환경에서는 물리 시간의 제약이 완화되므로, GDB의 중단점(breakpoint), 단계별 실행(step execution), 조건부 중단점(conditional breakpoint), 워치포인트(watchpoint) 등의 기능을 상대적으로 안전하게 사용할 수 있다.

Valgrind(Nethercote and Seward, 2007)의 Memcheck 도구는 메모리 누수(memory leak), 초기화되지 않은 메모리 읽기(use of uninitialized memory), 힙 버퍼 오버플로우(heap buffer overflow), 이중 해제(double free) 등의 메모리 오류를 탐지한다. Helgrind 도구는 멀티스레드 프로그램의 데이터 경합(data race)과 잠금 순서 역전(lock order inversion)을 탐지하며, 이는 멀티스레드 실행자(multi-threaded executor)를 사용하는 행동 제어 노드에서 특히 중요하다.

3.5 ros2_tracing

ros2_tracing(Bédard et al., 2022)은 LTTng(Linux Trace Toolkit next generation) 추적 프레임워크를 기반으로 한 ROS2 전용 추적(tracing) 도구이다. 커널 수준(kernel-level)과 사용자 수준(user-level)의 추적 이벤트(tracepoint)를 결합하여, 콜백 실행 시간, 메시지 전달 지연(end-to-end latency), 실행자 스케줄링 패턴, DDS 계층의 전송 타이밍 등을 나노초(nanosecond) 해상도로 기록한다.

ros2_tracing의 오버헤드는 일반적으로 수 마이크로초(microsecond) 수준으로, 실시간 행동 제어 시스템에 적용하더라도 성능에 미치는 영향이 최소화된다. 수집된 추적 데이터는 Trace Compass, Babeltrace2 등의 분석 도구로 시각화하여, 행동 제어 루프의 타이밍 위반(timing violation), 콜백 지연(callback jitter), 스레드 경합(thread contention), 메시지 유실(message drop) 등을 정밀하게 분석할 수 있다.

ros2_tracing이 기록하는 주요 추적 이벤트는 다음과 같다.

추적 이벤트기록 내용
ros2:callback_start콜백 함수의 실행 시작 시점
ros2:callback_end콜백 함수의 실행 종료 시점
ros2:rclcpp_publish메시지 발행 시점
ros2:rclcpp_subscription_callback_added구독 콜백 등록 시점
ros2:rcl_timer_init타이머 초기화 시점
ros2:rcl_service_init서비스 초기화 시점

3.6 RViz2

RViz2는 ROS2의 3차원 시각화 도구로서, 행동 제어 시스템의 공간적 측면을 디버깅하는 데 활용된다. 로봇의 위치·자세, 센서 데이터(포인트 클라우드, 레이저 스캔, 영상), 네비게이션 경로, 코스트맵(costmap), 마커(marker) 등을 3차원 공간에 중첩하여 시각화함으로써, 행동 제어의 공간적 의사결정(예: 장애물 회피 행동의 기동 경로)이 올바른지를 시각적으로 검증한다.

4. 체계적 디버깅 전략

4.1 결함 격리 전략

행동 제어 시스템에서 결함을 효율적으로 격리하기 위해, 다음의 체계적 절차를 적용한다.

  1. 증상 분류: 관찰된 이상 동작을 유형별로 분류한다. 행동 미실행(behavior not triggered), 잘못된 행동 전이(incorrect transition), 시간 초과(timeout), 행동의 조기 종료(premature termination), 비정상 종료(crash), 교착 상태(deadlock), 성능 저하(performance degradation) 등으로 구분한다.
  2. 계층별 점검: 결함이 행동 제어 로직 계층에 있는지, 통신 계층에 있는지, 센서·액추에이터 계층에 있는지를 계층적으로 확인한다. 통신 계층의 점검에는 ros2 topic echo, ros2 topic hz 등의 CLI 도구를, 센서 계층의 점검에는 RViz2를 활용한다.
  3. 입력 데이터 검증: 결함이 관찰된 행동의 입력 데이터(센서 데이터, 블랙보드 변수, 파라미터 값)가 기대 범위(expected range) 내에 있는지를 확인하여, 결함이 입력 오류에 기인하는지를 판별한다.
  4. 시간 분석: 결함 발현 시점의 타이밍 정보(행동 시작 시간, 전이 시간, 응답 시간, 콜백 실행 시간)를 ros2_tracing 또는 로그 타임스탬프로 분석하여, 경합 조건(race condition), 타이밍 의존 결함(timing-dependent fault), 또는 마감 시한 위반(deadline miss)의 가능성을 평가한다.
  5. 최소 재현 사례 구축: 결함을 재현하는 최소한의 시스템 구성(최소 노드 수, 단순화된 환경, 고정된 입력 데이터)을 구축하여, 원인 추적의 복잡도를 감소시킨다. 최소 재현 사례는 이후 회귀 테스트(regression test)의 기초가 된다.

4.2 회귀 방지 체계

발견된 결함의 수정 후에는, 해당 결함을 정확히 재현하는 테스트 케이스(test case)를 반드시 작성하여 회귀(regression)를 방지한다. ROS2에서는 launch_testing 프레임워크와 GTest를 결합한 통합 테스트를 작성하고, 이를 CI/CD(Continuous Integration / Continuous Delivery) 파이프라인에 포함시켜 향후 코드 변경 시 동일 결함의 재발을 자동으로 검증한다.

행동 트리 기반 시스템에서는 BehaviorTree.CPP의 TreeExecutionLog를 활용하여 정상 실행 경로를 기록하고, 이를 기대 실행 경로(expected execution trace)와 비교하는 자동화된 검증 스크립트를 구성할 수 있다.


참고 문헌

  • Bédard, C., Lütkebohle, I., & Dagenais, M. (2022). “ros2_tracing: Multipurpose Low-Overhead Framework for Real-Time Tracing of ROS 2.” IEEE Robotics and Automation Letters, 7(3), 6511–6518.
  • Bohren, J. & Cousins, S. (2010). “The SMACH High-Level Executive.” IEEE Robotics & Automation Magazine, 17(4), 18–20.
  • Faconti, D. (2019). BehaviorTree.CPP: A C++ library to create Behavior Trees. GitHub Repository.
  • Nethercote, N. & Seward, J. (2007). “Valgrind: A Framework for Heavyweight Dynamic Binary Instrumentation.” ACM SIGPLAN Notices, 42(6), 89–100.
  • Schillinger, P., Kohlbrecher, S., & von Stryk, O. (2016). “Human-Robot Collaborative High-Level Control with Application to Rescue Robotics.” IEEE International Conference on Robotics and Automation (ICRA), 2796–2801.
  • Zeller, A. (2009). Why Programs Fail: A Guide to Systematic Debugging. 2nd ed., Morgan Kaufmann.

v0.2.0