21.5. ModuleParams를 활용한 시스템 파라미터 결합(Binding) 기술
드론 펌웨어 개발이 웹(Web)이나 모바일 앱 개발과 가장 구분되는 극명한 차이점은 무엇일까? 바로 기체마다 무게, 모터 성능, 센서 위치가 모두 다르기 때문에, 코드를 한 줄도 고치지 않고 **비행 전 필드에서 수천 개의 변숫값을 실시간으로 조율(Tuning)**할 수 있어야 한다는 점이다.
PX4는 이를 위해 QGroundControl(QGC)과 같은 제어 스크린을 통해 수천 개의 변수 묶음을 무선으로 읽고 쓸 수 있는 거대한 파라미터(Parameter) 시스템을 내장하고 있다.
여러분이 짠 C++ 모듈의 내부 변수들(예: PID 제어기의 P 게인, 모터의 최대 속도 제한치)을 이 글로벌 파라미터 시스템의 혈망과 연결(Binding)하려면, 그저 전역 변수 하나를 선언하는 것으로는 어림도 없다. PX4는 이 복잡한 메모리 결속 작업을 완벽하게 자동화해 주는 **ModuleParams**라는 또 하나의 거대한 보조 클래스 블록을 제공한다.
1. 하드코딩(Hardcoding)의 종말
만약 기체의 최대 속도를 결정하는 로직을 날것의 C++ 코드로 짰다고 상상해 보자.
// 최악의 펌웨어 코드 (수정이 불가능함)
void CustomApp::control_logic() {
float max_speed = 15.0f; // 마의 숫자(Magic Number) 하드코딩
if (current_speed > max_speed) { /* 브레이크 */ }
}
이 코드는 실내 비행을 할 때는 아무 문제가 없을지 몰라도, 다음 날 야외에서 30m/s로 날려야 하는 미션이 주어졌을 때 개발자로 하여금 펌웨어를 처음부터 다시 컴파일해서 플래싱(Flashing)하게 만드는 지옥을 선사한다.
우리는 이 15.0f 라는 숫자를 내 하드디스크의 소스 코드가 아니라, 픽스호크 보드의 SD 카드 내장 파라미터 텍스트 영역에서 동적으로 읽어오도록 코드를 뜯어고쳐야 한다.
2. ModuleParams: 마법의 브로커
이런 동적 연결을 위해 PX4 개발자들은 ModuleParams라는 특별한 클래스를 상속받는다.
이 클래스의 주된 역할은 **“내 C++ 객체 메모리 주소(RAM)”**와 “PX4 시스템 파라미터 서버(ROM/SD Card)” 사이를 이어주는 가느다란 데이터 파이프라인(Broker)을 개통하는 것이다.
여러분의 모듈 클래스가 이 ModuleParams를 상속하게 되면, 여러분은 단 한 줄의 update() 메서드 호출만으로 QGroundControl에서 사용자가 마우스 광클릭으로 갱신한 수많은 파라미터 숫자들을 내 C++ 멤버 변수 안으로 순식간에 동기화(Sync)시킬 수 있는 기적 같은 능력을 얻게 된다.
하지만 놀랍게도 여러분의 CustomApp 모듈은 이미 앞선 장(21.4)에서 ModuleBase라는 거대한 부모를 상속받아버린 상태다.
C++에서 부모를 두 명 모시는(다중 상속) 것은 언제나 문법적 골칫거리를 낳기 마련이다. 그렇다면 PX4 시스템은 이 두 거대한 부모 클래스(ModuleBase와 ModuleParams)를 내 자식 객체에 어떻게 동시에 안전하게 접합(Grafting)시키고 초기화하는 것일까?
다음 단원(21.5.1)에서 C++ 다중 상속의 실전과 생성자 초기화 리스트(Initializer List)의 작동 원리를 파헤쳐보며 우아한 パ라미터 클래스의 탄생 과정을 지켜보자.