1293.23 노드의 Running에서 Success로의 전이

1. RUNNING에서 SUCCESS 전이의 의미

RUNNING에서 SUCCESS로의 전이는 행동 트리(Behavior Tree) 노드가 수행하던 비동기 작업이 성공적으로 완료되었음을 나타내는 상태 변화이다. 이 전이는 노드가 이전 Tick에서 RUNNING을 반환하여 작업의 진행 중임을 알린 후, 후속 Tick에서 작업의 완료를 확인하고 SUCCESS를 반환하는 시점에서 발생한다(Colledanchise & Ogren, 2018).

이 전이는 비동기 노드의 생명 주기에서 작업 완료(completion)에 해당하며, 자원 해제, 결과 데이터의 블랙보드 기록, 부모 노드에 대한 성공 보고 등의 후속 처리가 수반된다.

2. 전이 발생 조건

RUNNING → SUCCESS 전이가 발생하기 위해서는 다음 조건이 충족되어야 한다.

  1. 노드의 현재 상태가 RUNNING: 이전 Tick에서 RUNNING을 반환하여 작업이 진행 중인 상태에 있어야 한다.
  2. 부모 노드로부터 Tick이 재전파: 제어 노드의 재진입 규칙에 따라 RUNNING 상태인 자식 노드에 다시 Tick이 전달되어야 한다.
  3. 비동기 작업의 성공적 완료: 노드가 수행하던 외부 작업(액션 실행, 계산 처리 등)이 원하는 결과를 달성하여 완료되어야 한다.

3. StatefulActionNode에서의 구현

BehaviorTree.CPP의 StatefulActionNode에서 RUNNING → SUCCESS 전이는 onRunning() 콜백 내에서 수행된다. onRunning()은 노드가 RUNNING 상태에서 Tick될 때마다 호출되며, 작업 완료 여부를 확인하여 SUCCESS 또는 RUNNING을 반환한다(Faconti, 2022).

class MoveToTarget : public BT::StatefulActionNode {
    BT::NodeStatus onStart() override {
        // 이동 명령 전송
        send_navigation_goal();
        return BT::NodeStatus::RUNNING;
    }
    
    BT::NodeStatus onRunning() override {
        auto result = check_navigation_status();
        
        if (result == NavigationResult::REACHED) {
            // 목표 도달: SUCCESS 반환
            // 결과 데이터를 블랙보드에 기록
            setOutput("final_pose", get_current_pose());
            return BT::NodeStatus::SUCCESS;
        }
        
        if (result == NavigationResult::IN_PROGRESS) {
            return BT::NodeStatus::RUNNING;
        }
        
        return BT::NodeStatus::FAILURE;
    }
    
    void onHalted() override {
        cancel_navigation();
    }
};

4. ROS2 액션 기반 노드에서의 전이

ROS2 액션 인터페이스를 사용하는 행동 트리 노드에서 RUNNING → SUCCESS 전이는 액션 서버로부터 결과(result)를 수신하는 시점에서 결정된다. 액션의 결과 상태가 SUCCEEDED이면 SUCCESS를 반환하고, 그 외의 경우 FAILURE를 반환한다.

BT::NodeStatus onRunning() override {
    auto goal_handle = action_client_->get_goal_handle();
    
    if (!goal_handle) {
        return BT::NodeStatus::FAILURE;
    }
    
    auto status = goal_handle->get_status();
    
    switch (status) {
        case action_msgs::msg::GoalStatus::STATUS_SUCCEEDED:
            // 액션 성공 완료
            result_ = action_client_->get_result();
            setOutput("result", result_.value);
            return BT::NodeStatus::SUCCESS;
            
        case action_msgs::msg::GoalStatus::STATUS_EXECUTING:
        case action_msgs::msg::GoalStatus::STATUS_ACCEPTED:
            return BT::NodeStatus::RUNNING;
            
        default:
            return BT::NodeStatus::FAILURE;
    }
}

5. SUCCESS 전이 시 수행되는 후속 처리

5.1 결과 데이터의 블랙보드 기록

작업의 결과 데이터를 출력 포트(output port)를 통해 블랙보드에 기록한다. 이 데이터는 후속 노드가 입력 포트를 통해 참조할 수 있으며, 행동 트리 내에서의 데이터 흐름을 구성한다.

예를 들어, 경로 계획 노드가 SUCCESS를 반환할 때 계획된 경로를 블랙보드에 기록하면, 후속 경로 추종 노드가 이 경로를 읽어 실행할 수 있다.

5.2 자원 해제

RUNNING 상태에서 사용하던 자원을 해제한다. 타이머 중지, 임시 버퍼 해제, 파일 핸들 닫기 등이 이에 해당한다. BehaviorTree.CPP에서는 SUCCESS 반환 후 프레임워크가 내부적으로 노드의 상태를 IDLE로 리셋하며, 이 과정에서 onHalted()는 호출되지 않는다.

5.3 부모 노드에 대한 영향

SUCCESS가 부모 노드에 반환되면, 부모 노드의 유형에 따라 후속 동작이 결정된다.

부모 노드 유형자식 SUCCESS 시 부모의 동작
Sequence다음 자식으로 Tick 전파 진행
Fallback나머지 자식 건너뛰고 즉시 SUCCESS 반환
Parallel성공 카운트 증가, 임계값 도달 시 SUCCESS
ReactiveSequence다음 자식으로 Tick 전파 진행
ReactiveFallback나머지 자식 건너뛰고 즉시 SUCCESS 반환

Sequence 노드에서 자식의 SUCCESS는 해당 자식의 작업이 완료되었으므로 다음 단계로 진행해도 좋다는 신호이다. Fallback 노드에서 자식의 SUCCESS는 대안 중 하나가 성공하였으므로 더 이상의 시도가 필요 없다는 신호이다.

6. SUCCESS 전이의 시간적 특성

RUNNING → SUCCESS 전이는 비동기 작업의 실제 완료 시점과 행동 트리의 인지 시점 사이에 최대 T_{tick}의 지연이 존재한다. 비동기 작업이 두 Tick 사이에서 완료되면, 다음 Tick에서 onRunning()이 호출되어 완료를 확인할 때까지 행동 트리는 여전히 RUNNING 상태로 간주한다.

L_{completion} \leq T_{tick}

이 지연은 BehaviorTree.CPP의 WakeUpSignal 메커니즘을 통해 완화할 수 있다. 비동기 작업이 완료되면 WakeUpSignal을 통해 Tree::sleep()의 대기를 조기에 중단시켜, 다음 Tick을 앞당기는 것이 가능하다.

7. SUCCESS 전이와 트리 상태의 연쇄적 변화

하위 노드의 RUNNING → SUCCESS 전이는 상위 노드의 상태 변화를 연쇄적으로 유발할 수 있다. 예를 들어, Sequence 노드의 마지막 자식이 SUCCESS를 반환하면 Sequence 노드 자체도 SUCCESS를 반환하며, 이 Sequence가 상위 노드의 자식이면 상위 노드의 상태 결정에도 영향을 미친다.

Tick k:
  Root(Sequence): RUNNING
    ├── ConditionA: SUCCESS (이전에 완료)
    └── ActionB: RUNNING

Tick k+1:
  Root(Sequence): SUCCESS    ← ActionB의 SUCCESS로 인해 연쇄 전이
    ├── ConditionA: SUCCESS
    └── ActionB: SUCCESS     ← RUNNING → SUCCESS 전이 발생

이러한 연쇄적 상태 변화는 단일 Tick 내에서 트리의 깊은 계층에서부터 루트 노드까지 전파되며, 행동 트리 전체의 실행 완료를 결정하는 메커니즘이 된다.

8. SUCCESS 전이의 검증

RUNNING → SUCCESS 전이가 올바르게 동작하는지를 검증하기 위해 다음 사항을 확인해야 한다.

8.1 완료 조건의 정확성

SUCCESS를 반환하는 조건이 작업의 실제 성공을 정확히 반영하는지 확인한다. 예를 들어, 네비게이션 노드가 목표 위치 도달을 판단할 때 적절한 허용 오차(tolerance)를 적용하고 있는지, 센서 데이터에 기반한 판단이 신뢰할 수 있는지를 검증한다.

8.2 결과 데이터의 유효성

SUCCESS 반환 시 블랙보드에 기록하는 결과 데이터가 유효한 값인지 확인한다. 초기화되지 않은 변수나 이전 실행의 잔여 데이터가 결과로 보고되지 않도록 한다.

8.3 자원 누수 방지

RUNNING → SUCCESS 전이 후 모든 자원이 적절히 해제되었는지 확인한다. SUCCESS 반환 후에도 비동기 작업 스레드가 계속 실행되거나, ROS2 구독이 해제되지 않는 자원 누수(resource leak)가 발생하지 않도록 한다.


참고 문헌

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