29.6.2. 범플리스 트랜스퍼(Bumpless Transfer) 제어 연속성 알고리즘

29.6.2. 범플리스 트랜스퍼(Bumpless Transfer) 제어 연속성 알고리즘

1. 개요 및 범플리스 트랜스퍼(Bumpless Transfer)의 필요성

제어 공학(Control Engineering)에서 **범플리스 트랜스퍼(Bumpless Transfer)**란, 시스템을 구동하는 제어기(Controller)의 운용 모드가 변경될 때 제어 출력(Control Signal)이 불연속적으로 튀는(Jerking 혹은 Bumping) 현상을 방지하여 물리적 시스템의 충격을 없애는 기술을 말한다.

비행 중인 드론 체계에서 이 개념은 생존과 직결된다. 예를 들어, 기체가 45도로 크게 기울어진 채 순수 각속도 제어인 아크로(Acro) 모드로 비행하다가 조종자가 스위치를 수평 유지(Stabilized) 모드로 전환했다고 가정하자. 만약 조종기 스틱이 중앙(0도 지시)에 위치해 있다면, 새로운 안정화 제어기는 활성화되자마자 현재 각도(45도)와 목표 각도(0도) 사이의 거대한 오차(Error)를 발견하고 이를 즉시 복구하기 위해 최대 토크명령을 모러토 인가할 것이다. 이로 인해 기체는 허공에서 격렬하게 발작하듯 자세를 복구하게 되며, 이는 극한 상황에서 페이로드(Payload) 탈거 또는 추락으로 이어진다.

최신 PX4-Autopilot은 이러한 제어 불연속성을 해결하기 위해, 비행 태스크(Flight Task) 전환 순간에 초기 오차율을 영점화(Zeroing)하고 부드러운 전이를 창출하는 범플리스 트랜스퍼 알고리즘을 소스 코드 전반에 걸쳐 내장하고 있다.

2. 제어 연속성 알고리즘 아키텍처

PX4의 범플리스 트랜스퍼는 주로 FlightTask 아키텍처의 생명주기(Lifecycle) 함수인 activate() 메서드 내에서 초기화 로직으로 구현된다. 핵심 아키텍처는 다음의 두 가지 축으로 구성된다.

  1. 목표값 동기화 (Setpoint Alignment): 새로운 제어 모드가 시작되는 정확히 그 틱(Tick, 1사이클 연산 주기)에, 기체의 현재 물리적 상태 즉 EKF(Extended Kalman Filter)의 상태 추정치를 새로운 제어기의 초기 목표값(Initial Target Setpoint)으로 강제 덮어쓴다. 이를 통해 제어 오차(Error)를 강제로 0으로 만든다.
  2. 적분기 및 파생 상태 초기화 (Integrator Resetting): 이전 제어기의 누적 적분 오차(I-Term Windup)가 새로운 제어기로 흘러들어가는 것을 막기 위하여 내부 메모리 상태 객체들을 zero() 함수를 통해 클리어한다.

이러한 초기 설정 이후, 조종자의 실제 스틱 위치(예: 중앙 0도)를 향해 내부 스무딩 커브(Slew Rate Limiter 등) 알고리즘이 목표값을 부드럽게 감쇠 이동(Easing)시켜 충격 없는 기동을 완성한다.

3. 제어 신호 흐름 궤적 (Mermaid 설계도)

안정화(Stabilized) 모드로 전환되는 시점(t_1)을 기준으로 범플리스 트랜스퍼 기술이 적용되지 않았을 때와 적용되었을 때의 제어 변수 변화 궤적을 비교한 다이어그램이다.

graph TD
    subgraph 범플리스 트랜스퍼 미적용 (재난 상황)
    A1[아크로 모드 (Current Roll = 45도)] --> B1{t1 : 스위치 조작<br>Stabilized (조종기 스틱 중앙 0도)}
    B1 --> C1[Target Roll 오차 = 45도 발생]
    C1 --> D1[P-Controller 최대 토크 순간 인가]
    D1 --> E1((기체의 거친 튐 Jerk 발생))
    end

    subgraph 범플리스 트랜스퍼 적용 (PX4 아키텍처)
    A2[아크로 모드 (Current Roll = 45도)] --> B2{t1 : 스위치 조작<br>FlightTask::activate()}
    B2 --> C2[Target Roll = 현재 EKF Roll (45도) 로 초기화]
    C2 --> D2[초기 오차 0도 산출 -> 모터 토크 변화율 0]
    D2 --> E2[이후 조종기 스틱 목표(0도)를 향해 Slew Rate 기반 부드러운 이동]
    E2 --> F2((충격 없는 매끄러운 궤적 제어))
    end

4. 소스 코드 깊은 분석 (FlightTask.cppactivate())

PX4 펌웨어에서 범플리스 트랜스퍼 로직의 텍스트 기반 구현은 각 비행 태스크별 C++ 원시 코드에 명확하게 존재한다. 예를 들어 비행 모드 관리자(Flight Mode Manager)가 새로운 태스크를 구동시킬 때 가장 먼저 호출하는 activate() 메서드는 다음과 같은 형상으로 작성되어 있다.

// src/modules/flight_mode_manager/tasks/ManualPosition/FlightTaskManualPosition.cpp 참조 예시

bool FlightTaskManualPosition::activate(const vehicle_local_position_setpoint_s &last_setpoint)
{
    // 1. 부모 클래스(부재/기반 태스크)의 활성화 함수 호출
    bool ret = FlightTaskManualAltitude::activate(last_setpoint);

    // 2. 범플리스 트랜스퍼 (위치 제어 관점)
    // 현재 기체의 X, Y 좌표 및 속도를 새로운 제어 목표로 동기화한다.
    _position_setpoint(0) = _position(0);
    _position_setpoint(1) = _position(1);
    
    // 조종기의 헤딩(Yaw) 목표치 또한 갑자기 변하지 않도록,
    // 현재 EKF가 추정한 기체의 실제 헤딩 각도를 저장한다.
    _yaw_setpoint = _yaw;

    // 3. 내부 상태 및 미분기, 적분기 리셋
    _velocity_setpoint.setAll(0.0f);
    
    return ret;
}

이와 별개로, 가장 로우 레벨인 각속도 제어기 루프(RateControl.cpp)에서도 전환 시 이전 역학의 잔재를 지우는 로직이 작동한다.

// src/modules/mc_rate_control/RateControl.cpp
void RateControl::reset() {
    // 이전 모드에서 누적된 적분 제어항을 소거
    _torque_int.zero();
    // 가속도 변화율 계산을 위한 과거 버퍼 필터값 소거
    _angular_accel.zero(); 
}

조종자가 MAVLink나 스위치 트랜지션으로 전이 상태를 명시하면 Commander 모듈의 통제 하에 이러한 일괄 초기화(activate, reset) 프로세스가 동기적으로 이루어지기 때문에 안정성이 보장되는 것이다.

5. Ardupilot 대비 아키텍처 분리 차이

제어 튐 현상을 막기 위한 범플리스 트랜스퍼 설계 철학에 있어 두 시스템은 유사한 물리적 해법을 택하고 있으나 코드 구조 측면에서 상이하다.

  • PX4-Autopilot:
    비행 모드들(FlightTask)은 각각이 독립된 상속 구조의 클래스로 존재하며, 객체 지향의 다형성(Polymorphism)을 십분 활용한다. activate() 가상 함수(Virtual Function) 내부에서 각 모드의 성격(위치 유지, 고도 유지, 수평 유지)에 맞는 맞춤형 상태 동기화가 실행된다. 범플리스를 뒷받침하는 Slew Limiting(이동 변위율 제한기)은 별도의 유틸리티 라이브러리(slew_rate.cpp 또는 mathlib)로 철저히 분리되어 있어 범용성이 뛰어나다.
  • Ardupilot:
    비행 모드는 기능별(mode_stabilize.cpp, mode_acro.cpp)로 나뉘어져 있으며, init() 함수 내에서 ahrs.roll_sensor, ahrs.pitch_sensor 값을 읽어와 타겟(Target)으로 덮어쓰는 매우 직관적이고 밀접한(Tightly-coupled) 하드 코딩 방식으로 작성되어 있다. 코드의 접근성과 가독성은 뛰어나지만, 수많은 매개 변수의 통과 로직이 메인 Copter 클래스의 멤버 변수들을 광범위하게 참조하는 경향이 있어 모듈간 얽힘 현상을 유발할 소지가 있다.

요약하자면, PX4-Autopilot 내의 범플리스 트랜스퍼 알고리즘은 비행 태스크별 activate() 로직을 통해 EKF 상태 추정치를 현재의 목표(Setpoint)로 정렬하고 PID 적분기를 영점화함으로써, 상이한 제어 체제로 전환되어도 기체가 가장 부드러운 동적 궤적을 잇도록 보장해 준다.