1293.5 Tick의 생성 주체 (루트 노드)

1. 루트 노드의 역할

행동 트리에서 tick의 생성 주체(tick originator)는 루트 노드(root node)이다. 루트 노드는 트리 계층 구조의 최상위에 위치하며, 외부 실행 환경(execution environment)으로부터 실행 요청을 수신하여 트리 전체의 tick을 개시하는 유일한 진입점(entry point)이다. 어떠한 중간 노드나 단말 노드도 독립적으로 tick을 생성하지 않으며, 오직 루트 노드만이 tick의 기점 역할을 수행한다 (Colledanchise & Ögren, 2018).

2. 외부 실행 환경과 루트 노드의 관계

루트 노드가 tick을 “생성“한다는 표현은, 루트 노드가 자율적으로 tick을 발생시킨다는 의미가 아니다. 실제로 tick의 촉발은 루트 노드 외부의 실행 환경에 의해 이루어진다. 외부 타이머(timer) 또는 이벤트 루프(event loop)가 주기적으로 루트 노드의 tick() 함수를 호출하며, 루트 노드는 이 호출을 수신하여 자식 노드로 tick을 전파한다.

[외부 실행 환경]
    │
    │  주기적 호출: tree.tickRoot()
    ▼
[루트 노드]
    │
    │  tick 전파
    ▼
[자식 노드들]

이 구조에서 외부 실행 환경은 tick의 촉발자(trigger)이고, 루트 노드는 tick의 분배자(distributor)이다. 행동 트리 문헌에서 “루트 노드가 tick을 생성한다“라고 기술하는 것은, 트리 내부의 관점에서 tick이 루트 노드로부터 시작됨을 의미하는 것이다 (Faconti, 2024).

3. BehaviorTree.CPP에서의 루트 노드 구현

BehaviorTree.CPP 라이브러리에서 행동 트리의 실행은 Tree 객체의 tickRoot() 또는 tickWhileRunning() 메서드를 통해 이루어진다. 이 메서드는 트리의 루트 노드의 executeTick() 함수를 호출하며, 이것이 트리 전체의 tick 순회를 개시한다.

// BehaviorTree.CPP에서의 tick 실행
BT::Tree tree = factory.createTreeFromFile("my_tree.xml");
BT::NodeStatus status = tree.tickRoot();

tickRoot() 메서드는 단일 tick을 실행하고 루트 노드의 반환 상태를 반환한다. tickWhileRunning() 메서드는 루트 노드가 Running을 반환하는 동안 tick을 반복 실행하며, 이는 주기적 tick 실행의 편의 함수이다 (Faconti, 2024).

4. ROS2 환경에서의 Tick 촉발 메커니즘

ROS2 환경에서 행동 트리의 tick은 ROS2 타이머(timer)에 의해 촉발된다. ROS2 노드 내에서 타이머를 생성하고, 타이머의 콜백(callback) 함수에서 행동 트리의 tickRoot()를 호출하는 것이 일반적인 패턴이다.

// ROS2 타이머에 의한 주기적 tick 촉발
auto timer = this->create_wall_timer(
    std::chrono::milliseconds(10),  // 10ms 주기
    [&tree]() {
        tree.tickRoot();
    }
);

이 구조에서 ROS2의 실행기(executor)가 타이머 콜백을 주기적으로 호출하며, 타이머 콜백이 행동 트리의 루트 노드에 tick을 전달한다. 따라서 tick의 촉발 체인은 다음과 같다.

ROS2 Executor → Timer Callback → Tree.tickRoot() → Root Node.tick() → 자식 노드 순회

Nav2에서도 이 패턴이 사용되며, BtActionServer가 내부적으로 타이머를 통해 행동 트리를 주기적으로 tick한다 (Macenski et al., 2020).

5. 루트 노드의 유일성

하나의 행동 트리에는 정확히 하나의 루트 노드만 존재한다. 이는 행동 트리가 트리(tree) 자료 구조의 정의를 따르기 때문이다. 트리 자료 구조에서 루트는 부모가 없는 유일한 노드이며, 모든 비루트 노드는 정확히 하나의 부모를 가진다. 루트 노드의 유일성은 tick의 기점이 단일함을 보장하며, 이는 트리 순회의 결정론적 순서를 보장하는 전제 조건이다 (Colledanchise & Ögren, 2018).

복수의 루트 노드가 존재하는 구조는 행동 트리가 아닌 행동 포레스트(behavior forest)에 해당하며, 이 경우 tick의 생성과 전파에 대한 별도의 조정 메커니즘이 필요하다.

6. 루트 노드의 반환 상태와 Tick 결과

루트 노드는 트리 순회가 완료된 후 최종 반환 상태를 외부 실행 환경에 보고한다. 이 반환 상태는 트리 전체의 평가 결과를 요약하는 것으로, 외부 실행 환경은 이 상태에 기반하여 후속 동작을 결정한다.

루트 노드 반환 상태의미외부 실행 환경의 전형적 동작
Success트리의 목표가 달성됨임무 완료 처리 또는 새로운 임무 시작
Failure트리의 목표 달성에 실패함오류 처리 또는 대안 행동 시작
Running트리의 목표가 아직 진행 중임다음 tick 주기에 재실행

Running 상태의 반환은 tick 기반 실행 모델에서 특히 중요하다. 비동기 행동이 진행 중인 경우 루트 노드는 Running을 반환하며, 외부 실행 환경은 이를 인지하고 다음 tick 주기에 다시 tickRoot()를 호출하여 진행 상태를 확인한다. 이 반복 과정이 비동기 행동의 완료까지 지속된다.

7. 루트 노드와 서브트리의 관계

서브트리(subtree)는 행동 트리 내에 포함된 독립적인 트리 구조이다. 서브트리의 루트 노드는 상위 트리에서 하나의 자식 노드로 취급되며, 상위 트리의 tick이 서브트리의 루트 노드에 도달하면 서브트리 내부의 순회가 개시된다. 이 구조에서 서브트리의 루트 노드는 상위 트리의 관점에서는 일반 노드이고, 서브트리의 관점에서는 tick의 진입점이다. 그러나 서브트리의 루트 노드가 독립적으로 tick을 생성하는 것이 아니라, 상위 트리로부터 전파된 tick을 수신하여 서브트리 내부로 전달하는 것이다 (Faconti, 2024).

[전체 트리 루트]          ← tick의 유일한 기점
    ├→ [노드 A]
    └→ [서브트리 루트]     ← 상위 tick의 전파를 수신
         ├→ [노드 B]
         └→ [노드 C]

8. 루트 노드 설계 시 고려 사항

루트 노드는 행동 트리의 최상위 제어 정책을 구현하는 노드이다. 실무에서 루트 노드는 일반적으로 Sequence, Fallback, 또는 기타 제어 흐름 노드로 구성된다. 루트 노드의 선택은 트리 전체의 실행 의미론(execution semantics)에 직접적인 영향을 미친다.

예를 들어, 루트 노드가 Fallback 노드이면 트리는 여러 대안 행동 중 성공하는 첫 번째 행동을 실행하는 의미를 가지며, Sequence 노드이면 모든 자식 행동을 순차적으로 성공시켜야 하는 의미를 가진다. 루트 노드의 유형 선택은 로봇의 최상위 임무 구조를 반영해야 한다.


참고 문헌

  • Colledanchise, M. & Ögren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
  • Faconti, D. (2024). BehaviorTree.CPP Documentation. https://www.behaviortree.dev/
  • Macenski, S., Martín, F., White, R., & Clavero, J. G. (2020). The Marathon 2: A Navigation System. Proceedings of the IEEE/RSJ International Conference on Intelligent Robots and Systems (IROS).