데코레이터 노드의 반환 상태 변환 역할 (Return Status Transformation Role of Decorator Nodes)

데코레이터 노드의 반환 상태 변환 역할 (Return Status Transformation Role of Decorator Nodes)

1. 개요

데코레이터 노드의 반환 상태 변환 역할은 자식 노드가 반환한 상태(SUCCESS, FAILURE, RUNNING)를 다른 상태로 변환하여 부모 노드에 전달하는 기능이다. 이 변환을 통해 자식 노드의 코드를 수정하지 않고도 행동 트리의 논리적 흐름을 조정할 수 있다. 상태 변환은 데코레이터의 가장 기본적인 기능이며, 조건 반전, 실패 무시, 강제 결과 설정 등에 활용된다.

2. 상태 변환 유형

2.1 Inverter (반전)

자식의 SUCCESSFAILURE로, FAILURESUCCESS로 반전한다. RUNNING은 변환하지 않는다.

자식 상태Inverter 반환
SUCCESSFAILURE
FAILURESUCCESS
RUNNINGRUNNING
<Inverter>
    <Condition ID="IsObstacleDetected"/>
</Inverter>

NOT 논리 연산의 구현에 사용된다.

2.2 ForceSuccess (강제 성공)

자식의 상태에 관계없이 항상 SUCCESS를 반환한다(자식이 RUNNING인 경우는 예외).

자식 상태ForceSuccess 반환
SUCCESSSUCCESS
FAILURESUCCESS
RUNNINGRUNNING
<ForceSuccess>
    <Action ID="OptionalCleanup"/>
</ForceSuccess>

선택적 행동의 실패가 전체 시퀀스를 중단시키지 않도록 하는 데 사용된다.

2.3 ForceFailure (강제 실패)

자식의 상태에 관계없이 항상 FAILURE를 반환한다.

자식 상태ForceFailure 반환
SUCCESSFAILURE
FAILUREFAILURE
RUNNINGRUNNING

3. 상태 변환의 형식적 표현

상태 변환 함수 f_D는 다음과 같이 정의된다.

f_{\text{Inverter}}(s) = \begin{cases} \text{FAILURE} & \text{if } s = \text{SUCCESS} \\ \text{SUCCESS} & \text{if } s = \text{FAILURE} \\ \text{RUNNING} & \text{if } s = \text{RUNNING} \end{cases}

f_{\text{ForceSuccess}}(s) = \begin{cases} \text{SUCCESS} & \text{if } s \neq \text{RUNNING} \\ \text{RUNNING} & \text{if } s = \text{RUNNING} \end{cases}

4. 실용적 활용

4.1 Sequence에서의 선택적 단계

<Sequence>
    <Action ID="Step1"/>
    <ForceSuccess>
        <Action ID="OptionalStep2"/>
    </ForceSuccess>
    <Action ID="Step3"/>
</Sequence>

OptionalStep2가 실패하더라도 ForceSuccess에 의해 SUCCESS로 변환되므로, Step3가 계속 실행된다.

4.2 Fallback에서의 조건 반전 결합

<Fallback>
    <Sequence>
        <Inverter>
            <Condition ID="IsNightTime"/>
        </Inverter>
        <Action ID="DaytimeOperation"/>
    </Sequence>
    <Action ID="NighttimeOperation"/>
</Fallback>

낮 시간이면 주간 운용, 밤 시간이면 야간 운용을 실행한다.

5. 사용자 정의 상태 변환

5.1 조건부 변환

특정 조건에서만 상태를 변환하는 사용자 정의 데코레이터이다.

class ConditionalInverter : public BT::DecoratorNode
{
public:
    ConditionalInverter(const std::string& name,
                        const BT::NodeConfiguration& config)
        : BT::DecoratorNode(name, config)
    {}

    static BT::PortsList providedPorts()
    {
        return {BT::InputPort<bool>("invert", true,
                "반전 활성화 여부")};
    }

    BT::NodeStatus tick() override
    {
        auto status = child_node_->executeTick();

        bool should_invert;
        getInput("invert", should_invert);

        if (should_invert && status != BT::NodeStatus::RUNNING)
        {
            return (status == BT::NodeStatus::SUCCESS)
                       ? BT::NodeStatus::FAILURE
                       : BT::NodeStatus::SUCCESS;
        }
        return status;
    }
};

6. 설계 시 고려 사항

6.1 RUNNING 상태의 보존

대부분의 상태 변환 데코레이터는 RUNNING 상태를 변환하지 않고 그대로 전달한다. RUNNING을 변환하면 자식의 비동기 실행이 부모에게 올바르게 전달되지 않아 행동 트리의 실행 흐름이 파괴될 수 있다.

6.2 의미론적 명확성

상태 변환의 의미가 행동 트리의 컨텍스트에서 명확하여야 한다. ForceSuccess로 감싼 액션이 실패하였을 때, 그 실패가 무시되어도 안전한지를 신중히 판단하여야 한다.

7. 참고 문헌

  • Colledanchise, M., & Ogren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
  • BehaviorTree.CPP 공식 문서. https://www.behaviortree.dev/

버전날짜변경 사항
v0.12026-04-04초안 작성