1294.9 Sequence 노드의 Failure 반환 조건

1. Failure 반환의 정의

Sequence 노드가 FAILURE를 반환하는 조건은 자식 노드 중 하나가 FAILURE를 반환하는 것이다. 순차적 평가 과정에서 첫 번째로 FAILURE를 반환하는 자식이 발견되면, Sequence는 나머지 자식의 평가를 생략하고 즉시 FAILURE를 반환한다(Colledanchise & Ogren, 2018).

\text{Sequence} = \text{FAILURE} \iff \exists\, i \in \{1, \ldots, N\},\ C_i = \text{FAILURE} \wedge \forall\, j < i,\ C_j = \text{SUCCESS}

Failure 발생 시점

조건 노드에서의 Failure

조건 노드는 즉시 반환하므로, 조건이 충족되지 않으면 해당 Tick에서 바로 FAILURE가 결정된다.

Tick:
  children[0]: IsBatteryAbove20 → FAILURE
  children[1]: NavigateToGoal   → (평가되지 않음)
  Sequence → FAILURE

액션 노드에서의 Failure

비동기 액션 노드는 여러 Tick 동안 RUNNING을 반환한 후 FAILURE를 반환할 수 있다. 이 경우 해당 Tick에서 Sequence의 FAILURE가 확정된다.

Tick 1:
  children[0]: CheckCondition → SUCCESS
  children[1]: NavigateToGoal → RUNNING
  Sequence → RUNNING

Tick 2:
  children[1]: NavigateToGoal → FAILURE  ← 네비게이션 실패
  Sequence → FAILURE

Failure 시의 후속 처리

RUNNING 자식의 Halt

Sequence가 FAILURE를 반환하기로 결정할 때, 현재 RUNNING 상태인 다른 자식이 존재하면 해당 자식에게 Halt를 전달한다. 이 상황은 주로 ReactiveSequence에서 발생한다.

ReactiveSequence에서:
  Tick 1:
    children[0]: IsBatteryAbove20 → SUCCESS
    children[1]: NavigateToGoal   → RUNNING
    Sequence → RUNNING

  Tick 2:
    children[0]: IsBatteryAbove20 → FAILURE  ← 배터리 부족
    children[1]: NavigateToGoal   → Halt 호출 (RUNNING → IDLE)
    Sequence → FAILURE

WithMemory에서의 인덱스 초기화

WithMemory 모드의 Sequence가 FAILURE를 반환하면, 기억하고 있던 현재 자식 인덱스가 0으로 초기화된다. 다음에 Sequence가 다시 Tick되면 첫 번째 자식부터 실행을 시작한다.

if (child_status == NodeStatus::FAILURE) {
    haltChildren();
    current_child_idx_ = 0;  // 인덱스 초기화
    return NodeStatus::FAILURE;
}

Failure의 전파

Sequence의 FAILURE는 부모 노드에 전달된다. 부모 노드의 유형에 따라 이 FAILURE가 다르게 해석된다.

부모 노드 유형Sequence FAILURE 시 동작
Fallback다음 자식으로 이동 (대안 시도)
Sequence부모 Sequence도 FAILURE 반환
Decorator (Inverter)SUCCESS로 반전
루트 노드트리 전체가 FAILURE

Fallback 노드 하에서 Sequence의 FAILURE는 “이 방법은 실패했으니 다음 대안을 시도하라“는 의미를 가진다. 이는 시도-대안(try-alternative) 패턴의 기반이 된다.

<Fallback>
    <Sequence>  <!-- 방법 1: 실패하면 다음으로 -->
        <Condition ID="IsPathClear"/>
        <Action ID="NavigateDirect"/>
    </Sequence>
    <Sequence>  <!-- 방법 2: 대안 -->
        <Action ID="ComputeDetour"/>
        <Action ID="NavigateDetour"/>
    </Sequence>
</Fallback>

Failure 원인의 진단

Sequence의 FAILURE만으로는 어떤 자식이 실패했는지를 알 수 없다. 디버깅과 로그 분석에서 FAILURE의 원인을 추적하기 위해, StatusChangeLogger를 사용하여 각 자식의 상태 전이를 기록하거나, 실패한 자식이 블랙보드에 실패 원인을 기록하는 패턴을 사용한다.

BT::NodeStatus tick() override {
    bool result = performNavigation();
    if (!result) {
        setOutput("failure_reason", "Goal unreachable");
        return BT::NodeStatus::FAILURE;
    }
    return BT::NodeStatus::SUCCESS;
}

Sequence의 FAILURE는 그 자체로 오류가 아니라, 트리의 정상적인 의사 결정 결과이다. FAILURE는 “현재 조건에서 이 순차 작업을 수행할 수 없음“을 나타내는 논리적 신호이며, 상위 트리가 이를 활용하여 대안 행동을 선택할 수 있도록 한다(Colledanchise & Ogren, 2018).


참고 문헌

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