1296.86 액션 노드의 Halt 구현 패턴

1. 개요

Halt는 행동 트리에서 실행 중인 노드를 강제로 중단하는 메커니즘이다. 상위 제어 노드가 실행 흐름을 변경할 때, 현재 RUNNING 상태에 있는 자식 노드에 대해 halt를 호출하여 실행을 중지시킨다. Halt의 올바른 구현은 로봇 시스템의 안전성과 자원 관리에 직결되며, 물리적 동작을 수행하는 액션 노드에서 특히 중요하다.

BehaviorTree.CPP에서 halt는 TreeNode::halt() 가상 메서드를 통해 수행된다. StatefulActionNode에서는 onHalted() 콜백 메서드가 이를 대체하며, SyncActionNode에서는 단일 tick 내에서 완료되므로 halt가 호출되지 않는다.

2. Halt가 호출되는 상황

행동 트리에서 halt가 호출되는 주요 상황은 다음과 같다.

상황설명예시
Sequence 실패형제 노드의 실패로 시퀀스 중단이전 조건 노드가 FAILURE 반환
Fallback 성공이전 자식의 성공으로 현재 노드 불필요대체 경로가 이미 성공
Reactive 노드 재평가조건 변화로 실행 흐름 전환ReactiveFallback의 조건 변경
트리 중지전체 행동 트리의 실행 중지비상 정지 명령
데코레이터 개입Timeout, ForceFailure 등타임아웃 만료

3. Halt 구현의 기본 원칙

3.1 즉시 완료

onHalted()는 가능한 한 빠르게 완료되어야 한다. 블로킹 연산(동기 서비스 호출, 파일 입출력 대기 등)을 포함하면 행동 트리의 전체 실행이 지연된다. 비동기 취소 요청을 전송하고 즉시 반환하는 것이 바람직하다.

void onHalted() override
{
    // 비동기 취소 요청 전송 (블로킹 아님)
    if (goal_handle_)
    {
        action_client_->async_cancel_goal(goal_handle_);
    }
    // 즉시 반환
}

3.2 자원 해제

모든 할당된 자원(구독, 타이머, 파일 핸들, 스레드 등)을 해제하여 자원 누수를 방지한다.

void onHalted() override
{
    subscription_.reset();
    timer_.reset();
    goal_handle_.reset();
    writer_.reset();
}

3.3 상태 초기화

내부 상태 변수를 초기 상태로 복원하여, 동일 노드가 행동 트리의 반복 실행에서 재진입될 때 이전 실행의 잔여 상태가 영향을 미치지 않도록 한다.

void onHalted() override
{
    // 자원 해제
    if (goal_handle_)
    {
        action_client_->async_cancel_goal(goal_handle_);
        goal_handle_.reset();
    }

    // 상태 초기화
    goal_accepted_ = false;
    goal_completed_ = false;
    goal_succeeded_ = false;
    data_received_ = false;
}

3.4 안전 상태 전환

물리적 동작을 수행하는 노드에서는 halt 시 로봇이 안전한 상태로 전환되도록 해야 한다. 예를 들어, 비행 중 halt가 호출되면 드론은 위치 유지 모드로 전환되어야 한다.

4. Halt 구현 패턴

4.1 패턴 1: 단순 정리

ROS2 토픽 구독이나 타이머만 사용하는 노드에서의 기본 패턴이다.

void onHalted() override
{
    subscription_.reset();
    data_received_ = false;
}

4.2 패턴 2: 액션 취소 후 정리

ROS2 액션 클라이언트를 사용하는 노드에서의 표준 패턴이다.

void onHalted() override
{
    if (goal_handle_)
    {
        action_client_->async_cancel_goal(goal_handle_);
        goal_handle_.reset();
    }
    goal_completed_ = false;
    goal_succeeded_ = false;
}

4.3 패턴 3: 보상 동작 수행

halt 시 이전 동작의 효과를 원래 상태로 복원하는 보상 동작(compensating action)을 수행한다.

void onHalted() override
{
    // 그리퍼를 열어 물체 해제
    if (gripper_closed_)
    {
        auto open_msg = std_msgs::msg::Bool();
        open_msg.data = false;
        gripper_pub_->publish(open_msg);
        gripper_closed_ = false;
    }
}

4.4 패턴 4: 안전 모드 전환

안전 임계 동작(비행, 고속 이동 등)에서의 halt 패턴이다.

void onHalted() override
{
    // 진행 중인 액션 취소
    if (goal_handle_)
    {
        action_client_->async_cancel_goal(goal_handle_);
        goal_handle_.reset();
    }

    // 안전 모드로 전환
    auto mode_msg = std_msgs::msg::String();
    mode_msg.data = "POSITION_HOLD";
    flight_mode_pub_->publish(mode_msg);

    RCLCPP_INFO(node_->get_logger(),
        "비행 중단: 위치 유지 모드로 전환");
}

4.5 패턴 5: 데이터 저장 후 정리

장시간 데이터 수집 작업에서 halt 시 수집된 데이터를 저장하는 패턴이다.

void onHalted() override
{
    // 수집된 데이터 저장
    if (writer_)
    {
        writer_->close();
        writer_.reset();
        RCLCPP_INFO(node_->get_logger(),
            "데이터 기록 중단: %d개 메시지 저장됨",
            message_count_.load());
    }

    subscriptions_.clear();
}

5. Halt 미구현 시의 위험

onHalted()를 구현하지 않으면 다음 문제가 발생할 수 있다.

  • 자원 누수: 구독, 타이머, 파일 핸들 등이 해제되지 않아 메모리와 시스템 자원이 점진적으로 소진된다.
  • 진행 중인 동작의 지속: ROS2 액션이 취소되지 않아 로봇이 의도하지 않은 동작을 계속 수행한다.
  • 상태 불일치: 다음 실행에서 이전 상태가 남아 있어 예측 불가능한 동작이 발생한다.
  • 안전 위협: 비행 중 halt가 호출되었으나 비행이 계속되면, 행동 트리가 새로운 비행 명령을 전송하여 충돌이 발생할 수 있다.

6. Halt의 테스트

halt 구현의 올바름을 검증하기 위해 다음 시나리오를 테스트해야 한다.

  • onStart() 직후 halt
  • onRunning()RUNNING을 반환한 직후 halt
  • 외부 서비스 응답 대기 중 halt
  • 반복 실행에서 halt 후 재시작
  • 다중 연속 halt 호출
TEST(HaltTest, ResourceCleanupAfterHalt)
{
    auto node = createTestNode();
    node->executeTick();  // RUNNING 반환
    node->halt();

    // 자원이 해제되었는지 확인
    EXPECT_EQ(node->getSubscriptionCount(), 0);
    EXPECT_FALSE(node->hasActiveGoal());

    // 재시작이 정상적으로 동작하는지 확인
    auto status = node->executeTick();
    EXPECT_EQ(status, BT::NodeStatus::RUNNING);
}

7. 참고 문헌

  • Colledanchise, M. and Ögren, P., “Behavior Trees in Robotics and AI: An Introduction,” CRC Press, 2018.
  • Faconti, D. and Contributors, “BehaviorTree.CPP: A C++ library to build Behavior Trees,” GitHub Repository, https://github.com/BehaviorTree/BehaviorTree.CPP.
  • Macenski, S. et al., “The Marathon 2: A Navigation System,” arXiv preprint arXiv:2003.00368, 2020.

버전: 2026-04-04