27.2.3.1. 센서 통합 데이터를 ECL 내부 구조체로 변환하는 직렬화(Serialization) 과정
PX4의 센서 관선(Pipeline)은 다양한 하드웨어 벤더(Vendor)의 센서들이 토해내는 파편화된 원시(Raw) 데이터들을 1차적으로 sensor_combined, vehicle_gps_position, vehicle_air_data 와 같은 표준화된 uORB 토픽으로 묶어낸다.
하지만 이 uORB 구조체들은 여전히 OS의 타임스탬프와 하드웨어 종속적인 스케일 팩터(Scale Factor)를 품고 있다. 본 절에서는 ekf2 래퍼가 이 uORB 토픽들을 순수 수학엔진이 소화할 수 있는 ECL 내부 구조체(imuSample, gpsSample 등)로 변형시키는 직렬화(Serialization) 및 정규화(Normalization) 과정을 소스 코드 레벨에서 추적한다.
1. 단위 변환(Unit Conversion)과 스칼라 정규화
가장 기초적이지만 가장 치명적인 오류를 유발할 수 있는 것이 물리 단위의 불일치다. ECL 코어는 무조건 국제 표준 단위계(SI Units)인 미터(m), 초(s), 라디안(rad), 파스칼(Pa)만을 허용한다.
ekf2 래퍼는 uORB 데이터를 읽어 들인 직후, 변수 할당 단계에서 즉각적으로 스칼라 정규화를 수행한다.
- 기압계(Barometer): 측정된 밀리바(mbar) 단위의 기압을 파스칼 단위로 변환한다.
- GPS 속도: MAVLink 및 uORB에서 흔히 넘어오는 cm/s 단위의 속도 벡터 성분(
vel_n_m_s,vel_e_m_s등)을 소수점 스케일링을 통해 m/s 단위로 강제 캐스팅한다.
// src/modules/ekf2/EKF2.cpp 의 기압계 직렬화 예시 (의사코드)
if (_vehicle_air_data_sub.updated()) {
vehicle_air_data_s air_data;
_vehicle_air_data_sub.copy(&air_data);
baroSample baro_sample;
baro_sample.hgt = _ekf.global_position_to_altitude(air_data.baro_alt_meter);
// ECL 코어로 주입
_ekf.setBaroData(baro_sample);
}
2. 타임스탬프 동기화 및 델타 시간(Delta Time) 연산
센서 데이터가 필터에 주입될 때 가장 중요한 것은 시간의 일관성이다.
NuttX 운영체제는 부팅 후 경과한 마이크로초 단위의 절대 시간(hrt_absolute_time())을 사용하지만, ECL 내부의 EKF 수학 방정식은 이전 스텝에서 현재 스텝까지 ’얼마나 시간이 흘렀는가’를 나타내는 델타 시간(dt) 적분에 의존한다.
2.1 코닝(Coning) 및 스컬링(Sculling) 적분 데이터 변환
특히 EKF 확장의 핵심인 IMU 처리 방식에서 이 과정은 매우 정교하다.
최신 PX4 센서 파이프라인은 단순히 각속도(rad/s)와 가속도(m/s^2)의 스냅샷을 넘기지 않고, 두 샘플 사이의 고주파 신호를 펌웨어 하위 단에서 미리 적분해 놓은 델타 각(Delta Angle, \Delta\theta) 과 델타 속도(Delta Velocity, \Delta v) 를 넘겨준다.
ekf2 브릿지는 이 uORB의 델타 적분값과 그 적분 구간에 소요된 델타 시간 변수를 읽어내어 imuSample 구조체에 꼼꼼하게 직렬화한다.
// IMU 데이터의 직렬화 과정
struct imuSample imu_sample_new;
// 물리적 시간의 상대화
imu_sample_new.time_us = imu.timestamp;
// 각속도 및 가속도의 적분값 복사 (코닝/스컬링 보상 완료 상태)
imu_sample_new.delta_ang(0) = imu.delta_angle[0];
imu_sample_new.delta_ang(1) = imu.delta_angle[1];
imu_sample_new.delta_ang(2) = imu.delta_angle[2];
// 적분 구간 시간 변환 (마이크로초 -> 초)
imu_sample_new.delta_ang_dt = imu.delta_angle_dt * 1.0e-6f;
이러한 직렬화 덕분에 ECL 내부의 predictStates() 함수는 샘플링 주기 변동에 의한 적분 오차 없이 부드러운 상태 전이(State Transition) 행렬을 유도해 낼 수 있다.
3. 공간 정렬: 좌표계(Frame) 회전 및 오프셋 보상
하드웨어 레이아웃의 파편화를 수용하는 브릿지의 마지막 임무는 기준 좌표계(Reference Frame)로의 정렬이다.
3.1 보드 회전(Board Rotation) 보상
실제 비행체 조립 과정에서는 공간상 제약으로 비행 제어기(FC)를 90^\circ 돌려서 장착하거나 뒤집어서 장착하는 경우가 허다하다 (SENS_BOARD_ROT 파라미터). uORB 데이터는 센서 칩셋 자체의 축(Sensor Frame)을 기준으로 출력되지만, ECL 코어는 기체의 앞-오른쪽-아래 축인 FRD (Forward-Right-Down) 기체 프레임을 고집한다.
ekf2 래퍼는 직렬화 직전에 시스템 파라미터에서 추출한 회전 행렬(Rotation Matrix) R_{board} 을 원시 IMU 및 자기장 벡터에 곱해주는 전처리를 수행한다.
3.2 GPS 안테나 편심(Offset) 보상
마찬가지로, GPS 안테나는 보통 기체의 무게 중심(IMU 위치)에서 수십 센티미터 떨어진 마스트(Mast) 위에 설치된다. ekf2 브릿지는 파라미터 매니저로부터 이 3차원 물리적 이격 거리(EKF2_GPS_POS_X, Y, Z)를 읽어와, ECL의 gpsSample 구조체 속성에 위치 오프셋(Offset)으로 직렬화해 준다.
graph LR;
A[uORB 원시 데이터] --> B
subgraph "ekf2 브릿지 직렬화 과정"
B[물리 단위 정규화] --> C[시간 dt / 타임스탬프 상대화]
C --> D[보드 회전행렬 곱연산]
D --> E[물리적 이격 오프셋 속성 부여]
end
E --> F[ECL 내부 C++ 구조체]
4. 요약
ekf2 모듈의 Inbound 직렬화 과정은 단순히 변수를 메모리에 눌러 담는 함수가 아니다. 이것은 파편화된 다종다양한 하드웨어 센서 데이터를 “수학적으로 완벽하게 정제된, 시간과 공간이 통일된 SI 단위계의 고정 배열” 로 변형하는 결벽증적인 전처리 필터(Pre-processing Filter)다.
이 과정을 무사히 통과한 직렬화 데이터만이 비로소 ECL 코어의 엄격한 자코비안(Jacobian) 연산 진입을 허락받게 된다. 다음 절에서는 이렇게 연산이 끝난 후 다시 OS와 MAVLink 세계로 데이터를 내보내는 Outbound 역직렬화(Deserialization) 메커니즘을 분석한다.