返回无人机以减少电池电量
在这个项目中,我们将应用几种使用有限自动机计算代理系统的方法。
为什么是有限自动机?
有限自动机允许您在抽象级别创建调试环境或测试决策算法。 为了避免从头开始开发和维护解决方案的成本,我们将尝试其他几种方法。:
-使用标准库建模[StateMachines](https://juliapackages.com/p/statemachines )和
-使用Engee图形语言。
有限状态机的最简单例子
首先,让我们构建一个简单的确定性有限自动机(DFSM)。
]add StateMachines
让我们创建一个自动售货机 a1,它设置了在电池电量不足时将四轴飞行器返回底座的逻辑。
using StateMachines
a1 = Automaton([
Transition("landed", "flying", :takeoff), # Взлет по команде
Transition("flying", "returning", :low_battery), # Авто-возврат
Transition("flying", "returning", :return_cmd), # Возврат по команде
Transition("returning", "landed", :returned), # Посадка
], start="landed")
states = []
events = [ :idle, :takeoff, :low_battery, :returned ]
for event in events
prev_state = a1.state
StateMachines.exec!( a1, event )
append!( states, [a1.state] )
println( "Переход $(String(prev_state)) -> $(String(a1.state)) по событию: $(String(event))" )
end
另一个输出选项是图形。 对于此输出,我们将转换数组 states 和 events 在小写形式中,我们将为它们设置一定的顺序,以便输出不是按字母顺序执行,而是按更合乎逻辑的顺序执行。
]add CategoricalArrays Measures
using CategoricalArrays, Measures
gr()
# Зададим порядок событий и состояний (в противном случае они выводятся в алфавитном порядке)
events_ordered = levels!( categorical(string.(events)), ["idle", "takeoff", "low_battery", "returned"])
states_ordered = levels!( categorical(string.(states)), ["landed", "flying", "returning"])
plot(
plot( events_ordered, 1:length(events_ordered), title="События",
st=:steppre, yflip=true, lw=repeat([ 12; 2 ], length(events_ordered))[1:end-1] ),
plot( states_ordered, 1:length(states_ordered), title="Состояния",
st=:steppre, yflip=true, yaxis=nothing, c=2,
lw=repeat([ 12; 2 ], length(states_ordered))[1:end-1] ),
legend=false, xmirror=true, top_margin=5mm, right_margin = [10mm 0mm],
)
plot!( size=(800,300) )
我们已经建立了一个相当典型的图,它在UML中被称为 Sequence Diagram (图表последовательности).
如果另一种解释方便,则可以反转图形的轴。
# Зададим порядок событий и состояний (в противном случае они выводятся в алфавитном порядке)
events_ordered = levels!( categorical(string.(events)), ["idle", "takeoff", "low_battery", "returned"])
states_ordered = levels!( categorical(string.(states)), ["landed", "flying", "returning"])
plot(
plot( 1:length(events_ordered), events_ordered, title="События",
st=:steppre, lw=repeat([ 2; 12 ], length(events_ordered))[1:end-1] ),
plot( 1:length(states_ordered), states_ordered, title="Состояния",
st=:steppre, c=2, lw=repeat([ 2; 12 ], length(states_ordered))[1:end-1] ),
legend=false, xmirror=true, top_margin=5mm, right_margin = [10mm 0mm],
)
plot!( size=(800,300) )
在Engee环境中使用图表组件
有限自动机的编程任务便于对大型系统或生成的场景进行建模。 Engee中呈现的图形形式主义也非常适合表示小型决策算法。 Chart (有限状态机)。
我们定义了一个场景,其中事件的发生以块为单位进行建模。 Ступенчатая функция (Step),穿过街区 Разность (Difference). 等有限状态机的输入 Логика возврата 不会有步骤,而是离散脉冲。
在块下添加了注释元素,以便在模型中一目了然地看到整个测试场景。
剩下的就是在命令控制模式下运行模型并构建图形。:
model_name = "drone_rtb_state_machine";
model_name in [m.name for m in engee.get_all_models()] ? engee.open(model_name) : engee.load( "$(@__DIR__)/$(model_name).engee");
res = engee.run( model_name );
plot( res["Состояние"].time, res["Состояние"].value, label="Состояние",
yticks=((1,2,3), ("На базе","Полет","Возвращение")), lw=3, size=(600,300) )
您可以从此图生成代码(但是,由于C中不支持西里尔字符,因此最好为块选择一个名称 Chart,由拉丁字符组成)。
结论
我们创建了一个四轴飞行器最简单的功能之一的模型-当电池电量不足时"返回基地"。 您可以将此模型用作更复杂系统的测试场景,以检查受控环境中某些条件的顺序和发生情况。


