Перейти к содержанию

Математика процесса моделирования повреждений

Этот документ собирает все формулы подсистемы повреждений в одном месте: от обозначений и эволюции состояния до окончательного вида ОДУ 6-DoF с учётом повреждений. Сокращения: ЛА — летательный аппарат, ЦМ — центр масс, ОДУ — обыкновенное дифференциальное уравнение, MAC — Mean Aerodynamic Chord (средняя аэродинамическая хорда).

Обозначения и единицы

Все векторы заданы в связанной (body-fixed) системе координат: \(x\) — вперёд, \(y\) — вправо, \(z\) — вниз.

Символ Смысл Единицы
\(\mathcal{S} = \{s_1, \ldots, s_N\}\) множество секций (\(N=13\) для F-16)
\(f_s \in [0, 1]\) текущая доля потери секции \(s\) (section_loss)
\(m_s\), \(A_s\), \(c_s\) номинальная масса, площадь, хорда секции кг, м², м
\(\mathbf{r}_s = (x_s, y_s, z_s)^\top\) положение ЦМ секции в связанной СК м
\(\mathbf{I}^{loc}_s = (I^{loc}_{xx,s},\,I^{loc}_{yy,s},\,I^{loc}_{zz,s},\,I^{loc}_{xy,s})\) локальный тензор инерции относительно ЦМ секции кг·м²
\(C_{l\alpha,s}\) посекционный наклон кривой подъёма 1/рад
\(C_{D0,s}\) посекционный вклад в коэффициент паразитного сопротивления
\(\alpha\), \(\beta\) углы атаки и скольжения рад
\(S_{base}\), \(b_{base}\), \(\bar{c}_{base}\) базовые площадь, размах, MAC исходной геометрии м², м, м
\(\Delta m_{struct}\), \(\Delta \mathbf{r}_{struct}\), \(\Delta \mathbf{J}_{struct}\) структурные поправки (сброс груза, обледенение) кг, м, кг·м²

Соглашение об обозначениях моментов и числа Маха

В этом документе \(M_x, M_y, M_z\) — безразмерные коэффициенты моментов крена, тангажа и рыскания соответственно (то же, что \(C_l, C_m, C_n\) в западной нотации; в коде — mx, my, mz). Скалярное \(M\) без индекса — число Маха. Чтобы избежать путаницы, в математических формулах число Маха встречается только как параметр базовых табличных коэффициентов \(C_y^{base}(\alpha, M, \ldots)\) и не имеет собственного раздела.

Раскладка 13 секций F-16

Все формулы ниже опираются на разбиение ЛА на 13 именованных секций: 6 сегментов крыла (по 3 на каждую сторону: *_root, *_mid, *_tip), 2 половины стабилизатора, киль (vtail), 3 управляющие поверхности (rudder, aileron_left, aileron_right) и одна агрегированная секция фюзеляжа (fuselage_main). Каждая секция имеет фиксированные геометрические и массово-инерционные характеристики из калибровочного файла f16_geometry.yaml — именно их перебирают суммы \(\sum_s\) во всех формулах ниже.

Численные значения (площадь, координаты, массы, посекционные коэффициенты \(C_{l\alpha,s}\), \(C_{D0,s}\)) подобраны так, чтобы при \(f_s = 0\)\(s\) агрегированные параметры совпадали с baseline-значениями F16AngularParameters (полная масса 9295,44 кг, площадь крыла 27,87 м², MAC 3,45 м) с точностью ~1 % по массе и площади и ~5 % по тензору инерции — это инвариант калибровки.

Схема ниже показывает 13 секций в виде сверху с именами и габаритами; эта же раскладка используется при срабатывании события section_loss, когда поле section_name события указывает на конкретный прямоугольник на схеме.

Раскладка секций F-16 (вид сверху) с подписанными именами

Эволюция состояния повреждения по времени

Состояние повреждения \(\mathbf{D}(t)\) — кусочно-постоянная во времени функция, обновляющаяся скачками только в моменты срабатывания событий. Пусть \(\mathcal{E}_k = \{e \in \mathcal{P} \cup \mathcal{P}_{inj} : t_{k-1} < t_e \le t_k\}\) — множество событий из расписанного профиля и инжектированных одноразовых событий, попавших в окно интегратора \((t_{k-1}, t_k]\). Тогда

\[ \mathbf{D}(t) \;=\; \mathbf{D}(t_{k-1}) \;\oplus\; \bigoplus_{e \in \mathcal{E}_k} \Phi_e, \qquad t \in [t_{k-1}, t_k), \]

где \(\Phi_e\) — оператор применения события \(e\) к состоянию (мутация section_loss, control_failures, engine или structural), а \(\oplus\) — бинарная операция композиции, соответствующая ассоциативному наложению изменений в порядке вставки. Если \(\mathcal{E}_k = \emptyset\), то \(\mathbf{D}(t) = \mathbf{D}(t_{k-1})\) и пересчёт параметров не выполняется (важная оптимизация: бит-в-бит идентичность с baseline без повреждений).

Эффективная масса и центр масс

Эффективная масса каждой секции — линейное понижение по доле потери:

\[ m^{eff}_s \;=\; m_s\,(1 - f_s). \]

Полная масса ЛА с учётом структурной поправки:

\[ m \;=\; \sum_{s \in \mathcal{S}} m^{eff}_s \;+\; \Delta m_{struct}. \]

Центр масс — массово-взвешенное среднее уцелевших секций плюс структурный сдвиг:

\[ \mathbf{r}_{cg} \;=\; \frac{1}{\displaystyle\sum_s m^{eff}_s}\,\sum_{s \in \mathcal{S}} m^{eff}_s\,\mathbf{r}_s \;+\; \Delta\mathbf{r}_{struct}. \]

Симметричная потеря (например, обе законцовки) сохраняет \(y_{cg} = 0\), поскольку слагаемые с \(\pm y_s\) сокращаются. Асимметричная потеря порождает ненулевой \(y_{cg}\), что становится драйвером дисбаланса крена.

Числовой пример — потеря левой законцовки на 100 %

Для конкретного срабатывания WING_STRIKE_LEFT_TIP (section_name ="left_tip", loss_fraction = 1.0) с использованием значений из f16_geometry.yaml:

Величина Baseline После события \(\Delta\)
Масса \(m\), кг 9295,44 9195,44 \(-100\) (\(-1{,}1\,\%\))
Площадь крыла \(S\), м² 27,90 24,25 \(-3{,}65\) (\(-13{,}1\,\%\))
Размах \(b\), м 8,60 7,10 \(-1{,}50\) (\(-17{,}4\,\%\))
MAC \(\bar c\), м 3,452 3,673 \(+0{,}221\) (\(+6{,}4\,\%\))
\(y_{cg}\), м 0,000 \(+0{,}047\) сдвиг ЦМ вправо

Подсчёт \(y_{cg}\) — взвешенная сумма по уцелевшим секциям (вклады секций с \(y_s = 0\) и симметричных пар отбрасываются, остаётся только несимметричный вклад правой законцовки \(m_{rt}\,y_{rt} = 100 \cdot 4{,}30 = 430\) кг·м):

\[ y_{cg} \;=\; \frac{430}{9195{,}44} \;\approx\; 0{,}0468\ \text{м}. \]

Этот сдвиг становится плечом результирующей подъёмной силы относительно ЦМ — отсюда возникает нескомпенсированный момент крена, который мы получим в strip-theory ниже.

Кривые пересчёта при сим/асим потере

График ниже показывает поведение четырёх ключевых параметров (\(m\), \(S\), \(J_x\), \(y_{cg}\)) как функцию доли потери законцовки \(f\). Синяя линия — симметричная потеря (одинаково обе законцовки): \(m\), \(S\) и \(J_x\) спадают линейно, а \(y_{cg}\) остаётся точно в нуле — ось симметрии сохранена. Красная линия — асимметричная потеря (только левая): \(m\) и \(S\) спадают вдвое медленнее (теряется только одна секция вместо двух), но \(y_{cg}\) растёт линейно с \(f\) — это и есть драйвер крен-дисбаланса.

Кривые пересчёта параметров \(m\), \(S\), \(J_x\), \(y_{cg}\) при сим (синяя) и асим (красная) потере законцовки

Аэродинамические агрегаты

Эффективная площадь крыла суммирует только секции типа wing:

\[ S \;=\; \sum_{s \in \mathcal{W}} A_s\,(1 - f_s), \qquad \mathcal{W} = \{s \in \mathcal{S}:\,\text{type}_s = \text{wing}\}. \]

Эффективный размах — сумма расстояний до самой дальней уцелевшей точки на каждой стороне (выдерживает асимметричные потери, при которых на одной стороне крыло короче):

\[ b \;=\; \max_{\substack{s \in \mathcal{W}\\ \text{side}_s = L}} |y_s|\cdot\mathbb{1}[f_s < 1] \;+\; \max_{\substack{s \in \mathcal{W}\\ \text{side}_s = R}} |y_s|\cdot\mathbb{1}[f_s < 1]. \]

Если на стороне нет уцелевших секций (\(f_s = 1\) для всех), соответствующее \(\max\) берётся по пустому множеству и трактуется как 0 (полная потеря полукрыла).

Средняя аэродинамическая хорда (MAC) — площадно-взвешенное среднее хорд по уцелевшей площади:

\[ \bar{c} \;=\; \frac{1}{S}\,\sum_{s \in \mathcal{W}} c_s\,A_s\,(1 - f_s), \]

при \(S = 0\) (полная потеря крыла) принимается \(\bar{c} = 0\).

Тензор инерции через теорему Гюйгенса-Штейнера

Для каждой секции применяем теорему параллельных осей, привязывая локальную инерцию к текущему ЦМ ЛА \(\mathbf{r}_{cg}\). Обозначим \(\mathbf{r}'_s = \mathbf{r}_s - \mathbf{r}_{cg} = (r_x, r_y, r_z)_s\) — смещение ЦМ секции относительно ЦМ ЛА. Локальные моменты инерции масштабируются на \((1 - f_s)\) в предположении однородной плотности секции (потеря 30 % массы → потеря 30 % её собственного \(I^{loc}\)):

\[ J_{xx} \;=\; \sum_{s} \Bigl[ I^{loc}_{xx,s}(1-f_s) \;+\; m^{eff}_s\,(r_{y,s}^2 + r_{z,s}^2)\Bigr] \;+\; \Delta J^{struct}_x, \]
\[ J_{yy} \;=\; \sum_{s} \Bigl[ I^{loc}_{yy,s}(1-f_s) \;+\; m^{eff}_s\,(r_{x,s}^2 + r_{z,s}^2)\Bigr] \;+\; \Delta J^{struct}_y, \]
\[ J_{zz} \;=\; \sum_{s} \Bigl[ I^{loc}_{zz,s}(1-f_s) \;+\; m^{eff}_s\,(r_{x,s}^2 + r_{y,s}^2)\Bigr] \;+\; \Delta J^{struct}_z, \]
\[ J_{xy} \;=\; \sum_{s} \Bigl[ I^{loc}_{xy,s}(1-f_s) \;+\; m^{eff}_s\,r_{x,s}\,r_{y,s}\Bigr] \;+\; \Delta J^{struct}_{xy}. \]

Знак off-diagonal члена +m·rx·ry соответствует определению \(J_{xy} = \int x\,y\,dm\) (не \(-\int x\,y\,dm\)): эта конвенция согласована с F16AngularParameters.Jxy = 1331.4 и со структурой \(f16\_ode\_6dof\), где Jxy (а не Jxz) активный off-diagonal — отличие от стандартной западной аэрокосмической записи.

Strip-theory: дельты аэродинамических коэффициентов

После каждого срабатывания события базовые таблицы коэффициентов F-16 (\(C_y^{base}, C_x^{base}, \ldots\), функции \(\alpha, \beta, M, \delta_{ail}, \ldots\)) не модифицируются. Вместо этого подсистема производит аддитивные безразмерные дельты, нормированные на базовую (доповрежденческую) геометрию \(S_{base}\) и \(b_{base} = 2\,\max_{s \in \mathcal{W}} |y_s|\).

Подъёмная сила. Каждая повреждённая секция крыла теряет долю своего вклада \(C_{l\alpha,s}\,\alpha\), а вес секции — отношение её площади к базовой:

\[ \boxed{\;\Delta C_y(\alpha) \;=\; -\sum_{s \in \mathcal{W}} C_{l\alpha,s}\,\alpha\,f_s\,\frac{A_s}{S_{base}}\;} \]

Знак минус: повреждение отнимает подъёмную силу.

Сопротивление с моделью «рваного края». Сопротивление включает два эффекта: (1) потеря посекционного \(C_{D0,s}\) при полной потере секции снижает паразитное сопротивление, (2) частично разрушенная секция добавляет дополнительное сопротивление от рваной кромки, максимальное при \(f = 0.5\) (когда экспонируется максимальная площадь среза):

\[ \boxed{\;\Delta C_x \;=\; \sum_{s \in \mathcal{S}} \Bigl[-C_{D0,s}\,f_s\Bigr] \;+\; \sum_{s \in \mathcal{W}} k_J\,f_s\,(1 - f_s)\,\frac{A_s}{S_{base}}\;} \]

где \(k_J = 0{,}05\) — калиброванный эвристический коэффициент. Парабола \(f(1-f)\) имеет максимум \(0{,}25\) при \(f = 0{,}5\), что соответствует физической интуиции: целая или полностью оторванная секция обтекается чисто, а полусрезанная даёт максимум турбулентного сопротивления.

Боковая сила доминируется потерей вертикального оперения:

\[ \boxed{\;\Delta C_z(\beta) \;=\; -\sum_{s \in \mathcal{V}} k_{vt}\,\beta\,f_s, \qquad k_{vt} = 0{,}40\ \text{1/рад}\;} \]

где \(\mathcal{V}\) — секции типа vtail. Коэффициент \(k_{vt}\) откалиброван так, что полная потеря киля даёт \({\partial C_z}/{\partial\beta} \approx 0{,}40\), что соответствует реальному вкладу вертикального оперения F-16 в боковую устойчивость.

Момент крена возникает только при асимметрии — каждая секция вносит свой плечевой момент \(y_s/b_{base}\):

\[ \boxed{\;\Delta M_x(\alpha) \;=\; -\sum_{s \in \mathcal{W}} C_{l\alpha,s}\,\alpha\,f_s\,\frac{A_s}{S_{base}}\,\frac{y_s}{b_{base}}\;} \]

Симметричная потеря: \(y_s\) для левой и правой секций имеют противоположные знаки, и слагаемые сокращаются → \(\Delta M_x = 0\). Асимметричная потеря (например, только left_tip): остаётся ненулевой результирующий \(\Delta M_x\), пропорциональный и \(\alpha\), и \(f\) — это и есть драйвер дисбаланса крена в WING_STRIKE_LEFT_TIP.

Момент тангажа учитывает плечо \(x_s\) от ЦМ до аэродинамического центра секции (поэтому в формулу включаются как крылья, так и стабилизатор):

\[ \boxed{\;\Delta M_y(\alpha) \;=\; -\sum_{s \in \mathcal{W} \cup \mathcal{T}} C_{l\alpha,s}\,\alpha\,f_s\,\frac{A_s}{S_{base}}\,\frac{x^{arm}_s}{\bar{c}_{base}}\;} \]

где \(\mathcal{T}\) — секции типа stab, \(x^{arm}_s\)aero_x_arm (плечо от ЦМ ЛА до аэродинамического центра секции).

Момент рыскания — асимметричное сопротивление вокруг \(z\):

\[ \boxed{\;\Delta M_z \;=\; \sum_{s \in \mathcal{S}} \delta C_{x,s}\,\frac{y_s}{b_{base}}\;} \]

где \(\delta C_{x,s}\) — посекционный вклад в \(\Delta C_x\) (включая рваный край для секций крыла).

Числовой пример — \(\Delta C_y\) и \(\Delta M_x\) при потере законцовки

Для того же срабатывания WING_STRIKE_LEFT_TIP (\(f_{left\_tip} = 1{,}0\), остальные \(f_s = 0\)) при типичном крейсерском \(\alpha = 5° = 0{,}0873\) рад, используя \(C_{l\alpha,\,left\_tip} = 3{,}40\) 1/рад, \(A_{left\_tip} = 3{,}65\) м², \(S_{base} = 27{,}87\) м², \(y_{left\_tip} = -4{,}30\) м, \(b_{base} = 8{,}60\) м:

\[ \Delta C_y \;=\; -\,3{,}40 \cdot 0{,}0873 \cdot 1{,}0 \cdot \frac{3{,}65}{27{,}87} \;\approx\; -0{,}0389, \]
\[ \Delta M_x \;=\; -\,3{,}40 \cdot 0{,}0873 \cdot 1{,}0 \cdot \frac{3{,}65}{27{,}87} \cdot \frac{-4{,}30}{8{,}60} \;\approx\; +0{,}0195. \]

При базовом \(C_y^{base}(\alpha = 5°) \approx 0{,}393\) потеря составляет \(\Delta C_y / C_y^{base} \approx -9{,}9\,\%\) — заметная просадка подъёмной силы. Положительный \(\Delta M_x\) соответствует крен-моменту на правое полукрыло (поскольку левое потеряло свою долю подъёмной силы) — именно это и видит управляющий агент в виде растущего \(\omega_x\) после срабатывания события.

Графическая иллюстрация дельт

Левая панель ниже показывает \(\Delta C_y\) как функцию \(\alpha\) для симметричной потери обеих законцовок: коэффициент линеен по \(\alpha\) и масштабируется с \(f\) (здесь — 60 %), типичное значение при \(\alpha = 10°\) — около \(-0{,}10\), то есть \(\sim 12\,\%\) от здоровой подъёмной силы. Правая панель — \(\Delta M_x\) для асимметричной (только левой) потери: ненулевой, тоже линеен по \(\alpha\) и пропорционален \(f\) — это и есть драйвер вращения по крену.

Strip-theory дельты: симметричная потеря снижает \(\Delta C_y\) (слева), асимметричная порождает \(\Delta M_x\) (справа)

Сравнительная схема ниже собирает оба сценария в одну картинку: симметричная потеря (слева) сохраняет балансировку и снижает только подъёмную силу; асимметричная потеря (справа) дополнительно вносит сдвиг ЦМ и момент крена, растущий с долей потери \(f\) — качественное различие, о котором говорят формулы \(\Delta M_x\) и \(\mathbf{r}_{cg}\) выше.

Симметричная (слева) vs асимметричная (справа) потеря законцовки — обзор физических эффектов

Отказы рулевых поверхностей

Команды актюатору \(\mathbf{u}_{cmd}\) преобразуются в эффективные \(\mathbf{u}_{eff}\) до интегратора через посимвольное отображение apply_control_failures(u, state):

\[ u_{eff,i} \;=\; \begin{cases} \;u^{jam}_i & \text{если мода = jam}\\ \;\eta_i\,u_{cmd,i} & \text{если мода = efficiency\_loss},\;\eta_i \in [0, 1]\\ \;0 & \text{если мода} \in \{\text{lost}, \text{free\_floating}\}\\ \;u_{cmd,i} & \text{иначе (healthy)} \end{cases} \]

Здесь \(\eta_i\) — поле efficiency объекта ControlFailure, \(u^{jam}_i\) — поле jam_position_rad. Несколько отказов на одном индексе компонуются в порядке вставки в state.control_failures. Для split-stab режима (\(\mathbf{u} \in \mathbb{R}^4\)): индексы stab_left=0, stab_right=1, aileron=2, rudder=3.

Двигатель

\[ T_{eff} \;=\; \begin{cases} \;0 & \text{если hard\_failure}\\ \;\tau\,T_{base} & \text{иначе},\;\tau \in [0, 1] \end{cases} \]

В текущей угловой ОДУ воздушная скорость считается константой, поэтому \(T_{eff}\) читается потребителями отдельно через хелпер effective_thrust(base_thrust, state) из damage/propulsion.py — им пользуются, например, RL-награды и расширения динамики. Полный учёт тяги в самих ОДУ — задача будущего расширения.

Связь с уравнениями движения

В каждой точке интегратора полные коэффициенты получаются как сумма табличного значения и текущей дельты:

\[ C_y(t) = C_y^{base}(\alpha, M, \ldots) + \Delta C_y(t),\qquad M_i(t) = M_i^{base}(\alpha, \beta, \boldsymbol{\delta}, \ldots) + \Delta M_i(t),\;\;i \in \{x,y,z\}. \]

Уравнения движения 6-DoF в связанной СК с обновлёнными \(m\), \(\mathbf{J}\), \(S\), \(\bar{c}\), \(b\) принимают вид (упрощённо, для иллюстрации связи):

\[ m\,\dot{\mathbf{V}} + \boldsymbol{\omega} \times m\,\mathbf{V} \;=\; \mathbf{F}_{aero}\bigl(C_x, C_y, C_z;\,S,\,q\bigr) + \mathbf{F}_{thrust}(T_{eff}) + m\,\mathbf{g}, \]
\[ \mathbf{J}\,\dot{\boldsymbol{\omega}} + \boldsymbol{\omega} \times \mathbf{J}\,\boldsymbol{\omega} \;=\; \mathbf{M}_{aero}\bigl(M_x, M_y, M_z;\,S,\,b,\,\bar{c},\,q\bigr), \]

где \(q = \tfrac{1}{2}\rho V^2\) — скоростной напор, а тензор \(\mathbf{J}\) — теперь функция времени, поскольку при каждом срабатывании события пересчитывается apply_to_params(...). Все векторы и моменты заданы в связанной (body-fixed) СК, как и состояние ЛА. Именно эта замена \(\mathbf{J}_{base} \to \mathbf{J}(t)\), \(\mathbf{F}_{aero} \to \mathbf{F}_{aero} + \Delta\mathbf{F}\), \(\mathbf{u}_{cmd} \to \mathbf{u}_{eff}\) и превращает объект управления F-16 с фиксированными параметрами в объект с параметрами, зависящими от времени (кусочно-нестационарный — параметры меняются скачками в моменты событий и постоянны между ними).

Проработанный пример: WING_STRIKE_LEFT_TIP в полёте

В этом разделе мы прогоняем через все формулы выше один конкретный сценарий: пресет WING_STRIKE_LEFT_TIP — мгновенная полная потеря левой законцовки left_tip на \(t = 10\) с при горизонтальном полёте с постоянным \(\alpha = 5°\) и нулевой командой РУС. Цель — показать, как последовательное применение формул из предыдущих разделов даёт наблюдаемое поведение объекта управления.

Состояние повреждения и оператор события

Профиль состоит из одного события:

\[ e = (t_e = 10\,\text{с},\; \text{type} = \text{section\_loss},\; \text{payload} = \{\text{section: } \texttt{left\_tip},\ f: 1{,}0\}). \]

Оператор \(\Phi_e\) изменяет только одно поле состояния:

\[ \Phi_e:\quad \mathbf{D}.\text{section\_loss}[\texttt{left\_tip}] \;\leftarrow\; 1{,}0, \]

прочие поля (control_failures, engine, structural) остаются дефолтными. На шаге интегратора, накрывшем \(t = 10\) с, срабатывает \(\mathcal{E}_k = \{e\}\) и запускается полный пересчёт параметров через apply_to_params(...).

Шаг 1. Эффективная масса, ЦМ и геометрия

После применения формул для \(m^{eff}_s\) и агрегирования:

Параметр Значение Δ к baseline
\(m\) 9195,44 кг \(-100\) кг (\(-1{,}1\,\%\))
\(S\) 24,25 м² \(-3{,}65\) м² (\(-13{,}1\,\%\))
\(b\) 7,10 м \(-1{,}50\) м (\(-17{,}4\,\%\))
\(\bar{c}\) 3,673 м \(+0{,}221\) м (\(+6{,}4\,\%\))
\(y_{cg}\) \(+0{,}047\) м сдвиг вправо
\(x_{cg}\), \(z_{cg}\) без изменений

Подсчёт \(b\): размах правой стороны без изменений (\(\max |y| = 4{,}30\) м у right_tip), а на левой стороне самая дальняя уцелевшая секция — теперь left_mid с \(|y| = 2{,}80\) м, так что \(b = 4{,}30 + 2{,}80 = 7{,}10\) м.

Шаг 2. Тензор инерции

Для \(J_{xx}\) изменения сводятся к двум вычитаемым компонентам: вкладу left_tip через локальную \(I^{loc}_{xx}\) и через параллельно-осевой член \(m \cdot (r_y^2 + r_z^2)\):

\[ J_{xx,\,\text{тип}} \;=\; I^{loc}_{xx,\,lt}\,(1-1{,}0) \;+\; 0\cdot(r_{y,lt}^2 + r_{z,lt}^2) \;=\; 0, \]

вместо baseline-вклада \(220 + 100 \cdot (4{,}30^2 + 0{,}02^2) \approx 220 + 1849 = 2069\) кг·м². Plus небольшие сдвиги во всех остальных секциях из-за изменения опорного \(\mathbf{r}_{cg}\) (величина \(r'_s = \mathbf{r}_s - \mathbf{r}_{cg}\) слегка меняется для каждой секции). \(J_{xy}\) перестаёт быть нулевым, поскольку \(y_{cg} \neq 0\) — конкретное число зависит от полной суммы и обычно невелико для этого сценария.

Шаг 3. Strip-theory дельты в установившемся режиме

При \(\alpha = 5° = 0{,}0873\) рад (\(\beta = 0\)):

\[ \Delta C_y \;\approx\; -0{,}0389, \qquad \Delta M_x \;\approx\; +0{,}0195, \qquad \Delta C_x \;\approx\; -2{,}0\cdot 10^{-3}, \]
\[ \Delta C_z \;=\; 0\ (\text{киль не повреждён}), \qquad \Delta M_y \;\approx\; +1{,}4\cdot 10^{-4} \text{ (мал из-за } x^{arm}_{lt} = -0{,}10), \qquad \Delta M_z \;\approx\; +5\cdot 10^{-4}. \]

Доминируют два эффекта: просадка \(C_y\) (на ~10 % при крейсерском \(\alpha\)) и появление ненулевого \(\Delta M_x\) — именно из-за ненулевого плеча \(y_{lt}/b_{base} = -0{,}5\).

Шаг 4. Подстановка в ОДУ

В момент \(t > 10\) с шаг ОДУ выполняется с обновлёнными параметрами:

\[ m\,\dot{\mathbf{V}} \;=\; \mathbf{F}_{aero}\bigl(C_x^{base} + \Delta C_x,\; C_y^{base} + \Delta C_y,\; C_z^{base};\; S = 24{,}25,\; q\bigr) \;+\; m\,\mathbf{g}, \]
\[ \mathbf{J}(t)\,\dot{\boldsymbol{\omega}} + \boldsymbol{\omega} \times \mathbf{J}(t)\,\boldsymbol{\omega} \;=\; \mathbf{M}_{aero}\bigl(M_x^{base} + \Delta M_x,\; M_y^{base} + \Delta M_y,\; M_z^{base} + \Delta M_z;\; S, b = 7{,}10,\; \bar{c} = 3{,}673,\; q\bigr). \]

Член \(\mathbf{F}_{aero}\) потерял ~10 % подъёмной силы → ЛА начинает проседать по высоте; член \(\mathbf{M}_{aero}\) получил ненулевой \(M_x\)-компонент при \(\boldsymbol{\omega} \approx 0\)\(\dot{\omega}_x = M_x \cdot q \cdot S \cdot b / J_{xx} > 0\), и угловая скорость крена накапливается линейно.

Шаг 5. Наблюдаемая траектория

Графики ниже — результат численного интегрирования с этими параметрами (скрипт-демо example/failure_demos/f16_damage_dogfight_demo.py). До \(t = 10\) с — здоровый ЛА в горизонте; после \(t = 10\) с в повреждённом прогоне (оранжевая линия) явно видна угловая скорость крена \(\omega_x\), которая в здоровом прогоне (синяя) остаётся при нуле. Это и есть прямое следствие \(\Delta M_x \neq 0\) из шага 3. Параллельно \(\alpha\) дрейфует — уменьшение подъёмной силы заставляет ЛА снижаться, что меняет угол атаки. Тангаж \(\omega_z\) и руль высоты остаются в здоровых диапазонах: потеря \(\texttt{left\_tip}\) к оси тангажа не привязана.

Здоровая (синяя) vs повреждённая (оранжевая) траектория при \(\alpha\), \(\omega_x\), \(\omega_z\) и команде руля для пресета WING_STRIKE_LEFT_TIP

Шаг 6. Что видит RL-агент

Если агент обучается с damage_observable=False, он не получает явных сигналов о повреждении — только изменившуюся динамику: новый коэффициент усиления по руль-высоте → α (потому что \(S\) и \(\bar{c}\) другие), ненулевую корреляцию команда-крен (которой раньше не было), и общий тренд α на снижение. Адаптивные алгоритмы (iADP, AIDI, ET-DHP) идентифицируют новые \(\tilde F, \tilde G\) через невязки RLS или event-trigger обновления; неадаптивные обученные политики (PPO, SAC) могут деградировать — степень зависит от того, насколько повреждённые состояния попадали в распределение обучения.

Сводный вычислительный цикл

На каждом шаге интегратора:

  1. damage_manager.update(t_curr, t_prev) собирает \(\mathcal{E}_k\).
  2. Если \(\mathcal{E}_k \neq \emptyset\): применяются операторы \(\Phi_e\), затем apply_to_params пересчитывает \(m, S, b, \bar{c}, \mathbf{r}_{cg}, \mathbf{J}\).
  3. apply_control_failures(u_cmd, state)\(\mathbf{u}_{eff}\).
  4. f16_ode_6dof вычисляет \(C^{base}_*\) из таблиц по \(\alpha, \beta, M\) и добавляет \(\Delta C_*\) через delta_cy/cx/cz/mx/my/mz(α, β, geo, state).
  5. ОДУ интегрируется (Euler / RK4) с обновлёнными \(m, \mathbf{J}\) и полными \(C_*\).

Стоимость пересчёта — \(O(N)\) по числу секций (\(N=13\)), и он выполняется только в шагах со срабатываниями. На остальных шагах кэшированные параметры читаются напрямую — это обеспечивает бит-в-бит совместимость с исходным baseline без damage_profile.