智睿思维Logo智睿思维

MBSE建模学习之六:状态机和状态机图

状态机(StateMachine)

状态机(StateMachine)用于表示事件驱动的行为。在状态机图中,用系统的不同状态之间事件驱动的转移机制来说明一系列的行为发生过程。它一般作为一个模块(Block)的类目行为(ClassifierBehavior)。类目行为是一个类(如模块)从开始工作,一直到结束的整个过程的行为。一个模块只有一个类目行为。它也可以作为模块的一个普通的拥有行为(OwnedBehavior),表示模块的一种功能。

和活动(Activity)一样,状态机同时也是一种模块(Block)元素。一个复杂的状态机行为可以进行分解。在上层的状态机行为中,通过一个“子机状态”(SubmachineState)元素表示对下层或其它状态机的调用。

作为行为,状态机的发生一样需要规定发生的语境(Context)。如果状态机是某个模块的类目行为或拥有行为,则这个模块是状态机的语境;否则它自己是它的语境。状态机中的状态的内部行为(entry、do及exit)如果没有明确的语境,则它们的语境是这个状态机的语境。

状态机是通过状态机中的状态(State)以及状态是如何转换的来说明系统的行为过程。状态机中的状态(State)和转移(Transition)不像活动图中的动作(Action),它们本身并不说明究竟这个行为是如何把一个输入的信息(或其它物质)转为输出的信息(或其它物质)。(动作—Action中,可以通过语句或专用的动作类型来说明对象的生成、变换或删除等)但是,在状态和转移中可以包含其它行为(如一个活动),它可以用它包含的行为来说明具体是转换的细节。状态机更像是把系统的行为串联起来的一种作用,它着重展现的是系统在这个行为之间所处的状态,以及状态是在什么时机,或通过什么机制来转换的(这个时机被定义为触发器,这个机制是触发器的事件)。所以它适合作为系统的整个工作过程的总体说明,例如用来说明系统工作的任务阶段说明。

状态(State)

状态(State)是系统处于某种工作状态一种表示方法。状态除了有一个名称外,状态的“状态不变量”(StateInvariant)属性说明了系统处于这个状态的条件。“状态不变量”是一个约束(约束通常表示为一个等式或不等式),当系统处于这个状态的时候,应该满足这个约束(约束表达式的值应该是True)。

状态并非静态的概念。当系统进入、保持和退出一个状态的时候,都伴随着行为的发生。这三种行为称为状态的“entry”、“do”和“exit”内部行为。这三种内部行为,可以仅仅是一段文字描述(对应一个不透明行为),或者具体活动(Activity)、交互(Interaction)或另外一个状态机元素。这三个行为的发生顺序是:当系统进入这个状态的时候,先执行“entry”行为;执行完毕之后,如果有“do”行为,则执行。当有一个引发状态转移的事件发生的时候,在系统离开这个状态之前,执行“exit”行为(如果此时,“do”还没有执行完,则中断“do”的执行)。

状态用一个圆角矩形表示。其中的文字用“状态名称[状态不变量表达式]”表示。在“智睿思维基于模型的系统工程软件”(MBSES)中状态的内部行为可以通过属性框设置是否显示。下图是“开机”状态的两种显示方式。

有三种具体的状态类型。这三种状态都具有以上状态的这些基本特征。其中,简单状态(SimpleState)代表一个普通的状态。组合状态是可以包含其它状态的状态;子机状态是代表另外一个状态机的状态。在进一步说明其它状态类型之前,先搞清楚状态的转移是如何发生的。

转移(Transition)

“转移”用一个带箭头的线表示系统从一个状态转换到另外一个状态。转移的发生是由系统中的触发器(Trigger)引发的。在表示转移的线上面,会显示转移的说明文字,这个文字的语法如下:

[<trigger> [‘,’ <trigger>]* [‘[‘ <guard>’]’] [‘/’ <behavior-expression>]]

用中文表示语法表示为:

[<触发器> [‘,’ <触发器>]* [‘[‘ <守卫条件>’]’] [‘/’ <行为表达式>]]

如上所示,一个转移,它可能有一个或多个触发器,一个守卫条件(转移的发生需要满足这个条件,这个条件也是一个约束)。当转移发生的时候,可能还有一个行为发生,称为转移的“影响”属性。这个行为可能是一个活动、交互或另外一个状态机。

一个表示转移的文字示例如下:

“按下开机键[电源状态=有电]/接通电源()” 上面的文字表示系统从关闭状态到开机状态的转移,这个转移的触发器是用户“按下开机键”事件。此时,如果也满足“电源状态=有电”这个约束条件,则转移发生。转移发生后,将进行“接通电源()”这个“影响”行为。

转移也可以有“名称”。如果有名称,在MBSES软件中会显示在最前面,并且用“:”和触发器分隔。但一般情况下,应该把转移的触发条件作为触发器写在触发器属性,而不是名称。

转移的表示方法示例如下

从上面的说明我们可以了解到,状态机中状态以及状态的转移过程都是伴随是具体行为的发生的。造成转移发生的触发器,也是由于其它行为执行过程中产生的事件引发的。下面讲讲触发器

触发器(Trigger)

触发器是行为中定义中的一个点,在该点上一个事件的发生可能会产生这种影响。所以,触发器总是和一个事件关联在一起的。表示触发器的字符串,直接使用它关联事件的表达式(虽然触发器也可以有名称,但是在转移中触发器的表达式是直接使用关联事件的表达式,而不用它的名称)。

在进行状态机的仿真运行的时候,需要模拟触发器的触发,才能引发状态的转移。模拟触发的动作,通过选择仿真工具栏中触发器的下拉框。此外,有些触发器是会在仿真过程中由活动中的动作引发的,如“信号事件”触发器,则会通过一个“发送信号动作”引发。这种仿真中自动引发的事件,也会引起转移的发生。

触发器的事件类型

触发器的事件有5种事件类型,分别说明如下:

(1)调用事件(CallEvent)

调用事件是当作为状态机语境的模块的操作(Operation)被调用的时候发生的事件(对一个硬件来说,一个模块的操作被调用,可以理解为启动了硬件的一个功能)。当模块的操作被调用,可能会产生标识这个状态的属性或变量的变化,从而会引发状态的改变。

调用事件是用被调用操作的名称标识的,它的表示语法如下:

<call-event> ::= <name> [‘(‘ [<assignment-specification>] ‘)’]

<name>:被调用操作的名称

<assignment-specification>:可选的显示项,对应被调用操作的参数值。 调用事件一般通过“调用操作动作”(CallOperationAction)(见MBSE建模学习之四)引发。

(2)信号事件(SignalEvent)

信号事件是当作为状态机的语境的模块,接收到一个某种类型的信号的时候发生的事件。信号(Signal)是一种包含有属性的元素,它一般定义为一种有结构的数据类型。一个模块能够接收某种类型的信号,则应该有一个和信号对应的接收(Reception)方法来处理接收到的信号,这个接收的名称和信号名称相同,接收的参数和信号的属性对应。

定义一个信号事件,应该定义它对应的信号元素。信号事件触发器显示的是信号事件的信号名称。信号事件显示的语法如下:

<signal-event> ::= <name> [‘(‘ [<assignment-specification>] ‘)’]

<name>:信号的名称

[<assignment-specification>]:可选的显示项,和信号对应接收的参数的具体值,这些参数和信号的属性也对应。

信号接收事件可以由“发送信号动作”(SendSignalAction)触发(见MBSE建模学习之四)。

(3)任何接收事件(AnyReceiveEvent)

任何接收事件会显示一个“all”字符串。任何接收事件表示模块接收到任何信号或操作调用的时候都会发生。但是如果这个接收有具体对应的信号事件或调用事件对应,则不会重复的发生。任何接收事件也可以由一个“发送对象动作”(SendObjectAction)引发,所以可以用任何接收事件来处理除了信号事件和调用事件之外的其它任何接收事件。

(4)变动事件(ChangeEvent)

变动事件是当模块中的属性或一个变量的值变动时,符合变动事件给出的条件,则引发这个事件。

变动事件的语法是:

<change-event> ::= ‘when’ <value-specification>

即:“when”后面有个结果为布尔值的表达式,当这个表达式的值为“真”的时候,变动事件就引发。

(5)时间事件(TimeEvent)

时间事件是当系统时间符合事件定义的时间表达式的时候,事件就引发。时间表达式的定义有两种,一种是“绝对”时间,一种是“相对”时间。当时间事件的“是否是相对时间”属性等于True时,时间事件表示为“after”+ “时间量”。如“after 5s”,表示系统进入当前状态5秒之后引发此事件。当“是否相对时间”属性等于False时,时间事件表示为“at”+ “绝对时间表达式”。如“at 2021-12-24 18:00:00”;如果时间表达式中没有日期,表示每天这个时间都会发生一次。

一个转移可以有多个触发器,任何一个触发器发生,则转移就会发生。在“智睿思维基于模型的工程软件”(MBSES)中,转移的触发器定义界面如下:

在定义了“调用事件”或“信号事件”后,要通过工具栏上面的“选择操作”或“选择信号”按钮选择在模块中定义的操作或其它地方定义的信号。

组合状态(CompositeState)

组合状态是可以包含其它状态的状态。首先组合状态直接包含一个或多个“区域”(Region)元素,“区域”再包含其它的状态。

状态机也是包含一个默认的“区域”的,状态机中的状态都包含在这个区域中。在一个区域中,只有一个当前状态。不同的区域可以有各自的当前状态。不同区域中的行为是并行的。这种具有多个区域的组合状态称为“正交的”组合状态(是否正交属性=True)。

组合状态中每个区域都有自己的初始状态和终态。当进入组合状态之后,也是先从初始状态开始转移到第一个状态。组合状态中的状态可以直接转移到组合状态外的一个状态。

下图是一个系统简单的状态机图,其中“开机”状态是一个组合状态,其中包含两个状态“加载”和“工作”。

伪状态(Pseudostate)

伪状态即状态机图上不是系统真实状态的节点,这些伪状态节点为了表示状态机的开始、结束、分支等等。伪状态有如下几种类型:

“初始伪状态”(InitialPseudostate):表示状态机的开始。用一个实心圆形表示;如●。

“选择伪状态”(ChoicePseudostate):类似活动图中的决定节点,从一个菱形节点分支出去多个转移,每个转移有各自的“守卫”条件,只有符合条件的转移才发生。

“连接伪状态”(JunctionPseudostate):连接伪状态可以有多个“入”及多个“出”的转移。从连接伪状态“出”的转移应该具有不同的触发器及守卫条件。要记住,在一个区域中是不能有多个“当前状态”,所以从连接伪状态一次只能一个转移生效。

“分支”和“集合”伪状态:分支节点从一个状态分支到两个或多个并行状态区域;集合节点合并多个并行的区域。如下所示“分支”和“集合”的应用:

“终止伪状态”(TerminatePseudostate):用一个来表示,表示某个分支流程的终止。

“深历史伪状态”(DeepHistoryPseudostate)和“浅历史伪状态”(ShallowHistoryPseudostate):状态历史是和组合状态的区域相关的概念。这个概念可以跟踪从区域中退出时所处的状态配置。当从“深历史伪状态”退出区域,区域再次活动的时候,恢复到区域中最深层次的那个最后状态。当从“浅历史伪状态“退出区域时,区域再次成为活动区域,返回到区域中最顶层的那个最后状态。

“入点”(entryPoint)和“退出点”(exitPoint):当封装一个组合状态、不允许从其中的状态直接转移进或出的时候,设置一个“入点”和一个“退出点”,只能从外部状态转移进“入点”伪状态,从“退出点”伪状态转移出。

终态(FinalState)

用一个实心环形表示,代表状态机行为的结束。

状态机图的案例

下图是一个卫星“姿态控制”状态机(参考《SysML精粹》图8.1)的案例。

此图是“姿态控制子系统”的类目行为,即姿态控制子系统的整个工作过程。从初始状态开始,卫星处于“入轨”状态,执行内部行为“自旋稳定”。当轨道转移的时候,退出前执行“exit”内部行为“消自旋”,停止自旋。当轨道转移完成,进入新轨道“捕获”状态,首先“甩动量”,然后“确定姿态”;更新卫星的姿态之后,如果卫星“当前姿态==规则姿态”,则转移为“在站”组合状态;否则“转向”(Slew),直到卫星“当前姿态==规则姿态”。如果在“转向”状态收到“脱离轨道”命令(产生的触发器),则“姿态控制子系统”工作完毕。“在站”组合状态中常规情况下执行“维持规则姿态”行为。如果此时处于“有通讯链路”状态时,收到新的调整姿态命令(调用了“获取目标(规则姿态) ”操作产生的调用操作事件)转移到“转向”状态,继续调整姿态。如果“无通讯链路”状态超过2分钟,触发时间触发器“after 2 min”,状态转为“安全模式”(或者有“系统错误”事件也转为安全模式),跟踪太阳方位,直到“通讯链路恢复”事件发生,转入“捕获”状态。在“在站”组合状态下,收到“脱离轨道”命令事件,则子系统工作完毕,转为“终态”。