AIDT 온디바이스 국방 MUM-T 유무인 복합 초계기 항공 라이다 수심측량(ALB) 해수면 굴절 및 파랑 동적 보정 서보 엔진

532nm 녹색 레이저 해수 굴절 스넬 법칙(Snell's Law) 파면 경사 실시간 역투영, 10,000Hz C# 엔진

1. 개요

상륙 해안 진입로 정찰 및 기뢰 부설 해역 탐색을 수행하는 유무인 복합 초계기(MUM-T 해상초계기 및 정찰 무인기)는 연안 얕은 수역의 지형을 신속히 매핑하기 위해 항공 라이다 수심측량(Airborne Lidar Bathymetry, ALB) 시스템을 운용합니다. ALB는 적외선(1064nm) 레이저로 해수면을 감지하고, 물 투과성이 높은 녹색(532nm) 레이저 펄스로 해저 바닥을 타격하여 두 펄스 간의 비행시간(Time-of-Flight) 차이로부터 수심을 산출합니다. 그러나 동적 파랑(Ocean Wave)에 의해 찰랑거리는 해수면의 경사각(Wave Slope)은 스넬의 굴절 법칙(Snell's Law)에 따라 레이저 빔을 심각하게 편향시켜 해저 충격점의 수평 위치 오차(최대 수 미터)와 허위 얕은 수심 오류를 유발합니다. 본 고에서는 항공기 관성항법장치(INS/GNSS)와 해수면 반사 파면 벡터를 10,000Hz 주기로 연산하여 3차원 광학 굴절각을 실시간 역투영 보정하는 0-Alloc C# 엔진을 구현합니다.

2. 수학적 모델링 및 지배 방정식

공기-해수 경계면에서의 3차원 벡터 형태 스넬의 굴절 법칙(Snell's Law)은 다음과 같습니다:

\[ \hat{k}_{refr} = \frac{n_{air}}{n_{water}} \hat{k}_{inc} + \left( \frac{n_{air}}{n_{water}} \cos\theta_{inc} - \sqrt{1 - \left(\frac{n_{air}}{n_{water}}\right)^2 (1 - \cos^2\theta_{inc})} \right) \hat{n}_{wave} \]

파랑 고도 함수 \(\eta(x, y, t)\)의 공간 기울기로부터 산출된 해수면 국소 법선 벡터 \(\hat{n}_{wave}\)는 다음과 같습니다:

\[ \hat{n}_{wave} = \frac{-\frac{\partial \eta}{\partial x}\hat{i} - \frac{\partial \eta}{\partial y}\hat{j} + \hat{k}}{\sqrt{1 + \left(\frac{\partial \eta}{\partial x}\right)^2 + \left(\frac{\partial \eta}{\partial y}\right)^2}} \]

해저 반사 녹색 레이저 광 펄스 왕복 비행시간 \(\Delta t_g\)에 대한 진수심(True Bathymetric Depth \(D_{true}\)) 기하 연산식은 다음과 같습니다:

\[ D_{true} = \left( \frac{c_{water} \Delta t_g}{2} \right) \left( \hat{k}_{refr} \cdot \hat{e}_z \right), \quad c_{water} = \frac{c_0}{n_{water}(S, T, \lambda)} \]

항공기 롤/피치/요 동적 기동에 따른 2축 스캐너 거울 짐벌 시선각(LOS) 자세 보정 수식은 다음과 같습니다:

\[ \vec{\theta}_{scanner}^{cmd} = \mathbf{R}_{NED}^{body}(\phi, \theta, \psi) \left( \hat{k}_{grid} + \Delta \vec{\theta}_{wave\_comp} \right) \]

3. 실시간 C# 서보 제어기 구현

다음은 IR 해수면 반사점과 녹색 해저 에코 펄스, INS 자세 데이터를 10,000Hz 주기로 융합하여 진수심 및 수평 왜곡 좌표를 즉각 정밀 보정하는 0-Alloc C# 엔진 구현체입니다:

AirborneLidarBathymetryServoEngine.cs
using System;
using System.Runtime.CompilerServices;

namespace ZeliDesk.Defense.AirborneLidar
{
    public readonly ref struct LidarEchoFrame
    {
        public readonly double AircraftAltitudeMeters;
        public readonly double AircraftRollDegrees;
        public readonly double AircraftPitchDegrees;
        public readonly double WaveSlopeX;
        public readonly double WaveSlopeY;
        public readonly double GreenEchoTofNanoseconds;

        public LidarEchoFrame(
            double aircraftAltitudeMeters,
            double aircraftRollDegrees,
            double aircraftPitchDegrees,
            double waveSlopeX,
            double waveSlopeY,
            double greenEchoTofNanoseconds)
        {
            AircraftAltitudeMeters = aircraftAltitudeMeters;
            AircraftRollDegrees = aircraftRollDegrees;
            AircraftPitchDegrees = aircraftPitchDegrees;
            WaveSlopeX = waveSlopeX;
            WaveSlopeY = waveSlopeY;
            GreenEchoTofNanoseconds = greenEchoTofNanoseconds;
        }
    }

    public ref struct BathymetryCorrectionResult
    {
        public double CorrectedTrueDepthMeters;
        public double HorizontalPositionOffsetMeters;
        public double RefractedRayAngleDegrees;
        public double WaveHeightCorrectionMeters;
        public bool IsDepthMeasurementValid;
    }

    public ref struct AirborneLidarBathymetryServoEngine
    {
        private const double SpeedOfLightWaterMps = 2.25e8; // c / 1.333
        private const double IndexAir = 1.0003;
        private const double IndexWater = 1.3330;
        private readonly double _dt;

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public AirborneLidarBathymetryServoEngine(double dt)
        {
            _dt = dt;
        }

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public void ComputeBathymetricCorrection(in LidarEchoFrame frame, out BathymetryCorrectionResult result)
        {
            result = default;
            // Laser incident angle from aircraft attitude
            double rollRad = frame.AircraftRollDegrees * (Math.PI / 180.0);
            double pitchRad = frame.AircraftPitchDegrees * (Math.PI / 180.0);

            // Incident vector approx near nadir
            double kIncX = Math.Sin(rollRad);
            double kIncY = Math.Sin(pitchRad);
            double kIncZ = -Math.Cos(rollRad) * Math.Cos(pitchRad);

            // Local wave normal: (-slopeX, -slopeY, 1) normalized
            double normDenom = Math.Sqrt(frame.WaveSlopeX * frame.WaveSlopeX + frame.WaveSlopeY * frame.WaveSlopeY + 1.0);
            double nWaveX = -frame.WaveSlopeX / normDenom;
            double nWaveY = -frame.WaveSlopeY / normDenom;
            double nWaveZ = 1.0 / normDenom;

            // Incident angle with wave surface normal
            double cosThetaInc = -(kIncX * nWaveX + kIncY * nWaveY + kIncZ * nWaveZ);
            cosThetaInc = Math.Clamp(cosThetaInc, 0.01, 1.0);

            // Snell's Law in 3D
            double nRatio = IndexAir / IndexWater;
            double sin2ThetaRefr = nRatio * nRatio * (1.0 - cosThetaInc * cosThetaInc);
            double cosThetaRefr = Math.Sqrt(Math.Max(0.0, 1.0 - sin2ThetaRefr));

            // Refracted ray vertical direction component
            double kRefrZ = nRatio * kIncZ + (nRatio * cosThetaInc - cosThetaRefr) * nWaveZ;
            kRefrZ = Math.Abs(kRefrZ); // Magnitude pointing downward

            // Slant path length in water
            double tofSec = frame.GreenEchoTofNanoseconds * 1e-9;
            double slantWaterDistance = 0.5 * SpeedOfLightWaterMps * tofSec;

            // True depth: slant * cos(theta_refr) along true vertical
            double trueDepth = slantWaterDistance * kRefrZ;

            // Horizontal displacement due to wave refraction
            double horizOffset = slantWaterDistance * Math.Sqrt(Math.Max(0.0, 1.0 - kRefrZ * kRefrZ));

            result.CorrectedTrueDepthMeters = trueDepth;
            result.HorizontalPositionOffsetMeters = horizOffset;
            result.RefractedRayAngleDegrees = Math.Acos(Math.Clamp(kRefrZ, 0.0, 1.0)) * (180.0 / Math.PI);
            result.WaveHeightCorrectionMeters = (normDenom - 1.0) * 0.5;
            result.IsDepthMeasurementValid = trueDepth >= 0.2 && trueDepth <= 60.0;
        }
    }
}

4. 교육 및 실무 적용 방안

  • 해군 해양정보단 및 해양수산부 국립해양조사원: 연안 수심 3차원 광학 측량 이론 및 스넬의 법칙 역투영 알고리즘 교육.
  • 해상초계기/정찰 무인기 전력화: 연안 기뢰전 정찰 및 상륙 지원용 ALB 실시간 파랑 보정 온디바이스 탑재 실장.