BehaviorTree.CPP에서의 데코레이터 구현 (Decorator Implementation in BehaviorTree.CPP)
1. 개요
BehaviorTree.CPP 라이브러리는 데코레이터 노드를 구현하기 위한 BT::DecoratorNode 기반 클래스를 제공하며, 다양한 내장 데코레이터와 사용자 정의 데코레이터 확장 메커니즘을 지원한다. 본 절에서는 BehaviorTree.CPP에서의 데코레이터 구현 체계, 기반 클래스 인터페이스, 내장 데코레이터, XML 정의, 등록 방법을 다룬다.
2. DecoratorNode 기반 클래스
2.1 클래스 계층
BT::TreeNode (최상위)
└── BT::DecoratorNode (데코레이터 기반)
├── BT::InverterNode
├── BT::ForceSuccessNode
├── BT::ForceFailureNode
├── BT::RepeatNode
├── BT::RetryNode
├── BT::TimeoutNode
├── BT::DelayNode
├── BT::RunOnce
├── BT::KeepRunningUntilFailure
└── 사용자 정의 데코레이터
2.2 DecoratorNode의 핵심 인터페이스
class DecoratorNode : public TreeNode
{
public:
DecoratorNode(const std::string& name,
const NodeConfiguration& config);
// 자식 노드 설정
void setChild(TreeNode* child);
// 자식 접근
TreeNode* child();
const TreeNode* child() const;
// halt: 자식의 halt를 호출하고 자신을 IDLE로 설정
virtual void halt() override;
protected:
// 자식이 RUNNING이면 halt 호출
void haltChild();
TreeNode* child_node_;
};
2.3 tick() 메서드의 구현 패턴
사용자 정의 데코레이터는 tick() 메서드를 오버라이드하여 구현한다.
class MyDecorator : public BT::DecoratorNode
{
public:
MyDecorator(const std::string& name,
const BT::NodeConfiguration& config)
: DecoratorNode(name, config) {}
static BT::PortsList providedPorts()
{
return { /* 입력/출력 포트 정의 */ };
}
private:
BT::NodeStatus tick() override
{
// 1. 전처리 (선택)
// 2. 자식 tick: child_node_->executeTick()
// 3. 후처리: 반환 상태 변환 (선택)
// 4. 결과 반환
}
void halt() override
{
// 내부 상태 초기화
DecoratorNode::halt();
}
};
3. BehaviorTree.CPP 내장 데코레이터 목록
| 데코레이터 | XML 이름 | 주요 매개변수 |
|---|---|---|
| InverterNode | Inverter | 없음 |
| ForceSuccessNode | ForceSuccess | 없음 |
| ForceFailureNode | ForceFailure | 없음 |
| RepeatNode | Repeat | num_cycles |
| RetryNode | RetryNode | num_attempts |
| TimeoutNode | Timeout | msec |
| DelayNode | Delay | delay_msec |
| RunOnce | RunOnce | then_skip |
| KeepRunningUntilFailure | KeepRunningUntilFailure | 없음 |
4. XML에서의 데코레이터 정의
4.1 기본 사용
<Inverter>
<Action ID="MyAction"/>
</Inverter>
<Timeout msec="5000">
<Action ID="LongRunningAction"/>
</Timeout>
<RetryNode num_attempts="3">
<Action ID="UnreliableAction"/>
</RetryNode>
4.2 스크립트 속성 기반 데코레이터
<Action ID="Navigate"
_skipIf="goal_reached == true"
_onSuccess="navigation_complete = true"/>
5. 커스텀 데코레이터의 등록
BT::BehaviorTreeFactory factory;
// 방법 1: 일반 등록
factory.registerNodeType<MyDecorator>("MyDecorator");
// 방법 2: 매개변수와 함께 등록
factory.registerNodeType<MyDecorator>(
"MyDecorator", params);
6. 설계 시 고려 사항
6.1 executeTick() vs tick()
자식을 tick할 때 child_node_->executeTick()을 사용하여야 한다. tick()을 직접 호출하면 노드의 상태 관리 로직이 누락된다.
6.2 halt()의 올바른 구현
커스텀 데코레이터의 halt()에서는 내부 상태를 초기화하고, 기반 클래스의 halt()를 호출하여야 한다. 기반 클래스의 halt()가 자식의 halt를 처리한다.
7. 참고 문헌
- BehaviorTree.CPP 공식 문서. https://www.behaviortree.dev/
- Colledanchise, M., & Ogren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
| 버전 | 날짜 | 변경 사항 |
|---|---|---|
| v0.1 | 2026-04-05 | 초안 작성 |