1293.81 Tick 애니메이션을 통한 실행 흐름 시각화

1293.81 Tick 애니메이션을 통한 실행 흐름 시각화

1. Tick 애니메이션의 개념

Tick 애니메이션이란, 행동 트리의 Tick 실행 흐름을 시간에 따라 동적으로 재현하는 시각화 기법이다. 정적 스냅샷과 달리, 애니메이션은 Tick 전파의 순서, 노드 상태의 변화 과정, Halt 전파의 흐름을 시간축에 따라 순차적으로 표현한다. 이를 통해 개발자는 트리의 동적 동작을 직관적으로 이해하고, 실행 흐름의 시간적 특성을 파악할 수 있다(Faconti, 2022).

2. Groot2의 로그 재생 기능

Groot2는 FileLogger2로 기록된 바이너리 로그 파일을 로드하여, Tick 단위로 트리 상태를 순차적으로 재생하는 기능을 제공한다.

// 실행 시 로그 기록
BT::FileLogger2 logger(tree, "session.btlog");

while (rclcpp::ok()) {
    tree.tickOnce();
    rate.sleep();
}
// 세션 종료 후 Groot2에서 session.btlog 파일 재생

재생 시 제공되는 기능:

  • Tick 단위 전진/후진: 다음 Tick 또는 이전 Tick으로 이동하여 상태 변화를 추적한다.
  • 재생 속도 조절: 실제 속도, 느린 재생, 빠른 재생을 선택한다.
  • 특정 Tick으로 이동: Tick 번호를 지정하여 해당 시점으로 직접 이동한다.
  • 노드 상태 색상 변화: 각 Tick에서 노드의 상태에 따라 색상이 실시간으로 변경된다.

3. 애니메이션의 시간적 표현

3.1 Tick 간 전이 애니메이션

연속 Tick 사이의 상태 변화를 부드러운 전이로 표현한다.

Tick N:                          Tick N+1:
┌─────────────────┐              ┌─────────────────┐
│ Sequence [RUN]  │   ──→       │ Sequence [FAIL] │
│ ├─ Cond [OK]    │              │ ├─ Cond [FAIL]  │
│ └─ Act  [RUN]   │              │ └─ Act  [IDLE]  │
└─────────────────┘              └─────────────────┘
                    Halt 발생

3.2 Tick 내부 전파 애니메이션

단일 Tick 내에서의 전파 순서를 시간적으로 분해하여 표시한다. 이는 깊이 우선, 왼쪽에서 오른쪽 전파의 순서를 시각적으로 확인할 수 있게 한다.

Tick N 내부 전파:
  t₁: Root 방문 ──→ Sequence 방문
  t₂: Sequence ──→ Condition_A 방문 → SUCCESS
  t₃: Sequence ──→ Condition_B 방문 → SUCCESS
  t₄: Sequence ──→ Action_1 방문 → RUNNING
  t₅: Sequence 반환: RUNNING
  t₆: Root 반환: RUNNING

4. Chrome Tracing 기반 타임라인 애니메이션

Chrome Tracing 형식으로 기록된 실행 흐름은 크롬 브라우저의 타임라인 뷰어에서 애니메이션으로 표시된다. 각 노드의 실행이 시간축 위의 수평 막대로 표현되며, 막대의 길이가 실행 시간에 비례한다.

시간축 →
Node_A  ████                          ████
Node_B       ██                            ██
Node_C          █████                         █████████
                Tick N                        Tick N+1

이 표현에서 각 노드의 실행 시간, 노드 간의 순차적 관계, Tick 간의 간격을 동시에 파악할 수 있다.

5. 사용자 정의 애니메이션 구현

5.1 터미널 기반 애니메이션

GUI가 없는 환경에서 터미널 출력으로 Tick 상태를 주기적으로 갱신하는 방식이다.

void animateInTerminal(const BT::Tree& tree) {
    while (rclcpp::ok()) {
        executor_.spin_some();
        tree_.tickOnce();
        
        // 터미널 화면 지우기
        printf("\033[2J\033[H");
        printf("=== Tick #%d ===\n", tick_count_++);
        
        printTreeWithColors(tree_);
        
        rate.sleep();
    }
}

void printTreeWithColors(const BT::Tree& tree) {
    tree.applyVisitor([](const%20BT::TreeNode*%20node) {
        const char* color = "\033[0m";  // 기본
        switch (node->status()) {
            case BT::NodeStatus::RUNNING: color = "\033[33m"; break;  // 노랑
            case BT::NodeStatus::SUCCESS: color = "\033[32m"; break;  // 녹색
            case BT::NodeStatus::FAILURE: color = "\033[31m"; break;  // 적색
            default: color = "\033[90m"; break;                       // 회색
        }
        printf("%s%s [%s]\033[0m\n", 
               color, node->name().c_str(), 
               BT::toStr(node->status()).c_str());
    });
}

5.2 웹 기반 애니메이션

WebSocket을 통해 트리 상태를 브라우저로 전송하고, JavaScript로 트리 그래프를 렌더링하는 방식이다. D3.js 등의 시각화 라이브러리를 사용하여 노드의 상태 변화를 애니메이션으로 표현할 수 있다.

6. 애니메이션의 분석적 활용

6.1 비정상 동작의 시각적 감지

  • 조건 진동: 노드의 색상이 매 Tick마다 녹색과 적색으로 번갈아 변하는 것으로 감지된다.
  • 작업 스턱: 노드의 주황색(RUNNING)이 장시간 유지되는 것으로 감지된다.
  • 연쇄 Halt: 다수의 노드가 동시에 주황색에서 회색으로 전이하는 것으로 감지된다.
  • 불필요한 재시작: 노드가 회색 → 주황색 → 회색을 빠르게 반복하는 것으로 감지된다.

6.2 성능 병목의 시각적 식별

Chrome Tracing 타임라인에서 특정 노드의 막대가 다른 노드에 비해 현저히 긴 경우, 해당 노드가 성능 병목임을 시각적으로 식별할 수 있다.

7. 애니메이션 재생의 성능 고려 사항

실시간 애니메이션은 시각화 데이터의 생성과 전송에 의한 오버헤드를 가진다. 이 오버헤드가 Tick 실행 시간에 미치는 영향을 최소화하기 위해, 시각화 데이터의 전송을 비동기적으로 수행하거나, 매 Tick이 아닌 일정 간격으로 스냅샷을 전송하는 샘플링 전략을 적용한다.


참고 문헌

  • Colledanchise, M., & Ogren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
  • Faconti, D. (2022). BehaviorTree.CPP documentation and API reference. https://www.behaviortree.dev/