27.3.1.8. 2차원 풍속(Wind Velocity) 추정 모델 변수 할당 (인덱스 22~23)

27.3.1.8. 2차원 풍속(Wind Velocity) 추정 모델 변수 할당 (인덱스 22~23)

EKF 24상태 공간의 길고 긴 여정 끝에 만나는 마지막 2개의 인덱스(22~23번)는 공기역학적인 힘에 의존하는 고정익(Fixed-wing)과 VTOL(Vertical Take-Off and Landing) 기체에 있어서 가장 생존과 직결된 외부 환경 변수인 바람(Wind) 을 추정하는 데 쓰인다.

본 절에서는 StateSample 구조체의 마지막 꼬리를 장식하는 2차원 풍속 벡터(Wind Velocity Vector)의 물리적 정의와, 이 변수가 대기속도(Airspeed) 센서 데이터와 결합하여 어떻게 실시간으로 추정되는지 분석한다.


1. 상태 변수 매핑: idx: 22~23

src/lib/ecl/EKF/common.h 파일의 StateSample 구조체 선언부 맨 마지막을 보면, 인덱스 22번부터 시작하는 길이 2의 슬라이스가 wind_vel 이라는 이름으로 할당되어 있다.

// src/lib/ecl/EKF/common.h 내부의 풍속 슬라이싱
struct StateSample {
    matrix::Vector<float, 24> states;

    // ... (0~21 인덱스는 quat, vel, pos, gyro/accel biases, mag_I, mag_B)

    // 인덱스 22부터 시작하는 길이 2의 슬라이스를 2차원 풍속 벡터로 선언
    const matrix::Vector2f& wind_vel{states.slice<2, 1>(22, 0)}; 
};

wind_vel 참조자가 포인팅하는 두 개의 실수 v_{w,N}, v_{w,E} 의 물리적 의미는 지구 고정 프레임인 NED(North-East-Down) 좌표계 기준 수평 방향으로 불어오는 바람의 속도(m/s) 이다.

  • states[22] (v_{w,N}): 북쪽(North)을 향해 불어가는 바람의 속도 성분 (m/s)
  • states[23] (v_{w,E}): 동쪽(East)을 향해 불어가는 바람의 속도 성분 (m/s)

수직 낙하 기류(Down draft)나 상승 기류(Thermal) 같은 3차원 바람(Z축 성분)은 추정의 한계성 및 복잡도 증가 문제로 24상태 EKF 모델에는 포함되지 않고 무시된다.


2. 대지속도(Ground Speed)와 대기속도(Airspeed)의 상관관계

이 2차원 풍속 벡터의 수학적 조립 원리를 이해하려면, 비행기 역학의 가장 유명한 공식인 ’바람 삼각형(Wind Triangle)’을 상기해야 한다.

\vec{V}_{Ground} = \vec{V}_{Air} + \vec{V}_{Wind}

  • \vec{V}_{Ground}: 기체가 지면을 기준으로 이동하는 실제 속도 (GPS 속도 또는 EKF의 4~6번 인덱스 vel 변수)
  • \vec{V}_{Air}: 기체가 대기를 뚫고 지나가는 속도 (피토관(Pitot tube) 기반 Airspeed 센서 측정치)
  • \vec{V}_{Wind}: 대기(공기 덩어리) 자체가 지면을 기준으로 이동하는 속도 (우리가 구하고자 하는 22~23번 상태 변수)

우리가 얻을 수 있는 확실한 데이터는 기수가 향하는 방향으로 맞바람이 얼마나 세게 들어오는지 측정하는 피토관의 ’대기속도(Airspeed) 스칼라 값’과, 하늘 어딘가에서 GPS가 쏴주는 지면 기준 ‘대지속도(Ground Speed) 벡터값’ 두 개뿐이다.
EKF는 이 두 가지 데이터를 융합(Fusion)하여 바람의 방향과 속도를 역산(Inverse)해 낸다.


3. 선회 비행(Loiter)을 통한 풍속 360도 교차 검증

하지만 기체가 직선 비행만을 수행하면 문제가 발생한다. 뒤에서 부는 약한 뒷바람(Tail wind)인지, 아니면 기체가 엔진 출력을 내어 앞으로 빨리 날아가는 중인지 측정값만으로는 수학적으로 구분할 방도가 없기 때문이다 (관측성, Observability 부족).

풍속 추정 상태 변수(22~23번)가 진정한 효력을 발휘하려면 기체가 허공에서 원을 그리며 도는 선회 비행(Loiter/Orbit) 을 수행해야 한다.

  1. 기체가 일정한 대기속도(Airspeed, 예: 15m/s)를 유지하며 원을 그린다.
  2. 이때 만약 서쪽에서 동쪽으로 부는 강렬한 편서풍(West wind, V_{wind,E} > 0)이 불고 있다면?
  3. 비행기가 서쪽(바람 부는 방향)을 향해 헤딩을 틀 때는 맞바람이 불어 GPS 대지속도가 뚝 떨어질 것이고, 반대로 동쪽을 향해 헤딩을 틀 때는 뒷바람을 맞아 GPS 대지속도가 급격히 솟구칠 것이다.
  4. EKF 공분산 연산 루틴은 원을 그리는 내내 요동치는 GPS 속도(\vec{V}_{Ground})와 꼿꼿이 유지되는 대기속도(\vec{V}_{Air})의 차이(Innovation)를 체인 룰로 묶어 계산해 낸다.
  5. 가장 차이가 극심하게 벌어지는 지점의 벡터 성분을 파악하여 22번(v_{w,N})과 23번(v_{w,E}) 인덱스에 ’진짜 바람의 속도와 방향’을 채워 넣는다.

이 풍속 추정이 완료되면 기체는 비로소 바람에 떠밀리기 전에 기수를 바람 부는 쪽으로 살짝 비틀어 넣는 크랩 비행(Crabbing) 각도를 계산할 수 있게 되어, 어떤 악천후 속에서도 경로를 벗어나지 않고 완벽한 직선 궤적(Straight-line Trajectory)을 유지할 수 있게 된다.

자, 이로써 0번 쿼터니언부터 23번 풍속 벡터까지 EKF 24상태의 거대한 구조체 매핑 분석을 모두 완주했다. 다음 절에서는 이 24개의 변수를 매 밀리초(ms) 단위로 앞을 향해 밀어내는 거대한 선형 변환의 수레바퀴, 상태 예측 함수(predictState)의 실제 C++ 동역학 구현체 내부로 직접 들어가 보겠다.