1292.40 Fallback 노드의 Running 처리

1. Running 상태의 의미

Fallback 노드가 Running을 반환한다는 것은, 현재 시도 중인 대안 자식 노드가 아직 작업을 완료하지 못하였으며, 해당 대안의 성공 또는 실패 여부가 아직 확정되지 않았음을 부모 노드에 보고하는 것이다. Fallback 노드의 Running 상태는 “현재 대안을 시도 중이며, 결과를 기다리고 있다“는 의미를 가진다 (Colledanchise & Ögren, Behavior Trees in Robotics and AI: An Introduction, 2018).

2. Running 반환의 조건

Fallback 노드가 Running을 반환하기 위한 조건은 다음과 같다: 자식 노드 c_i가 Running을 반환하고, c_i 이전의 모든 자식 c_1, \ldots, c_{i-1}이 Failure를 반환한 경우이다.

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

이 조건에서 자식 c_i가 Running을 반환하면, Fallback 노드는 후속 자식 c_{i+1}, \ldots, c_N에 tick을 전달하지 않고 즉시 Running을 반환한다. 이는 현재 대안의 결과가 확정되지 않은 상태에서 차선의 대안을 미리 시도하지 않는다는 원칙을 따른다.

상태 기억형 Fallback의 Running 처리

인덱스 기억 메커니즘

상태 기억형 Fallback 노드는 Running을 반환한 자식의 인덱스를 내부 변수에 저장한다. 후속 tick에서 Fallback 노드는 저장된 인덱스의 자식부터 실행을 재개하며, 이전에 Failure를 반환한 자식에는 tick을 재전달하지 않는다.

function FallbackWithMemory.tick():
    for i = remembered_index to N:
        status = child[i].tick()
        if status == Running:
            remembered_index = i
            return Running
        if status == Success:
            remembered_index = 0
            return Success
    remembered_index = 0
    return Failure

이 메커니즘은 Sequence 노드의 상태 기억 메커니즘과 구조적으로 동일하되, Success와 Failure의 역할이 교환되어 있다 (Faconti, BehaviorTree.CPP Documentation, 2024).

다중 Tick에 걸친 실행 예제

다음의 Fallback 노드를 고려한다.

Fallback [F1]
 ├─ Action [A1: 주요 경로 추종]
 ├─ Action [A2: 대체 경로 추종]
 └─ Action [A3: 안전 정지]
Tick실행 자식반환 상태F1 반환기억 인덱스
t_1A1RunningRunning0
t_2A1RunningRunning0
t_3A1Failure, A2Running1
t_4A2RunningRunning1
t_5A2SuccessSuccess0

tick t_1t_2에서 A1이 Running을 반환하는 동안, F1은 A1의 인덱스(0)를 기억한다. tick t_3에서 A1이 Failure를 반환하면, 동일한 tick 내에서 A2에 tick이 전달된다. A2가 Running을 반환하면 인덱스가 1로 갱신된다. tick t_5에서 A2가 Success를 반환하면 F1도 Success를 반환하고 인덱스를 초기화한다.

반응형 Fallback의 Running 처리

재평가 메커니즘

ReactiveFallback 노드는 Running 상태에서도 매 tick마다 첫 번째 자식부터 재평가한다. 이전에 Failure를 반환한 자식이 환경 변화에 의해 Success를 반환할 수 있으며, 이 경우 Running 상태의 후속 자식에 halt가 요청된다.

function ReactiveFallback.tick():
    for i = 0 to N:
        status = child[i].tick()
        if status == Running:
            halt_children_after(i)
            return Running
        if status == Success:
            halt_children_after(i)
            return Success
    return Failure

우선순위 복원에 의한 Running 자식 전환

ReactiveFallback에서 가장 중요한 동작 패턴은, 이전에 실패한 상위 우선순위 대안이 후속 tick에서 성공하면 현재 Running 상태의 하위 우선순위 대안을 중단하는 것이다.

ReactiveFallback [RF1]
 ├─ Sequence [S1: 최적 경로]
 │   ├─ Condition [C1: 최적 경로 존재]
 │   └─ Action [A1: 최적 경로 추종]
 └─ Action [A2: 대체 경로 추종]

Tick t_k: C1(Failure) \rightarrow S1(Failure) \rightarrow A2(Running) \rightarrow RF1(Running)

최적 경로가 존재하지 않으므로 S1이 실패하고, 대체 경로 추종(A2)이 실행 중이다.

Tick t_{k+1}: C1(Success) \rightarrow A1(Running) \rightarrow S1(Running) \rightarrow A2에 halt 요청 \rightarrow RF1(Running)

최적 경로가 새로 발견되어 C1이 Success를 반환한다. S1이 Running을 반환하므로, RF1은 Running 상태의 A2에 halt를 요청하고 S1의 Running 상태를 자신의 반환 상태로 전파한다. 이로써 Running 자식이 A2에서 S1으로 전환되며, 더 높은 우선순위의 대안으로 실행이 복원된다 (Colledanchise & Ögren, 2018).

Running 상태의 상향 전파

Fallback 노드의 Running 상태는 Sequence 노드와 동일하게 부모 노드로 상향 전파된다.

Root
 └─ Sequence [S1]
     ├─ Condition [C1]
     └─ Fallback [F1]
         ├─ Action [A1]   ← Running 반환
         └─ Action [A2]

A1이 Running을 반환하면, F1도 Running을 반환하고, S1도 Running을 반환하며, 실행 엔진에 전체 트리가 아직 실행 중임이 보고된다.

Sequence 노드 Running 처리와의 비교

속성Sequence 노드Fallback 노드
Running 반환 조건자식이 Running, 선행 자식 모두 Success자식이 Running, 선행 자식 모두 Failure
상태 기억 대상Running 자식의 인덱스Running 자식의 인덱스
후속 자식 tick 전달하지 않음하지 않음
반응형 재평가 시 halt 조건선행 자식이 Failure 반환선행 자식이 Success 반환

두 노드의 Running 처리는 구조적으로 동일하되, Success와 Failure의 역할이 정확히 교환된 쌍대 관계를 유지한다.

Running 처리의 설계적 고려사항

Fallback 노드에서 Running 상태가 오랜 기간 지속되면, 현재 시도 중인 대안이 성공 또는 실패를 결정하지 못하는 상황에 해당한다. 이 경우 Timeout 데코레이터를 통해 시간 제한을 부여하여, 일정 시간 내에 결과가 확정되지 않으면 Failure로 처리하고 다음 대안으로 진행하도록 설계할 수 있다. 이는 로봇이 하나의 대안에 무한히 머무르는 것을 방지하는 안전 장치이다.


참고 문헌

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