1294.46 ReactiveFallback의 매 Tick 재평가 규칙

1. 매 Tick 재평가의 정의

ReactiveFallback의 매 Tick 재평가(per-tick re-evaluation) 규칙이란, Fallback이 RUNNING 상태인 동안 매번 Tick을 수신할 때마다 첫 번째 자식(인덱스 0)부터 순차적으로 모든 자식을 다시 평가하는 규칙이다. 이전 Tick에서의 자식 반환 결과는 기억되지 않으며, 매 Tick이 독립적인 완전한 평가 주기를 구성한다(Colledanchise & Ogren, 2018).

2. 재평가 규칙의 상세

2.1 규칙 1: 항상 인덱스 0부터 시작

이전 Tick에서 어떤 자식이 RUNNING을 반환했는지와 무관하게, 매 Tick에서 인덱스 0의 자식부터 평가를 시작한다.

Tick N:   i=0(F) → i=1(F) → i=2(RUNNING) → RUNNING
Tick N+1: i=0(F) → i=1(F) → i=2(RUNNING) → RUNNING  (0부터 재시작)
Tick N+2: i=0(S)                           → SUCCESS  (대안 변화 감지)

2.2 규칙 2: FAILURE 자식도 재평가

FallbackWithMemory에서 건너뛰어지는 FAILURE 자식들이 ReactiveFallback에서는 매 Tick마다 다시 평가된다. 이를 통해 이전에 실패했던 대안의 가용성 변화를 지속적으로 확인한다.

2.3 규칙 3: SUCCESS 발생 시 RUNNING 자식 Halt

재평가 과정에서 이전에 FAILURE였던 자식이 SUCCESS를 반환하면, 현재 RUNNING 상태인 후속 자식에게 Halt를 전달한다.

Tick N:
  children[0]: CondA → FAILURE
  children[1]: ActB  → RUNNING
  ReactiveFallback → RUNNING

Tick N+1:
  children[0]: CondA → SUCCESS   ← 재평가에서 변화 감지
  children[1]: ActB  → Halt      ← RUNNING 자식 중단
  ReactiveFallback → SUCCESS

2.4 규칙 4: RUNNING 또는 SUCCESS 이후의 자식은 미평가

하나의 자식이 RUNNING 또는 SUCCESS를 반환하면, 그 이후의 자식에게는 Tick이 전달되지 않는다.

3. ReactiveSequence 재평가 규칙과의 대칭성

규칙ReactiveSequenceReactiveFallback
시작 인덱스항상 0항상 0
재평가 대상이전 SUCCESS 자식이전 FAILURE 자식
조기 종료 트리거FAILURESUCCESS
RUNNING 자식 Halt 원인앞쪽 조건 FAILURE앞쪽 조건 SUCCESS
계속 진행 상태SUCCESSFAILURE

4. 재평가에 의한 우선순위 감시

ReactiveFallback의 재평가 규칙은 앞쪽 자식을 우선순위 감시(priority monitor) 역할로 활용하는 패턴을 가능하게 한다. 우선순위가 높은 대안(앞쪽)이 가용해지면, 현재 진행 중인 낮은 우선순위 대안(뒤쪽)을 즉시 중단한다.

<ReactiveFallback>
    <!-- 우선순위 감시 조건들 -->
    <Condition ID="IsGoalAlreadyAchieved"/>
    <Condition ID="IsFastPathAvailable"/>
    <!-- 현재 진행 중인 대안 -->
    <Action ID="UseSlowPath"/>
</ReactiveFallback>

매 Tick마다 목표 달성 여부와 빠른 경로의 가용성이 재평가된다. UseSlowPath 진행 중 빠른 경로가 가용해지면 UseSlowPath가 Halt된다.

5. 재평가의 비용 분석

5.1 Tick당 노드 방문 수

RUNNING 상태의 자식이 인덱스 k에 위치할 때, 매 Tick마다 k+1개의 노드가 방문된다.

자식 배열: [Cond₁, Cond₂, Cond₃, AsyncAct]
AsyncAct가 RUNNING일 때:
  매 Tick 방문: Cond₁, Cond₂, Cond₃, AsyncAct → 4개

FallbackWithMemory에서는 AsyncAct만 방문하므로 1개이다.

5.2 총 비용 비교

비동기 작업이 M Tick 동안 RUNNING을 유지하는 경우:

  • ReactiveFallback: (k+1) \times M 노드 방문
  • FallbackWithMemory: k + 1 + (M-1) \times 1 = k + M 노드 방문

이 비용 구조는 ReactiveSequence와 SequenceWithMemory의 비용 구조와 동일하다.

6. 재평가와 조건-행동 패턴

ReactiveFallback에서 조건 노드를 앞에 배치하는 패턴은 “조건이 충족되면 행동을 중단“하는 의미론을 구현한다.

<ReactiveFallback>
    <Condition ID="IsAtChargingStation"/>
    <Action ID="NavigateToChargingStation"/>
</ReactiveFallback>
Tick 1: IsAtChargingStation→F, Navigate→R  → RUNNING
Tick 2: IsAtChargingStation→F, Navigate→R  → RUNNING
Tick 3: IsAtChargingStation→S              → SUCCESS (Navigate Halt)

네비게이션 중 충전소에 도착하면(다른 요인에 의해 위치가 변경되거나 충전소가 이동해온 경우 등) 네비게이션이 즉시 중단된다.

7. 재평가와 액션 노드의 관계

ReactiveFallback에서 앞쪽에 배치된 액션 노드는 매 Tick마다 재실행된다. 이미 FAILURE를 반환한 액션이 다시 실행되면, onStart()부터 다시 시작하여 부수 효과가 반복 발생할 수 있다. 따라서 ReactiveFallback에서도 앞쪽에는 조건 노드(부수 효과 없는 순수 평가)만 배치하고, 비동기 액션은 뒤쪽에 배치하는 것이 설계 원칙이다(Faconti, 2022).

<!-- 권장 패턴: 조건 → 조건 → 액션 -->
<ReactiveFallback>
    <Condition ID="CondA"/>
    <Condition ID="CondB"/>
    <Action ID="AsyncAction"/>    <!-- 뒤쪽에 배치 -->
</ReactiveFallback>

<!-- 비권장 패턴: 액션이 앞에 위치 -->
<ReactiveFallback>
    <Action ID="SomeAction"/>     <!-- 매 Tick 재실행 — 위험 -->
    <Action ID="AnotherAction"/>
</ReactiveFallback>

참고 문헌

  • 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/