1295.77 XML에서의 ReactiveSequence 노드 정의
1. XML 기본 구문
BehaviorTree.CPP에서 ReactiveSequence 노드는 <ReactiveSequence> 태그로 정의한다.
<BehaviorTree ID="ReactiveSequenceBasic">
<ReactiveSequence>
<ConditionNode_1 />
<ConditionNode_2 />
<ActionNode />
</ReactiveSequence>
</BehaviorTree>
ReactiveSequence는 추가 속성(파라미터)을 필요로 하지 않으므로, 태그 내에 자식 노드만을 나열한다. 자식의 나열 순서가 평가 순서를 결정하며, 앞에 위치한 자식이 먼저 평가된다.
2. name 속성
디버깅과 로깅을 위해 name 속성을 부여할 수 있다.
<ReactiveSequence name="SafeNavigation">
<IsSafe name="CheckSafety" />
<IsLocalized name="CheckLocalization" />
<NavigateToGoal name="GoToTarget" goal="{target}" />
</ReactiveSequence>
name 속성은 Groot2 시각화 도구와 로그 파일에서 노드를 식별하는 데 사용된다.
3. 전형적 배치 패턴
3.1 단일 조건 + 단일 행동
가장 기본적인 패턴으로, 하나의 조건이 유지되는 동안 하나의 행동을 수행한다.
<ReactiveSequence>
<IsBatteryOK threshold="20.0" />
<ExecuteMission waypoints="{mission_waypoints}" />
</ReactiveSequence>
3.2 다중 조건 + 단일 행동
복수의 전제 조건이 모두 충족되는 동안 행동을 수행한다.
<ReactiveSequence>
<IsHardwareHealthy />
<IsLocalizationValid min_confidence="0.8" />
<IsPathClear lookahead_distance="3.0" />
<FollowPath path="{planned_path}" controller_id="FollowPath" />
</ReactiveSequence>
조건 노드는 좌에서 우로(위에서 아래로) 순차 평가된다. 가장 근본적이거나 가장 빈번히 변동하는 조건을 앞에 배치한다.
3.3 조건 + 서브트리 행동
복잡한 행동을 서브트리로 분리하여 배치한다.
<ReactiveSequence>
<IsSafe />
<SubTree ID="ComplexMission" />
</ReactiveSequence>
4. 중첩 구조의 XML 표현
4.1 ReactiveSequence 내부에 Sequence
<ReactiveSequence>
<IsSafe />
<Sequence>
<PrepareAction />
<ExecuteAction />
<FinalizeAction />
</Sequence>
</ReactiveSequence>
안전 조건이 매 Tick에서 재평가되고, 내부 Sequence는 메모리를 가지므로 PrepareAction 완료 후 ExecuteAction으로 진행한다. 안전 조건 위반 시 전체 Sequence에 Halt가 전파된다.
4.2 ReactiveSequence 내부에 Parallel
<ReactiveSequence>
<IsLocalized />
<ParallelAll max_failures="0">
<NavigateToGoal goal="{target}" />
<MapEnvironment />
</ParallelAll>
</ReactiveSequence>
위치 추정이 유효한 동안 이동과 매핑을 동시에 수행한다.
4.3 ReactiveSequence 내부에 ReactiveFallback
<ReactiveSequence>
<IsHardwareNormal />
<ReactiveFallback>
<Sequence>
<IsBatteryLow />
<ReturnToBase />
</Sequence>
<ExecuteMission waypoints="{waypoints}" />
</ReactiveFallback>
</ReactiveSequence>
하드웨어 정상 조건 하에서, 배터리 상태에 따른 행동 선택을 수행한다.
5. Nav2에서의 실제 사용 예시
ROS2 Nav2의 기본 행동 트리에서 ReactiveSequence가 사용되는 실제 예시이다.
<!-- Nav2 navigate_to_pose_w_replanning_and_recovery.xml 발췌 -->
<BehaviorTree ID="NavigateWithReplanning">
<PipelineSequence>
<RateController hz="1.0">
<ComputePathToPose goal="{goal}" path="{path}"
planner_id="GridBased" />
</RateController>
<ReactiveSequence>
<PathValid path="{path}" />
<FollowPath path="{path}" controller_id="FollowPath" />
</ReactiveSequence>
</PipelineSequence>
</BehaviorTree>
PathValid 조건이 매 Tick에서 재평가되어, 경로가 무효화되면 FollowPath가 Halt된다. 상위의 PipelineSequence가 경로 재계획을 수행한다.
6. 조건 노드의 XML 정의
ReactiveSequence에서 사용되는 조건 노드는 SUCCESS 또는 FAILURE만을 반환하도록 구현되어야 한다. XML에서 조건 노드의 포트를 통해 임계값이나 파라미터를 설정한다.
<ReactiveSequence>
<!-- 조건 노드: 포트를 통한 파라미터 설정 -->
<IsBatteryAbove threshold="15.0" />
<IsLocalizationConfident min_confidence="0.7"
max_covariance="0.5" />
<IsObstacleFree scan_topic="/scan"
min_distance="0.5" />
<!-- 행동 노드 -->
<NavigateToGoal goal="{target_position}" />
</ReactiveSequence>
7. BehaviorTree.CPP 4.x의 스크립팅 조건
BehaviorTree.CPP 4.x에서는 <Script> 태그와 사전/사후 조건을 통해 간단한 조건을 인라인으로 정의할 수 있다.
<ReactiveSequence>
<Script code="battery_ok := battery_level > 20.0" />
<Precondition if="battery_ok" else="FAILURE">
<NavigateToGoal goal="{target}" />
</Precondition>
</ReactiveSequence>
다만, 이 방식은 복잡한 조건에는 적합하지 않으며, 전용 조건 노드를 구현하는 것이 일반적이다.
8. XML 정의의 모범 사례
-
조건 노드에 의미 있는 이름 부여:
<IsSafe />대신<IsSafe name="CollisionSafetyCheck" />처럼 구체적인 이름을 부여하여 디버깅을 용이하게 하라. -
조건의 순서를 문서화: XML 주석으로 조건의 배치 순서와 근거를 기록하라.
<ReactiveSequence> <!-- 하드웨어 안전 (가장 근본적) --> <IsHardwareHealthy /> <!-- 위치 추정 유효성 (하드웨어 정상 전제) --> <IsLocalized /> <!-- 경로 장애물 (위치 추정 전제) --> <IsPathClear /> <!-- 주 행동 --> <NavigateToGoal goal="{target}" /> </ReactiveSequence>
3. **복잡한 하위 트리는 서브트리로 분리**: ReactiveSequence의 마지막 자식이 복잡해지면 서브트리로 분리하여 가독성을 유지하라.