1294.87 XML에서의 Sequence 노드 정의

1. BehaviorTree.CPP의 XML 기반 트리 정의

BehaviorTree.CPP는 행동 트리를 XML 형식으로 정의할 수 있는 기능을 제공한다. XML 정의는 런타임에 파싱되어 트리 객체로 인스턴스화되므로, C++ 코드를 수정하지 않고 트리 구조를 변경할 수 있다. Sequence 노드와 그 변형은 미리 정의된 XML 태그를 통해 선언된다(Faconti, 2022).

2. Sequence 노드의 XML 태그

2.1 기본 Sequence (SequenceWithMemory)

<Sequence name="optional_name">
    <!-- 자식 노드들 -->
</Sequence>

<Sequence> 태그는 BehaviorTree.CPP v4의 SequenceNode 클래스에 매핑된다. 이 노드는 SequenceWithMemory 동작을 수행한다. name 속성은 선택적이며, 디버깅과 로깅을 위한 식별자로 사용된다.

2.2 ReactiveSequence

<ReactiveSequence name="optional_name">
    <!-- 자식 노드들 -->
</ReactiveSequence>

<ReactiveSequence> 태그는 ReactiveSequence 클래스에 매핑되며, 매 Tick 첫 번째 자식부터 재평가하는 비상태적 Sequence를 정의한다.

3. XML 정의의 기본 구조

3.1 완전한 트리 정의

<?xml version="1.0"?>
<root BTCPP_format="4">
    <BehaviorTree ID="MainTree">
        <Sequence name="main_sequence">
            <Action ID="Step1"/>
            <Action ID="Step2"/>
            <Action ID="Step3"/>
        </Sequence>
    </BehaviorTree>
</root>

<root> 요소의 BTCPP_format="4" 속성은 BehaviorTree.CPP v4 형식임을 명시한다. <BehaviorTree> 요소의 ID 속성은 트리의 고유 식별자이다.

4. Sequence 노드의 자식 배치

4.1 조건과 행동의 배치

<Sequence>
    <!-- 전제 조건 -->
    <Condition ID="IsPreconditionMet"/>
    <!-- 행동 -->
    <Action ID="PerformAction"/>
    <!-- 후속 행동 -->
    <Action ID="ReportCompletion"/>
</Sequence>

4.2 중첩된 제어 노드의 배치

<Sequence>
    <Action ID="Initialize"/>
    <Fallback>
        <Action ID="PrimaryMethod"/>
        <Action ID="AlternativeMethod"/>
    </Fallback>
    <Action ID="Finalize"/>
</Sequence>

Sequence의 자식으로 다른 제어 노드(Fallback, Sequence 등)를 중첩할 수 있다.

5. 블랙보드 포트와의 연동

5.1 입출력 포트 사용

<Sequence>
    <Action ID="ComputePath"
            goal="{target_goal}"
            path="{computed_path}"/>
    <Action ID="FollowPath"
            path="{computed_path}"/>
</Sequence>

블랙보드 포트는 중괄호 {} 표기법으로 참조한다. {target_goal}은 블랙보드에서 target_goal 키의 값을 읽고, {computed_path}는 출력 포트로 계산된 경로를 블랙보드에 기록한다. Sequence 내의 노드 간 데이터 전달에 활용된다.

6. 서브트리 참조

6.1 SubTree를 이용한 모듈화

<Sequence>
    <SubTree ID="NavigationSubTree"
             goal="{mission_goal}"/>
    <SubTree ID="ManipulationSubTree"
             target="{target_object}"/>
    <Action ID="ReportComplete"/>
</Sequence>

<SubTree> 태그로 다른 트리를 참조하여 Sequence의 자식으로 사용할 수 있다. 이는 복잡한 시퀀스를 서브트리로 분해하여 가독성과 재사용성을 향상시킨다.

7. 데코레이터와의 결합

7.1 Sequence 자식에 데코레이터 적용

<Sequence>
    <Timeout msec="5000">
        <Action ID="NavigateToPose"/>
    </Timeout>
    <Retry num_attempts="3">
        <Action ID="GraspObject"/>
    </Retry>
    <ForceSuccess>
        <Action ID="OptionalStep"/>
    </ForceSuccess>
    <Action ID="DeliverObject"/>
</Sequence>

각 Sequence 자식에 개별적으로 데코레이터를 적용할 수 있다. Timeout은 타임아웃 초과 시 FAILURE를, Retry는 실패 시 재시도를, ForceSuccess는 실패를 무시하는 동작을 추가한다.

8. ReactiveSequence의 XML 패턴

8.1 안전 감시 패턴

<ReactiveSequence>
    <Condition ID="IsBatteryOK"/>
    <Condition ID="IsCommsActive"/>
    <Sequence>
        <Action ID="Step1"/>
        <Action ID="Step2"/>
    </Sequence>
</ReactiveSequence>

외부 ReactiveSequence가 안전 조건을 매 Tick 감시하고, 내부 Sequence(WithMemory)가 순차 작업을 수행한다.

8.2 조건-행동 쌍 패턴

<ReactiveSequence>
    <Condition ID="IsTargetVisible"/>
    <Action ID="TrackTarget"/>
</ReactiveSequence>

9. XML 유효성 검증

9.1 트리 모델에 의한 검증

BehaviorTree.CPP는 XML 파싱 시 다음을 검증한다:

  1. 노드 ID의 유효성: 등록되지 않은 노드 ID가 사용되면 오류를 발생시킨다.
  2. 포트의 유효성: 선언되지 않은 포트가 사용되면 경고 또는 오류를 발생시킨다.
  3. 자식 수: 제어 노드에 자식이 없으면 오류를 발생시킨다.
<!-- 오류: 등록되지 않은 노드 ID -->
<Sequence>
    <Action ID="UnregisteredAction"/>    <!-- 오류 발생 -->
</Sequence>

10. XML 정의 시 주의 사항

  1. 태그명의 정확성: <Sequence><ReactiveSequence>는 서로 다른 클래스에 매핑되므로, 의도한 동작에 맞는 태그를 사용해야 한다.

  2. 자식 순서의 중요성: XML에서 자식 요소의 순서가 Sequence의 실행 순서를 결정한다. 좌→우 평가 순서가 XML의 상→하 순서에 대응한다.

  3. v4 형식 명시: BTCPP_format="4" 속성을 반드시 명시하여, v3과의 호환성 문제를 방지한다(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/