Engee documentation
Notebook

Simulation of automatic transmission operation

In this example, we will analyze the Chart tool and the logic of finite automata implemented by it, based on the principles of automatic gear shifting depending on speed.

At a simplified level, let's consider the differences in the operation of two types of algorithms – using states and using transition nodes.

At the beginning of the demonstration, we will declare an auxiliary function for running the model and proceed to the analysis of the implemented algorithms.

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)

At the top level, the model contains two gearshift algorithms. The inputs for both charts are identical. The tables set the threshold values for the speed at which it is necessary to either increase or decrease the transmission, and the value of the current speed itself, set by the sine wave.

image.png

Next, let's look at each Chart individually. The upper block uses the logic of the nodes and, depending on the speed, outputs the gear shift parameter +-1, which allows you to increase or decrease the gear, which is stored in the loop. The initial transfer value in both cases is 1.

image.png

In the second case, depending on the speed, we switch between different states in which a suitable transmission is set for the input speed mode.

image.png

Now let's run the model itself and analyze the generated values.

In [ ]:
run_model("car") # Запуск модели.
Building...
Progress 0%
Progress 0%
Progress 26%
Progress 100%
Progress 100%
Out[0]:
SimulationResult(
    "GearChart.gear" => WorkspaceArray{Float64}("car/GearChart.gear")
,
    "ShiftChart.shift" => WorkspaceArray{Float64}("car/ShiftChart.shift")
,
    "Bias.1" => WorkspaceArray{Float64}("car/Bias.1")
,
    "gear" => WorkspaceArray{Float64}("car/gear")

)

We are reading the cached data from the simout.
In this case:

v is the speed of the car;

shift is the shift parameter for the gearbox algorithm implemented using nodes.;

gear_node – transmission values for Chart using nodes;

gear_state – transmission values for a Chart with states.

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);

Now let's move on to analyzing the received data. Let's start with speed. As we can see from the graph below, the speed is set by a sine wave in the range from 0 to 120. The initial speed value is not zero. It is designed to visually demonstrate the differences between algorithms using nodes and states.

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

Next, we will analyze the system using nodes. As we can see, the initial value of this system in the first step is not the first gear, but the second. This is because the node immediately reported the increment of the counter.

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

Now let's pay attention to the state-based system. The initial transfer value is 1. This is due to the fact that in the case of states in the absence of initialization logic, we will start with the input state and then go through a maximum of one state per clock cycle.

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

Now let's compare the values calculated by different transmission simulation systems. As we can see from the results below, the first two bars are different. This is due to the logic processing features described above.

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

Conclusion

In this demo, we analyzed the differences in the logic of nodes and states. Using this example, we got a clear idea of how different algorithms implemented using the Chart block are processed.