VAPS XT入门教程15.02:状态机
系列索引:VAPS XT入门教程索引
VAPS XT提供了状态机功能,用于实现不同状态间的切换。
最左侧的带圆点的为入口,有且只有一个。
Normal为常显状态,从入口进来之后就是Normal状态。
Press为按下状态
鼠标左键简单点击的操作为:Normal->Press->Normal。
按下然后松开。
Naormal->Press的触发条件为evPress,即鼠标按下
Press->Normal的触发条件为evRelease,即鼠标松开。
此图就是最简单的点击一次的操作状态图。
原理
一个健壮的状态机可以让你的程序,不论发生何种突发事件都不会突然进入一个不可预知的程序分支。
这正是VAPS XT这种软件需要的功能,飞机上的软件一切都要是可控的,所有的状态都是可预测的,这也是适航认证的重点。
定义
状态机是有限状态自动机(FSM, Finite State Machine)的简称,是现实事物运行规则抽象而成的一个数学模型。
先来解释什么是“状态”(State)。现实事物是有不同状态的,例如一个LED等,就有 亮 和 灭 两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有限个,例如LED灯的状态就是两个 亮 和 灭。
状态机,也就是 State Machine ,不是指一台实际机器,而是指一个数学模型。说白了,一般就是指一张状态转换图。
举例
以物理课学的灯泡图为例,就是一个最基本的小型状态机
可以画出以下的状态机图
这里就是两个状态:①灯泡亮,②灯泡灭
如果打开开关,那么状态就会切换为 灯泡亮 。灯泡亮 状态下如果关闭开关,状态就会切换为 灯泡灭。
状态机的全称是有限状态自动机,自动两个字也是包含重要含义的。给定一个状态机,同时给定它的当前状态以及输入,那么输出状态时可以明确的运算出来的。
例如对于灯泡,给定初始状态灯泡灭,给定输入“打开开关”,那么下一个状态时可以运算出来的。
四大概念
下面来给出状态机的四大概念。
- State ,状态。一个状态机至少要包含两个状态。例如上面灯泡的例子,有 灯泡亮和 灯泡灭两个状态。
- Event ,事件。事件就是执行某个操作的触发条件或者口令。对于灯泡,“打开开关”就是一个事件。
- Action ,动作。事件发生以后要执行动作。例如事件是“打开开关”,动作是“开灯”。编程的时候,一个 Action 一般就对应一个函数。
- Transition ,变换。也就是从一个状态变化为另一个状态。例如“开灯过程”就是一个变换。
下图是VAPS XT transition的图
Trigger就是Event,Action就是对应着Action,Guard应该对应着State,这个过程就是Transition。
通过拖拽实现的状态图也是类似。
Data Flow
Internal Transition和状态图好理解,因为它基本上快把 “我是用状态机实现的” 写在脸上了。
之前我一直不理解Data Flow是怎么实现的,昨晚(2022.06.29)洗澡前突然写到状态机这个功能,瞬间顿悟了。
实现
Data Flow中使用的是某个数据结构的实例
- 默认情况下,实例创建后会有一个默认值
- 数值(不管是谁以什么方式)修改后,实例值改变,同时触发数据更新事件
- 数据更新事件发送后,实例处于等待状态
- 数据更新事件发送后,进入数据更新回调函数后进入下一个实例的状态机中
Data Flow表格中的应该就是数据更新事件和数据更新回调这个流
根据状态迁移,定义状态机状态如下:
1 |
|
发生的事件如下:
1 |
|
不论是状态还是事件都可以根据实际情况增加调整。
定义一个结构体用来表示当前状态转换信息:
1 |
|
事件回调函数:实际应用中不同的事件发生需要执行不同的action,就需要定义不同的函数, 为方便起见,本例所有的事件都统一使用同一个回调函数。功能:打印事件发生后进程的前后状态,如果状态发生了变化,就调用对应的回调函数。
1 |
|
为各个状态定义迁移表数组:
1 |
|
实现event发生函数:
1 |
|
功能:根据发生的event以及当前的进程state,找到对应的StateTransform 结构体,并调用do_action()
1 |
|
功能:根据结构体变量StateTransform,实现状态迁移,并调用对应的回调函数。
1 |
|
总结
- VAPS XT核心功能就是建立在状态机这个功能上面
- 最终状态只有一个,Data Flow不允许Destination部分有相同实例
- 带处理动作(Action)的状态机叫做ATN(Augmented Transition Network,增强转换网络),从名字就可以看出来它是用来补充状态机状态转换的。
低代码开发
VAPS XT的大部分操作可以通过官方Editor拖拽、调整属性完成,这就完成了80%的工作。
但是无法通过Editor拖拽、调整属性完成的部分,就需要使用代码来补充了。
因为基本控件是由VAPS XT提供了,设计人员只是进行复杂界面组合,生成代码功能也是由VAPS XT提供的。所以说VAPS XT是低代码开发软件。
需要代码开发的部分有
- 数据流,即Data Flow
- 响应函数,Transtitions
- State Chart,这个是VAPS XT图形化状态机,它结合了数据流和响应函数
State Chart/Transtitions
State Chart一般和Trnastitions搭配使用,但是Transtitions可以完全取代State Chart
在Action部分,我们可以实现复杂的处理逻辑,操作的语言为简化版的C。
你需要了解:
- for/foreach循环,用于操作数组
- if/else判断
- var变量定义
- when
这些都是C/C++/Python等等中最常用的关键字
Data Flow
数据流部分分为两部分:入口和出口。
入口可以重复,出口不可以重复。
下面是可以的
1 |
|
下面的是不可以的
1 |
|
输入以后编辑器会报错。
数据流就是将控件/数据结构等的某个属性值赋值给另一个控件/数据结构等的某个属性值。
语法包括
- IfElse 用于判断
- 常用的函数比如:abs/ceil等等
演示
VAPS XT提供了预览功能,所谓的预览功能就是在设计时或者设计完成后,不编译就可查看运行效果的方式。
打开VAPS XT官方示例工程中的PFDExample
点击工具栏的Play按钮即可不编译就运行程序
仿真运行时,所有的数据接口处于灰色状态,并且不可修改。
同时,各个控件、模块的数值会根据Data Flow更新(PFDExample中没有状态图和Transition)。
VAPS XT只提供了这一种仿真功能,剩下的只能是编译运行了。
可以看到,预览过程中的各个状态的更新基本上就是状态机的在线演示。
说明
在工具栏有几个控件用于界面状态机开发
- Initial Transition 入口点,有且只有一个
- State 状态,程序某一个时刻会停留在某个状态
- Transition 连接两个State,和internal transition效果一样
- Guard 用于限制,相当于if判断
- Choice 判断相当于switch/case
- Note 注释
- Connector 连接State和对应的Note
- History 跟踪当前父状态中上一个嵌套的状态
- Deep History 跟踪当前父状态中上一个嵌套的子状态
- Link 一般是State与State间连接,Link可以连接State和某个State的子状态
问题
- 部分功能是使用代码实现的,如何在不编译的情况下实现代码功能的运行。
下一篇:VAPS XT入门教程15.02.01:状态机与界面操作
技术交流群,欢迎加入讨论。这个圈子很小,大佬可能没兴趣加这些群聊社区之类的。所以只能带你入门,当然,欢迎大佬指导