[하이브리드 항법 시스템: 제3편] 산업용 고성능 INS(관성항법장치) 이해와 GPS 교란 시뮬레이터 만들기

안녕하세요! 자율비행과 무인 항법 기술의 최전선에서 연구에 매진하고 계신 대학생, 그리고 연구원 여러분. 쿼드(QUAD) 드론연구소입니다.

지난 <제2편>에서는 드론의 두뇌 역할을 하는 PX4 EKF2의 상태 추정 원리를 알아보고, 안전한 테스트를 위한 Gazebo SITL 시뮬레이터 환경을 구축해 보았습니다. 가상 환경에서 드론을 띄워보니 어떠셨나요? GPS가 켜져 있을 때는 마치 궤도를 타듯 아주 안정적으로 비행했을 것입니다.

하지만, 만약 시뮬레이터에서 GPS를 강제로 끄면(GNSS-Denied) 어떻게 될까요? 드론은 자신의 위치를 잃고 서서히, 혹은 급격하게 엉뚱한 곳으로 흘러가기 시작합니다. 바로 ‘드리프트(Drift)’ 현상 때문입니다.

이번 **<제3편>**에서는 왜 우리가 흔히 쓰는 저가형 센서만으로는 장거리 ‘추측 항법(Dead Reckoning)’이 불가능한지 그 태생적 한계를 수학적으로 분석해 봅니다. 그리고 이를 극복하기 위해 실제 산업 및 국방 분야에서 사용하는 **고성능 산업용 INS(관성항법장치)**의 하드웨어 기술(MEMS vs FOG)을 깊게 파보겠습니다. 마지막으로 Gazebo 시뮬레이터를 이용해 센서 등급에 따른 오차 발산(Drift)을 직접 시뮬레이션해 보는 시간도 갖겠습니다.


1. 추측 항법의 최대 적: 이중 적분과 오차의 눈덩이 효과

GPS가 끊긴 상황에서 드론은 오직 자신의 내부에 탑재된 **IMU(Inertial Measurement Unit, 관성 측정 장치)**에 의존해야 합니다. IMU는 크게 회전 속도를 측정하는 ‘자이로스코프’와 직선 가속도를 측정하는 ‘가속도계’로 이루어져 있습니다.

추측 항법(Dead Reckoning)으로 위치를 계산하는 원리는 단순합니다.

  1. 가속도계가 측정한 가속도(a)를 한 번 적분하여 **속도(v)**를 구합니다. (v=∫adt)
  2. 구해진 속도를 다시 한번 적분하여 **위치(p)**를 구합니다. (p=∫vdt)

문제는 현실의 센서 데이터에는 항상 **’노이즈(Noise)’**와 **’바이어스(Bias, 영점 편향)’**가 존재한다는 점입니다. 가속도 데이터에 아주 미세한 상수 오차(Bias) ϵ이 섞여 있다고 가정해 봅시다.

  • 속도 오차: ∫ϵdt=ϵt (시간에 비례하여 증가)
  • 위치 오차: ∫ϵtdt=21​ϵt2 (시간의 제곱에 비례하여 폭발적으로 증가)

여기에 자이로스코프의 미세한 각도 오차까지 더해지면 기체의 기울기 계산이 틀어지고, 중력 가속도가 수평 가속도로 잘못 투영되어 위치 오차는 **시간의 3제곱(t3)**에 비례하여 걷잡을 수 없이 발산하게 됩니다. 스마트폰에 들어가는 1천 원짜리 IMU로는 1분만 GPS가 끊겨도 수십, 수백 미터의 오차가 발생하는 이유가 바로 이것입니다.


2. 하드웨어 깊게 파보기: MEMS vs FOG 기술 비교

수백 km를 날아가는 자폭 드론(Kamikaze UAV)이 GPS 없이 목표물에 근접하려면, 이 오차의 누적 속도를 극단적으로 늦춰줄 **고성능 관성항법장치(INS)**가 필요합니다. 산업용 INS 센서는 크게 두 가지 기술로 나뉩니다.

📍 FOG (Fiber Optic Gyroscope, 광섬유 자이로스코프)

  • 원리: 광섬유 코일을 빛이 양방향으로 순환할 때, 센서가 회전하면 한쪽 빛의 경로가 길어져 도달 시간에 차이가 발생하는 ‘사냑 효과(Sagnac Effect)’를 이용합니다.
  • 특징: 기계적인 마찰이나 움직이는 부품이 없어 진동에 매우 강하며, 바이어스 불안정성(Bias Instability)이 0.003∘/hr 이하로 측정될 만큼 초정밀을 자랑합니다. 잠수함이나 대형 항공기, 장거리 순항 미사일에 주로 쓰입니다.
  • 단점: 코일을 감아야 하므로 부피가 크고 무거우며(수 kg 단위), 가격이 수천만 원에서 수억 원에 달합니다. 소형 자폭 드론에 싣기에는 SWaP-C(Size, Weight, Power, and Cost) 측면에서 매우 부적합합니다.

📍 MEMS (Micro-Electro-Mechanical Systems, 미세 기계 전자 시스템)

  • 원리: 실리콘 반도체 내부에 머리카락보다 얇은 미세한 빗살 모양의 구조물을 만들고, 회전이나 가속 시 구조물이 미세하게 흔들리며 변하는 정전 용량(Capacitance)을 측정합니다.
  • 특징: 초소형, 초경량(수십 그램), 저전력이며 대량 생산이 가능해 저렴합니다.
  • 단점 및 극복: 과거에는 노이즈가 심해 스마트폰이나 완구용 드론에만 쓰였으나, 최근에는 가공 기술과 온도 보정(Calibration) 알고리즘이 비약적으로 발전했습니다. 바이어스 불안정성이 1.5∘/hr 수준으로 낮아진 ‘전술급(Tactical Grade)’ MEMS INS가 등장하면서 판도가 바뀌었습니다.

💡 자폭 드론을 위한 센서 선택 가이드 (SWaP-C 고려)

비행기나 헬기와 달리 한 번 날아가면 돌아오지 않는 자폭 드론, 혹은 크기가 작은 정찰용 드론에는 **’전술급 하이엔드 MEMS INS’**가 최적의 선택입니다. 대표적으로 SBG Systems의 Ellipse-D / Ekinox Micro, MicroStrain의 3DM-GQ7 / 3DM-CV7, 그리고 Honeywell의 HG4930과 같은 제품들이 시장을 선도하고 있습니다. 이 제품들은 10~100g 내외의 가벼운 무게임에도 불구하고 자체적인 칼만 필터(EKF)를 내장하여 수십 분 동안의 GPS 단절(Outage) 상황에서도 수 미터 이내로 오차를 억제하는 놀라운 성능을 보여줍니다.


3. [실습] Python을 이용한 INS 등급별 오차 누적 시뮬레이션

백문이 불여일견입니다. 그렇다면 센서의 등급에 따라 장거리 비행 시 추측 항법의 위치 오차가 얼마나 차이 나는지 Python 시뮬레이션을 통해 직접 확인해 보겠습니다.

우리는 센서의 스펙 시트에 나오는 핵심 지표인 **바이어스 불안정성(Bias Instability)**과 **백색 잡음(Random Walk)**을 기반으로 1차원 가속도 이중 적분 모델을 만들 것입니다.

[요구 사항] numpymatplotlib 라이브러리가 설치된 Python 환경을 준비해 주세요.

Python
import numpy as np
import matplotlib.pyplot as plt

def simulate_ins_1d(duration_sec, dt, accel_bias_mg, velocity_random_walk):
    """
    1차원(직선) 비행 조건에서 센서 노이즈에 따른 추측 항법 위치 오차를 시뮬레이션합니다.
    :param duration_sec: 총 비행 시간 (초)
    :param dt: 샘플링 시간 (초)
    :param accel_bias_mg: 가속도계 바이어스 (mg, 1mg = 0.001g)
    :param velocity_random_walk: 속도 랜덤 워크 노이즈 (m/s/sqrt(hr))
    """
    g = 9.80665  # 중력 가속도 (m/s^2)
    n_steps = int(duration_sec / dt)
    time = np.linspace(0, duration_sec, n_steps)
    
    # 1. 실제 기체는 일정한 속도로 직진한다고 가정 (실제 가속도 = 0)
    true_accel = np.zeros(n_steps)
    
    # 2. 센서 스펙 단위 변환
    bias_m_s2 = (accel_bias_mg / 1000.0) * g
    # VRW 단위를 이산 시간의 표준편차로 변환: (m/s/sqrt(hr)) -> (m/s^2)
    noise_std_dev = (velocity_random_walk / 60.0) * (1 / np.sqrt(dt))
    
    # 3. 가속도계 측정값 생성 (실제 가속도 + 바이어스 + 백색 잡음)
    noise = np.random.normal(0, noise_std_dev, n_steps)
    measured_accel = true_accel + bias_m_s2 + noise
    
    # 4. 추측 항법 (이중 적분: 가속도 -> 속도 -> 위치)
    estimated_vel = np.zeros(n_steps)
    estimated_pos = np.zeros(n_steps)
    
    for i in range(1, n_steps):
        estimated_vel[i] = estimated_vel[i-1] + measured_accel[i] * dt
        estimated_pos[i] = estimated_pos[i-1] + estimated_vel[i] * dt
        
    return time, estimated_pos

# --- 시뮬레이션 파라미터 설정 ---
duration = 600  # 10분(600초) 동안 GPS 끊김 가정
dt = 0.01       # 100Hz 샘플링

# 1. 저가형 Consumer IMU (스마트폰, 장난감 드론 급)
# 가속도 바이어스: 약 2mg, VRW: 0.1 m/s/sqrt(hr)
time, pos_consumer = simulate_ins_1d(duration, dt, accel_bias_mg=2.0, velocity_random_walk=0.1)

# 2. 전술급 Tactical MEMS INS (자폭 드론 타겟 센서)
# 가속도 바이어스: 약 0.05mg, VRW: 0.02 m/s/sqrt(hr)
time, pos_tactical = simulate_ins_1d(duration, dt, accel_bias_mg=0.05, velocity_random_walk=0.02)

# 3. 고정밀 Navigation Grade FOG (군용 순항 미사일 급)
# 가속도 바이어스: 약 0.005mg, VRW: 0.005 m/s/sqrt(hr)
time, pos_nav = simulate_ins_1d(duration, dt, accel_bias_mg=0.005, velocity_random_walk=0.005)

# --- 그래프 시각화 ---
plt.figure(figsize=(10, 6))
plt.plot(time, pos_consumer, label="Low-cost Consumer IMU Error", color='red')
plt.plot(time, pos_tactical, label="Tactical MEMS INS Error (e.g., SBG, MicroStrain)", color='blue', linewidth=2)
plt.plot(time, pos_nav, label="Navigation Grade FOG Error", color='green', linewidth=2)

plt.title("Position Drift Over Time Without GPS (10 Minutes)")
plt.xlabel("Time (seconds)")
plt.ylabel("Position Error (meters)")
plt.legend()
plt.grid(True)
plt.show()

[코드 분석 및 결과 해석] 위 코드를 실행해 보면 놀라운 결과를 확인할 수 있습니다. 실제로는 가만히 있거나 일정한 속도로 날아가고 있음에도 불구하고, 가속도계의 미세한 오차가 적분되면서 **저가형 센서(빨간 선)**는 10분 만에 오차가 수십~수백 미터, 심지어 수 킬로미터까지 치솟아 곡선을 그리며 발산합니다.

반면, 우리가 도입할 **전술급 MEMS INS(파란 선)**는 오차 증가 곡선이 훨씬 완만하여 10분이 지나도 수 미터~수십 미터 내외로 오차를 선방해 냅니다. 고정밀 FOG 센서(초록 선)는 거의 바닥에 붙어있습니다.

이 실험을 통해 우리는 **”왜 장거리 비행 드론에는 수백만 원짜리 전술급 INS를 탑재해야만 하는가?”**에 대한 명확한 해답을 얻을 수 있습니다.


4. Gazebo SITL 환경에서의 센서 노이즈 모델링

방금 Python으로 확인한 수학적 모델을 우리가 앞서 <제2편>에서 구축한 Gazebo SITL 시뮬레이터에 적용할 수도 있습니다. 시뮬레이터 상의 가상 드론이 실제 산업용 드론과 똑같은 오차 특성을 가지도록 만들려면, Gazebo의 imu_sensor 플러그인(Plugin) 설정을 수정해야 합니다.

드론의 IMU(INS) 특성 변경

/home/quad/PX4-Autopilot/Tools/simulation/gz/models/x500_base/model.sdf

XML
      <sensor name="imu_sensor" type="imu">
        <always_on>1</always_on>
        <update_rate>250</update_rate>
        <imu>
          <angular_velocity>
            <x>
              <noise type="gaussian">
                <mean>0</mean>
                <stddev>0.0000436</stddev> <!-- 자이로 ARW -->
                <dynamic_bias_stddev>0.00000727</dynamic_bias_stddev> <!-- 자이로 바이어스 불안정성 -->
                <dynamic_bias_correlation_time>400.0</dynamic_bias_correlation_time>
              </noise>
            </x>
            <y>
              <noise type="gaussian">
                <mean>0</mean>
                <stddev>0.0000436</stddev>
                <dynamic_bias_stddev>0.00000727</dynamic_bias_stddev>
                <dynamic_bias_correlation_time>400.0</dynamic_bias_correlation_time>
              </noise>
            </y>
            <z>
              <noise type="gaussian">
                <mean>0</mean>
                <stddev>0.0000436</stddev>
                <dynamic_bias_stddev>0.00000727</dynamic_bias_stddev>
                <dynamic_bias_correlation_time>400.0</dynamic_bias_correlation_time>
              </noise>
            </z>
          </angular_velocity>
          <linear_acceleration>
            <x>
              <noise type="gaussian">
                <mean>0</mean>
                <stddev>0.000196</stddev> <!-- 가속도계 VRW -->
                <dynamic_bias_stddev>0.000049</dynamic_bias_stddev> <!-- 가속도계 바이어스 불안정성 -->
                <dynamic_bias_correlation_time>400.0</dynamic_bias_correlation_time>
              </noise>
            </x>
            <y>
              <noise type="gaussian">
                <mean>0</mean>
                <stddev>0.000196</stddev>
                <dynamic_bias_stddev>0.000049</dynamic_bias_stddev>
                <dynamic_bias_correlation_time>400.0</dynamic_bias_correlation_time>
              </noise>
            </y>
            <z>
              <noise type="gaussian">
                <mean>0</mean>
                <stddev>0.000196</stddev>
                <dynamic_bias_stddev>0.000049</dynamic_bias_stddev>
                <dynamic_bias_correlation_time>400.0</dynamic_bias_correlation_time>
              </noise>
            </z>
          </linear_acceleration>
        </imu>
      </sensor>

GPS 교란

PX4 시뮬레이션에서 GPS 노이즈를 실시간으로 제어할 수 있도록 다음과 같은 파일들을 수정했습니다. 주요 목표는 Gazebo 모델의 navsat 센서에 노이즈를 추가하고, PX4의 GPS 시뮬레이션 모듈에 동적 파라미터를 추가하는 것이었습니다.

  1. /home/quad/PX4-Autopilot-1.15.4/src/modules/simulation/sensor_gps_sim/parameters.c
  2. /home/quad/PX4-Autopilot-1.15.4/src/modules/simulation/sensor_gps_sim/SensorGpsSim.hpp
  3. /home/quad/PX4-Autopilot-1.15.4/src/modules/simulation/sensor_gps_sim/SensorGpsSim.cpp
1. parameters.c
  • 수정 내용: 새로운 GPS 노이즈 파라미터 추가
  • 세부 사항:
    • SIM_GPS_POS_STD: 위치 노이즈 표준편차 (기본 0.2m, 범위 0-100m)
    • SIM_GPS_ALT_STD: 고도 노이즈 표준편차 (기본 0.5m, 범위 0-100m)
    • SIM_GPS_VXY_STD: XY 속도 노이즈 표준편차 (기본 0.06m/s, 범위 0-100m/s)
    • SIM_GPS_VZ_STD: Z 속도 노이즈 표준편차 (기본 0.158m/s, 범위 0-100m/s)
  • 목적: QGroundControl에서 실시간으로 GPS 노이즈를 조정할 수 있도록 파라미터화
2. SensorGpsSim.hpp
  • 수정 내용: 새로운 파라미터 정의 추가
  • 세부 사항: DEFINE_PARAMETERS 매크로에 위의 4개 파라미터 추가
  • 목적: 헤더 파일에서 파라미터 선언
3. SensorGpsSim.cpp
  • 수정 내용: GPS 노이즈 계산을 파라미터 기반으로 변경
  • 세부 사항:
    • 위도/경도 노이즈: _sim_gps_pos_std.get() 사용
    • 고도 노이즈: _sim_gps_alt_std.get() 사용
    • 속도 노이즈: _sim_gps_vxy_std.get(), _sim_gps_vz_std.get() 사용
    • 타입 캐스팅 수정 (float → double 변환 경고 해결)
  • 목적: 하드코딩된 노이즈 값을 동적 파라미터로 대체하여 실시간 조정 가능

이러한 수정으로 시뮬레이터 실행 중에 GPS 노이즈를 동적으로 테스트할 수 있게 되었습니다.


마무리하며

이번 **<제3편>**에서는 추측 항법이 가지는 수학적 한계(이중 적분에 의한 오차의 눈덩이 효과)를 분석하고, 이를 방어하기 위한 필수 하드웨어인 **산업용 고성능 INS(전술급 MEMS)**의 중요성을 살펴보았습니다. 또한, 파이썬을 통한 시뮬레이션으로 스펙 시트의 숫자가 실제 비행 궤적에 어떤 결과를 초래하는지 눈으로 직접 확인했습니다.

하지만 아무리 좋은 전술급 MEMS INS를 사용하더라도, 수백 킬로미터를 날아가면 결국 오차는 수백 미터 이상 벌어지게 됩니다. 즉, 하드웨어만으로는 완벽할 수 없습니다.

그래서 다음 **<제4편>**에서는 외부 고성능 INS가 뽑아낸 정밀한 오도메트리(Odometry) 데이터를 ROS 2 통신 브릿지를 통해 PX4의 비행 제어 루프 속으로 자연스럽게 주입(Injection)하고 융합하는 실전 소프트웨어 통합 아키텍처에 대해 다뤄보겠습니다. 자폭 드론의 두뇌와 감각 기관이 하나로 연결되는 다음 연재도 기대해 주세요!


YouTube Tutorial

재생

Author: maponarooo, CEO of QUAD Drone Lab

Date: April 17, 2026

Similar Posts

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 필드는 *로 표시됩니다