커스텀 데코레이터의 기반 클래스 상속 (Custom Decorator’s Base Class Inheritance)
1. 개요
커스텀 데코레이터는 BT::DecoratorNode를 상속하여 구현한다. 기반 클래스는 단일 자식 관리, halt 전파, 상태 관리 등의 공통 기능을 제공하며, 파생 클래스는 tick() 메서드를 구현하여 데코레이터의 동작을 정의한다.
2. 상속 구조
#include <behaviortree_cpp/decorator_node.h>
class CooldownDecorator : public BT::DecoratorNode
{
public:
CooldownDecorator(const std::string& name,
const BT::NodeConfiguration& config)
: BT::DecoratorNode(name, config),
last_success_time_(std::chrono::steady_clock::time_point::min())
{}
static BT::PortsList providedPorts()
{
return {
BT::InputPort<double>("cooldown_sec", 5.0,
"쿨다운 시간 (초)")
};
}
private:
BT::NodeStatus tick() override;
void halt() override;
std::chrono::steady_clock::time_point last_success_time_;
};
3. 생성자의 규약
3.1 필수 매개변수
커스텀 데코레이터의 생성자는 반드시 const std::string& name과 const BT::NodeConfiguration& config를 매개변수로 받아야 한다. 이 서명은 BT::BehaviorTreeFactory::registerNodeType()이 기대하는 형태이다.
// 올바른 생성자 서명
MyDecorator(const std::string& name,
const BT::NodeConfiguration& config);
// 추가 매개변수가 필요한 경우
MyDecorator(const std::string& name,
const BT::NodeConfiguration& config,
rclcpp::Node::SharedPtr ros_node);
3.2 추가 매개변수
ROS2 노드 등 추가 매개변수가 필요한 경우, registerNodeType()의 가변 인자를 통해 전달한다.
factory.registerNodeType<MyDecorator>(
"MyDecorator", ros_node);
4. 기반 클래스가 제공하는 기능
| 기능 | 메서드 | 설명 |
|---|---|---|
| 자식 설정 | setChild() | 팩토리가 자동 호출 |
| 자식 접근 | child(), child_node_ | 자식 포인터 반환 |
| 자식 halt | haltChild() | RUNNING 상태의 자식 halt |
| halt | halt() | 자식 halt + 자신 IDLE 전환 |
| 노드 타입 | type() | NodeType::DECORATOR 반환 |
5. 설계 시 고려 사항
5.1 virtual 키워드
tick()과 halt()는 기반 클래스에서 virtual로 선언되어 있으므로, 파생 클래스에서 override 키워드를 사용하여 오버라이드한다.
5.2 내부 상태의 초기화
생성자에서 모든 내부 상태 변수를 명시적으로 초기화한다. 초기화되지 않은 변수는 첫 번째 tick에서 예측 불가능한 동작을 초래할 수 있다.
6. 참고 문헌
- BehaviorTree.CPP 공식 문서. https://www.behaviortree.dev/
| 버전 | 날짜 | 변경 사항 |
|---|---|---|
| v0.1 | 2026-04-05 | 초안 작성 |