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

模块三:结构建模

如何描述一个系统由什么组成 — 以及每个结构关键字如何映射到底层精确的 KerML 构造。

KerML → SysML:结构建模概念对应关系

本模块中的每一个结构性关键字都是 KerML L1 构件在 SysML L2 的具体应用。下表展示了本模块所有概念的层次对应关系。

SysML v2 概念(L2)底层 KerML 构件(L1)SysML 额外添加了什么
part defClass(一种 Classifier)关键字意味着默认复合包含;实例有身份,随时间持续存在
part(用法)Class 类型化的复合 FeatureisComposite = true;默认多重性 [1..1]
ref partClass 类型化的非复合 FeatureisComposite = false;被引用对象独立存在
attribute defDataType(一种 Classifier)实例无身份——纯値。可携带不变量和单位约束
attribute(用法)DataType 类型化的 Feature値类型子元素;生命周期与父级相同
enum defEnumerationLiteral 成员的 DataType封闭的命名値集合;每个字面量无身份
item defClass(KerML 层与 part def 相同)仅是约定:表明流动参与者而非持久结构组件
port defType 边界上带方向的 Feature标记交互点;~T 共轭反转所有方向
connectConnector(一种 Feature)连接 Feature 实例;SysML 提供命名和匿名两种形式
interface def带 end Feature 的 Association为命名的连接模板添加类型化流声明
specializes(在 part def 上)Subclassification 关系子类型继承父类型的所有特征
subsets(在 part 上)Subsetting 关系子特征的値从父特征的池中取得
redefinesRedefinition 关系替换继承的特征,缩窄其类型、多重性或値
表 0 — 模块三 SysML v2(L2)概念与 KerML(L1)来源的对照
注意

part defitem def 的关键区别是约定,而不是 KerML 语义。两者都映射到 Class。SysML 使用 item def 来表明某事物是流动的(信号、流体、数据包)而不是持久结构。工具可以利用这个约定验证流连接。

1

部件与分解

KerML 来源:part defClass; part → 复合 Feature; ref part → 非复合 Feature

在 SysML v2 中,结构建模回答的是:这个系统由什么构成?这些部件之间是什么关系?主要工具是 part

🏠 生活类比

想想一辆汽车。它有发动机、四个车轮、底盘、油筒。发动机本身又有气缸、曲轴、燃油啦射器。SysML v2 让你精确地描述这种嵌套的“由…构成”结构,细化到你需要的任何层次。

定义与用法

1part def Engine {
2 attribute displacement : Real;
3 attribute cylinders : Integer;
4}
5
6part def Car {
7 part engine : Engine; // 一个复合 Engine 子元素
8 part wheel : Wheel[4]; // 四个复合 Wheel 子元素
9 part chassis : Chassis;
10}

复合 vs 引用:part vs ref part

两者都是由 Class 类型化的 Feature。区别在于 KerML 的 isComposite 标志:

🏠 生活类比

复合就像焊接在汽车里的发动机:它与汽车共生共死。引用就像坐在车里的司机:他们下车后仍然独立存在。

1part def Fleet {
2 part car : Car[1..*]; // isComposite=true:被车队拥有
3 ref part driver : Person; // isComposite=false:司机独立存在
4 attribute name : String; // DataType 子元素:Fleet 删除时一同消失
5}
6
7// 删除 Fleet 也会删除它的 Car(复合所有权)
8// 以及 name 値(DataType,没有独立对象)。Driver 不受影响。
关键字KerML 属性生命周期使用场景
partisComposite = true与父级相同子级是父级物理上的一部分
ref partisComposite = false独立于父级子级被共享或独立存在
attributeDataType 类型化与父级相同存储数字、字符串或量
表 1 — SysML v2 中的结构所有权
⚠️ 常见错误

每个 part 用法默认多重性为 [1..1]——恰好一个。忘记为可选部件写 [0..1] 或为集合写 [1..*] 是最常见的结构建模错误。

2

属性与値类型

KerML 来源:attribute defDataType; attribute → 由 DataType 类型化的 Feature; enum def → 带 EnumerationLiteral 的 DataType

属性存储表征部件特性的数据値。在 KerML 中,它们是由 DataType 类型化的 Feature——DataType 是一种实例不携带身份的 Classifier。像 3.7"Generic" 这样的値不是对象;它们只是属于所属实例的量或标签。

标量値类型——基本 DataType

SysML v2 在 ScalarValues 标准库中提供四种基本标量类型:

类型表示的内容典型用途示例字面量
Real64 位 IEEE 754 浮点数。不附带单位时覆盖全范围物理量。无量纲比値、原始传感器读数、系数3.14-0.51.0e6
Integer整数(无小数部分)。精确算法。计数、索引、协议版本号、CAN ID4-1255
StringUnicode 字符序列。标签、标识符、文字描述、供应商名称"GPS""BoschMotorsport"
Boolean恰好是 truefalse标志位、启用/禁用开关、有效性指示truefalse
表 2 — SysML v2 标量基本类型(ScalarValues 库)
1private import ScalarValues::*;
2
3part def Sensor {
4 attribute sampleRate : Real; // 无量纲;实际中优先使用 ISQ::FrequencyValue
5 attribute label : String; // 人可读的名称
6 attribute channelCount : Integer; // 必须是整数
7 attribute enabled : Boolean; // 该传感器当前是否激活?
8}
注意

仅对无量纲量使用 Real。对于携带单位的物理测量値,请使用 ISQ 类型——见下文。这让工具在模型验证时能检查单位兼容性。

ISQ 量类型——感知物理量的値类型

ISQ(国际量制)标准库为每种物理量定义了带类型的値。每个 ISQ 类型都是一个携带量纲元数据的 DataType:模型知道 MassValueLengthValue 不是同种东西,3.7[V] 不能赋给 MassValue 属性。値的写法是 数字[单位]

1private import ISQ::*; // 量类型:MassValue、LengthValue 等
2private import SI::*; // SI 单位:kg、m、s、A、K 及导出单位
ISQ 类型物理量SI 单位示例赋値
MassValue质量kg= 1.2[kg]
LengthValue长度/距离m= 0.35[m]
TimeValue时间/持续时间s= 2.5[s]
ElectricPotentialValue电压V= 3.7[V]
ElectricCurrentValue电流A= 15[A]
EnergyValue能量/功J(或 W·h)= 44.4[W*h]
PowerValue功率W= 250[W]
FrequencyValue频率Hz= 400[Hz]
PressureValue压强Pa= 101325[Pa]
TemperatureValue热力学温度K(或 °C)= 298[K]
SpeedValue速度/速率m/s= 340[m/s]
AccelerationValue加速度m/s²= 9.81[m/s^2]
ForceValueN= 500[N]
VolumeValue体积m³(或 L)= 0.05[L]
表 3 — 常用 ISQ 量类型
1package DroneModel {
2 private import ISQ::*;
3 private import SI::*;
4
5 part def Battery {
6 attribute nominalVoltage : ISQ::ElectricPotentialValue = 22.2[V];
7 attribute capacity : ISQ::EnergyValue;
8 attribute peakCurrent : ISQ::ElectricCurrentValue;
9 attribute mass : ISQ::MassValue;
10 }
11
12 part def Motor {
13 attribute kv : Real; // 无量纲:RPM/V
14 attribute maxCurrent : ISQ::ElectricCurrentValue;
15 attribute stallTorque : ISQ::TorqueValue;
16 }
17}
⚠️ 常见错误

不要对同一物理量混用 ISQ 类型和原始 Real。如果 Battery.voltageISQ::ElectricPotentialValue,所有赋値或比较它的约束也必须使用兼容单位的値。将裸展 Real 赋给 ISQ 属性是类型错误。

attribute def 定义自己的値类型

attribute def 创建一个新的命名 DataType——一种可复用的结构化値类型。当一个概念不只是单个数字时使用它:

1attribute def GeoCoordinate {
2 private import ISQ::*;
3 attribute latitude : Real; // 度,-90 到 +90
4 attribute longitude : Real; // 度,-180 到 +180
5 attribute altitude : ISQ::LengthValue;
6}
7
8attribute def BatteryHealth {
9 attribute stateOfCharge : Real; // 0.0 到 1.0
10 attribute cycleCount : Integer;
11 attribute temperature : ISQ::TemperatureValue;
12 attribute internalResistance : ISQ::ElectricalResistanceValue;
13}
14
15part def UAV {
16 attribute homePosition : GeoCoordinate;
17 attribute batteryState : BatteryHealth;
18}
注意

attribute def 在 KerML 中是 DataType,不是 Class。这意味着 GeoCoordinate 的实例没有身份:两个字段相同的坐标被认为是相等的。不存在“这个特定坐标对象”的概念。如果你需要身份,请改用 part def

enum def 定义枚举

当一个属性只能取一组固定命名値之一时,使用枚举。在 KerML 中,每个字面量是一个 EnumerationLiteral;枚举本身是一个 DataType

1enum def FlightMode {
2 enum MANUAL;
3 enum STABILISED;
4 enum AUTO;
5 enum RETURN_TO_HOME;
6 enum EMERGENCY;
7}
8
9enum def HealthStatus {
10 enum OK;
11 enum DEGRADED;
12 enum FAILED;
13}
14
15part def FlightController {
16 attribute currentMode : FlightMode := FlightMode::STABILISED;
17 attribute systemHealth : HealthStatus := HealthStatus::OK;
18}
💡 何时用枚举,何时用属性

当有效値的集合是封闭的且建模时已知时(飞行模式、运行状态),使用 enum def。当値是测量値或计数(没有固定词汇表)时,使用 RealInteger。对枚举概念避免使用 String——它没有封闭世界语义,无法被工具验证。

四种値赋値方式

语法名称回答的问题能否被覆盖?
= expr绑定値这个値始终是什么?不能——永久不变量
:= expr初始値这个値什么开始?能——实例生命周期内可以改变
default = expr默认绑定除非特化覆盖,値默认是什么?能——子类型可以重定义
default := expr默认初始除非特化覆盖,値默认从什么开始?能——子类型可以重定义
表 4 — 四种値赋値方式
🏠 生活类比

想想汽车仪表盘。绑定値就像车轮数量永远是 4——结构不变量。初始値就像出厂时油量从满格开始——使用过程中会变化。默认绑定就像所有车型共用的标准胎压——除非运动车型覆盖它。默认初始就像座椅位置的出厂设置——每个司机都可以更改。

1part def Motor {
2 attribute cylinders : Integer = 4; // 绑定:始终为4,不可改变
3 attribute currentRPM : Real := 0; // 初始:从0开始,运行时会变化
4 attribute idleRPM : Real default = 800; // 默认绑定:800,子类型可覆盖
5 attribute vendor : String default := "Generic"; // 默认初始:可覆盖的起始値
6}
7
8part def RacingMotor specializes Motor {
9 attribute idleRPM : Real = 1200 redefines idleRPM; // 覆盖默认绑定
10}
⚠️ 常见错误

=永久不变量,不是起始点。写 attribute rpm : Real = 0 意味着转速在整个实例生命周期内都不能偏离零。当你的意思是“从这个値开始,但运行过程中会变化”时,请使用 :=

3

流动项(Item)——在部件间流动的事物

KerML 来源:item defClass(KerML 层与 part def 相同;区别是 SysML 约定)

流动项(item)是在部件之间流动的事物——信号、数据包、流体、物理材料、能量。与 part def 一样,item def 映射到 KerML Class:实例有身份,可以携带属性。与 part def 的区别纯粹是约定——流动项是流中的参与者,而不是持久的结构组件。

🏠 生活类比

部件是管道和泵;流动项是流过它们的东西。燃油管路(part)输送燃油(item)。网线(part)传输数据包(item)。转轴(part)传递扩矩(item)。

定义流动项

1item def ElectricalPower {
2 private import ISQ::*;
3 attribute voltage : ISQ::ElectricPotentialValue;
4 attribute current : ISQ::ElectricCurrentValue;
5}
6
7item def DataPacket {
8 attribute payload : String;
9 attribute checksum : Integer;
10 attribute priority : Integer default = 0;
11}
12
13item def Fuel {
14 private import ISQ::*;
15 attribute volumeFlow : ISQ::VolumeFlowRateValue;
16}

流动项在端口和流中的使用

1port def PowerPort {
2 out item power : ElectricalPower;
3}
4
5part def DriveSystem {
6 part battery : Battery { port powerOut : PowerPort; }
7 part motor : Motor { port powerIn : ~PowerPort; }
8
9 flow of ElectricalPower
10 from battery.powerOut.power
11 to motor.powerIn.power;
12}
概念关键字KerML 来源用途
流动项定义item defClass描述流动事物是什么的模板
流动项用法itemClass 类型化的复合 Feature特定上下文中的具体流动参与者
端口特征out item / in item带方向的 Feature声明端口发送或接收什么,以及方向
流语句flow of X from … to …ItemFlow显式连接两个流动项端点
表 5 — 流动项相关构件及其 KerML 来源
4

端口与连接

KerML 来源:port def → Type 边界上的带方向 Feature; connectConnector; interface def → 带 end Feature 的 Association

端口(Port)是部件的定义交互点。在 KerML 中,端口是一个由 Type 拥有的带方向 Feature,位于类型的边界上。连接(Connection)通过 KerML Connector 实例将端口 Feature 链接在一起。

端口定义

1port def ElectricalPort {
2 out item power : ElectricalPower; // 发送电力
3 in item control : ControlSignal; // 接收控制信号
4}
5
6// 共轭 ~ElectricalPort 反转所有方向:
7// in item power, out item control

部件上的端口

1part def PowerSupply { port output : ElectricalPort; } // 供方侧
2part def Controller { port input : ~ElectricalPort; } // 需方侧(共轭)

连接端口

connect 语句创建一个连接两个 Feature 实例的 KerML Connector

1part def System {
2 part psu : PowerSupply;
3 part controller : Controller;
4
5 connect psu.output to controller.input; // 匿名 Connector
6
7 connection powerLink : ElectricalInterface // 命名、类型化 Connector
8 connect psu.output to controller.input;
9}

接口定义

interface def 映射到 KerML Association——一个其实例就是连接本身的 Classifier,带有命名的 end Feature 标识每个参与者:

1interface def PowerInterface {
2 end port supplier : ElectricalPort;
3 end port consumer : ~ElectricalPort;
4 flow of ElectricalPower from supplier.power to consumer.power;
5}
6
7part def System {
8 part psu : PowerSupply; part controller : Controller;
9 interface : PowerInterface
10 connect supplier ::> psu.output
11 to consumer ::> controller.input;
12}
💡 何时使用哪种

简单的点对点布线使用裸 connect。当你想记录协议、包含流声明,或在多个子系统中复用接口模式时,使用 interface def + interface

5

分解模式

KerML 来源:直接 → 复合 Feature;子集 → Subsetting 关系;特化 → Subclassification;重定义 → Redefinition

四种将系统分解为部件的模式,每种模式映射到不同的 KerML 关系集合。

模式一——直接分解

1part def AircraftSystem {
2 part airframe : Airframe;
3 part propulsion : PropulsionSystem;
4 part avionics : Avionics;
5 part fuelSystem : FuelSystem;
6}

模式二——抽象池与子集

声明一个抽象池特征,然后使用 subsets 关键字(KerML Subsetting 关系)引入命名的个体。abstract 关键字强制池被完全覆盖:

1part def PropulsionSystem {
2 abstract part engine : Engine[1..4]; // 池——必须完全命名
3 part leftEngine : TurboFan subsets engine; // KerML Subsetting 关系
4 part rightEngine : TurboFan subsets engine;
5}

模式三——特化与重定义

使用 specializes(KerML Subclassification)进行特化,然后使用 redefines(KerML Redefinition)缩窄继承的特征:

1part def Vehicle {
2 part powertrain : Powertrain;
3 attribute range : ISQ::LengthValue;
4}
5
6part def ElectricVehicle specializes Vehicle {
7 part powertrain : ElectricPowertrain redefines powertrain; // 缩窄类型
8 attribute range : ISQ::LengthValue = 500[km] redefines range; // 固定値
9}
10
11part def HybridVehicle specializes Vehicle {
12 part powertrain : HybridPowertrain redefines powertrain;
13}

模式四——多重性驱动的分解

1part def SolarArray {
2 part panel : SolarPanel[1..*]; // 至少一块板
3 part string : PanelString[2..8]; // 2到8串
4 part inverter : Inverter; // 恰好一个逆变器
5}
模式KerML 机制使用场景关键语法
直接分解复合 Feature(拥有成员)简单的扁平结构part x : T;
抽象池 + 子集Subsetting 关系从池中命名个体abstract part pool : T[n];
part x : T subsets pool;
特化 + 重定义Subclassification + Redefinition通用→具体的逐步精化part def Sub specializes Super {
 part x : NarrowT redefines x;}
多重性驱动KerML 多重性 Feature数量可变的组件part x : T[1..*];
表 6 — 分解模式及其 KerML 来源
6

完整示例

一个综合了本模块所有内容的无人机系统。注意:末尾的 devUAV 用法使用了 :>> 简写——两种形式都有效;简写在紧凑的用法级覆盖中很常见。

1package UAVSystem {
2 private import ISQ::*; private import SI::*; private import ScalarValues::*;
3
4 enum def FlightMode { enum MANUAL; enum STABILISED; enum AUTO; enum RTH; }
5
6 // 流动项(KerML Class,约定:流动)
7 item def ElectricalPower {
8 attribute voltage : ISQ::ElectricPotentialValue;
9 attribute current : ISQ::ElectricCurrentValue; }
10 item def ControlCommand {
11 attribute channel : Integer; attribute pwmValue : Integer; }
12
13 // 端口(KerML 带方向 Feature)
14 port def PowerPort { out item pwr : ElectricalPower; }
15 port def MotorPort { in item cmd : ControlCommand; in item pwr : ElectricalPower; }
16
17 // 部件(KerML Class)
18 part def Battery {
19 attribute capacity : ISQ::EnergyValue;
20 attribute nominalVoltage : ISQ::ElectricPotentialValue = 22.2[V];
21 attribute health : Real default := 1.0;
22 port powerOut : PowerPort; }
23
24 part def FlightController {
25 attribute loopRate : ISQ::FrequencyValue = 400[Hz];
26 attribute mode : FlightMode := FlightMode::STABILISED;
27 port powerIn : ~PowerPort;
28 port motorCmd : MotorPort[4]; }
29
30 part def Motor {
31 attribute kv : Real;
32 attribute maxCurrent : ISQ::ElectricCurrentValue;
33 port ctrl : MotorPort; }
34
35 part def MotorAssembly { part motor : Motor; part prop : Propeller; }
36 part def Propeller {
37 attribute diameter : ISQ::LengthValue; attribute pitch : ISQ::LengthValue; }
38
39 // UAV:抽象池 + 直接分解
40 part def UAV {
41 attribute mass : ISQ::MassValue;
42 attribute maxPayload : ISQ::MassValue;
43 part battery : Battery; part fc : FlightController;
44 abstract part motorAsm : MotorAssembly[4];
45 part frontLeft : MotorAssembly subsets motorAsm; // 显式 subsets
46 part frontRight : MotorAssembly subsets motorAsm;
47 part rearLeft : MotorAssembly subsets motorAsm;
48 part rearRight : MotorAssembly subsets motorAsm;
49 connect battery.powerOut to fc.powerIn;
50 connect fc.motorCmd[1] to frontLeft.motor.ctrl;
51 connect fc.motorCmd[2] to frontRight.motor.ctrl;
52 connect fc.motorCmd[3] to rearLeft.motor.ctrl;
53 connect fc.motorCmd[4] to rearRight.motor.ctrl; }
54
55 // 用法级覆盖(此处使用 :>> 简写)
56 part devUAV : UAV {
57 :>> mass = 1.2[kg]; :>> maxPayload = 0.5[kg];
58 part :>> battery { :>> capacity = 44.4[W*h]; }
59 part :>> fc { :>> loopRate = 500[Hz]; } }
60}

此模型演示了:enum def(FlightMode)、ISQ 属性item def(KerML Class,流动约定)、port def(带方向 Feature)、复合分解显式 subsets 的抽象池connect(Connector)以及用法级重定义简写

7

本模块总结

SysML v2 概念KerML 来源关键规则
part defClass实例有身份,随时间持续存在
part复合 Feature(isComposite=true随父级创建和销毁;默认 [1..1]
ref part非复合 Feature(isComposite=false子级独立存在;父级持有引用
attribute defDataType无身份——两个相等的値不可区分
attributeDataType 类型化的 Feature生命周期与父级相同;物理量使用 ISQ 类型
enum def带 EnumerationLiteral 的 DataType用于封闭的命名値集合
item defClass(流动约定)KerML 层与 part def 相同;表明流动参与者
port defType 边界上的带方向 Feature~T 共轭反转所有方向
connectConnector连接 Feature 实例;类型化连接使用 interface def
subsetsSubsetting 关系从池中添加命名个体;原始池保留
specializesSubclassification子类型继承所有特征;与 redefines 配合使用缩窄
redefinesRedefinition替换继承的特征;可缩窄类型、多重性或値
表 7 — 模块三概念与其 KerML 来源
下一讲

模块四 — 行为建模 — 动作、动作流、状态机,以及如何描述系统随时间的行为。