ForceSuccess 데코레이터의 동작 (Operation of the ForceSuccess Decorator)

ForceSuccess 데코레이터의 동작 (Operation of the ForceSuccess Decorator)

1. 개요

ForceSuccess 데코레이터는 자식 노드의 반환 상태가 FAILURE이더라도 이를 SUCCESS로 변환하여 부모 노드에 전달하는 데코레이터이다. 자식이 SUCCESS를 반환하면 그대로 SUCCESS를 전달하며, RUNNING은 변환하지 않고 통과시킨다. 이 데코레이터는 자식 행동의 실패가 전체 행동 트리의 흐름에 영향을 미치지 않아야 하는 경우, 즉 선택적(optional) 행동의 실패를 무시하는 데 활용된다.

2. 상태 변환 규칙

2.1 변환 테이블

자식 반환ForceSuccess 반환변환 여부
SUCCESSSUCCESS통과
FAILURESUCCESS변환
RUNNINGRUNNING통과

2.2 수학적 표현

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

구현

class ForceSuccessNode : public BT::DecoratorNode
{
public:
    ForceSuccessNode(const std::string& name)
        : DecoratorNode(name, {})
    {}

    BT::NodeStatus tick() override
    {
        setStatus(BT::NodeStatus::RUNNING);
        auto child_status = child_node_->executeTick();

        if (child_status == BT::NodeStatus::RUNNING)
        {
            return BT::NodeStatus::RUNNING;
        }
        return BT::NodeStatus::SUCCESS;
    }
};

활용 사례

Sequence 내 선택적 단계

Sequence 내에서 특정 단계의 실패가 전체 시퀀스를 중단시키지 않도록 한다.

<Sequence>
    <Action ID="MoveToTarget"/>
    <ForceSuccess>
        <Action ID="TakePicture"/>  <!-- 실패해도 계속 -->
    </ForceSuccess>
    <Action ID="ReturnToBase"/>
</Sequence>

사진 촬영에 실패하더라도 기지 귀환은 수행된다.

선택적 센서 초기화

<Sequence>
    <Action ID="InitializeMainSensor"/>
    <ForceSuccess>
        <Action ID="InitializeAuxSensor"/>
    </ForceSuccess>
    <Action ID="StartMission"/>
</Sequence>

보조 센서 초기화가 실패하더라도 임무를 시작한다.

로깅/알림 행동의 실패 무시

<Sequence>
    <Action ID="PerformTask"/>
    <ForceSuccess>
        <Action ID="SendNotification"/>
    </ForceSuccess>
</Sequence>

알림 전송의 실패가 작업 결과에 영향을 미치지 않도록 한다.

Fallback의 모든 분기 시도

<Sequence>
    <ForceSuccess>
        <Action ID="TryOptimizedPath"/>
    </ForceSuccess>
    <Action ID="FollowStandardPath"/>
</Sequence>

최적화된 경로를 시도하되, 실패하더라도 표준 경로로 진행한다.

Inverter와의 비교

특성InverterForceSuccess
SUCCESS 입력FAILURESUCCESS
FAILURE 입력SUCCESSSUCCESS
변환 방향양방향 반전단방향 (FAILURE→SUCCESS)
정보 보존결과 의미 반전실패 정보 소실
용도NOT 논리 연산실패 무시

ForceSuccess는 자식의 성공/실패 구분을 제거하여 항상 성공으로 간주하므로, 자식의 실패 정보가 손실된다. 실패 원인을 추적하여야 하는 경우에는 로깅을 병행하여야 한다.

설계 시 주의 사항

안전 행동에 적용 금지

안전에 중요한 행동에 ForceSuccess를 적용하면, 행동의 실패가 은폐되어 위험한 상태가 정상으로 인식될 수 있다.

<!-- 안티패턴: 안전 행동의 실패를 무시 -->
<ForceSuccess>
    <Action ID="ActivateSafetyBrake"/>  <!-- 위험! -->
</ForceSuccess>

디버깅 어려움

ForceSuccess에 의해 실패가 성공으로 변환되면, 문제 발생 시 원인 추적이 어려워진다. ForceSuccess로 감싼 행동에는 실패 시 로깅을 추가하여 디버깅을 지원하는 것이 바람직하다.

RUNNING 상태의 보존

ForceSuccessRUNNING 상태를 변환하지 않고 통과시킨다. 자식이 비동기적으로 실행 중인 동안에는 RUNNING이 전달되며, 자식이 최종적으로 SUCCESS 또는 FAILURE를 반환할 때에만 SUCCESS로 변환된다.

참고 문헌

  • 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초안 작성