1292.34 Sequence 노드의 실패 조건

1. 실패 조건의 정의

Sequence 노드의 실패 조건(failure condition)은 다음과 같다: 자식 노드 중 하나라도 Failure를 반환하면 Sequence 노드는 즉시 Failure를 반환한다. 이 조건은 Sequence 노드의 논리곱(logical AND) 의미론에서 직접 도출되며, 논리곱에서 하나의 피연산자가 거짓이면 전체 결과가 거짓이 되는 것과 동일한 원리이다 (Colledanchise & Ögren, Behavior Trees in Robotics and AI: An Introduction, 2018).

2. 형식적 정의

Sequence 노드 S가 자식 노드 c_1, c_2, \ldots, c_N을 가질 때, S가 Failure를 반환하기 위한 충분조건은 다음과 같다.

\exists\, i \in \{1, 2, \ldots, N\} : \text{status}(c_i) = Failure \implies \text{status}(S) = Failure

이 조건은 존재 양화(existential quantification)로 표현되며, 단 하나의 자식이라도 실패하면 전체가 실패한다는 존재 조건(existential condition)이다. 더 정밀하게 기술하면, Failure를 반환하는 자식은 왼쪽에서 오른쪽 순서로 처음 만나는 자식이며, 해당 자식 이전의 모든 자식은 Success를 반환한 상태이다.

\text{status}(S) = Failure \iff \exists\, i : \text{status}(c_i) = Failure \wedge \forall\, j < i : \text{status}(c_j) = Success

3. 조기 종료에 의한 즉시 실패

Sequence 노드의 실패 조건에서 핵심적인 특성은 조기 종료(short-circuit)이다. 임의의 자식 c_i가 Failure를 반환하면, Sequence 노드는 후속 자식 c_{i+1}, c_{i+2}, \ldots, c_N에 tick을 전달하지 않고 즉시 Failure를 반환한다. 이 조기 종료 메커니즘은 불필요한 계산을 회피하여 실행 효율을 극대화한다.

조기 종료에 의해 tick을 수신하지 못한 자식 노드는 Idle 상태를 유지하며, 해당 tick의 실행 추적에 포함되지 않는다.

4. 실패 발생 위치에 따른 영향

4.1 첫 번째 자식에서의 실패

첫 번째 자식 c_1이 Failure를 반환하면, 나머지 모든 자식에 tick이 전달되지 않는다. 이 경우의 실행 추적은 가장 짧다.

\tau_k = \langle (c_1, Failure) \rangle

이 패턴은 조건 노드를 Sequence의 첫 번째 자식으로 배치하는 가드(guard) 패턴에서 전형적으로 나타난다. 선행 조건이 충족되지 않으면 후속 액션이 전혀 실행되지 않는다.

중간 자식에서의 실패

i번째 자식(1 < i < N)에서 Failure가 발생하면, c_1부터 c_{i-1}까지는 이미 Success를 반환한 상태이며, c_{i+1}부터 c_N까지는 tick을 수신하지 못한다.

\tau_k = \langle (c_1, S), (c_2, S), \ldots, (c_{i-1}, S), (c_i, F) \rangle

이 경우, 이미 성공적으로 완료된 자식(c_1, \ldots, c_{i-1})의 작업이 수행된 후에 실패가 발생하였으므로, 해당 작업의 부작용(side effect)이 이미 적용된 상태일 수 있다. 이는 행동 트리 설계 시 고려하여야 할 중요한 사항이다.

4.2 마지막 자식에서의 실패

마지막 자식 c_N에서 Failure가 발생하면, 이전의 모든 자식이 Success를 반환한 상태에서 최종 단계에서만 실패한 것이다. 이 패턴은 다단계 임무에서 마지막 단계의 실패를 나타낸다.

5. 상태 기억형 Sequence에서의 실패

상태 기억형 Sequence 노드(SequenceWithMemory)에서 실패가 발생하면, 기억하고 있던 자식 인덱스가 0으로 초기화된다. 이는 다음 tick에서 Sequence가 첫 번째 자식부터 다시 실행을 시작함을 의미한다 (Faconti, BehaviorTree.CPP Documentation, 2024).

예를 들어, 이전 tick에서 c_2가 Running을 반환하여 인덱스 2를 기억하고 있던 상태에서, 후속 tick에서 c_2가 Failure를 반환하면, Sequence는 Failure를 반환하고 인덱스를 0으로 초기화한다. 다음 tick에서는 c_1부터 다시 실행이 시작된다.

6. 반응형 Sequence에서의 실패

ReactiveSequence 노드에서의 실패는 추가적인 의미를 가진다. ReactiveSequence는 매 tick마다 첫 번째 자식부터 재평가하므로, 이전 tick에서 Success를 반환한 자식이 후속 tick에서 Failure를 반환할 수 있다. 이 경우 현재 Running 상태에 있는 후속 자식에 halt가 요청된다.

ReactiveSequence [RS1]
 ├─ Condition [C1: 배터리 잔량 확인]
 └─ Action [A1: 경로 추종]

Tick t_k: C1(Success) \rightarrow A1(Running) \rightarrow RS1(Running)

Tick t_{k+1}: C1(Failure) \rightarrow A1에 halt 요청 \rightarrow RS1(Failure)

이 사례에서 C1의 실패는 A1의 강제적 비활성화를 유발하며, 이는 반응형 노드의 환경 변화에 대한 즉각적 대응 메커니즘이다.

7. 실패와 Halt의 연관

Sequence 노드가 Failure를 반환할 때, 현재 Running 상태에 있는 자식 노드가 존재하면 해당 노드에 halt가 요청된다. 이 상황은 주로 반응형 Sequence에서 발생한다. 일반 Sequence에서는 Failure를 반환하는 자식 자체가 실행 중인 노드이므로, 해당 자식의 실행이 종료되고 Failure가 반환되는 것이지 별도의 halt가 필요하지 않다.

8. 실패 조건의 설계적 활용

8.1 실패 전파를 통한 상위 수준 제어

Sequence 노드의 실패는 부모 노드로 전파된다. 부모 노드가 Fallback 노드인 경우, Sequence의 실패는 Fallback이 다음 대안 자식을 실행하는 계기가 된다. 이러한 실패 전파 메커니즘을 통해 행동 트리는 계층적 대안 탐색(hierarchical fallback) 구조를 구현한다 (Colledanchise & Ögren, 2018).

Fallback
 ├─ Sequence: [주요 경로 실행]
 │   ├─ Condition: 주요 경로 존재 확인
 │   └─ Action: 주요 경로 추종
 └─ Sequence: [대체 경로 실행]
     ├─ Condition: 대체 경로 존재 확인
     └─ Action: 대체 경로 추종

첫 번째 Sequence가 실패하면, Fallback이 두 번째 Sequence를 실행하여 대안을 시도한다.

8.2 빠른 실패를 위한 자식 배치 전략

실패 가능성이 높은 자식을 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/