Введение
Однажды меня попросили разработать модель динамики полета АСП (авиационного средства поражения) в отечественном ПО, в среде SimInTech. Причем даже не разработать с нуля, а тупо повторить уже созданную ранее модель в Матлабе (с Симулинком) и любезно выложенную в открытый доступ на гитхабе: https://github.com/JohannesAutenrieb/MissileSimulation
Я подумал - почему бы и нет, можно повторить, ведь в Симинтеке есть практически все требуемые блоки, а если каких нет, то доработаю по образу и подобию. Без погружения в детали, в конце концов так оно и вышло, а итоговый результат был почти идентичен натуральному оригинальному.
В этой модели рассматривается свободный и/или регулируемый полет типового изделия AGARD-B, примерно такой формы:


Приведем краткое описание: "AGARD-B представляет собой конфигурацию "корпус-крыло". Все размеры даны в единицах диаметра корпуса "D", поэтому модель может быть изготовлена в любом масштабе, соответствующем конкретной аэродинамической трубе. Тело представляет собой тело вращения длиной 8.5 диаметров, состоящее из цилиндрического сегмента длиной 5.5 диаметра и носовой части длиной 3 диаметра..." Подробнее всё можно найти в сети, например: https://wiki5.ru/wiki/AGARD-B_wind_tunnel_model
Модели
Исходная модель, назовём её прототипом, реализована в программном обеспечении MATLAB/Simulink, и кроме собственно математической модели, содержит набор разных сценариев полета АСП и некоторые из этапов верификации самой модели.
За базовые параметры взяты следующие характеристики:
- диаметр D = 0.150 м,
- длина L = 1.618 м;
- масса M = 30 кг.
Внешний вид прототипа модели АСП и её системы управления представлен на рисунке:

Опуская детали и трудности "копирования" модели из одной среды в другую, это не является предметом данной заметки, в конце концов итоговый результат у меня был подобен оригинальному:

Приведу для сравнения еще пару внутренностей субмоделей. Регулятор тангажа:


Расчёт числа Маха и учет ветра:


Но мне справедливо возразили - а чем и как докажешь, что твоя модель в Симинтеке считает в точности так же, да ещё и в динамике с произвольными воздействиями, как и исходная модель в Симулинке, которому мы доверяем? Нужна верификация, сказали. Или хотя бы валидация, если за аксиому примем что прототип в Симулинке сделан верно. Чем-то надо подтвердить одинаковость моделей.
Сравнение результатов
Именно этому посвящена данная краткая статья - подходу к сравнению результатов двух расчетов. Наверняка, в теории есть много разных подходов к сравнению, я выбрал метод последовательного тестирования моделей, приведу его краткий алгоритм:
1) Подготавливаем набор тестов, т.е. набор входных воздействий в модель. Желательно чтобы это были не константы и тем более не нули, а изменяющиеся во времени дискретные или непрерывные значения. Потому что при входном сигнале x(t)=0 что sin(2·x) что 2·sin(x) дадут в динамике одинаковый ответ, и формально можно сказать что две модели двойного синуса икс одинаковые, но вот если x(t) будет меняться во времени, то вы увидите разницу, и придется исправить ошибку.
2) Для каждого теста определяемся также с выходными расчетными переменными, которые нас будут интересовать и которые будем сравнивать. У меня это были координаты центар масс ракеты, ориентация, скорости и ускорения по осям, силы и т.д.
3) Задаем двум готовым моделям (в Симулинке и в Симинтеке) одинаковые входные данные. В прототипе, взятом с гитхаба, кстати тоже набор тестов приведен. Мне пришлось его несколько расширить чтобы охватить по возможности все части модели. В моем случае получилось 22 разных сценария, и до 20 расчетных переменных в каждом, которые надо и интересно было сравнить, на рисунке приведены частичные результаты. Физически на диске я имел 22 файла (проекта) в формате Симулинка, и 22 проекта в формате Симинтека. Модель при этом оставалась везде одной и то же, менялись только входные воздействия.

4) Настраиваем одинаковые параметры расчета в обеих средах моделирования, в каждом из тестов. Был выбран самый простой метод интегрирования - метод Эйлера с постоянным шагом, чтобы метод интегрирования не вносил своих погрешностей и отличий в результаты. Также, сравнивались результаты при методах интегрирования Рунге-Кутты 4 порядка (ode4 (Runge-Kutta) в Simulink, RK4 в среде SimInTech). Экспериментально было выяснено что они тоже дают в большинстве случаев одинаковые результаты.
5) Шаг интегрирования задаем равным и там и там, я сравнивал всё с шагом 0.001 с. Конечное время тоже одинаковое, например 2 секунды. Или 100 секунд, зависит от вашей модели и от задачи.
6) Задаем вывод в файл(ы) одинаковых расчетых переменных, то есть результатов расчета.
7) Выполняем расчет в Симулинке.
8) Выполняем расчет в Симинтеке.
9) Сравниваем результаты обеих расчетов, накладывая на одном графике одинаковую расчетную переменную первого и второго расчетов. Также, можно взять разницу между ними и убедиться что она равна нулю на всём интервале моделирования. Либо, если результаты все же отличаются (например из-за особенностей реализации методов интегрирования в разных программных средах), можно посчитать среднеквадратичное отклонение на заданном времени расчета, или еще как-то по-другому оценить рассогласование.
Мне хватило наложения графиков друг на друга и расчета разницы между ними. Приведу внешний вид одного из простых тестов:

А вот один из графиков сравнения, из которого видно что результаты совпадают чуть более чем полностью. Таких графиков я получил сотни, приводить их все здесь не представляется возможным.


В теории, задача валидации выглядела довольно простой, кроме того что это большой объем чисто технической работы. Но на практике я столкнулся с рядом трудностей.
Опуская трудности переноса самой модели - она всё же не маленькая, более 500 блоков и субмоделей плюс бесконечные уровни вложенности, в самом начале я столкнулся с базовой проблемой: как именно результаты расчета Симулинка выложить в файл, чтобы этот файл потом "понимал" Симинтек? Не являясь сильно опытным пользователем Матлаба с Симулинком, ответа у меня не было. Погуглив и перебрав по возможности все блоки импорта-экспорта в Симулинке, ничего подходящего что выгружало бы результат расчета в один из распространенных текстовых форматов, в Симулинке я не нашёл. Какой-то бинарный только *.mat формат был подходящим, в него Симулинк выгружает временные серии в своём формате. Но как его потом прочитать, оставалось загадкой:

Погуглив тему еще несколько раз, я понял что надо воспользоваться уже языком Матлаба, чтобы перегнать эти временные серии в человеческий (текстовый) формат. Который потом уже в Симинтеке так или иначе я прочитаю. В результате у меня родился такой скрипт для Матлаба (при помощи функции записи матрицы https://www.mathworks.com/help/matlab/ref/writematrix.html):

Полученные CSV-файлы по каждой из расчетных переменных, потом я считывал в Симинтеке блоком "Считывание строк из файла". Каждую переменную приходилось записывать в свой файл.
Итого, сначала я прогонял все расчеты в симулинке, потом запускал в работу этот скрипт в Матлабе, а дальше уже полученные CSV-файлы считывал в Симинтеке.
Далее, первые тесты которые я начал гнать на полной модели, выдавали хотя и похожий, но разный результат. А иногда сильно разный. Искать визуально ошибки в схеме на 600 блоков - такое себе занятие. Ничего решительно не нашлось. А делать пошаговый расчет и отлавливать отдельно по сигналам, делать трассировку где и что я выполнил не так, как в прототипе - тоже занятие требующее многих лет жизни и свободного времени и мотивации.
Пришлось решать задачу по частям, и сначала отладить не всю модель, а по составным частям. Сначала регуляторы, потом модель тела с 6-ю степенями свободы, затем матрицы преобразования, составные части расчета аэродинамических коэффициентов. Делая сравнение по составным частям, постепенно все ошибки я нашёл, вычистил их, и смог вернуться к валидации модели АСП в целом.
Далее уже всё шло хорошо, только иногда появлялись новые ошибки в незадействованных предыдущими тестами частях модели, но их уже было относительно легко находить, меняя (зануляя) те или иные входные сигналы и отслеживая в каком именно месте сидит ошибка.
Иногда результаты совпадали "не очень хорошо", и я наблюдал такую бахрому, даже на сведенных к минимуму спорных местах:

Но мы пришли к мнению что это из-за разницы реализации тригонометрических функций в Симулинке и Симинтеке, и всё же это рассогласование (10 в минус 12 степени) очень близко к нулю, и считаем что оно 0.
Заключение
В отечественном ПО SimInTech можно набрать думаю практически любую модель, выполненную в среде MATLAB/Simulink. Наверно, справедливо и обратное утверждение. Есть также конвертор моделей из Симулинка в Симинтек, которым можно пользоваться. Правда он всё равно не отменит ручного труда. В настоящей статье приведен один из подходов к сравнению полученных результатов моделирования в каждом из ПО.
Если публикация вызовет интерес, возможно в будущем более подробно опишу методику переноса модели из одного пакета в другой. Благодарю за внимание!
Автор: Александр Щекатуров