21.8.3. 센서 노이즈 필터링 및 이벤트 발동(Trigger) 조건식
지금까지 우리는 FSM의 뼈대를 세우고 안전장치(Interlock)를 걸어 잠근 뒤, 20ms마다 깨어나 상태를 비틀어대는 구조체를 완성했다.
하지만 남은 가장 무서운 적은 바로 ‘물리적 세계의 불확실성’, 즉 센서 노이즈(Sensor Noise) 다.
FSM이 STATE_ARMED(무장) 상태에서 STATE_TRIGGER(투하) 상태로 천이하기 위한 유일한 조건은 “현재 고도가 목표 고도(TARGET_ALT)를 넘었는가?” 이다.
// [초보자의 순진한 발동 조건식]
if (_current_altitude >= _target_altitude) {
_current_state = AppState::TRIGGER;
}
만약 드론이 아직 목표 고도인 50m에 도달하지 않고 48m 부근을 날아가고 있다고 치자.
그런데 갑자기 강력한 산바람(Gust)이 불어와 드론을 때리면, 기압계 센서는 순간적인 압력 강하를 ’고도 상승’으로 착각하여 단 1프레임(20ms) 동안 고도 값을 55m로 튀게(Spike) 만든다. EKF 필터가 이를 억누르기 전, 우리의 모듈이 하필 그 20ms의 찰나에 깨어나 저 조건식을 검사한다면?
투하 지점도 아닌 엉뚱한 하늘 한가운데서 약을 다 쏟아버리고 수백만 원짜리 임무를 망치게 된다.
1. 로우 데이터(Raw Data)의 함정
uORB 토픽(vehicle_local_position_s)에서 꺼내온 고도(z) 값은 EKF라는 위대한 필터를 거치긴 했으나, 완전히 매끄러운 유리구슬 같은 상태는 아니다. 물리적인 픽스호크 보드의 진동, 프로펠러의 난기류, 기상 변화 등이 섞여 항상 미세한 톱니바퀴 마냥 출렁이고 있다.
이 출렁이는 데이터를 그대로 FSM 루프의 방아쇠(Trigger) 조건식에 집어넣는 행위는 룰렛 게임을 하는 것과 같다.
진정한 항공 코어 시스템 엔지니어라면, 이 ‘순간적인 튐(Spike)’ 현상들에 방아쇠가 당겨지지 않도록 소프트웨어적인 쿠션(Cushion)을 FSM 진입관문 바로 앞에 설치해야만 한다.
2. 노이즈 필터링 전략
드론 제어 시스템에서 이런 종류의 고주파 센서 노이즈를 짓누르기 위해 주로 사용하는 두 가지 핵심 전략이 있다.
- Low Pass Filter (LPF, 저주파 통과 필터): 현재 들어온 튀는 데이터와 과거의 안정적인 데이터를 적당한 비율로 섞어버림으로써 뾰족한 가시를 둥글게 깎아내는 방법.
- Hysteresis (히스테리시스/이력 현상): 조건의 문턱(Threshold)을 넘었다고 즉시 격발하는 것이 아니라, “문턱을 넘은 상태가 일정 시간(예: 0.5초) 이상 끈질기게 유지되는가?“를 검사하는 타이머 기반 딜레이 검증 방법.
이 두 가지 필터링 기법들을 우리의 FSM 조건식 앞에 어떻게 C++ 코드로 유려하게 심어 넣을 수 있는지, 그 첫 번째 무기인 ’1차 IIR 기반 LPF 알고리즘’부터 다음 장 21.8.3.1에서 구현해 보자.