28.1.3.1.2. Ardupilot의 mode.cpp 중심 하드코딩된 거대 제어 루프(Monolithic Loop) 구조
PX4-Autopilot이 객체 지향의 마법인 비동기 다이나믹 태스크 스위칭과 다형성을 구사하며 현대 소프트웨어 공학의 극의에 닿으려 우아하게 코드를 설계했다면, Ardupilot은 철저히 드론 하드웨어 제어의 날것(Raw) 그대로의 거친 실용주의를 지향한다. Ardupilot 코스 트리(예: ArduCopter 디렉터리) 심장부에 똬리를 틀고 있는 mode.cpp 파일과 update_flight_mode() 메인 함수는 이러한 C언어풍 모놀리식(Monolithic) 강결합 아키텍처의 정수이자 산역사를 그대로 보여준다.
1. 정적 할당(Static Allocation) 방식과 영구적 메모리 상주(Resident Memory)
Ardupilot은 PX4처럼 조종사가 조종기 모드 스위치를 딸깍거리며 변경할 때마다, 비행 중인 아찔한 공중에서 칩셋의 힙(Heap) 영역 메모리에 객체를 새롭게 생성(new)하고 구형 객체를 부수는(delete) 아슬아슬한 사치를 결코 부리지 않는다.
- 메모리 록인(Memory Lock-in): 픽스호크(Pixhawk) 큐브 보드에 메인 전원이 인가되고 RTOS 펌웨어가 초기화되는 시스템 부팅 찰나에,
Copter최상위 메인 객체 클래스는ModeLoiter,ModeRTL,ModeAuto등 수십여 개에 이르는 모든 비판적 비행 모드 객체 인스턴스들을 시스템 램(RAM)의 정적 데이터 영역(Static Data Area / BSS)에 일괄적으로 미리 정적 할당(Static Pre-allocation)하여 쐐기를 박아버린다. - 내가 지금 매뉴얼 수동 비행 중이든, GPS 자율 비행 중이든 아무런 상관없이, 이 방대한 모든 모드 서브 객체들은 보드 전원이 툭 꺼질 때까지 조금의 움직임도 없이 항상 램 메모리에 영구적으로 풀사이즈로 상주하며 묵묵히 대기한다.
이 무식한 하드코딩 기법은 전체적인 램 여유 공간 측면에서는 PX4의 지연 할당(Lazy Allocation) 메모리 효율성에 비하면 매우 비효율적이고 무겁다. 하지만 찰나의 공중 비행 도중 램 단편화 스트레스로 인한 동적 메모리 할당 에러(Out-of-memory Panic)가 발생하여 모드 전환이 치명적으로 누락 실패할 수학적 확률 자체를 물리적인 0%로 영구 차단해버리는, 거칠지만 절대 확실한 아키텍처적 무결성 안정성(Reliability)을 확고히 담보해 준다.
2. 400Hz 거대 제어 루프(Fast Loop) 속의 획일적 전역 Switch-Case 분기 폭격
하늘을 비행 중인 Ardupilot의 메인 스레드는 보통 400Hz(초당 타겟 400번 순환)라는 맹렬한 마이크로 속도로 돌아가는 Fast 메인 루프를 가지며, 이 안에서는 비행 궤적을 갱신하는 update_flight_mode() 라는 거대한 핵심 함수가 쉴 새 없이 타격 호출된다.
- 이 중추 함수 내부를 들여다보면 우아한 객체 지향 다형성이나 비동기 브로드캐스팅 따위는 존재하지 않는다. 절벽처럼 무식하고 거대한
switch(control_mode)하드코딩 분기 문법이 거대한万里의 장성처럼 코드 파일을 수백 줄에 걸쳐 겹겹이 둘러싸고 있다. - 스케줄러 틱(Tick)이 돌 때마다 순차적으로 전역 변수인
control_mode(예:RTL) 열거형 숫자를 확인하고,case LOITER:레이블 지점을 만나면 램에 이미 상주해 있던mode_loiter.run()실행 함수를 명시적으로 하드코딩하여 직접 함수 호출(Direct Synchronous Method Call) 다이빙을 꽂아버린다.
3. 리니어(Linear) 구조의 폭력적 런타임 속도와 스파게티 의존성의 덫
3.1 압도적인 마이크로 레이턴시(Micro-latency)의 패권
이러한 Ardupilot 특유의 무식해 보일 정도의 모놀리식 절차적 정적 바인딩 루프 구조는, 사실 C++ 가상 함수 테이블(vtable) 주소를 타고 들어가 점프를 한 번 더 거쳐야 하는 마이크로초 단위의 CPU 캐시 미스 오버헤드(Overhead)조차 단칼에 봉쇄해 버린다.
메모리 주소의 우회 없이 CPU의 인스트럭션 큐(Instruction Queue) 파이프라인을 1차원 직선적으로 파도 타고 쾌속으로 내려가며 메모리 호출을 다이렉트 산술 실행해 버리기 때문에, 조종기 명령이 센서의 물리적 PWM 펄스로 뒤바뀌는 제어 지연 시간(Latency Time) 최소화 측면에서는 그 어떤 아키텍처보다 극한의 반응 속도 효율을 폭력적으로 뿜어낸다. 펌웨어가 뻗었을 때 디버깅(Debugging)을 할 때도 코드의 실행 흐름이 징그러울 정도로 1차원 리니어(Linear)하게 위에서 아래로 이어지므로, 주니어 개발자 입장에선 함수 에러 역추적 콜스택(Call-stack) 그리기가 상대적으로 직관적 편안함을 선사한다.
3.2 거대한 스파게티 의존성(Spaghetti Dependency)의 늪
하지만 십수 년의 너무 긴 오픈소스 역사 동안 전 세계에서 이 거대한 코어 switch-case 문장 뱃속 안에 덕지덕지 수많은 예외 처리 구문과 기체 특화 하드웨어 제어 로직 찌꺼기들이 기워지고 얽히면서, 현재의 Ardupilot mode.cpp는 사실상 손대기 두려운 엄청난 덩치의 레거시 스파게티 코드가 되어버린 지 오래다.
만약 대학원 연구실에서 완전히 전무후무한 새로운 커스텀 융합 모드 알고리즘을 추가하려 할 경우, 이 빽빽하고 민감한 메인 루프 스위치 분기문 척추 한가운데를 전기톱으로 쪼개고 비집고 들어가, 치명적인 글로벌 전역 객체 변수들을 수동으로 위험하게 공유하며 억지로 새 살을 하드코딩으로 꿰매 붙여야 한다. 혹여나 커스텀 모드 논리 알고리즘 블록에서 배열 수위 조절 실패 자제 결함이나 while 무한 루프 버그가 단 0.1초라도 발생하면, 철저히 통신망이 결합이 끊어진 채 안전했던(Decoupled) PX4와 달리, Ardupilot은 전체 400Hz 동기식 메인 루프 스레드 전체 멱살이 잡혀 즉각적으로 영구 블로킹(Blocking Lock-up)되어 버린다. 그 순간 하늘에 떠 있던 거친 금속 드론 쇳덩어리가 그대로 공중에서 돌덩이로 굳어 수직 추락해 버리는 살벌하고도 치명적인 양날의 검(Double-edged Sword) 아키텍처를 태생적으로 쥐고 있다.