1293.47 실행 중인 자식 노드의 중단 처리

1293.47 실행 중인 자식 노드의 중단 처리

1. 중단 처리의 개요

행동 트리(Behavior Tree)에서 실행 중인 자식 노드의 중단 처리란, RUNNING 상태의 노드가 부모로부터 Halt를 수신하였을 때 진행 중인 작업을 안전하게 종료하고 노드를 초기 상태로 복원하는 과정이다. 중단 처리는 외부 시스템에 위임된 작업의 취소, 내부 상태의 리셋, 자원의 해제를 포함하며, 이 과정이 올바르게 수행되어야 행동 트리의 일관성과 안전성이 보장된다(Colledanchise & Ogren, 2018).

2. 노드 유형별 중단 처리

2.1 동기 노드의 중단 처리

동기 노드(SyncActionNode, ConditionNode)는 tick() 호출 내에서 즉시 SUCCESS 또는 FAILURE를 반환하므로, RUNNING 상태를 가지지 않는다. 따라서 동기 노드에 대한 Halt 호출은 사실상 발생하지 않으며, 중단 처리가 필요하지 않다.

2.2 비동기 노드의 중단 처리

비동기 노드(StatefulActionNode)는 RUNNING 상태를 가지며, 외부 시스템에 장기 실행 작업을 위임한다. 이 노드의 중단 처리는 onHalted() 가상 메서드를 통해 구현된다.

class NavigateAction : public BT::StatefulActionNode {
public:
    BT::NodeStatus onStart() override {
        action_client_->send_goal(goal_);
        return BT::NodeStatus::RUNNING;
    }

    BT::NodeStatus onRunning() override {
        auto status = action_client_->get_status();
        if (status == ActionStatus::SUCCEEDED) {
            return BT::NodeStatus::SUCCESS;
        }
        if (status == ActionStatus::FAILED) {
            return BT::NodeStatus::FAILURE;
        }
        return BT::NodeStatus::RUNNING;
    }

    void onHalted() override {
        // 1. 외부 작업 취소
        action_client_->cancel_goal();
        
        // 2. 내부 상태 리셋
        goal_handle_.reset();
        
        // 3. 자원 해제 (필요 시)
        // ...
    }
};

2.3 제어 노드의 중단 처리

제어 노드의 중단 처리는 자식에 대한 Halt 전파와 자신의 내부 상태 리셋으로 구성된다.

void SequenceNode::halt() {
    // RUNNING 자식에 Halt 전파
    haltRunningChildren();
    
    // 내부 상태 리셋
    current_child_index_ = 0;  // WithMemory의 경우
    
    // 기본 리셋
    resetStatus();
}

2.4 데코레이터 노드의 중단 처리

데코레이터 노드의 중단 처리는 자식에 대한 Halt 전파와 데코레이터별 내부 상태(카운터, 타이머 등)의 리셋으로 구성된다.

void RepeatNode::halt() {
    halt_child();           // 자식에 Halt 전파
    repeat_count_ = 0;      // 반복 카운터 리셋
    resetStatus();          // 상태 리셋
}

3. 중단 처리의 실행 순서

Halt 수신 시 중단 처리는 다음 순서로 수행된다.

1. 자식에 Halt 전파 (제어/데코레이터 노드의 경우)
2. 외부 작업 취소 (비동기 액션 노드의 경우)
3. 내부 상태 리셋
4. 노드 상태를 IDLE로 설정

이 순서는 자식의 중단이 먼저 완료된 후 부모의 상태가 리셋되도록 보장한다. 이를 통해 트리의 하위 노드부터 상위 노드까지 깨끗한 상태로 복원된다.

4. ROS2 액션 기반 작업의 중단 처리

ROS2 환경에서 비동기 액션 노드가 ROS2 액션 서버에 목표를 전송한 경우, 중단 처리 시 해당 목표를 취소해야 한다.

void onHalted() override {
    if (goal_handle_) {
        auto cancel_future = action_client_->async_cancel_goal(goal_handle_);
        // 취소 요청 전송 (비동기, 결과 대기하지 않음)
    }
    goal_handle_.reset();
}

ROS2 액션의 취소는 비동기적으로 처리되므로, onHalted()에서 취소 요청만 전송하고 취소 완료를 대기하지 않는 것이 일반적이다. 취소 완료 대기는 Tick 실행을 차단하여 실시간 제약을 위반할 수 있기 때문이다.

5. 중단 처리에서의 주의 사항

5.1 블로킹 연산 회피

onHalted() 내에서 블로킹 연산(동기적 네트워크 호출, 긴 대기 등)을 수행하면 Tick 실행 시간이 증가하여 시스템 응답성이 저하된다. 중단 처리는 가능한 한 비블로킹으로 수행해야 한다.

// 부적절: 블로킹 대기
void onHalted() override {
    auto result = action_client_->cancel_goal_and_wait(goal_handle_);
    // 취소 완료까지 블로킹 → Tick 지연 유발
}

// 적절: 비블로킹 취소
void onHalted() override {
    action_client_->async_cancel_goal(goal_handle_);
    // 취소 요청만 전송, 즉시 반환
}

5.2 예외 안전성

onHalted() 내에서 예외가 발생하면 상위 노드의 Halt 처리가 중단될 수 있다. 중단 처리 코드는 예외 안전하게 구현해야 하며, 외부 시스템 호출의 실패를 적절히 처리해야 한다.

void onHalted() override {
    try {
        action_client_->async_cancel_goal(goal_handle_);
    } catch (const std::exception& e) {
        // 로그 기록, 예외를 상위로 전파하지 않음
        RCLCPP_WARN(node_->get_logger(), 
                    "Cancel failed: %s", e.what());
    }
    goal_handle_.reset();
}

5.3 멱등성 보장

동일한 노드에 Halt가 중복 호출될 수 있으므로, 중단 처리는 멱등(idempotent)하게 구현해야 한다. 이미 취소된 작업을 다시 취소하거나, 이미 해제된 자원을 다시 해제하는 것이 오류를 유발하지 않아야 한다.

void onHalted() override {
    if (goal_handle_) {  // null 확인
        action_client_->async_cancel_goal(goal_handle_);
        goal_handle_.reset();
    }
}

6. 중단 처리와 상태 전이

중단 처리 전후의 노드 상태 전이는 다음과 같다.

중단 전: RUNNING
  ↓ halt() 호출
중단 중: onHalted() 실행 (외부 작업 취소, 내부 상태 리셋)
  ↓ resetStatus() 호출
중단 후: IDLE

IDLE 상태로 전이된 노드가 다시 Tick을 수신하면, onStart()가 호출되어 새로운 실행이 시작된다. 이전 실행의 상태는 완전히 소실되며, 이는 중단 처리의 의도된 동작이다.

7. 중단 처리의 물리적 영향

로봇공학에서 중단 처리는 소프트웨어적 상태 리셋뿐 아니라 물리적 영향도 고려해야 한다.

작업 유형중단 시 필요한 물리적 처리
네비게이션이동 중단, 속도 0으로 감속
매니퓰레이션그리퍼 정지 (또는 안전 위치로 이동)
회전회전 중단, 각속도 0으로 감속
센서 스캔스캔 중단, 센서 기본 위치로 복귀
통신 전송전송 취소, 연결 유지/해제 결정

물리적 작업의 즉시 중단이 안전하지 않은 경우(예: 고속 이동 중 급정지), 중단 처리에서 안전한 감속 명령을 전송한 후 반환해야 한다. 감속 완료 대기는 Tick을 차단하므로, 감속 명령 전송만 수행하고 실제 감속은 하위 제어 시스템에 위임하는 것이 적절하다.


참고 문헌

  • 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/