Ran Wei / SysML v2 系列 / 模块 4
EN
SysML v2 — Ran Wei

模块四:行为建模

如何描述系统的行为——动作、数据流、控制流和状态机——以及每个行为关键字如何映射到底层 KerML Occurrence 层构件。

KerML → SysML:行为建模概念对应关系

SysML v2 的行为建模建立在 KerML 的 Occurrence(发生事件)层上——该语言层用于描述随时间发生的事物,与描述持续存在的事物的结构层相对应。本模块中的每个行为关键字都是该 KerML Occurrence 层中某个 L1 构件在 SysML L2 的应用。

SysML v2 概念(L2)底层 KerML 构件(L1)SysML 额外添加了什么
action defBehavior(一种 Classifier,KerML Occurrence 层)关键字表示某个在时间区间内发生的事情;实例是发生事件,不是持久对象
action(用法)Behavior 类型化的 Feature默认复合 [1..1];在父动作的生命周期内执行
perform action引用 Behavior 的 FeatureMembership通过名称调用行为的简写,无需声明子动作体
in / out / inout 参数Behavior 上带方向的 Feature方向限定谁提供或接收値;可由任意分类器类型化
流(动作上的流动项流)ItemFlowInteraction 的特化)声明在两个动作参数端点之间传递的流动项
successionSuccession(带时间语义的 Connector源必须完成后目标才可开始;编码时间顺序
first / thenSuccession 的简写一对顺序约束;可链接成动作序列
if / else / merge决策/合并 ControlNode 模式条件路由:根据年守条件执行一个分支;merge 重新合并分支
loop带年守的 Succession 循环条件成立时重复体
fork / joinFork/Join ControlNode 模式fork 同时激活多个动作;join 等待所有完成
state def / stateStateDefinition(特化自 ActionDefinition / BehaviorDefinition为行为添加 entry/do/exit 语义和带触发的转换
transitionTransitionUsage(一种 Succession为状态间的时间顺序添加触发器、年守和效果
acceptAcceptActionUsage等待消息或信号到达后再继续
sendSendActionUsage向另一个元素发送消息或信号
occurrence defOccurrence(KerML Occurrence 层根)可复用的「发生的事物」类型;action def、state def 等的基类
表 0 — 模块四 SysML v2(L2)概念与 KerML(L1)来源的对照
注意

在 KerML 中,Occurrence 层位于 Core 层之上。Occurrence 特化自 Class,并添加了「在时间区间内发生」的概念。Behavior 进一步特化自 Occurrence,添加了「被执行」的概念。SysML v2 的每个行为关键字——action defstate deftransition——在 KerML 层最终都是 BehaviorOccurrence 的特化。

1

动作与行为

KerML 来源:action defBehavior(Occurrence 层); action → 由 Behavior 类型化的 Feature

动作(action)描述系统在时间区间内所做的事情。这是与模块三的根本区别:部件存在,动作发生。在 KerML 层面,Behavior 特化自 Occurrence,而 Occurrence 特化自 Class——因此结构建模中所有的机制(特化、特征、多重性、链接)同样适用于行为。

🏠 生活类比

汽车持续存在。启动发动机是一个动作——它在时间区间内发生,有输入(騥匙、燃油),产生输出(运行中的发动机),并最终终止。汽车(结构)和启动序列(行为)是两种不同类型的模型元素,但在 KerML 中都是 Classifier。

定义和使用动作

模块一中的定义/用法分离同样适用于此。action def 定义模板;action 在特定上下文中使用它:

1action def FuelPump {
2 in item fuelRequest : FuelRequest; // 输入:请求内容
3 out item fuelDelivery : Fuel; // 输出:输送的燃油
4}
5
6action def EngineStart {
7 action primeSystem : PrimeFuelSystem; // 子动作:由其 action def 类型化的 Feature
8 action crankEngine : CrankEngine;
9 action fireIgnition : FireIgnition;
10}

嵌套与分解

动作可以任意层次嵌套。每个子动作是一个复合 Feature,其执行在父动作的生命周期内——与结构建模中复合 part 被其父部件拥有的方式完全一致:

1action def MissionProfile {
2 action takeOff : TakeOff;
3 action cruise : CruiseSegment;
4 action land : Landing;
5 // 没有显式顺序时,执行顺序未定义。
6 // 使用 succession / then 指定顺序(见第 3 节)。
7}
注意

action def 映射到 KerML Behavioraction 用法映射到由该 Behavior 类型化的 Feature。由于 Behavior 本身是 Class,动作定义可以相互特化(specializes),动作用法可以使用 subsetsredefines——与结构特征完全相同。

调用已有动作定义

使用 perform action 通过名称调用一个已定义的动作,无需重新声明其体。这是一个成员引用,不是新定义:

1action def SystemTest {
2 perform action runDiagnostics : Diagnostics; // 按类型引用 Diagnostics
3 perform action logResults : Logger;
4}
⚠️ 常见错误

action 不是编程意义上的函数调用。它是由 Behavior 类型化的 Feature——有生命周期,可以并发执行子动作,并参与完整类型系统。把它当作方法调用来思考,当引入顺序、并发和数据流时就会产生困惑。

2

动作参数与数据流

KerML 来源:参数 → Behavior 上带方向的 Feature; 流动项流 → ItemFlow

动作通过参数传递流动项来相互通信。参数是动作定义上带方向的 Feature——与模块三中端口特征的 in / out / inout 机制相同,但应用于动作。KerML 来源相同:Classifier 上带方向的 Feature

声明参数

1action def ComputeTrajectory {
2 in attribute startPos : GeoCoordinate; // 输入:起始位置
3 in attribute targetPos : GeoCoordinate; // 输入:目标位置
4 in attribute windSpeed : ISQ::SpeedValue; // 输入:环境数据
5 out attribute trajectory : Trajectory; // 输出:计算的路径
6 out attribute flightTime : ISQ::TimeValue; // 输出:预估时间
7}

子动作之间的流动项流

在复合动作内部,流动项流将一个子动作的输出参数连接到另一个的输入参数。这是结构 flow 语句在行为领域的类比,映射到 KerML ItemFlow

1action def DriveControl {
2 action sense : SenseEnvironment { out item data : SensorData; }
3 action plan : PlanRoute { in item data : SensorData;
4 out item cmd : DriveCommand; }
5 action execute : ExecuteCommand { in item cmd : DriveCommand; }
6
7 // 流动项流:一个动作的输出首先进入下一个的输入
8 flow sense.data to plan.data;
9 flow plan.cmd to execute.cmd;
10}
🏠 生活类比

想想一条生产线。燊接工位(sense)把它的输出交给涂调工位(plan),后者再把输出交给装配工位(execute)。流动项流就是各工位间的传送带。

通过层次绑定参数

使用 bind 可以将外部动作的参数绑定到内部子动作的参数,在不创建流动项流对象的情况下跨动作边界传递値:

1action def MissionPlan {
2 in attribute origin : GeoCoordinate;
3 out attribute path : Trajectory;
4
5 action compute : ComputeTrajectory {
6 bind compute.startPos = origin; // 外部输入绑定到内部输入
7 bind compute.trajectory = path; // 内部输出绑定到外部输出
8 }
9}
注意

参数是 Feature,因此遵守所有 Feature 规则:它们携带多重性,可由任意 Classifier 类型化(包括 DataType 和 Class),并可在动作定义的特化中被子集或重定义。

3

控制流与顺序

KerML 来源:successionSuccession(一种 Connector); if/else → 决策/合并 ControlNode; fork/join → Fork/Join ControlNode

默认情况下,复合动作中的子动作没有定义的执行顺序。它们可以并发执行、以任意顺序执行,或仅在数据依赖关系满足时执行。要强制指定顺序,SysML v2 提供了 succession 以及更高级的控制流构件。

Succession:显式顺序

两个动作之间的 succession 意味着:第一个动作必须完成后,第二个才可以开始。这是结构连接器在行为领域的类比——它是一个 KerML Succession,本身是 Connector 的特化:

1action def EngineStart {
2 action prime : PrimeFuelSystem;
3 action crank : CrankEngine;
4 action fire : FireIgnition;
5
6 succession prime then crank; // prime 必须完成后 crank 才能开始
7 succession crank then fire; // crank 必须完成后 fire 才能开始
8}

first / then 简写可以紧凑地链接顺序:

1action def EngineStart {
2 action prime : PrimeFuelSystem;
3 action crank : CrankEngine;
4 action fire : FireIgnition;
5
6 first prime then crank then fire; // 等价于两个 succession 语句
7}

条件分支:if / else

if 块声明一个决策节点:年守表达式被评估,执行恰好一个分支。KerML 模型是带有年守出口 Succession 的 DecisionNode 控制节点:

1action def HandleRequest {
2 action validate : ValidateRequest;
3 action process : ProcessRequest;
4 action reject : RejectRequest;
5 action respond : SendResponse;
6
7 first validate;
8 if validate.isValid {
9 then process;
10 } else {
11 then reject;
12 }
13 // merge 节点隐式合并两个分支
14 then respond;
15}
注意

merge 关键字将多个入站分支重新合并为一个出口流。当两个或多个分支在共同的继续前汇聚时,就需要它——没有它,继续将要求所有分支都完成(join 语义)而不是任意一个分支完成。

并行执行:fork / join

fork 同时激活多个子动作。join 等待直到所有Fork 出的动作都完成才继续。它们映射到 KerML Fork/Join 控制节点模式:

1action def SystemInitialise {
2 action loadFirmware : LoadFirmware;
3 action selfTest : RunSelfTest;
4 action calibrateSensors : Calibrate;
5 action connectNetwork : ConnectNetwork;
6 action reportReady : ReportReady;
7
8 // 四个初始化任务并行运行
9 fork {
10 then loadFirmware;
11 then selfTest;
12 then calibrateSensors;
13 then connectNetwork;
14 }
15 // 等待四个任务都完成后完成报告
16 join then reportReady;
17}

循环

1action def PollSensor {
2 action read : ReadSensorValue;
3 action process : ProcessReading;
4
5 loop {
6 first read then process;
7 } while process.shouldContinue;
8}
⚠️ 常见错误

Succession 和 Fork/Join 建模的是完成顺序,不是时间。Succession 不是说“100 毫秒后开始下一个动作”——它说的是第一个必须完成后第二个才可以开始。对于实时时间约束,请使用关于动作持续时间的需求约束,而不是使用 succession。

4

状态机

KerML 来源:state defStateMachine(特化自 Behavior); transitionTransitionUsage(一种 Succession

状态机建模行为取决于当前状态的系统。在 SysML v2 中,state def 映射到 KerML StateMachine,它本身是 Behavior 的特化。这意味着状态机是行为——它们可以作为动作用法出现,接收参数,并被组合进更大的动作网络中。

🏠 生活类比

想想交通信号控制器。它不执行顺序算法——它总是处于三种状态之一(红灯、黄灯、绿灯),并在收到事件时改变状态(计时器触发、传感器触发)。状态机捕捉的正是这种响应式、事件驱动的行为。

定义状态

每个状态可以有可选的 entrydoexit 动作:

1state def TrafficLightController {
2 entry; // 初始伪状态——执行从这里开始
3
4 state RED {
5 entry action activateRed : ActivateRedLight; // 进入时执行
6 do action holdRed : HoldRedSignal; // 处于状态时持续执行
7 exit action deactivateRed : DeactivateLight; // 离开时执行
8 }
9
10 state AMBER {
11 entry action activateAmber : ActivateAmberLight;
12 }
13
14 state GREEN {
15 entry action activateGreen : ActivateGreenLight;
16 do action holdGreen : HoldGreenSignal;
17 }
18}

转换

transition 是一个 TransitionUsage——一个添加了触发器、可选的年守和可选的效果动作的 KerML Succession

1// 语法:transition <源状态> accept <触发器> if <守卫> do <效果> then <目标状态>
2
3state def TrafficLightController {
4 state RED; state AMBER; state GREEN;
5
6 entry; then RED; // 初始转换:从 RED 状态开始
7
8 transition RED
9 accept TimerExpired
10 then GREEN;
11
12 transition GREEN
13 accept TimerExpired | PedestrianRequest
14 then AMBER;
15
16 transition AMBER
17 accept TimerExpired
18 then RED;
19}

年守条件与效果

1state def SafetyController {
2 state NORMAL; state DEGRADED; state SAFE_SHUTDOWN;
3
4 entry; then NORMAL;
5
6 transition NORMAL
7 accept HealthCheck // 触发器:由 HealthCheck 事件触发
8 if systemHealth < 0.5 // 守卫:仅当健康值较低时触发
9 do action log : LogDegradation // 效果:转换过程中执行
10 then DEGRADED;
11
12 transition DEGRADED
13 accept HealthCheck
14 if systemHealth < 0.1
15 then SAFE_SHUTDOWN;
16}

状态内的 accept 和 send

1state def CommandProcessor {
2 state IDLE; state PROCESSING;
3
4 entry; then IDLE;
5
6 transition IDLE
7 accept CommandReceived // 等待 CommandReceived 事件
8 then PROCESSING;
9
10 state PROCESSING {
11 do action work : ProcessCommand;
12 exit action notify {
13 send : CompletionSignal; // 离开时发送信号
14 }
15 }
16
17 transition PROCESSING accept work.done then IDLE;
18}
注意

在 SysML v2 中,状态机是一等公民的行为。state def 可以作为更大动作序列中 action 用法的类型。这意味着你可以将状态机与顺序和并行动作流组合——这在 SysML v1 中是嵌嵌扣扣的。

5

发生事件与快照

KerML 来源:occurrence defOccurrence(KerML Occurrence 层根); snapshot → 在时间熵上的结构投影

KerML 的 Occurrence 层引入了两个支撑本模块所有内容的基本概念:发生事件(在时间区间内发生的事物)和快照(单一时刻宜发生事件的样子)。SysML v2 中的每个动作、状态和消息最终都是一个发生事件。

发生事件定义

occurrence def 命名一种可复用的「发生的事物」类型——在将其特化为动作或状态机之前最通用的形式。当你想描述事件或交互而不需要立即确定它们是动作、状态还是消息时,它很有用:

1occurrence def SystemEvent;
2occurrence def FaultEvent specializes SystemEvent {
3 attribute severity : Integer;
4 attribute component : String;
5}
6
7occurrence def RecoveryAction specializes SystemEvent {
8 attribute targetComponent : String;
9}

快照——穿越时间的结构切片

快照捕捉一个部件在发生事件特定时刻的状态。它是一个结构投影——一个关于在该时刻持有哪些属性値和子部件配置的观点。快照用于声明前置条件、后置条件和不变量:

1action def ChargeBattery {
2 in part battery : Battery;
3
4 // 前置条件:充电开始时电池的状态
5 snapshot startState {
6 assert constraint { battery.stateOfCharge < 0.9 }
7 }
8
9 action doCharge : Charge;
10
11 // 后置条件:充电结束时电池的状态
12 snapshot endState {
13 assert constraint { battery.stateOfCharge >= 0.99 }
14 }
15}
注意

快照不是插入动作序列中的检查点。它们描述在发生事件开始和结束时必须成立的结构条件。工具利用它们进行验证:如果仿真或形式分析表明后置条件无法到达,则存在建模缺陷。

时间切片与时间顺序

1requirement def ResponseTime {
2 subject mission : MissionAction;
3 require constraint {
4 // 任务的结束必须在其开始后 60 秒内发生
5 mission.endShot.time - mission.startShot.time <= 60[s]
6 }
7}
🏠 生活类比

发生事件就像一段影片片段:它覆盖一段时间。快照是这段片段的单帧画面。时间切片是从一个时刻到另一个时刻的子片段。SysML v2 让你可以对单帧(快照)或整段片段(发生事件)做出断言。

6

完整示例

以下模型综合了本模块的所有内容:一个 UAV 自驾仪行为,结合了顺序动作、数据流、判断、并发和流模式管理状态机。

1package UAVBehaviour {
2 private import ISQ::*; private import SI::*;
3 private import UAVSystem::*; // 模块三工作示例中的部件
4
5 // ── 发生事件(共享事件词汇) ───────────────────────
6 occurrence def FlightEvent;
7 occurrence def TakeoffCleared specializes FlightEvent;
8 occurrence def LandingCleared specializes FlightEvent;
9 occurrence def FaultDetected specializes FlightEvent {
10 attribute severity : Integer;
11 }
12
13 // ── 状态机:飞行模式 ─────────────────────────────────
14 state def FlightModeController {
15 state GROUND; state TAKEOFF; state CRUISE;
16 state LANDING; state EMERGENCY;
17
18 entry; then GROUND;
19
20 transition GROUND
21 accept TakeoffCleared
22 then TAKEOFF;
23
24 transition TAKEOFF
25 accept AltitudeReached
26 if altitude >= 50[m]
27 then CRUISE;
28
29 transition CRUISE
30 accept LandingCleared
31 then LANDING;
32
33 transition LANDING
34 accept TouchdownDetected
35 then GROUND;
36
37 // 从每个状态:故障触发紧急状态
38 transition GROUND
39 accept FaultDetected
40 if severity >= 2
41 do action log : LogEmergency
42 then EMERGENCY;
43 transition TAKEOFF
44 accept FaultDetected
45 if severity >= 2
46 then EMERGENCY;
47 transition CRUISE
48 accept FaultDetected
49 if severity >= 2
50 then EMERGENCY;
51 transition LANDING
52 accept FaultDetected
53 if severity >= 2
54 then EMERGENCY;
55 }
56
57 // ── 传感器融合动作 ─────────────────────────────────────
58 action def SensorFusion {
59 in item gpsData : GPSReading;
60 in item imuData : IMUReading;
61 out attribute navEstimate : NavigationState;
62 }
63
64 // ── 导引律动作 ───────────────────────────────────────────
65 action def GuidanceLaw {
66 in attribute navEstimate : NavigationState;
67 in attribute targetWP : Waypoint;
68 out attribute motorCmds : MotorCommandSet;
69 }
70
71 // ── 顶层自驾仪循环 ─────────────────────────────────────
72 action def AutopilotLoop {
73 in part uav : UAV;
74
75 // 状态机与导引循环并发运行
76 action modeCtrl : FlightModeController;
77
78 action fuse : SensorFusion;
79 action guide : GuidanceLaw;
80 action actuate : ActuateMotors;
81
82 // 数据流:融合输出首先进入导引输入
83 flow fuse.navEstimate to guide.navEstimate;
84 flow guide.motorCmds to actuate.motorCmds;
85
86 // 控制流:每次迭代内的序列
87 loop {
88 first fuse then guide then actuate;
89 } while uav.flightMode != FlightMode::GROUND;
90
91 // 前置条件快照
92 snapshot preCheck {
93 assert constraint { uav.battery.health >= 0.2 }
94 }
95 }
96}

此模型演示了:occurrence def(共享事件词汇)、带触发器和年守的 state def动作参数和流动项流(传感器融合管道)、带 first/thensuccession、带终止条件的 loop、与顺序循环并发运行的并发状态机,以及 快照前置条件

7

本模块总结

SysML v2 概念KerML 来源关键规则
action defBehavior(Occurrence 层)实例是发生事件,不是持久对象;在时间区间内发生
action(用法)Behavior 类型化的 Feature默认复合 [1..1];在父动作的生命周期内执行
参数(in/out/inoutBehavior 上带方向的 Feature与端口特征相同的机制;可由任意 Classifier 类型化
流动项流(flow X to YItemFlow将一个子动作的输出参数连接到另一个的输入参数
bind X = YBindingConnector不创建流动项流对象,跨动作边界传递値
succession / first/thenSuccession(一种 Connector源必须完成后目标才可开始;建模时间顿序
if / else / merge决策/合并 ControlNode条件分支;merge 将分支重新合并为共同的继续
fork / joinFork/Join ControlNodefork:同时激活所有;join:等待所有完成
loop带年守的 Succession 循环条件成立时重复体
state defStateDefinition(特化自 ActionDefinition / BehaviorDefinition响应式行为;每个状态都有 entry/do/exit 动作
transitionTransitionUsage(一种 Succession为状态间的顺序添加触发器、年守和效果
acceptAcceptActionUsage等待信号或消息到达后再继续
sendSendActionUsage向另一个元素发送信号或消息
occurrence defOccurrence(KerML Occurrence 层根)最通用的发生事件类型;action def、state def 等的基类
snapshot时间熵上的结构投影就发生事件声明结构条件(前/后置条件)
表 — 模块四概念与其 KerML 来源
下一讲

模块 5 — 需求与约束 — 需求定义、满足关系,以及如何针对模型进行验证。