28.6.1.1. 수평(XY) 제어와 수직(Z) 제어의 완전한 디커플링(Decoupling) 및 비동기 Setpoint 융합
멀티로터의 제어 역학을 깊이 파고들어 갈 때, 가장 두드러지는 특성 중 하나는 기체가 수평으로 이동하는 행위(XY축 제어)와 위아래로 승강하는 행위(Z축 제어)가 물리적으로 매우 독립적으로 분리(Decoupling)되어 있다는 점이다.
멀티로터는 전진하기 위해 기체를 앞으로 기울일 때(Pitch Down), 고도를 유지하기 위해 수직 추력 성분비가 감소한 만큼 전체 추력을 미세하게 더 올려주어야 하지만, 근본적으로 “XY 좌표 도달 로직“과 “Z 고도 도달 로직“은 서로 간섭 없이 개별 계산될 수 있다. PX4-Autopilot의 mc_pos_control은 이 역학적 디커플링을 소프트웨어 아키텍처에 그대로 반영하여 수평-수직 비동기 셋포인트(Async Setpoint) 융합 방식을 취하고 있다.
1. 물리적 디커플링(Physical Decoupling)의 근거
고정익 비행기는 고도를 높이기 위해 기수를 쳐들면 필연적으로 전진 속도가 희생되는 강한 결합(Strong Coupling) 상태에 놓여 있다. 그러나 멀티로터는 시스템 모델링 관점에서 다음과 같이 분리(Separation)가 가능하다.
- Z축 제어 (수직): 총 4개의 모터 추력(Total Thrust) 합산값으로 순수하게 결정됨.
- XY축 제어 (수평): 추력의 방향 벡터(Thrust Vectoring) 즉, 롤(Roll)과 피치(Pitch)라는 자세(Attitude) 에 의해서 결정됨.
따라서 멀티로터 제어 모델에서는 목표 좌표까지의 3차원 유클리드 공간 궤적을 억지로 한 번에 미분 방정식으로 푸는 대신, XY 평면 상의 2D 문제와 Z 축 상의 1D 문제를 독립적인 PID 파이프라인으로 완전히 나누어 계산한 뒤 제일 마지막에 합성하는 구조가 훨씬 유리하다.
2. 코드 레벨 디커플링 설계: PositionControl 클래스
PX4의 src/lib/PositionControl 라이브러리를 열어보면, 이 디커플링 철학이 C++ 함수 수준에서부터 완벽히 분리되어 있음을 관찰할 수 있다.
// 1. Z축(고도) 독립 계산
_vel_sp(2) = _z_ctrl.update(_pos_sp(2), _pos(2), _vel_sp(2), _vel(2), _acc_sp(2), dt);
// 2. XY축(수평) 독립 계산
Vector2f vel_sp_xy = _xy_ctrl.update(Vector2f(_pos_sp), Vector2f(_pos),
Vector2f(_vel_sp), Vector2f(_vel),
Vector2f(_acc_sp), dt);
_vel_sp(0) = vel_sp_xy(0);
_vel_sp(1) = vel_sp_xy(1);
위 로직에서 고도 제어기(_z_ctrl)와 수평 제어기(_xy_ctrl)는 어떠한 상태 변수(State Variable)도 상호 참조하지 않는다.
각 제어기는 자신의 축에 배당된 위치 오차(Position Error)를 넘겨받아 자신만의 PID 게인 파라미터(MPC_XY_P vs MPC_Z_P)를 곱하여 독립적인 목표 속도 스칼라/벡터를 산출해낸다.
3. 체공 모드(Hold/Position)의 비동기적(Asynchronous) 셋포인트 융합
이 완벽한 소프트웨어적 디커플링 구조는 조종사가 조종기 스틱을 움직일 때 가장 극적인 성능 최적화를 가져온다.
멀티로터의 “Position 모드” 비행 시, 조종사는 “오른쪽 스틱(Elevator/Aileron)“으로 XY 이동을 명령하고, “왼쪽 스틱(Throttle)“으로 Z 승강을 명령한다. 인간의 손가락은 결코 동기화(Synchronized)되어 완벽히 동시에 작동하지 않는다.
PX4 제어기는 조종기의 두 스틱 입력을 비동기적으로(Asynchronously) 융합하여 해석한다.
- 반쪽짜리 Hold 상태 허용: 조종사가 스로틀 스틱을 중립(Deadzone)에 두고 우측 스틱만으로 전진하는 상황을 가정해보자. (흔히 말하는 직진 비행).
이때 고도 제어기(_z_ctrl)는 “Hold(고도 고정)” 궤적 로직에 갇혀 속도 목표값을 철저하게0으로 유지하는 반면, 수평 제어기(_xy_ctrl)는 “Cruising(순항)” 상태 머신으로 넘어가 목표 속도 10m/s를 산출한다. - 독립적 저크(Jerk) 스무딩: 스로틀 스틱을 갑자기 풀로 쳤을 때, Z축 방향으로는 강한 저크 궤적(수직 급가속)이 생성되지만, 이것이 XY 축으로 부드럽게 순항 중인 궤적을 전혀 간섭하거나 훼손하지 않는다.
- 최종 Thrust 융합 (Hover Thrust 보상): 독립적으로 계산된 a_{req\_x}, a_{req\_y}, a_{req\_z} 가속도 벡터는 모듈 맨 마지막 단계에서 기하학적 삼각함수 연산을 통해 최종 중력 상쇄가 고려된 3D 추력 벡터(Thrust Vector) 하나로 조립(Fusion)되어 자세 제어기로 넘겨진다.
이 비동기 융합 모델은 바람이 심하게 부는 환경에서도 고도를 1cm 단위로 유지하면서 수평으로는 부드럽게 미끄러지듯 날아가는 압도적인 안정감을 보장한다.
4. ArduCopter와의 위치/고도(Position/Altitude) 디커플링 비교
- ArduCopter (AltHold 기반 확장 파이프라인): ArduPilot 생태계에서 멀티콥터의 기본 비행 축은 역사적으로
AltHold모드에서 파생되었다. 즉, 수직 제어(고도 유지)가 가장 근간이 되며, 그 위에 수평으로 위치를 유지하는Loiter모드가 덧씌워진 레거시 상속 모델에 가깝다. 제어 파이프라인이 Z루프 우선순위로 강하게 얽혀 있다. - PX4 (독립 병렬 파이프라인): 앞선 수학적 모델링에서 확인한 것처럼, PX4는 Z축(
_z_ctrl)과 XY축(_xy_ctrl)을 완벽하게 병렬(Parallel) 대칭 구조의 객체 인스턴스로 분리했다. 이를 통해 외부 컴퓨터에서 Offboard 모드를 통해 X축만 제어 권한을 뺏고, Y축과 Z축은 픽스호크가 자율적으로 Hold하도록 만드는 등, 각 차원의 자율성을 축 단위로 해체/조립하는 극대화된 모듈화의 이점을 누릴 수 있다.