1297.2 조건 노드와 액션 노드의 구분

1. 리프 노드의 두 가지 유형

행동 트리(Behavior Tree)의 리프 노드(leaf node)는 조건 노드(Condition Node)와 액션 노드(Action Node)로 분류된다. 두 노드 유형은 모두 트리의 말단에 위치하여 자식 노드를 갖지 않으며, 부모 제어 노드로부터 tick 신호를 수신하여 동작한다는 공통점을 지닌다. 그러나 이 두 노드는 목적, 반환 상태, 부작용(side effect), 실행 시간의 관점에서 본질적으로 구별된다(Colledanchise & Ogren, 2018).

2. 목적의 차이

2.1 조건 노드: 상태 질의

조건 노드의 목적은 환경이나 시스템의 현재 상태를 **질의(query)**하는 것이다. 조건 노드는 “배터리가 충분한가?”, “장애물이 존재하는가?”, “목표 지점에 도달하였는가?“와 같은 논리적 명제를 평가한다. 이 과정에서 조건 노드는 외부 환경이나 내부 상태를 변경하지 않으며, 오직 현재 상태에 대한 참/거짓 판정만을 수행한다.

2.2 액션 노드: 상태 변경

액션 노드의 목적은 로봇이나 환경의 상태를 **변경(mutation)**하는 것이다. 목표 지점으로의 이동, 그리퍼의 개폐, 메시지의 발행, 경로의 계산 등이 액션 노드의 대표적인 동작이다. 액션 노드는 실행 과정에서 로봇의 물리적 상태, 블랙보드의 데이터, 외부 시스템의 상태 등을 의도적으로 변경한다.

3. 반환 상태의 차이

행동 트리의 노드는 SUCCESS, FAILURE, RUNNING의 세 가지 상태(NodeStatus)를 반환할 수 있다. 조건 노드와 액션 노드는 이 반환 상태의 사용 범위에서 명확히 구별된다.

특성조건 노드액션 노드
SUCCESS 반환조건 충족 시행동 성공 완료 시
FAILURE 반환조건 미충족 시행동 실패 시
RUNNING 반환반환 불가행동 진행 중 반환 가능

조건 노드는 반드시 SUCCESS 또는 FAILURE를 즉시 반환해야 하며, RUNNING 상태를 반환하는 것은 금지된다. 이는 조건 평가가 비동기적 대기 없이 현재 tick 내에서 완료되어야 함을 의미한다. 반면, 액션 노드는 장시간 소요되는 동작(예: 내비게이션, 매니퓰레이션)을 수행할 때 RUNNING을 반환하여 다음 tick에서 실행을 계속할 수 있다.

4. 부작용의 유무

4.1 조건 노드의 부작용 금지

조건 노드는 순수 함수(pure function)와 유사하게 동작해야 한다. 동일한 입력 상태에 대하여 항상 동일한 결과를 반환하며, 블랙보드 값의 변경, 토픽 메시지의 발행, 서비스 호출을 통한 상태 변경 등의 부작용을 발생시키지 않아야 한다. 이 원칙은 조건 노드가 반응적 제어 노드(ReactiveSequence, ReactiveFallback) 하위에서 매 tick마다 반복적으로 평가되는 상황에서 특히 중요하다. 부작용이 존재하면 반복 평가 시 예기치 않은 상태 변화가 누적될 수 있다.

4.2 액션 노드의 의도적 부작용

액션 노드는 본질적으로 부작용을 수반한다. 로봇의 이동, 센서의 활성화, 데이터의 기록, 블랙보드 값의 갱신 등은 모두 의도된 부작용이다. 액션 노드의 설계에서는 부작용의 범위를 명확히 정의하고, 중단(halt) 시 부작용의 정리(cleanup)를 적절히 수행하는 것이 중요하다.

5. 실행 시간의 차이

조건 노드는 단일 tick 내에서 즉시 완료되어야 한다. 센서 값의 비교, 블랙보드 변수의 확인, 논리 연산 등은 계산 복잡도가 낮은 연산으로 구성되며, 밀리초 이하의 시간에 완료되는 것이 일반적이다. 조건 평가에 네트워크 통신이나 파일 입출력과 같은 차단적(blocking) 연산이 포함되면, 전체 행동 트리의 tick 주기가 지연되어 실시간 반응성이 저해된다.

액션 노드는 수 초에서 수 분에 이르는 장시간 동작을 수행할 수 있다. 이러한 동작은 RUNNING 상태를 통해 비동기적으로 처리되며, 각 tick에서 동작의 진행 상태를 확인하여 완료 또는 실패를 판정한다.

6. 중단 처리의 차이

6.1 조건 노드의 halt 비활성화

BehaviorTree.CPP에서 ConditionNode 클래스의 halt() 메서드는 final로 선언되어 재정의가 불가능하며, 노드 상태의 초기화만을 수행한다. 조건 노드는 항상 즉시 완료되므로 진행 중인 동작을 중단할 필요가 없기 때문이다.

// ConditionNode의 halt - 재정의 불가
virtual void halt() override final
{
    resetStatus();
}

6.2 액션 노드의 halt 구현 필요성

액션 노드는 RUNNING 상태에서 중단될 수 있으므로, halt() 메서드를 적절히 구현하여 진행 중인 동작을 안전하게 종료해야 한다. 내비게이션 중단 시 속도 명령을 영점으로 설정하거나, 비동기 요청의 취소, 할당된 자원의 해제 등이 이에 해당한다.

// ActionNode의 halt - 사용자 정의 구현 필요
void halt() override
{
    // 진행 중인 동작의 안전한 종료
    cancel_goal();
    release_resources();
    resetStatus();
}

7. BehaviorTree.CPP에서의 클래스 계층 구조

BehaviorTree.CPP 라이브러리에서 조건 노드와 액션 노드는 모두 LeafNode를 상속하지만, 서로 다른 기반 클래스를 통해 구현된다.

TreeNode
└── LeafNode
    ├── ConditionNode     ← 조건 노드
    ├── ActionNodeBase    ← 액션 노드
    │   ├── SyncActionNode
    │   ├── StatefulActionNode
    │   └── CoroActionNode
    └── ...

ConditionNode는 단일 클래스로 제공되며, 모든 조건 노드가 동일한 실행 모델(즉시 반환, halt 비활성)을 따른다. 반면, ActionNodeBase는 동기(synchronous), 상태 유지(stateful), 코루틴(coroutine) 등 다양한 실행 모델을 지원하는 복수의 하위 클래스를 제공한다.

8. XML 정의에서의 구분

BehaviorTree.CPP의 XML 기반 트리 정의에서 조건 노드와 액션 노드는 동일한 방식으로 리프 요소에 기술된다. 노드 유형의 구분은 XML 구조가 아닌 C++ 클래스의 상속 관계에 의해 결정된다. 따라서 노드 등록 시 ConditionNode를 상속한 클래스와 ActionNodeBase를 상속한 클래스가 자동으로 구분된다.

<BehaviorTree>
    <Sequence>
        <Condition ID="IsBatteryOk"/>      <!-- 조건 노드 -->
        <Action ID="MoveToGoal"/>          <!-- 액션 노드 -->
    </Sequence>
</BehaviorTree>

XML에서 <Condition> 태그와 <Action> 태그는 가독성을 위한 관례적 구분이며, 실제 노드 유형의 판별은 등록된 클래스의 상속 계층에 의존한다.

9. 설계 판단 기준

특정 기능을 조건 노드로 구현할지 액션 노드로 구현할지 판단할 때, 다음의 기준을 적용한다.

  1. 상태 변경 여부: 실행 결과로 인해 시스템이나 환경의 상태가 변경되면 액션 노드, 변경되지 않으면 조건 노드이다.
  2. 실행 시간: 즉시 완료되는 연산이면 조건 노드, 비동기적 대기가 필요하면 액션 노드이다.
  3. 반복 실행 안전성: 매 tick마다 반복 실행해도 동일한 결과를 보장하면 조건 노드, 반복 실행 시 부작용이 누적되면 액션 노드이다.

예를 들어, 센서 값을 읽어 임계값과 비교하는 것은 조건 노드이다. 그러나 센서를 초기화하거나 캘리브레이션을 수행하는 것은 상태를 변경하므로 액션 노드이다.

10. 참고 문헌

  • 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