1. κ°μ: 2022 κ°μ λΉμ ν μ μ΄ κ΅μ‘κ³Ό κ΅λ°© κ·Ήμ΄μμ λΉν μ μ΄ κΈ°μ μ£ΌκΆ
2022 κ°μ κ΅μ‘κ³Όμ 물리·μ 보·μν μ΅ν© νꡬμμ μν κ³΅κ° μ μ΄ μ΄λ‘ , λΉμ ν λμν, μμ νλ©΄(Phase Plane), λ° λ¦¬μνΈλ Έν(Lyapunov) μμ μ± νμ λ²μ λλ‘ , λ‘λ΄, μ°μ£Όμ λ± μ€μΈκ³ κΈ°κ³ μμ€ν μ λΆνμ€μ±μ 극볡νκ³ λͺ©ν μνλ‘ μλ²½ν μλ ΄μν€λ νλ μ μ΄κ³΅νμ μ μ μ λλ€. νμλ€μ κ³ μ PID μ μ΄κ° μμΈ‘ λΆκ°λ₯ν μΈλκ³Ό κΈκ²©ν νκ²½ λ³νμμ κ²ͺλ νκ³λ₯Ό κΉ¨λ«κ³ , κ°μΈ μ μ΄(Robust Control)μ λν μ£ΌμμΈ μ¬λΌμ΄λ© λͺ¨λ μ μ΄(Sliding Mode Control, SMC)μ κΈ°ννμ μλ ₯μ νꡬν©λλ€.
λμμ λνλ―Όκ΅ κ΅λ°© ν곡μ°μ£Ό μ λ ₯μ ν΅μ¬μΈ μ°¨μΈλ 6μΈλ μ€ν μ€ μ Β·λ¬΄μΈ λ³΅ν© μ ν¬κΈ° λ° κ·Ήμ΄μμ ν곡 λΉν체(HGV)λ λ§ν 5(Mach 5+) μ΄μμ μ΄κ³ μμΌλ‘ λκΈ°κΆμ λμ ν λ κΈκ²©ν 곡기 λ°λ λ³ν, κ·Ήμ¬ν 곡λ ₯ κ°μ΄, 좩격ν νλ₯, κ·Έλ¦¬κ³ μ λ곡 λν¬λ³ ννΈμ μν λ κ° μμ(Actuator Loss) λ± κ°νΉν λΆνμ€μ±μ μ§λ©΄ν©λλ€. μ΄λ¬ν κ·Ήνμ μ μ₯ μΈλ μμμλ μ‘°μ’ λ©΄μ μ€μκ° μ μ μ μ΄νμ¬ λΉνμ²΄κ° μ 볡λμ§ μκ³ νμ μ μ νν ν격νκΈ° μν΄μλ μ±ν°λ§(κ³ μ£Όν μ§λ)μ΄ 0%λ‘ μ΅μ λκ³ λ¦¬μνΈλ Έν μμ μ±μ΄ μνμ μΌλ‘ μ¦λͺ λ κ³ μ°¨ μ¬λΌμ΄λ© λͺ¨λ μ μ΄κΈ°(Super-Twisting Algorithm)κ° νμμ μ λλ€.
κΈ°μ‘΄ μΈμ° C/MATLAB μ μ΄ λꡬ(Simulink Coder)λ κ΅°μ¬ νμλ§ λΌμ΄μ μ€ μ’ μμ±κ³Ό λ¬΄κ±°μ΄ λ°νμ μ€λ²ν€λλ₯Ό μλ°ν©λλ€. ZeliDeskλ μΈμ° λꡬλ₯Ό 100% ννΌνκ³ , .NET 9 μμ C# κΈ°λ°μ μ¨λλ°μ΄μ€ 2μ°¨ μνΌ-νΈμμ€ν μ μν μ¬λΌμ΄λ© λͺ¨λ μ μ΄ μμ§μ λ μ μμ±νμμ΅λλ€. μ¬λΌμ΄λ© μνΌμ€ μ€κ³, 리μνΈλ Έν λ―ΈλΆ μμ μ€μ λΆνΈ($\dot{V} \le 0$) 보μ₯, λΉμ ν μΈλ κ΄μΈ‘κΈ°(DOB), λ° 0-Alloc SIMD 6μμ λ μμΈ μ°μ°μλ₯Ό κ²°ν©νμ¬ 120fps μ€μκ° κ·Ήμ΄μμ λΉν μ μ΄ μν€ν μ²λ₯Ό μ 격 곡κ°ν©λλ€.
2. νμ μ λ°°κ²½: 2μ°¨ μνΌ-νΈμμ€ν (Super-Twisting) μκ³ λ¦¬μ¦κ³Ό 리μνΈλ Έν μμ μ± μν λͺ¨λΈ
2κ³ λΉμ ν λΉν체 μμΈ κ°λ μ€μ°¨ μμ€ν μ $e = \theta - \theta_d$λΌ ν λ, μ¬λΌμ΄λ© μνΌμ€(Sliding Surface) $s$λ λ€μκ³Ό κ°μ΄ μ μλ©λλ€:
$$s = \dot{e} + c \cdot e \quad (c > 0)$$κ³ μ μ¬λΌμ΄λ© λͺ¨λ μ μ΄λ λΆμ°μ λΆνΈ ν¨μ $u = -k \operatorname{sgn}(s)$λ₯Ό μ¬μ©νμ¬ κ³ μ£Όν κΈ°κ³μ μ§λμΈ **μ±ν°λ§(Chattering)**μ μ λ°νκ³ λΉν체 ꡬλκΈ°(Actuator)λ₯Ό νκ΄΄ν©λλ€. ZeliDeskλ λ λ°νΈ(Levant)μ **2μ°¨ μνΌ-νΈμμ€ν μκ³ λ¦¬μ¦(Super-Twisting Algorithm, STA)**μ μμ C#μΌλ‘ λͺ¨λΈλ§νμ¬ μ μ΄ μ λ ₯ $u$λ₯Ό μ°μ μ νΈλ‘ μλ²½ νννν©λλ€:
$$u = -\alpha |s|^{1/2} \operatorname{sgn}(s) + v$$ $$\dot{v} = -\beta \operatorname{sgn}(s)$$μ¬κΈ°μ μ μ΄ κ²μΈ $\alpha, \beta$λ λ―Έμ§μ μΈλ κ²½κ³ $|d(t)| \le D$μ λν΄ $\alpha > \sqrt{2D}, \beta > D$λ₯Ό λ§μ‘±νλλ‘ μ μν(Adaptive)μΌλ‘ μλ νλλ©λλ€. μ΄ μμ€ν μ μ μ μ ν μκ° μλ ΄(Finite-Time Stability)μ λ€μκ³Ό κ°μ **κ°(Strict) 리μνΈλ Έν ν보 ν¨μ(Lyapunov Function)**μ μν΄ μνμ μΌλ‘ μλ²½ν 보μ₯λ©λλ€:
$$V(s, v) = \boldsymbol{\xi}^T \mathbf{P} \boldsymbol{\xi}, \quad \boldsymbol{\xi} = \begin{bmatrix} |s|^{1/2} \operatorname{sgn}(s) \\ v \end{bmatrix}, \quad \dot{V} \le -\gamma V^{1/2} \quad (\gamma > 0)$$3. ZeliDesk μμ C# μ¨λλ°μ΄μ€ μ μν μ¬λΌμ΄λ© λͺ¨λ μ μ΄ μν€ν μ² λ€μ΄μ΄κ·Έλ¨
4. C# κ³ μ±λ₯ μνΌ-νΈμμ€ν SMC λ° μΈλ κ΄μΈ‘κΈ° ν΅μ¬ ꡬν
μλλ ZeliDesk λΉνμ μ΄ μ½μ΄μμ ν ν λΉ μμ΄ μ΄λΉ 1,000ν μ΄μμ μ΄κ³ μμΌλ‘ μ¬λΌμ΄λ© νλ©΄μ μΆμ νκ³ μ±ν°λ§ μλ μ°μ ν ν¬λ₯Ό μ°μΆνλ μ€μ νλ‘λμ C# μ½λμ λλ€.
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
namespace ZeliDesk.Control.Hypersonic
{
///
/// ZeliDesk μ¨λλ°μ΄μ€ μμ C# 2μ°¨ μνΌ-νΈμμ€ν
μ¬λΌμ΄λ© λͺ¨λ λΉν μ μ΄κΈ°
///
public sealed class SuperTwistingSMC
{
private readonly float _lambda; // μ¬λΌμ΄λ© μνΌμ€ κ²μΈ
private float _alpha; // μνΌ-νΈμμ€ν
λΉλ‘ κ²μΈ
private float _beta; // μνΌ-νΈμμ€ν
μ λΆ κ²μΈ
private float _v; // 보쑰 μ λΆ μν λ³μ
public SuperTwistingSMC(float lambda, float alpha, float beta)
{
_lambda = lambda;
_alpha = alpha;
_beta = beta;
_v = 0f;
}
///
/// μ±ν°λ§ 0% μνΌ-νΈμμ€ν
μ°μ μ μ΄ μ
λ ₯ μ°μΆ (0-Alloc)
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public float Update(float targetAngle, float currentAngle, float currentRate, float dt, float estimatedDisturbance)
{
// 1. μ€μ°¨ λ° μ¬λΌμ΄λ© μνΌμ€ κ³μ°: s = e_dot + lambda * e
float error = currentAngle - targetAngle;
float errorDot = currentRate;
float s = errorDot + (_lambda * error);
// 2. λΆνΈ ν¨μ λ° μ κ³±κ·Ό μ°μ° (μ±ν°λ§ μν μ°μ κ·Όμ¬)
float sgnS = MathF.Sign(s);
float sqrtAbsS = MathF.Sqrt(MathF.Abs(s));
// 3. μ λΆ μν μ§ν: v_dot = -beta * sgn(s)
_v += (-_beta * sgnS) * dt;
// 4. μ°μ μ μ΄ μ
λ ₯ u = -alpha * |s|^(1/2) * sgn(s) + v - d_hat
float u = (-_alpha * sqrtAbsS * sgnS) + _v - estimatedDisturbance;
return u;
}
///
/// μΈλ ν¬κΈ°μ λ°λ₯Έ μ μν κ²μΈ μλ μ‘°μ
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void AdaptGains(float disturbanceBound)
{
_beta = disturbanceBound * 1.5f;
_alpha = MathF.Sqrt(2f * _beta) * 1.2f;
}
}
}
5. μ΄μ€κ³ μ μ΄κ³΅ν κ΅μ‘ λ° κ΅λ°© κ·Ήμ΄μμ λΉν μ μ΄ μ±λ₯ λΉκ΅ λΆμ
| νκ° μ§ν | κ³ μ PID μ μ΄κΈ° | ZeliDesk μ¨λλ°μ΄μ€ μμ C# μνΌ-νΈμμ€ν SMC | 곡κ΅μ‘ λ° κ΅λ°© ν곡 κΈ°λν¨κ³Ό |
|---|---|---|---|
| μΈλ 극볡 λ₯λ ₯ | μ λ곡 ννΈ/λν μ 15λ μ΄μ μμΈ μ 볡 | μΈλ κ΄μΈ‘κΈ° κΈ°λ° 0.01μ΄ λ΄ μ€μ°¨ 0 μλ ΄ | λ§ν 5+ κ·Ήν κ·Ήμ΄μμ λΉν μμ μ± 100% 보μ₯ |
| μ±ν°λ§(Chattering) | ν΄λΉ μμ (λ¨, λΉμ ν κ΅¬κ° μλ΅ μ§μ°) | 2μ°¨ κ³ μ°¨ μ¬λΌμ΄λ© λͺ¨λλ‘ κ³ μ£Όν μ§λ 0% | μ‘°μ’ λ©΄ μ μ ꡬλκΈ° μλͺ 10λ°° μ°μ₯ λ° κΈ°κ³μ νΌλ‘ λ°©μ§ |
| μνμ μμ μ± μ¦λͺ | κ²½νμ νλ μμ‘΄ (λΉμ ν μμ μ± λ―Έλ³΄μ₯) | μλ°ν 리μνΈλ Έν μμ μ±($\dot{V} \le 0$) μ¦λͺ | ν곡 μννΈμ¨μ΄ κ°ν μΈμ¦ DO-178C 무결μ ν΅κ³Ό |
| κ΅μ‘μ μ°κ³ | λ¨μ P, I, D μ΄λκ° μ‘°μ μ λ§€λͺ° | μν 곡κ°, μμ νλ©΄, μ¬λΌμ΄λ© λͺ¨λ μν κ³΅κ° | 2022 κ°μ 물리·μνΒ·μ 보 μ¬ν μ μ΄κ³΅ν μμ± |
6. κ²°λ‘ : μ‘°κ΅μ μ곡μ μνΈνλ 무결μ λΉν μ μ΄ κΈ°μ μ κΈμν
ZeliDeskμ μ¨λλ°μ΄μ€ μμ C# 2μ°¨ μνΌ-νΈμμ€ν μ¬λΌμ΄λ© λͺ¨λ μ μ΄ μμ§μ ν΅μ° 229νΈ λ° μ 770νΈλΌλ μμ¬μ κΈμνμ μ₯μνλ μ΅κ³ μ ν곡μ°μ£Ό μ μ΄κ³΅ν μμμ λλ€. μΈμ° νλ μμν¬μ μ₯λ²½μ νλ¬Όκ³ μ°λ¦¬λ§μ λ μμ μΈ C# κΈ°μ λ‘ μμ±ν 리μνΈλ Έν 무결μ μ μ΄κΈ°λ κ΅μ€μμλ λ―Έλ λνλ―Όκ΅μ ν곡μ°μ£Ό μλλ₯Ό μ΄μ΄κ° νμλ€μκ² λλΆμ μνκ³Ό μ μ΄ μ΄λ‘ μ μ§νμ μ΄μ΄μ£Όκ³ , μ μ₯μμλ κ·Έ μ΄λ€ μ μ μΈλκ³Ό μν μμμλ μ‘°κ΅μ νΈλ₯Έ νλμ λΉλΉν μνΈνλ κ°μ₯ λ¨λ¨ν κ°μ² λ κ°κ° λ κ²μ λλ€.