1294.56 Fallback 내부의 Sequence 중첩

1. 중첩 구조의 의미

Fallback 내부에 Sequence를 배치하는 중첩 구조는 “여러 조건부 행동 중 가장 적합한 하나를 선택“하는 패턴을 구현한다. Fallback의 각 자식이 하나의 대안을 나타내고, 각 대안이 Sequence로 구성되어 “조건이 충족되면 행동을 수행“하는 조건부 행동을 정의한다(Colledanchise & Ogren, 2018).

2. 기본 구조

<Fallback>
    <Sequence>
        <Condition ID="ConditionA"/>
        <Action ID="ActionA"/>
    </Sequence>
    <Sequence>
        <Condition ID="ConditionB"/>
        <Action ID="ActionB"/>
    </Sequence>
    <Action ID="DefaultAction"/>
</Fallback>

이 구조의 실행 흐름:

  1. ConditionA를 평가한다. 참이면 ActionA를 수행하고 Fallback은 SUCCESS를 반환한다.
  2. ConditionA가 거짓이면 Sequence 1이 FAILURE를 반환하고, Fallback은 다음 자식으로 진행한다.
  3. ConditionB를 평가한다. 참이면 ActionB를 수행한다.
  4. ConditionB도 거짓이면 DefaultAction을 수행한다.

3. 논리적 해석

3.1 if-elseif-else 구조와의 대응

이 중첩 구조는 프로그래밍 언어의 조건 분기문과 직접적으로 대응한다.

// 의사 코드 대응
if (ConditionA) {
    ActionA();
} else if (ConditionB) {
    ActionB();
} else {
    DefaultAction();
}

3.2 논리식 표현

(\text{CondA} \land \text{ActA}) \lor (\text{CondB} \land \text{ActB}) \lor \text{Default}

OR 연산(Fallback) 내부에 AND 연산(Sequence)이 포함된 복합 논리식이다.

실행 추적 예시

예시 1: 첫 번째 조건 충족

Fallback:
  Sequence 1:
    ConditionA → SUCCESS
    ActionA → SUCCESS
  → Fallback SUCCESS (Sequence 2, DefaultAction 미평가)

예시 2: 두 번째 조건 충족

Fallback:
  Sequence 1:
    ConditionA → FAILURE
  → Sequence 1 FAILURE (ActionA 미실행)
  Sequence 2:
    ConditionB → SUCCESS
    ActionB → SUCCESS
  → Fallback SUCCESS (DefaultAction 미평가)

예시 3: 모든 조건 미충족

Fallback:
  Sequence 1:
    ConditionA → FAILURE
  → Sequence 1 FAILURE
  Sequence 2:
    ConditionB → FAILURE
  → Sequence 2 FAILURE
  DefaultAction → SUCCESS
  → Fallback SUCCESS

예시 4: 비동기 행동의 진행

Tick 1:
  Fallback:
    Sequence 1:
      ConditionA → FAILURE
    Sequence 2:
      ConditionB → SUCCESS
      ActionB → RUNNING
  → Fallback RUNNING

Tick 2 (FallbackWithMemory):
  Fallback:
    Sequence 2 (재진입):
      ActionB → SUCCESS
  → Fallback SUCCESS

로봇 공학 적용 사례

사례 1: 환경 기반 네비게이션 전략 선택

<Fallback>
    <Sequence>
        <Condition ID="IsGPSAvailable"/>
        <Action ID="NavigateWithGPS"/>
    </Sequence>
    <Sequence>
        <Condition ID="IsMapAvailable"/>
        <Action ID="NavigateWithMap"/>
    </Sequence>
    <Sequence>
        <Condition ID="AreWallsDetected"/>
        <Action ID="NavigateWithWallFollowing"/>
    </Sequence>
    <Action ID="RandomExplore"/>
</Fallback>

GPS가 가용하면 GPS 네비게이션을, 지도가 있으면 지도 기반 네비게이션을, 벽이 감지되면 벽 추종을 사용한다. 어느 것도 가능하지 않으면 무작위 탐색을 수행한다.

사례 2: 장애물 회피 전략 선택

<Fallback>
    <Sequence>
        <Condition ID="CanGoAround"/>
        <Action ID="CircumnavigateObstacle"/>
    </Sequence>
    <Sequence>
        <Condition ID="CanWaitForClear"/>
        <Action ID="WaitForPath"/>
    </Sequence>
    <Action ID="RequestAlternativeRoute"/>
</Fallback>

사례 3: 파지 전략 선택

<Fallback>
    <Sequence>
        <Condition ID="IsObjectSmall"/>
        <Action ID="PrecisionGrasp"/>
    </Sequence>
    <Sequence>
        <Condition ID="IsObjectLarge"/>
        <Action ID="PowerGrasp"/>
    </Sequence>
    <Sequence>
        <Condition ID="IsObjectFlat"/>
        <Action ID="SuctionGrasp"/>
    </Sequence>
</Fallback>

물체의 크기와 형태에 따라 적절한 파지 전략을 선택한다.

조건의 순서와 우선순위

Fallback의 좌→우 평가 순서에 의해, 앞쪽에 배치된 조건부 행동이 더 높은 우선순위를 가진다. 여러 조건이 동시에 참인 경우, 가장 왼쪽의 조건부 행동만 실행된다.

<Fallback>
    <Sequence>
        <Condition ID="IsEmergency"/>     <!-- 최우선: 비상 대응 -->
        <Action ID="EmergencyResponse"/>
    </Sequence>
    <Sequence>
        <Condition ID="IsLowBattery"/>    <!-- 차순위: 충전 -->
        <Action ID="GoCharge"/>
    </Sequence>
    <Action ID="ContinueMission"/>        <!-- 기본: 임무 수행 -->
</Fallback>

비상 상황과 배터리 부족이 동시에 발생하면, 비상 대응이 우선 실행된다.

조건의 상호 배타성

이 패턴에서 조건들이 상호 배타적(mutually exclusive)일 필요는 없다. 여러 조건이 동시에 참이 될 수 있으며, 그 경우 Fallback의 좌→우 평가 순서에 의해 가장 앞쪽의 조건부 행동만 실행된다. 그러나 조건들이 상호 배타적이면, Fallback의 동작이 더 예측 가능해지고 디버깅이 용이해진다.

Reactive 변형에서의 동작 차이

ReactiveFallback 내부에 Sequence가 배치된 경우, 매 Tick마다 앞쪽 조건이 재평가된다.

<ReactiveFallback>
    <Sequence>
        <Condition ID="IsFastPathClear"/>
        <Action ID="UseFastPath"/>
    </Sequence>
    <Action ID="UseSlowPath"/>
</ReactiveFallback>

UseSlowPath 진행 중 빠른 경로가 정리되면, 다음 Tick에서 IsFastPathClear가 SUCCESS를 반환하여 UseSlowPath가 Halt되고 UseFastPath로 전환된다. 이 동적 전환은 FallbackWithMemory에서는 불가능하다(Faconti, 2022).


참고 문헌

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