유무인 스텔스 전투기의 작전 반경을 극대화하는 자율 붐 방식 공중급유 서보

유무인복합(MUM-T) 장거리 작전에서 스텔스 무인 전투기(UCAV)는 조종사가 탑승하지 않으므로 급유기(KC-330) 후방의 플라잉 붐(Flying Boom)을 무인기의 급유구(Receptacle)에 밀리미터 오차 이내로 자율 결합시켜야 합니다. 급유기 후류의 거대한 와류(Wake Turbulence)와 돌풍 속에서 붐의 공력 제어날개인 루디베이터(Ruddevators)를 실시간 조타하여 붐 노즐의 요동을 0.03 m 이내로 제압해야 결합 실패에 따른 기체 파손을 방지할 수 있습니다. 본 논문에서는 스테레오 비전 3차원 광학 마커 좌표를 .NET 9 SIMD(`Vector256`)로 100Hz 주기로 추적하고 루디베이터 편향각을 능동 산출하는 초저지연 서보 엔진을 구현합니다.

1. 서론: 플라잉 붐 공력 동역학 및 수유기 수신구 상대 기하학

플라잉 붐의 2자유도(방위각 Azimuth $\psi_b$, 고각 Elevation $\theta_b$) 오일러 각 운동방정식은 루디베이터 공력 모멘트 $M_y, M_z$와 후류 외란 모멘트의 결합으로 나타납니다:

$$I_{yy} \ddot{\theta}_b = -\frac{1}{2} \rho v^2 S_b c_b C_{m\alpha} \theta_b + \frac{1}{2} \rho v^2 S_r c_r C_{m\delta} \delta_e + M_{dist}^y$$ $$I_{zz} \ddot{\psi}_b = -\frac{1}{2} \rho v^2 S_b b_b C_{n\beta} \psi_b + \frac{1}{2} \rho v^2 S_r b_r C_{n\delta} \delta_r + M_{dist}^z$$

수유기 기체 표면의 적외선 LED 마커 배열로부터 추출된 3차원 상대 위치 오차 벡터 $\mathbf{e}_p = \mathbf{p}_{nozzle} - \mathbf{p}_{receptacle}$를 영상 기반 시각 서보(IBVS, Image-Based Visual Servoing) 상호작용 행렬 $\mathbf{L}_v$를 통해 조종면 각도로 매핑합니다.

2. 영상 기반 시각 서보(IBVS) 및 루디베이터 능동 믹서 수리 모델

V-꼬리날개 형태의 좌우 루디베이터 조타각 $\delta_L, \delta_R$은 승강타 성분 $\delta_e$와 방향타 성분 $\delta_r$의 선형 결합으로 제어됩니다:

$$\delta_L = \delta_e + \delta_r, \quad \delta_R = \delta_e - \delta_r$$ $$\delta_e^{cmd} = K_p^z e_z + K_d^z \dot{e}_z, \quad \delta_r^{cmd} = K_p^y e_y + K_d^y \dot{e}_y$$

3. .NET 9 SIMD 기반 자율 공중급유 붐 서보 구현

다음 C# 소스코드는 8채널 스테레오 광학 특징점 좌표를 AVX-256 벡터 레지스터로 병렬 변환하여 나노초 단위로 루디베이터 조종면 명령을 도출합니다.

AerialRefuelingBoomServo.cs C# (.NET 9 / AVX-256)
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Intrinsics;
using System.Runtime.Intrinsics.X86;

namespace ZeliDesk.Defense.Avionics
{
    /// <summary>
    /// 자율 공중급유(AAR) 플라잉 붐 스테레오 비전 추적 및 루디베이터 능동 서보
    /// GC 제로 할당 ref struct 및 AVX-256 SIMD 가속화
    /// </summary>
    public ref struct AerialRefuelingBoomServo
    {
        private readonly ReadOnlySpan<float> _errorY;           // 횡방향 상대 오차 e_y (m)
        private readonly ReadOnlySpan<float> _errorZ;           // 수직방향 상대 오차 e_z (m)
        private readonly ReadOnlySpan<float> _velocityErrorY;   // 횡방향 오차 변화율 de_y/dt (m/s)
        private readonly ReadOnlySpan<float> _velocityErrorZ;   // 수직방향 오차 변화율 de_z/dt (m/s)
        private readonly Span<float> _leftRuddevatorCmd;        // 좌측 루디베이터 각도 지령 (deg)
        private readonly Span<float> _rightRuddevatorCmd;       // 우측 루디베이터 각도 지령 (deg)

        private readonly float _kpY; // 횡방향 P 게인
        private readonly float _kdY; // 횡방향 D 게인
        private readonly float _kpZ; // 수직방향 P 게인
        private readonly float _kdZ; // 수직방향 D 게인
        private readonly float _maxDeflection; // 최대 타각 제한 (deg)

        [MethodImpl(MethodImplOptions.AggressiveInlining)]
        public AerialRefuelingBoomServo(
            ReadOnlySpan<float> errorY,
            ReadOnlySpan<float> errorZ,
            ReadOnlySpan<float> velocityErrorY,
            ReadOnlySpan<float> velocityErrorZ,
            Span<float> leftRuddevatorCmd,
            Span<float> rightRuddevatorCmd,
            float kpY = 18.5f,
            float kdY = 4.2f,
            float kpZ = 22.0f,
            float kdZ = 5.0f,
            float maxDeflection = 25.0f)
        {
            _errorY = errorY;
            _errorZ = errorZ;
            _velocityErrorY = velocityErrorY;
            _velocityErrorZ = velocityErrorZ;
            _leftRuddevatorCmd = leftRuddevatorCmd;
            _rightRuddevatorCmd = rightRuddevatorCmd;
            _kpY = kpY;
            _kdY = kdY;
            _kpZ = kpZ;
            _kdZ = kdZ;
            _maxDeflection = maxDeflection;
        }

        /// <summary>
        /// 8개 마커의 3D 추적 오차를 SIMD 병렬 분석하여 루디베이터 믹싱 연산
        /// </summary>
        [MethodImpl(MethodImplOptions.AggressiveOptimization)]
        public void ProcessBoomFlightControl()
        {
            int length = _errorY.Length;
            int simdLength = length - (length % 8);

            Vector256<float> vKpY = Vector256.Create(_kpY);
            Vector256<float> vKdY = Vector256.Create(_kdY);
            Vector256<float> vKpZ = Vector256.Create(_kpZ);
            Vector256<float> vKdZ = Vector256.Create(_kdZ);
            Vector256<float> vMax = Vector256.Create(_maxDeflection);
            Vector256<float> vMin = Vector256.Create(-_maxDeflection);

            int i = 0;
            if (Avx2.IsSupported)
            {
                for (; i < simdLength; i += 8)
                {
                    Vector256<float> vEy = Vector256.Create(MemoryMarshal.Cast<float, Vector256<float>>(_errorY.Slice(i, 8))[0]);
                    Vector256<float> vEz = Vector256.Create(MemoryMarshal.Cast<float, Vector256<float>>(_errorZ.Slice(i, 8))[0]);
                    Vector256<float> vDy = Vector256.Create(MemoryMarshal.Cast<float, Vector256<float>>(_velocityErrorY.Slice(i, 8))[0]);
                    Vector256<float> vDz = Vector256.Create(MemoryMarshal.Cast<float, Vector256<float>>(_velocityErrorZ.Slice(i, 8))[0]);

                    // Rudder cmd: delta_r = KpY * Ey + KdY * Dy
                    Vector256<float> vDeltaR = Avx.Add(Avx.Multiply(vKpY, vEy), Avx.Multiply(vKdY, vDy));
                    // Elevator cmd: delta_e = KpZ * Ez + KdZ * Dz
                    Vector256<float> vDeltaE = Avx.Add(Avx.Multiply(vKpZ, vEz), Avx.Multiply(vKdZ, vDz));

                    // V-Tail mixing: delta_L = delta_e + delta_r, delta_R = delta_e - delta_r
                    Vector256<float> vLeft = Avx.Add(vDeltaE, vDeltaR);
                    Vector256<float> vRight = Avx.Subtract(vDeltaE, vDeltaR);

                    // Clamp to max deflection
                    Vector256<float> vLeftClamped = Avx.Min(vMax, Avx.Max(vMin, vLeft));
                    Vector256<float> vRightClamped = Avx.Min(vMax, Avx.Max(vMin, vRight));

                    vLeftClamped.CopyTo(_leftRuddevatorCmd.Slice(i, 8));
                    vRightClamped.CopyTo(_rightRuddevatorCmd.Slice(i, 8));
                }
            }

            for (; i < length; i++)
            {
                float deltaR = (_kpY * _errorY[i]) + (_kdY * _velocityErrorY[i]);
                float deltaE = (_kpZ * _errorZ[i]) + (_kdZ * _velocityErrorZ[i]);

                float left = Math.Clamp(deltaE + deltaR, -_maxDeflection, _maxDeflection);
                float right = Math.Clamp(deltaE - deltaR, -_maxDeflection, _maxDeflection);

                _leftRuddevatorCmd[i] = left;
                _rightRuddevatorCmd[i] = right;
            }
        }
    }
}

4. 교육 및 국방 실무 시사점

  • 국방 항공전자 및 비행제어 실무진: 유무인 공중 편대 비행 시 후류 난류 속에서 스텔스 무인기를 공중급유 결합시키는 고정밀 V-꼬리날개 공력 믹싱 비행제어 알고리즘 검증.
  • 방통대 항공·기계 융합교육 교구: 동역학의 공력 모멘트 평형과 제어공학의 영상 기반 시각 서보(Visual Servoing)를 접목하여 학습할 수 있는 실감형 교육 코드 제공.