Преобразование модели MATLAB Simulink в модель Engee
Введение
В этом примере мы рассмотрим процесс автоматического переноса пользовательских наработок из MATLAB Simulink в Engee, а также сравним результат переноса, промоделировав исходную и полученную модели.
Получение скрипта для построения модели
Первый шаг переноса модели из Simulink – автоматическое получение скрипта для построения модели Engee при помощи командного управления. Для начала определим переменные для файлов этого примера:
путь_примера = "$(@__DIR__)" # Путь к папке примера
имя_модели = "alphabetafilter" # Имя моделей
модельSLX = путь_примера*"/slx/"*имя_модели*".slx"; # Путь к исходной модели
mkdir(joinpath(путь_примера,"engee")); # Создаём папку для результирующей модели
скриптJL = путь_примера*"/engee/convert_script.jl"; # Путь к результирующему скрипту
модельENGEE = путь_примера*"/engee/"*имя_модели*".engee"; # Путь к результирующей модели
Модель MATLAB Simulink, которую мы используем в данном примере, – alphabetafilter.slx
из примера интеграции кода Си в модель Engee.
Теперь воспользуемся функцией программного управления engee.convert_model()
.
Эта функция сначала определяет содержимое исходной модели –
подсистемы, блоки, параметры, связи блоков и подсистем.
Затем на основе полученных данных она создаёт скрипт .jl
с командами программного управления для построения новой модели .engee
engee.convert_model(модельSLX, скриптJL); # Получение скрипта .jl для автоматического создания модели Engee
⚠️ При конвертации моделей стоит учитывать, что в текущем релизе Engee:
engee.version()
поддерживается конвертация блоков, поддерживаемых генератором кода.
В дальнейшем также будет реализована поддержка конвертации для вcех блоков библиотеки Engee.
Содержимое полученного скрипта приведено ниже. В коде для автоматического построения модели .engee
используются следующие функции:
engee.create()
– создаёт новую модель;engee.add_block()
– добавляет блок из библиотеки Engee;engee.set_param!()
– обновляет параметры модели/блока;engee.delete_contents()
– удаляет содержимое системы;engee.add_line()
– добавляет связь/связи между блоками;engee.save()
– сохраняет модель;engee.close()
– закрывает модель.
Дополнительно с программным управлением можно ознакомиться в соответствующем примере.
Результирующий код
model = engee.create("alphabetafilter")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/processNoiseVariance")
engee.set_param!("alphabetafilter/processNoiseVariance", "SignalType"=>"real")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/measurementNoiseVariance")
engee.set_param!("alphabetafilter/measurementNoiseVariance", "SignalType"=>"real")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/y")
engee.set_param!("alphabetafilter/y", "SignalType"=>"real")
engee.add_block("/Basic/Ports & Subsystems/Subsystem", "alphabetafilter/determineAlphaBeta")
engee.delete_contents("alphabetafilter/determineAlphaBeta")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/determineAlphaBeta/processNoiseVariance")
engee.set_param!("alphabetafilter/determineAlphaBeta/processNoiseVariance", "SignalType"=>"real")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/determineAlphaBeta/measurementNoiseVariance")
engee.set_param!("alphabetafilter/determineAlphaBeta/measurementNoiseVariance", "SignalType"=>"real")
engee.add_block("/Basic/Math Operations/Add", "alphabetafilter/determineAlphaBeta/Add")
engee.add_block("/Basic/Math Operations/Add", "alphabetafilter/determineAlphaBeta/Add1")
engee.set_param!("alphabetafilter/determineAlphaBeta/Add1", "Inputs"=>"+-")
engee.add_block("/Basic/Math Operations/Add", "alphabetafilter/determineAlphaBeta/Add2")
engee.set_param!("alphabetafilter/determineAlphaBeta/Add2", "Inputs"=>"+-")
engee.add_block("/Basic/Math Operations/Bias", "alphabetafilter/determineAlphaBeta/Bias")
engee.set_param!("alphabetafilter/determineAlphaBeta/Bias", "Bias"=>"4")
engee.add_block("/Basic/Math Operations/Bias", "alphabetafilter/determineAlphaBeta/Bias1")
engee.set_param!("alphabetafilter/determineAlphaBeta/Bias1", "Bias"=>"-1")
engee.add_block("/Basic/Math Operations/Bias", "alphabetafilter/determineAlphaBeta/Bias2")
engee.set_param!("alphabetafilter/determineAlphaBeta/Bias2", "Bias"=>"-2")
engee.add_block("/Basic/Math Operations/Bias", "alphabetafilter/determineAlphaBeta/Bias3")
engee.set_param!("alphabetafilter/determineAlphaBeta/Bias3", "Bias"=>"-1")
engee.add_block("/Basic/Sources/Constant", "alphabetafilter/determineAlphaBeta/Constant")
engee.set_param!("alphabetafilter/determineAlphaBeta/Constant", "Value"=>"dt")
engee.set_param!("alphabetafilter/determineAlphaBeta/Constant", "SampleTime"=>"0.0")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/determineAlphaBeta/Gain")
engee.set_param!("alphabetafilter/determineAlphaBeta/Gain", "Gain"=>"8")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/determineAlphaBeta/Gain1")
engee.set_param!("alphabetafilter/determineAlphaBeta/Gain1", "Gain"=>"1/4")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/determineAlphaBeta/Gain2")
engee.set_param!("alphabetafilter/determineAlphaBeta/Gain2", "Gain"=>"-1")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/determineAlphaBeta/Gain3")
engee.set_param!("alphabetafilter/determineAlphaBeta/Gain3", "Gain"=>"-1")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/determineAlphaBeta/Gain4")
engee.set_param!("alphabetafilter/determineAlphaBeta/Gain4", "Gain"=>"2")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/determineAlphaBeta/Gain5")
engee.set_param!("alphabetafilter/determineAlphaBeta/Gain5", "Gain"=>"-1")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/determineAlphaBeta/Gain6")
engee.set_param!("alphabetafilter/determineAlphaBeta/Gain6", "Gain"=>"4")
engee.add_block("/Basic/Math Operations/Math Function", "alphabetafilter/determineAlphaBeta/Math Function")
engee.set_param!("alphabetafilter/determineAlphaBeta/Math Function", "Operator"=>"square")
engee.add_block("/Basic/Math Operations/Math Function", "alphabetafilter/determineAlphaBeta/Math Function1")
engee.set_param!("alphabetafilter/determineAlphaBeta/Math Function1", "Operator"=>"square")
engee.add_block("/Basic/Math Operations/Math Function", "alphabetafilter/determineAlphaBeta/Math Function2")
engee.set_param!("alphabetafilter/determineAlphaBeta/Math Function2", "Operator"=>"square")
engee.add_block("/Basic/Math Operations/Math Function", "alphabetafilter/determineAlphaBeta/Math Function3")
engee.set_param!("alphabetafilter/determineAlphaBeta/Math Function3", "Operator"=>"reciprocal")
engee.add_block("/Basic/Math Operations/Product", "alphabetafilter/determineAlphaBeta/Product")
engee.set_param!("alphabetafilter/determineAlphaBeta/Product", "Inputs"=>"**")
engee.add_block("/Basic/Math Operations/Product", "alphabetafilter/determineAlphaBeta/Product1")
engee.set_param!("alphabetafilter/determineAlphaBeta/Product1", "Inputs"=>"**")
engee.add_block("/Basic/Math Operations/Sqrt", "alphabetafilter/determineAlphaBeta/Sqrt")
engee.add_block("/Basic/Math Operations/Sqrt", "alphabetafilter/determineAlphaBeta/Sqrt1")
engee.add_block("/Basic/Ports & Subsystems/Out1", "alphabetafilter/determineAlphaBeta/alpha")
engee.set_param!("alphabetafilter/determineAlphaBeta/alpha", "InitialOutput"=>"0")
engee.add_block("/Basic/Ports & Subsystems/Out1", "alphabetafilter/determineAlphaBeta/beta")
engee.set_param!("alphabetafilter/determineAlphaBeta/beta", "InitialOutput"=>"0")
engee.add_line("alphabetafilter/determineAlphaBeta", "Add/1", "Sqrt/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Math Function2/1", "Bias1/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain1/1", "Math Function2/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Sqrt/1", "Add1/2")
engee.add_line("alphabetafilter/determineAlphaBeta", "Bias/1", "Add1/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Bias1/1", "Gain2/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Add2/1", "beta/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Math Function/1", "Product/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain5/1", "Sqrt1/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Add1/1", "Gain1/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Bias3/1", "Gain5/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Product1/1", "Math Function1/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Product1/1", "Gain/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Product1/1", "Bias/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Bias2/1", "Gain3/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Product/1", "Product1/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain/1", "Add/2")
engee.add_line("alphabetafilter/determineAlphaBeta", "Sqrt1/1", "Gain6/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain2/1", "alpha/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain2/1", "Bias2/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain2/1", "Bias3/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain3/1", "Gain4/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain6/1", "Add2/2")
engee.add_line("alphabetafilter/determineAlphaBeta", "Math Function1/1", "Add/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Gain4/1", "Add2/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "Constant/1", "Math Function/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "measurementNoiseVariance/1", "Math Function3/1")
engee.add_line("alphabetafilter/determineAlphaBeta", "processNoiseVariance/1", "Product/2")
engee.add_line("alphabetafilter/determineAlphaBeta", "Math Function3/1", "Product1/2")
engee.add_block("/Basic/Ports & Subsystems/Subsystem", "alphabetafilter/filterInputSignal")
engee.delete_contents("alphabetafilter/filterInputSignal")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/filterInputSignal/alpha")
engee.set_param!("alphabetafilter/filterInputSignal/alpha", "SignalType"=>"real")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/filterInputSignal/beta")
engee.set_param!("alphabetafilter/filterInputSignal/beta", "SignalType"=>"real")
engee.add_block("/Basic/Ports & Subsystems/In1", "alphabetafilter/filterInputSignal/y")
engee.set_param!("alphabetafilter/filterInputSignal/y", "SignalType"=>"real")
engee.add_block("/Basic/Math Operations/Add", "alphabetafilter/filterInputSignal/Add")
engee.add_block("/Basic/Math Operations/Add", "alphabetafilter/filterInputSignal/Add1")
engee.set_param!("alphabetafilter/filterInputSignal/Add1", "Inputs"=>"+-")
engee.add_block("/Basic/Math Operations/Add", "alphabetafilter/filterInputSignal/Add2")
engee.add_block("/Basic/Math Operations/Add", "alphabetafilter/filterInputSignal/Add3")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/filterInputSignal/Gain")
engee.set_param!("alphabetafilter/filterInputSignal/Gain", "Gain"=>"dt")
engee.add_block("/Basic/Math Operations/Gain", "alphabetafilter/filterInputSignal/Gain1")
engee.set_param!("alphabetafilter/filterInputSignal/Gain1", "Gain"=>"1/dt")
engee.add_block("/Basic/Math Operations/Product", "alphabetafilter/filterInputSignal/Product")
engee.set_param!("alphabetafilter/filterInputSignal/Product", "Inputs"=>"**")
engee.add_block("/Basic/Math Operations/Product", "alphabetafilter/filterInputSignal/Product1")
engee.set_param!("alphabetafilter/filterInputSignal/Product1", "Inputs"=>"**")
engee.add_block("/Basic/Discrete/Unit Delay", "alphabetafilter/filterInputSignal/Unit Delay")
engee.set_param!("alphabetafilter/filterInputSignal/Unit Delay", "InitialCondition"=>"0")
engee.set_param!("alphabetafilter/filterInputSignal/Unit Delay", "SampleTime"=>"-1")
engee.add_block("/Basic/Discrete/Unit Delay", "alphabetafilter/filterInputSignal/Unit Delay1")
engee.set_param!("alphabetafilter/filterInputSignal/Unit Delay1", "InitialCondition"=>"0")
engee.set_param!("alphabetafilter/filterInputSignal/Unit Delay1", "SampleTime"=>"-1")
engee.add_block("/Basic/Ports & Subsystems/Out1", "alphabetafilter/filterInputSignal/x")
engee.set_param!("alphabetafilter/filterInputSignal/x", "InitialOutput"=>"0")
engee.add_line("alphabetafilter/filterInputSignal", "Add1/1", "Product/2")
engee.add_line("alphabetafilter/filterInputSignal", "Add1/1", "Product1/1")
engee.add_line("alphabetafilter/filterInputSignal", "Unit Delay/1", "Add/1")
engee.add_line("alphabetafilter/filterInputSignal", "Add3/1", "Unit Delay1/1")
engee.add_line("alphabetafilter/filterInputSignal", "Unit Delay1/1", "Add3/2")
engee.add_line("alphabetafilter/filterInputSignal", "Unit Delay1/1", "Gain/1")
engee.add_line("alphabetafilter/filterInputSignal", "y/1", "Add1/1")
engee.add_line("alphabetafilter/filterInputSignal", "Product/1", "Add2/2")
engee.add_line("alphabetafilter/filterInputSignal", "Add2/1", "Unit Delay/1")
engee.add_line("alphabetafilter/filterInputSignal", "Add2/1", "x/1")
engee.add_line("alphabetafilter/filterInputSignal", "Gain1/1", "Add3/1")
engee.add_line("alphabetafilter/filterInputSignal", "Product1/1", "Gain1/1")
engee.add_line("alphabetafilter/filterInputSignal", "alpha/1", "Product/1")
engee.add_line("alphabetafilter/filterInputSignal", "Gain/1", "Add/2")
engee.add_line("alphabetafilter/filterInputSignal", "Add/1", "Add2/1")
engee.add_line("alphabetafilter/filterInputSignal", "Add/1", "Add1/2")
engee.add_line("alphabetafilter/filterInputSignal", "beta/1", "Product1/2")
engee.add_block("/Basic/Ports & Subsystems/Out1", "alphabetafilter/x")
engee.set_param!("alphabetafilter/x", "InitialOutput"=>"0")
engee.add_line("alphabetafilter", "measurementNoiseVariance/1", "determineAlphaBeta/2")
engee.add_line("alphabetafilter", "processNoiseVariance/1", "determineAlphaBeta/1")
engee.add_line("alphabetafilter", "determineAlphaBeta/1", "filterInputSignal/1")
engee.add_line("alphabetafilter", "determineAlphaBeta/2", "filterInputSignal/2")
engee.add_line("alphabetafilter", "y/1", "filterInputSignal/3")
engee.add_line("alphabetafilter", "filterInputSignal/1", "x/1")
engee.save(model, "alphabetafilter.engee")
engee.close()
end
Построение модели Engee
Второй и завершающий шаг переноса модели Simulink в модель Engee – воспроизведение полученного скрипта:
cd(joinpath(путь_примера,"engee")) # Переходим в папку примера – в ней будет располагаться модель .engee
include(скриптJL) # Запускаем выполнение скрипта .jl для автоматического создания модели .engee
В результате выполнения предыдущей ячейки в папке текущего примера появится требуемый файл модели .engee
. Полученная модель готова к использованию.
При помощи функций engee.load()
и engee.open()
программного управления мы можем убедиться, что построенная модель с подсистемами открываются, и, следовательно, они созданы корректно.
# Функция для проверки модели и подсистем на открытие
function model_check(name::String, path::String, subsystem::String, delay::Int) # Функция получает имя и путь модели, имя подсистемы, время ожидания
model = engee.load(path) # Загружаем модель
sleep(delay) # Ожидаем завершения синхронизации GUI
engee.open(joinpath(name,subsystem)) # Открываем подсистему
sleep(delay) # Ожидаем завершения синхронизации GUI
engee.save(model, name*".engee"; force=true) # Обновляем модель
sleep(delay) # Ожидаем завершения синхронизации GUI
# Закрываем модель
try
engee.close(model)
catch e
engee.close_all()
end
sleep(delay) # Ожидаем завершения синхронизации GUI
return nothing # Функция ничего не возвращает
end;
Проверим, созданы ли модель и подсистемы – откроем подсистемы по очереди. Для выполнения ячейки требуется некоторое время, чтобы произошла синхронизация графического пользовательского интерфейса (GUI).
подсистемы = ["filterInputSignal", "determineAlphaBeta"] # Вектор с именами открываемых подсистем
for i in подсистемы # Цикл по вектору
model_check(имя_модели, модельENGEE, i, 5) # Циклический вызов функции проверки модели и подсистем
# время ожидания = 3 [сек]. При медленной синхронизации GUI
# рекомендуется увеличить время ожидания
end
В процессе выполнения ячейки в среде моделирования Engee открываются и закрываются вкладки модели и подсистем. Необходимо дождаться завершения выполнения всех команд управления моделью и GUI.
Далее перейдём к верификации автоматически построенной модели .engee
.
Верификация полученной модели
Воспользуемся способом, описанным в примере интеграции кода на языке Си.
Моделирование исходной модели Simulink
Исходные данные для верификации – результаты работы модели Simulink. Для получения результатов сгенерируем из неё код при помощи Simulink Embedded Coder.
# Загружаем и устанавливаем библиотеку MATLAB, если она ещё не установлена
import Pkg; Pkg.add("MATLAB")
cgModel = модельSLX # Путь модели Simulink
cgPath = mkdir(joinpath(путь_примера,"slx","cg")); # Создаём директорию для результатов генерации кода из модели Simulink
using MATLAB # Подключаем библиотеку MATLAB
mat""" % Вставка кода на языке MATLAB
model = load_system($cgModel); % Загружаем модель Simulink в память
path = $cgPath; % Сохраняем путь к папке генерации кода
set_param(0, 'CacheFolder', path) % Определяем путь к папке кэша моделирования
set_param(0, 'CodeGenFolder', path) % Определяем путь к папке генерации кода
slbuild(model) % Генерируем код из исходной модели Simulink
set_param(0, 'CacheFolder', '') % Сбрасываем путь к папке кэша моделирования
set_param(0, 'CodeGenFolder', '') % Сбрасываем путь к папке генерации кода
""" # Конец вставки кода
Модель, в которой при помощи блока C Function
встраивается сгенерированный код из модели Simulink, – test_cg_simulink.engee
. Необходимые пути к файлам Си уже указаны в блоке C Function
.
Загрузим, выполним и закроем эту модель.
тест_моделиSLX = engee.load(joinpath(путь_примера, "test_cg_simulink.engee"), force = true); # Загружаем модель для сбора исходных данных верификации
результаты_моделиSLX = engee.run(тест_моделиSLX); # Выполняем модель и сохраняем исходные данные
engee.close(тест_моделиSLX, force = true);
Для наглядности построим графики сигналов, полученных в результате моделирования:
# Передадим результаты моделирования в отдельные переменные:
noisy_t_slx = результаты_моделиSLX["noisy"].time;
noisy_v_slx = результаты_моделиSLX["noisy"].value;
filtered_t_slx = результаты_моделиSLX["filtered"].time;
filtered_v_slx = результаты_моделиSLX["filtered"].value;
plot(noisy_t_slx, noisy_v_slx, label = "Исходный сигнал") # Строим график зашумленного сигнала
plot!(filtered_t_slx, filtered_v_slx, label = "Отфильтрованный сигнал") # Строим график отфильтрованного сигнала (при помощи кода, сгенерированного из модели Simulink)
plot!(legend = :bottomright) # Расположение легенды
title!("Результаты работы исходной модели Simulink") # Заголовок
xlabel!("Время, [с]") # Подпись оси X
ylabel!("Амплитуда") # Подпись оси Y
Моделирование полученной модели Engee
Теперь перейдём к моделированию и получению результатов от модели Engee, построенной при помощи автоматически сгенерированного скрипта.
Определяем настраиваемые параметры модели (те же значения, что и в модели Simulink):
# Настраиваемые параметры модели:
dt = 0.01;
Gain = 1/dt;
Генерируем код Си из автоматически построенной модели Engee:
engee.generate_code(модельENGEE, путь_примера*"/engee/code") # Автоматическая генерация кода Си из модели Engee
Идентичная предыдущей модель, в которой также при помощи блока
C Function
встраивается сгенерированный код из модели Engee, – test_cg_engee.engee
. Необходимые пути к файлам Си уже указаны в блоке C Function
.
Загрузим, выполним и закроем эту модель.
тест_моделиENGEE = engee.load(joinpath(путь_примера, "test_cg_engee.engee"), force = true); # Загружаем модель для сбора данных верификации модели Engee
результаты_моделиENGEE = engee.run(тест_моделиENGEE); # Выполняем модель и сохраняем исходные данные
engee.close(тест_моделиENGEE, force = true);
Для наглядности построим графики сигналов, полученных в результате моделирования:
# Передадим результаты моделирования в отдельные переменные:
noisy_t_engee = результаты_моделиENGEE["noisy"].time;
noisy_v_engee = результаты_моделиENGEE["noisy"].value;
filtered_t_engee = результаты_моделиENGEE["filtered"].time;
filtered_v_engee = результаты_моделиENGEE["filtered"].value;
plot(noisy_t_engee, noisy_v_engee, label = "Исходный сигнал") # Строим график зашумленного сигнала
plot!(filtered_t_engee, filtered_v_engee, label = "Отфильтрованный сигнал") # Строим график отфильтрованного сигнала (при помощи кода, сгенерированного из модели Engee)
plot!(legend = :bottomright) # Расположение легенды
title!("Результаты работы построенной модели Engee") # Заголовок
xlabel!("Время, [с]") # Подпись оси X
ylabel!("Амплитуда") # Подпись оси Y
Сравнение результатов моделирования
Графики позволяют уверенно сделать вывод, что результаты построения моделей в двух рассматриваемых нами средах моделирования аналогичны. Вычислим минимальные и максимальные значения абсолютных отклонений результатов моделирования для модели Simulink и сконвертированной из неё модели Engee:
# Вычисляем абсолютные отклонения величин смоделированных сигналов
Δ_noisy_v = noisy_v_slx .- noisy_v_engee;
Δ_filtered_v = filtered_v_slx .- filtered_v_engee;
println("""Абсолютные отклонения величин сигналов для построенной модели Engee от исходной модели Simulink:
- зашумленный сигнал минимум: $(minimum(Δ_noisy_v)) максимум: $(maximum(Δ_noisy_v))
- отфильтрованный сигнал минимум: $(minimum(Δ_filtered_v)) максимум: $(maximum(Δ_filtered_v))""")
Как видно из графического и аналитического сопоставления, в работе автоматически сгенерированной модели Engee нет отклонений по сравнению с работой исходной модели Simulink.
Выводы
В этом примере мы рассмотрели процесс конвертации моделей Simulink в модель Engee, провели верификацию построенной модели при помощи автоматической генерации кода. Также подробно ознакомились с применением многих функций программного управления Engee. По итогам этого эксперимента мы установили, что сконвертированная модель Engee не отличается от исходной Simulink. Исходную модель можно удалить за ненадобностью и во избежание путаницы:
# rm(модельSLX; force=true); # При необходимости раскомментируйте строку