1293.52 Sequence에서의 조기 종료 (Failure 시)
1. Sequence 조기 종료의 원리
Sequence 노드에서 자식이 FAILURE를 반환하면, Sequence는 나머지 자식을 평가하지 않고 즉시 FAILURE를 반환한다. 이는 Sequence의 AND 의미론에 기반한다. 모든 자식이 SUCCESS를 반환해야 Sequence가 SUCCESS를 반환하므로, 하나의 자식이라도 FAILURE를 반환하면 전체 결과가 확정된다(Colledanchise & Ogren, 2018).
2. 조기 종료의 상세 알고리즘
function Sequence.tick():
for i = start_index to children.size() - 1:
child_status = children[i].tick()
if child_status == FAILURE:
// 조기 종료: 즉시 FAILURE 반환
haltRunningChildren()
resetIndex()
return FAILURE
if child_status == RUNNING:
// 현재 자식에서 멈춤 (이후 자식 Tick 안 함)
return RUNNING
resetIndex()
return SUCCESS
start_index는 WithMemory Sequence에서는 메모리 인덱스이고, ReactiveSequence에서는 항상 0이다.
3. 구체적 실행 흐름
3.1 조건 노드의 조기 종료
Sequence
├── CheckBattery (조건) → SUCCESS
├── CheckMotors (조건) → FAILURE ← 조기 종료
├── CheckSensors (조건) → (Tick 안 됨)
└── StartMission (액션) → (Tick 안 됨)
CheckMotors가 FAILURE를 반환하면, CheckSensors와 StartMission은 Tick되지 않는다. 모터 점검이 실패한 상태에서 센서 점검이나 임무 시작이 무의미하기 때문이다.
3.2 비동기 액션 노드의 조기 종료
Sequence (WithMemory)
├── NavigateToPickup (비동기) → SUCCESS (이전 Tick에서 완료)
├── GraspObject (비동기) → FAILURE ← 조기 종료
└── NavigateToDropoff (비동기) → (Tick 안 됨)
GraspObject가 파지에 실패하면, NavigateToDropoff는 실행되지 않는다. 물체를 잡지 못한 상태에서 배치 위치로 이동하는 것이 무의미하기 때문이다.
4. 조기 종료와 Halt의 연동
Sequence에서 FAILURE에 의한 조기 종료가 발생할 때, RUNNING 상태인 다른 자식이 있으면 Halt가 호출된다. 이는 주로 Parallel 노드 내의 Sequence나, ReactiveSequence에서 발생한다.
4.1 ReactiveSequence에서의 조기 종료와 Halt
ReactiveSequence:
Tick N-1:
IsBatteryOk.tick() → SUCCESS
IsPathClear.tick() → SUCCESS
Navigate.tick() → RUNNING
반환: RUNNING
Tick N:
IsBatteryOk.tick() → FAILURE ← 조기 종료
→ Navigate에 Halt 호출 (RUNNING → IDLE)
반환: FAILURE
IsBatteryOk의 FAILURE에 의해 조기 종료가 발생하면, IsPathClear은 Tick되지 않고, 이전 Tick에서 RUNNING이었던 Navigate에 Halt가 호출된다.
5. 조기 종료의 빈도 분석
조기 종료의 발생 빈도는 자식 노드의 실패 확률과 배치 순서에 의존한다. 자식 i의 실패 확률을 p_i라 하면, 인덱스 j에서 조기 종료가 발생할 확률은 다음과 같다.
P(\text{조기 종료 at } j) = p_j \cdot \prod_{i=0}^{j-1} (1 - p_i)
앞쪽 자식의 실패 확률이 높을수록, 전체적인 조기 종료 확률이 높아져 불필요한 후속 자식의 실행이 감소한다.
6. 조기 종료에 의한 부수 효과 방지
조기 종료는 후속 자식의 실행을 방지하므로, 부수 효과(side effect)를 가진 후속 자식의 불필요한 실행을 자연스럽게 차단한다. 예를 들어, 전제 조건이 충족되지 않은 상태에서 물리적 작업이 시작되는 것을 방지한다.
<Sequence>
<IsArmCalibrated/> <!-- 실패 시 조기 종료 -->
<IsObjectDetected/> <!-- 실패 시 조기 종료 -->
<GraspObject/> <!-- 전제 조건 미충족 시 실행 안 됨 -->
</Sequence>
이 구조에서 팔이 캘리브레이션되지 않은 상태에서 파지 동작이 시도되지 않으며, 물체가 감지되지 않은 상태에서도 파지 동작이 시도되지 않는다. 이는 조기 종료에 의한 자연스러운 안전 보장이다.
7. WithMemory와 ReactiveSequence에서의 차이
| 특성 | WithMemory Sequence | ReactiveSequence |
|---|---|---|
| 조기 종료 대상 | 현재 인덱스부터의 자식 | 인덱스 0부터의 자식 |
| 이전 성공 자식의 재평가 | 안 함 | 매 Tick 수행 |
| 이전 성공 자식의 FAILURE에 의한 조기 종료 | 불가 | 가능 |
| 조기 종료 빈도 | 낮음 | 높음 (조건 변화 시) |
8. 로봇공학에서의 적용
Sequence의 조기 종료는 로봇공학에서 전제 조건 검증 패턴의 핵심이다. 비용이 높거나 위험한 작업을 실행하기 전에 경량 조건을 먼저 검증하여, 전제 조건이 충족되지 않으면 작업 실행을 방지한다.
<Sequence>
<!-- 경량 검증 (조기 종료 후보) -->
<IsSystemHealthy/>
<IsWorkspaceValid/>
<IsToolAttached/>
<!-- 고비용 작업 (전제 조건 충족 시만 실행) -->
<PerformMachining/>
</Sequence>
참고 문헌
- 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/