1297.26 범위 검사 조건 노드의 구현

1. 범위 검사의 정의

범위 검사 조건 노드(range check condition node)는 블랙보드에서 읽은 값이 지정된 하한(lower bound)과 상한(upper bound) 사이에 있는지를 판정하는 조건 노드이다. 값 v, 하한 l, 상한 u에 대하여 l \leq v \leq u이면 SUCCESS를, 그렇지 않으면 FAILURE를 반환한다(Colledanchise & Ogren, 2018).

범위 검사는 로봇공학에서 센서 값의 정상 범위 확인, 관절 각도의 허용 한계 확인, 속도/고도/온도 등의 운용 범위 검증에 광범위하게 사용된다. 단일 임계값 비교(부등호 비교)와 달리, 상한과 하한을 동시에 검사하므로 하나의 노드로 양방향 경계를 검증할 수 있다.

2. 폐구간 범위 검사 구현

가장 일반적인 형태인 폐구간(closed interval) 범위 검사 [l, u]의 구현이다. 경계값 자체가 허용 범위에 포함된다.

class IsValueInRange : public BT::ConditionNode
{
public:
    IsValueInRange(const std::string& name, const BT::NodeConfig& config)
        : BT::ConditionNode(name, config) {}

    BT::NodeStatus tick() override
    {
        double value;
        auto result = getInput("value", value);
        if (!result)
        {
            return BT::NodeStatus::FAILURE;
        }

        double min_val, max_val;
        getInput("min", min_val);
        getInput("max", max_val);

        return (value >= min_val && value <= max_val)
            ? BT::NodeStatus::SUCCESS
            : BT::NodeStatus::FAILURE;
    }

    static BT::PortsList providedPorts()
    {
        return {
            BT::InputPort<double>("value", "검사 대상 값"),
            BT::InputPort<double>("min", "하한값"),
            BT::InputPort<double>("max", "상한값")
        };
    }
};

3. 개구간 및 반개구간 범위 검사

경계값의 포함 여부에 따라 네 가지 구간 유형이 존재한다:

구간 유형수학 표기조건경계값 포함
폐구간[l, u]l \leq v \leq u양쪽 포함
개구간(l, u)l < v < u양쪽 제외
반개구간 (좌개)(l, u]l < v \leq u상한만 포함
반개구간 (우개)[l, u)l \leq v < u하한만 포함

구간 유형을 매개변수로 지정할 수 있는 확장 구현은 다음과 같다:

class IsValueInRangeEx : public BT::ConditionNode
{
public:
    IsValueInRangeEx(const std::string& name, const BT::NodeConfig& config)
        : BT::ConditionNode(name, config) {}

    BT::NodeStatus tick() override
    {
        double value, min_val, max_val;
        auto result = getInput("value", value);
        if (!result)
        {
            return BT::NodeStatus::FAILURE;
        }
        getInput("min", min_val);
        getInput("max", max_val);

        bool include_min, include_max;
        getInput("include_min", include_min);
        getInput("include_max", include_max);

        bool above_min = include_min ? (value >= min_val) : (value > min_val);
        bool below_max = include_max ? (value <= max_val) : (value < max_val);

        return (above_min && below_max)
            ? BT::NodeStatus::SUCCESS
            : BT::NodeStatus::FAILURE;
    }

    static BT::PortsList providedPorts()
    {
        return {
            BT::InputPort<double>("value", "검사 대상 값"),
            BT::InputPort<double>("min", "하한값"),
            BT::InputPort<double>("max", "상한값"),
            BT::InputPort<bool>("include_min", true, "하한 포함 여부 (기본값: true)"),
            BT::InputPort<bool>("include_max", true, "상한 포함 여부 (기본값: true)")
        };
    }
};

4. XML에서의 활용

<Sequence>
    <!-- 온도가 10~40°C 범위인지 확인 -->
    <Condition ID="IsValueInRange"
        value="{temperature}" min="10.0" max="40.0"/>

    <!-- 고도가 10~120m 범위인지 확인 -->
    <Condition ID="IsValueInRange"
        value="{altitude}" min="10.0" max="120.0"/>

    <!-- 속도가 0~2.0 m/s 범위인지 확인 -->
    <Condition ID="IsValueInRange"
        value="{speed}" min="0.0" max="2.0"/>

    <Action ID="Execute"/>
</Sequence>

동적 범위 설정이 필요한 경우 하한과 상한을 블랙보드 키로 매핑한다:

<Condition ID="IsValueInRange"
    value="{joint_angle}"
    min="{joint_min_limit}"
    max="{joint_max_limit}"/>

5. 범위 외 검사 (Out-of-Range)

값이 범위 밖에 있는지를 판정하는 역조건도 필요한 경우가 있다. 이는 범위 검사 노드에 Inverter 데코레이터를 적용하여 구현할 수 있다:

<Inverter>
    <Condition ID="IsValueInRange"
        value="{temperature}" min="0.0" max="80.0"/>
</Inverter>

또는 전용 범위 외 검사 노드를 구현할 수 있다:

class IsValueOutOfRange : public BT::ConditionNode
{
public:
    IsValueOutOfRange(const std::string& name, const BT::NodeConfig& config)
        : BT::ConditionNode(name, config) {}

    BT::NodeStatus tick() override
    {
        double value, min_val, max_val;
        auto result = getInput("value", value);
        if (!result)
        {
            return BT::NodeStatus::FAILURE;
        }
        getInput("min", min_val);
        getInput("max", max_val);

        return (value < min_val || value > max_val)
            ? BT::NodeStatus::SUCCESS
            : BT::NodeStatus::FAILURE;
    }

    static BT::PortsList providedPorts()
    {
        return {
            BT::InputPort<double>("value", "검사 대상 값"),
            BT::InputPort<double>("min", "하한값"),
            BT::InputPort<double>("max", "상한값")
        };
    }
};

6. 비정상 입력 처리

6.1 NaN 및 Inf 검사

부동소수점 값이 NaN이나 Inf인 경우, 범위 검사 전에 유효성을 확인해야 한다. NaN과의 비교는 IEEE 754 표준에 따라 항상 거짓을 반환하므로 범위 검사가 의도대로 동작하지 않을 수 있다.

BT::NodeStatus tick() override
{
    double value, min_val, max_val;
    auto result = getInput("value", value);
    if (!result)
    {
        return BT::NodeStatus::FAILURE;
    }

    // NaN 및 Inf 검사
    if (std::isnan(value) || std::isinf(value))
    {
        return BT::NodeStatus::FAILURE;
    }

    getInput("min", min_val);
    getInput("max", max_val);

    return (value >= min_val && value <= max_val)
        ? BT::NodeStatus::SUCCESS
        : BT::NodeStatus::FAILURE;
}

6.2 역전된 범위 검사

하한이 상한보다 큰 경우(l > u)는 범위가 역전된 비정상 상태이다. 이 상황을 방어적으로 처리한다:

if (min_val > max_val)
{
    return BT::NodeStatus::FAILURE;
}

7. 정수형 범위 검사

정수(int) 타입에 대한 범위 검사도 동일한 패턴으로 구현된다. 부동소수점 오차 문제가 없으므로 경계값 처리가 명확하다.

class IsIntInRange : public BT::ConditionNode
{
public:
    IsIntInRange(const std::string& name, const BT::NodeConfig& config)
        : BT::ConditionNode(name, config) {}

    BT::NodeStatus tick() override
    {
        int value, min_val, max_val;
        auto result = getInput("value", value);
        if (!result) return BT::NodeStatus::FAILURE;
        getInput("min", min_val);
        getInput("max", max_val);

        return (value >= min_val && value <= max_val)
            ? BT::NodeStatus::SUCCESS
            : BT::NodeStatus::FAILURE;
    }

    static BT::PortsList providedPorts()
    {
        return {
            BT::InputPort<int>("value", "검사 대상 정수 값"),
            BT::InputPort<int>("min", "하한값"),
            BT::InputPort<int>("max", "상한값")
        };
    }
};

8. 로봇공학에서의 범위 검사 적용 사례

적용 분야검사 대상하한상한단위
관절 제어관절 각도관절 최소 한계관절 최대 한계rad
내비게이션로봇 속도0.0최대 허용 속도m/s
드론 비행비행 고도최저 안전 고도최대 허용 고도m
환경 감시센서 온도운용 최저 온도운용 최고 온도°C
전원 관리공급 전압최소 동작 전압최대 허용 전압V
매니퓰레이션파지 힘최소 파지 힘최대 안전 힘N

이러한 범위 검사는 로봇 시스템의 안전 운용을 보장하는 핵심 조건으로, 행동 트리의 ReactiveSequence와 결합하여 실시간으로 지속 감시되는 것이 일반적이다.

9. 참고 문헌

  • Colledanchise, M., & Ogren, P. (2018). Behavior Trees in Robotics and AI: An Introduction. CRC Press.
  • Faconti, D., & Colledanchise, M. (2022). BehaviorTree.CPP Documentation. https://www.behaviortree.dev/

version: 0.1.0