Документация Engee
Notebook

Имитация работы автоматической коробки передач

Открыть пример в Engee

В данном примере мы разберём инструмент Chart и реализуемую им логику конечных автоматов, основанную на принципах автоматического переключения передач в зависимости от скорости.

На упрощённом уровне рассмотрим различия в работе алгоритмов двух типов – с применением состояний и с использованием узлов переходов.

В начале демонстрации объявим вспомогательную функцию для запуска модели и перейдём к анализу реализованных алгоритмов.

In [ ]:
# Подключение вспомогательной функции запуска модели.
function run_model( name_model)
    
    Path = (@__DIR__) * "/" * name_model * ".engee"
    
    if name_model in [m.name for m in engee.get_all_models()] # Проверка условия загрузки модели в ядро
        model = engee.open( name_model ) # Открыть модель
        model_output = engee.run( model, verbose=true ); # Запустить модель
    else
        model = engee.load( Path, force=true ) # Загрузить модель
        model_output = engee.run( model, verbose=true ); # Запустить модель
        engee.close( name_model, force=true ); # Закрыть модель
    end
    sleep(5)
    return model_output
end
Out[0]:
run_model (generic function with 1 method)

На верхнем уровне модель содержит два алгоритма перключения передач. Входы для обоих чартов идентичны. В таблицах заданы пороговые значения для скорости, при которых необходимо либо повысить передачу, либо понизить её, и само значение текущей скорости, заданное синусоидой.

image.png

Далее рассмотрим каждый Chart в отдельности. Верхний блок использует логику узлов и в зависимости от скорости выдаёт параметр сдвига передачи +-1, что позволяет выполнить повышение или понижения передачи, которое хранится в петле. Начальное значение передачи в обоих случаях равно 1.

image.png

Во втором случае в зависимости от скорости мы переключаемся между различными состояниями, в которых задаётся подходящая передача под входной скоростной режим.

image.png

Теперь запустим саму модель и проанализируем залогированные значения.

In [ ]:
run_model("car") # Запуск модели.
Building...
Progress 100%
Out[0]:
Dict{String, DataFrames.DataFrame} with 4 entries:
  "GearChart.gear"   => 1001×2 DataFrame…
  "ShiftChart.shift" => 1001×2 DataFrame…
  "Bias.1"           => 1001×2 DataFrame…
  "gear"             => 1001×2 DataFrame

Считываем из simout залогированные данные. В данном случае:

v – это скорость автомобиля;

shift – параметр сдвига для алгоритма коробки передач, реализованной с использованием узлов;

gear_node – значения передачи для Chart с использованием узлов;

gear_state – значения передачи для Chart с состояниями.

In [ ]:
v = simout["car/Bias.1"];
v = collect(v);
shift = simout["car/ShiftChart.shift"];
shift = collect(shift);
gear_node = simout["car/gear"];
gear_node = collect(gear_node);
gear_state = simout["car/GearChart.gear"];
gear_state = collect(gear_state);

Теперь перейдём к анализу полученных данных. Начнём со скорости. Как мы видим из графика, приведённого ниже, скорость задана синусоидой в диапазоне от 0 до 120. Начальное значение скорости не нулевое. Оно задано с целью наглядной демонстрации различий алгоритмов с применением узлов и состояний.

In [ ]:
plot(v.time, v.value)
Out[0]:

Далее проанализируем систему с применением узлов. Как мы видим, начальное значение данной системы на первом шаге – не первая передача, а вторая. Это связано с тем, что узел сразу сообщил о приращении счётчика.

In [ ]:
plot(gear_node.time, gear_node.value)
plot!(shift.time, shift.value)
Out[0]:

Теперь обратим внимание на систему, реализованную на основе состояний. Начальное значение передачи равно 1. Это связано с тем, что в случае с состояниями при отсутствии логики инициализации мы начнём с входного состояния и далее будем проходить максимум по одному состоянию за такт.

In [ ]:
plot(gear_state.time, gear_state.value)
Out[0]:

Теперь сравним значения, рассчитанные различными системами имитации работы коробки передач. Как мы видим из результатов ниже, первые два такта различаются. Это связано с особенностями обработки логики, описанными выше.

In [ ]:
difference = gear_state.value-gear_node.value;
print("Различие в логике переключения передачь: "*string(difference[1:3]))
Различие в логике переключения передачь: [-1.0, -1.0, 0.0]

Вывод

В данной демонстрации мы проанализировали различия в логике узлов и состояний. На этом примере мы получили наглядное представление о том, как обрабатываются разные алгоритмы, реализованные при помощи блока Chart.

Блоки, использованные в примере