1293.30 Fallback 노드의 자식 재진입 규칙
1. 재진입 규칙의 의의
Fallback 노드에서 자식 노드가 RUNNING을 반환하면, 다음 Tick에서 해당 자식에 다시 Tick을 전달하여 작업의 완료 여부를 확인해야 한다. Sequence 노드와 마찬가지로, RUNNING을 반환한 자식에 도달하기까지의 이전 자식들(이미 FAILURE를 반환한 자식들)을 다시 평가할 것인지가 핵심적인 설계 결정이다. 이 결정은 메모리(Memory) 속성에 의해 결정되며, Fallback 노드의 동작 특성을 근본적으로 변경한다(Colledanchise & Ogren, 2018).
2. WithMemory 모드의 재진입 규칙
WithMemory 모드의 Fallback 노드는 이전 Tick에서 FAILURE를 반환한 자식들의 다음 인덱스를 기억하고, 후속 Tick에서는 기억된 인덱스의 자식부터 실행을 재개한다. 이미 FAILURE를 반환한 자식은 재시도하지 않는다.
2.1 동작 과정
Tick 1: Fallback[Memory]
→ Child_0.tick() → FAILURE (대안 1 실패)
→ Child_1.tick() → RUNNING (대안 2 시도 중)
인덱스 기억: 1
반환: RUNNING
Tick 2: Fallback[Memory]
→ Child_1.tick() → RUNNING (Child_0 건너뜀, 계속 시도)
반환: RUNNING
Tick 3: Fallback[Memory]
→ Child_1.tick() → SUCCESS (대안 2 성공)
인덱스 리셋: 0
반환: SUCCESS
2.2 인덱스 리셋 조건
- Fallback이 SUCCESS를 반환할 때 (자식 중 하나가 성공)
- Fallback이 FAILURE를 반환할 때 (모든 자식이 실패)
- Fallback에 Halt가 호출될 때
2.3 적합한 사용 사례
WithMemory 모드는 이전 대안의 재시도가 무의미하거나 비효율적인 경우에 적합하다. 예를 들어, 첫 번째 대안이 “직선 경로로 이동“이고 이 경로가 차단되어 FAILURE를 반환한 경우, 경로가 즉시 해제될 가능성이 낮으므로 두 번째 대안인 “우회 경로로 이동“에 집중하는 것이 합리적이다.
<FallbackStar> <!-- WithMemory Fallback -->
<NavigateDirect goal="{target}"/>
<NavigateDetour goal="{target}"/>
<WaitAndRetry/>
</FallbackStar>
3. WithoutMemory (Reactive) 모드의 재진입 규칙
ReactiveFallback 노드는 매 Tick마다 첫 번째 자식부터 모든 자식을 재평가한다. 이전에 FAILURE를 반환한 자식도 다시 Tick되며, 상위 우선순위 자식이 SUCCESS를 반환하면 현재 RUNNING 중인 하위 자식이 Halt된다.
3.1 동작 과정
Tick 1: ReactiveFallback
→ Child_0.tick() → FAILURE (우선 전략 실패)
→ Child_1.tick() → RUNNING (대안 전략 시도)
반환: RUNNING
Tick 2: ReactiveFallback
→ Child_0.tick() → FAILURE (재평가, 여전히 실패)
→ Child_1.tick() → RUNNING (재진입, 계속 시도)
반환: RUNNING
Tick 3: ReactiveFallback
→ Child_0.tick() → SUCCESS (재평가, 우선 전략 성공!)
→ Child_1에 Halt 호출 (대안 전략 중단)
반환: SUCCESS
3.2 우선순위 복귀 메커니즘
ReactiveFallback의 핵심적 특성은 우선순위 복귀(priority restoration)이다. 하위 우선순위 대안이 RUNNING 중이더라도, 상위 우선순위 대안이 다시 실행 가능해지면 즉시 상위 대안으로 전환한다. 이는 다음과 같은 시나리오에서 유용하다.
- 우선 경로가 일시적으로 차단되었다가 해제되는 경우
- 높은 우선순위 센서가 일시적 장애 후 복구되는 경우
- 최적 전략이 일시적 조건에 의해 사용 불가하다가 재사용 가능해지는 경우
3.3 적합한 사용 사례
ReactiveFallback은 대안 간 우선순위가 명확하고, 상위 우선순위 대안이 재사용 가능해지면 즉시 전환해야 하는 경우에 적합하다.
<ReactiveFallback>
<UseHighPrecisionSensor/> <!-- 우선: 고정밀 센서 -->
<UseLowPrecisionSensor/> <!-- 대안: 저정밀 센서 -->
<UseDeadReckoning/> <!-- 최후: 추측 항법 -->
</ReactiveFallback>
고정밀 센서가 일시적으로 사용 불가하여 저정밀 센서를 사용하더라도, 고정밀 센서가 복구되면 즉시 전환한다.
4. 두 모드의 비교
| 특성 | WithMemory | WithoutMemory (Reactive) |
|---|---|---|
| 이전 자식 재평가 | 하지 않음 | 매 Tick마다 수행 |
| 상위 우선순위 복귀 | 불가 | 즉시 가능 |
| Tick 실행 비용 | 낮음 | 높음 |
| 전형적 사용 | 비가역적 대안 시도 | 우선순위 기반 선택 |
| RUNNING 자식 Halt 빈도 | 낮음 | 높음 (우선순위 변경 시) |
5. Sequence와의 재진입 규칙 대칭
Fallback의 재진입 규칙은 Sequence의 재진입 규칙과 대칭적이다.
| 구분 | Sequence | Fallback |
|---|---|---|
| 건너뛰는 자식의 상태 | 이전에 SUCCESS를 반환한 자식 | 이전에 FAILURE를 반환한 자식 |
| 재진입 대상 | RUNNING 중인 자식 | RUNNING 중인 자식 |
| Reactive 시 Halt 조건 | 이전 자식이 FAILURE로 변경 | 이전 자식이 SUCCESS로 변경 |
이 대칭 구조를 이해하면 Sequence와 Fallback의 조합을 통한 복잡한 행동 로직의 설계가 직관적으로 가능해진다.
6. 설계 시 주의 사항
6.1 ReactiveFallback에서의 불필요한 Halt 방지
ReactiveFallback에서 상위 자식의 반환 상태가 빈번하게 변동하면, 하위 자식에 대한 Halt와 재시작이 반복적으로 발생하여 작업이 완료되지 못하는 상황이 발생할 수 있다. 이를 방지하기 위해 조건 노드에 히스테리시스를 적용하거나, 상위 자식의 상태가 안정화된 후에만 전환이 이루어지도록 설계해야 한다.
6.2 WithMemory에서의 교착 방지
WithMemory Fallback에서 현재 시도 중인 대안이 무한히 RUNNING을 유지하는 경우, 이전 대안이 다시 사용 가능해지더라도 전환되지 않는다. 이를 방지하기 위해 각 대안에 타임아웃을 설정하여, 일정 시간 내에 완료되지 않으면 FAILURE를 반환하도록 한다.
참고 문헌
- 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/