21.8.3.1.1. 기압계 돌풍(Gust)에 의한 급격한 고도 스파이크를 오인식하지 않도록 1차 IIR(Infinite Impulse Response) 필터 구현 및 알파(Alpha) 값 튜닝
우리가 앞서 짠 1차 IIR 필터 공식 (ALPHA * raw) + ((1 - ALPHA) * filtered)는 완벽해 보이지만, 현장 비행 테스트(Flight Test)에서 조종사들이 욕을 하며 픽스호크 보드를 떼어 던지게 만드는 주범이 바로 저 ALPHA 값 단위 하나에 숨어있다.
알파 값이 드론의 미션 수행에 미치는 치명적인 영향(Trade-off)을 분석해 보자.
1. 알파(Alpha) 값의 양면성: 부드러움 vs 지연 시간(Latency)
- 상황 A (알파값이 너무 작을 때, 예:
0.01): - 장점: 고도 데이터가 방석처럼 푹신푹신해진다. 거센 돌풍(Gust)이 기압계를 때려 고도가 순간적으로 10m 넘게 튀어도 끄떡하지 않는다.
- 치명적 단점 (위상 지연): 드론이 실제로 이륙해서 50m 목표 고도를 돌파(48m -> 51m)했는데도, 필터링 된 값은 여전히 과거에 얽매여 49.0m, 49.1m… 하며 달팽이처럼 서서히 올라간다. 결국 드론은 50m가 아니라 60m, 70m까지 치솟은 한참 뒤에야 “어라? 50m 넘었네?” 하고 뒷북으로 밸브(TRIGGER)를 열게 된다. 투하 지점이 수십 미터 빗나간다.
- 상황 B (알파값이 너무 클 때, 예:
0.8): - 장점: 거의 실시간(Zero-latency)으로 센서 값을 쫓아간다. 드론이 50m 선을 넘는 즉시 칼같이 투하 밸브가 열린다.
- 치명적 단점 (노이즈 취약): 목표 고도 근처도 안 간 40m 지점에서 돌풍을 한 대 맞고 센서가 51m로 튄 순간, 필터가 그걸 부드럽게 깎아주지 못하고 같이 50m 선을 넘어버려 허공에 약을 다 쏟아버린다.
2. 주파수 응답을 고려한 동적 알파(Dynamic Alpha) 튜닝
항공 엔지니어들은 이 딜레마를 해결하기 위해 하드코딩된 상수가 아니라, Run() 함수의 주파수(dt)와 차단 주파수(Cutoff Frequency)를 계산하여 수학적으로 완벽한 알파 값을 산출하는 방식을 쓴다.
시간 상수(Time Constant, \tau)와 샘플링 타임(dt)을 이용한 알파 값 도출 공식은 다음과 같다.
\alpha = \frac{dt}{\tau + dt}
이 공식의 묘미는, 내 모듈의 루프 속도(dt)가 컴퓨터의 부하 때문에 흔들리더라도 차단 주파수의 성질을 일정하게 유지시켜 준다는 것이다.
void PayloadAutoDrop::Run() {
// 1. 완벽한 dt(Delta Time) 계산
hrt_abstime now = hrt_absolute_time();
float dt_s = (now - _last_run_time) / 1e6f;
_last_run_time = now;
// 2. 동적 알파 값 계산 (시정수 타우 설정)
// 타우(tau)가 0.1초라는 것은, 필터가 센서의 변화량의 63.2%를 따라잡는 데
// 0.1초가 걸린다는 뜻이다. (약 1.5Hz 이상의 튐 성분은 잘라버리겠다는 의미)
const float TAU = 0.1f;
float dynamic_alpha = dt_s / (TAU + dt_s);
// ... (이전과 동일한 필터링 로직에 dynamic_alpha 적용) ...
_filtered_altitude_m = (dynamic_alpha * raw_altitude_m) +
((1.0f - dynamic_alpha) * _filtered_altitude_m);
}
이제 조종사는 QGroundControl에서 소스 코드를 건드리지 않고도 파라미터로 저 TAU 값 하나만 돌려보면서 기체의 진동 억제력과 반응 속도를 즉각적으로 저울질(Tuning)할 수 있게 된다.
노이즈 필터링이 끝났다면, 드디어 우리의 모듈이 uORB 게시판에 단순히 글씨(데이터)를 적는 것을 넘어, 진짜 물리적인 서보 모터의 팔통을 꺾어버리는 ’제어 명령(vehicle_command)’의 치명적인 메커니즘을 21.8.4장에서 결합해 볼 시간이다.