SysML v2
The MBSE working group has a subgroup "Application example" that deals with the pilot implementation of SysML V2, which is provided by the OMG. The main goal is to develop a first feeling for the possibilities but also the pitfalls of the new version SysML v2. Therefore the focus is on getting to know the syntax and semantics of the new version, the differences to v1, and just playing around with the language.
On the basis of an application example, the following aspects will be put through their paces:
- Modeling of requirements, behavior, and structure
- Collaboration and modularization of SysML v2 models
- Collecting feedback for the SST SysML v2 working group
- Evaluation of the existing implementation in Eclipse and Jupyter Notebook
Since there is currently not much literature available on the topic of SysML v2, we try to get a picture ourselves and make our findings and our example model available on this page.
Useful Links:
An extensive SysML Example
Under construction ...
This image depicts the high-level architecture of our robotic vacuum cleaner model. As shown, the modules within the architecture import pertinent information from other modules, facilitating the robot's operation.
package 'Robotic Vacuum Cleaner'{
import Controller::*;
import Navigation::*;
import EnergySupplySystem::*;
import VacuumingSystem::*;
import Ports::*;
part def RoboticVacuumCleaner{
part ControllerSystem : controller;
part NavigationSystem : navigation;
part EnergySystem : energySupplySystem;
part VaccumingSystem : vacuumingSystem;
port driverUnitControlSignal : DriverUnitControlSignal;
port powerSignal : PowerSignal;
port dirtyAirFlow : DirtyAirFlow;
port cleanAirFlow : CleanAirFlow;
connect ControllerSystem to NavigationSystem;
interface def ports {
end supliertPort : DriverUnitControlSignal;
end consumertPort: DriverUnitControlSignal;
}
interface: ports connect
supliertPort ::> driverUnitControlSignal to
consumerPort ::> NavigationSystem.driverUnitControlSignal;
// Interfaces to/from Vaccuming System
connect ControllerSystem to VacuumingSystem;
// Control signal for level of suction intesity
interface def suctionLevelPorts {
end supplierPort : SuctionLevel;
end consumerPort : SuctionLevel;
}
interface: suctionLevelPorts connect
supplierPort ::> ControllerSystem.suctionLevel;
consumerPort ::> VacuumingSystem.suctionLevel;
// Control signal for brush rotation level
interface def brushRotationLevelPorts {
end supplierPort : BrushRotationLevel;
end consumerPort : BrushRotationLevel;
}
interface: brushRotationLevelPorts connect
supplierPort ::> ControllerSystem.brushRotationLevel;
consumerPort ::> VacuumingSystem.brushRotationLevel;
// Current fill state of debris container
interface def fillStatePorts {
end supplierPort : FillState;
end consumerPort : FillState;
}
interface: fillStatePorts connect
supplierPort ::> VacuumingSystem.fillState;
consumerPort ::> ControllerSystem.fillState;
// Dirty air flow
interface def dirtyAirPorts {
end supplierPort : DirtyAirFlow;
end consumerPort : DirtyAirFlow;
}
interface: dirtyAirPorts connect
supplierPort ::> dirtyAirFlow;
consumerPort ::> VacuumingSystem.dirtyAirFlow;
// Clean air flow
interface def cleanAirPorts {
end supplierPort : CleanAirFlow;
end consumerPort : CleanAirFlow;
}
interface: cleanAirPorts connect
supplierPort ::> VacuumingSystem.cleanAirFlow;
consumerPort ::> cleanAirFlow;
}
}
The depicted image shows the controller, which assumes responsibility for interfacing with external systems and relaying information to the various sub-systems.
package Controller{
import Ports::*;
part def controller{
port driverSignal : ~DriverUnitControlSignal;
port powerSignal : ~PowerSignal;
// To Vacuuming System
port suctionLevel : SuctionLevel;
port brushRotationLevel : BrushRotationLevel;
// From Vacuuming System
port fillState : ~FillState;
}
}
ToDo: add description.
package EnergySupplySystem{
import Ports::*;
part def energySupplySystem{
port powerSignal : PowerSignal;
}
}
This image portrays the high-level architecture of our navigation system. Similarly to the previous module, the architecture imports data from other modules to enable proper functionality
package Navigation{
import Ports::*;
import Parts::*;
part def navigation{
part DriveController : driveController;
part Motor[2] : dcMotor;
part laserTower : Lasertower;
part bumber : Bumber;
part infrarotController : InfrarotController;
port driverUnitControlSignal : DriverUnitControlSignal;
port powerSignal : PowerSignal;
}
}
The image illustrates the discrete components utilized in the navigation system.
package Parts{
part def driveController {
part stearingController;
part orientationController;
}
part def dcMotor {
attribute maxTorque :> ISQ::torque;
attribute rpm0 : Real;
attribute voltage :> ISQ::voltage;
part motorTire : tire [1..2];
state def motorDirection {
entry; then idle;
state idle;
transition idle_to_left
first idle
then left;
transition idle_to_right
first idle
then right;
state left;
transition left_to_idle
first left
then idle;
state right;
transition right_to_idle
first right
then idle;
}
}
part def Lasertower {
attribute distance : LengthValue;
attribute distanceAngle : Real;
attribute motor;
port position : LaserTowerPosition;
port psu : powerSupplyPort;
}
part def Bumber {
attribute isContact : Boolean;
port Contact : contact;
}
part def TimeOfFlightSensor{
port i2cSlave : i2c;
}
part def InfrarotController{
part timeOfFlightSensor;
port psu : powerSupplyPort;
port i2cMaster : i2c;
}
}
This image showcases the public ports utilized in the system's operation.
package Ports {
import ScalarValues::*;
import ISQ::*;
import SI::*;
import ISQSpaceTime::*;
import ISQMechanics::*;
port def DriverUnitControlSignal {
in forward :> Boolean;
in left :> Boolean;
in right :> Boolean;
}
port def PowerSignal{
out constantCurrent :> totalCurrent;
out constantVoltage :> voltage;
}
// Ports for Vacuuming System
port def DirtyAirFlow{
in dirtyAirFlow :> ISQSpaceTime::volume;
}
port def CleanAirFlow{
out cleanAirFlow :> ISQSpaceTime::volume;
}
port def Debris {
out debrisVolume :> SI::'m³';
out debrisMass :> SI::kg;
}
port def FillState {
out fillState :> Real;
}
port SuctionLevel {
out suctionLevel :> Real;
}
port SuctionPower {
out suctionPower :> ISQ::power;
}
port BrushRotationLevel {
out brushRotationLevel :> Real;
}
port def BrushRotationSpeed {
out brushRotationSpeed :> ISQSpaceTime::rotationalFrequency;
}
}
ToDo: add description.
package VacuumingSystem{
import BrushSystem::*;
import SuctionDevice::*;
import FilterSystem::*;
import Ports::*;
part def vacuumingSystem{
part bs : brushSystem;
part sd : suctionDevice;
part fs : filterSystem;
port dirtyAirFlow : DirtyAirFlow;
port cleanAirFlow : CleanAirFlow;
port debris : Debris;
port fillState : FillState;
port suctionLevel : ~SuctionLevel;
port brushRotationLevel : ~BrushRotationLevel;
interface def rotationLevelPorts {
end supplierPort : BrushRotationLevel;
end consumerPort : BrushRotationLevel;
}
interface: rotationLevelPorts connect
supplierPort ::> brushRotationLevel;
consumerPort ::> bs.brushRotationLevel;
interface def externalDirtyAirPorts {
end supplierPort : DirtyAirFlow;
end consumerPort : DirtyAirFlow;
}
interface: externalDirtyAirPorts connect
supplierPort ::> dirtyAirFlow;
consumerPort ::> sd.dirtyAirFlowIn;
connect sd to fs;
interface def internalDirtyAirPorts {
end supplierPort : DirtyAirFlow;
end consumerPort : DirtyAirFlow;
}
interface: internalDirtyAirPorts connect
supplierPort ::> sd.dirtyAirFlowOut;
consumerPort ::> fs.dirtyAirFlow;
interface def cleanAirPorts {
end supplierPort : CleanAirFlow;
end consumerPort : CleanAirFlow;
}
interface: cleanAirPorts connect
supplierPort ::> fs.cleanAirFlow;
consumerPort ::> cleanAirFlow;
interface def suctionLevelPorts {
end supplierPort : SuctionLevel;
end consumerPort : SuctionLevel;
}
interface: suctionLevelPorts connect
supplierPort ::> suctionLevel;
consumerPort ::> sd.suctionlevel;
interface def fillStatePorts {
end supplierPort : FillState;
end consumerPort : FillState;
}
interface: fillStatePorts connect
supplierPort ::> fs.fillState;
consumerPort ::> fillState;
}
}
ToDo: add description.
package BrushSystem {
import Ports::*;
import ISQSpaceTime::*;
calc def calcSetpointRPM (rotationLevel : Real, maxRPM :> ISQSpaceTime::rotationalFrequency) :> ISQSpaceTime::rotationalFrequency {
rotationLevel * maxRPM
}
part def MainBrush {
port rotationSpeed : ~BrushRotationSpeed;
}
part def SmallBrush {
port rotationSpeed : ~BrushRotationSpeed;
}
part def BrushController {
port rotationSpeed : BrushRotationSpeed;
port brushRotationLevel : ~BrushRotationLevel;
attribute parMaxRPM :> ISQSpaceTime::rotationalFrequency;
calc setpointRPM : calcSetpointRPM (
rotationLevel = brushRotationLevel::brushRotationLevel,
maxRPM = parMaxRPM
) return pOut = rotationSpeed::rotationSpeed;
}
part def brushSystem{
part mb : MainBrush;
part sb : SmallBrush[2];
part bc : BrushController{
attribute redefines parMaxRPM = 167; // 10000 rpm is a common rotational speed of the brushes, recalculation because rotationalFrequency is [1/s]
};
port brushRotationLevel : ~BrushRotationLevel;
connect bc to mb;
interface def rotationSetPointMainPorts {
end supplierPort : BrushRotationSpeed;
end consumerPort : BrushRotationSpeed;
}
interface: rotationSetPointMainPorts connect
supplierPort ::> bc.brushRotationSpeed;
consumerPort ::> mb.brushRotationSpeed;
connect bc to sb;
interface def rotationSetPointSmallPorts {
end supplierPort : BrushRotationSpeed;
end consumerPort : BrushRotationSpeed;
}
interface: rotationSetPointSmallPorts connect
supplierPort ::> bc.brushRotationSpeed;
consumerPort ::> sb.brushRotationSpeed;
}
}
ToDo: add description.
package FilterSystem {
import Ports::*;
part def Tank {
port debris : ~Debris;
port fillState : FillState;
// Missing State Machine
}
part def Filter {
port dirtyAirFlow : DirtyAirFlow;
port cleanAirFlow : CleanAirFlow;
port debris : Debris;
}
part def filterSystem {
port dirtyAirFlow : DirtyAirFlow;
port cleanAirFlow : CleanAirFlow;
port fillState : FillState;
part filter : Filter;
part tank : Tank;
interface def dirtyAirFlowPorts {
end supplierPort : DirtyAirFlow;
end consumerPort : DirtyAirFlow;
}
interface: dirtyAirFlowPorts connect
supplierPort ::> dirtyAirFlow;
consumerPort ::> filter.dirtyAirFlow;
interface def cleanAirFlowPorts {
end supplierPort : CleanAirFlow;
end consumerPort : CleanAirFlow;
}
interface: cleanAirFlowPorts connect
supplierPort ::> filter.cleanAirFlow;
consumerPort ::> cleanAirFlow;
connect filter to tank;
interface def debrisPorts {
end supplierPort : Debris;
end consumerPort : Debris;
}
interface: dirtyAirFlowPorts connect
supplierPort ::> filter.debris;
consumerPort ::> tank.debris;
interface def fillStatePorts {
end supplierPort : fillState;
end consumerPort : fillState;
}
interface: fillStatePorts connect
supplierPort ::> tank.fillState;
consumerPort ::> fillState;
}
}
ToDo: add description.
package SuctionDevice {
import Ports::*;
import ISQ::*;
import ISQMechanics::*;
import ISQSpaceTime::*;
import ScalarValues::*;
calc def calcActualPower (powerLevel :> Real, maxPower :> ISQ::power) :> ISQ::power {
powerLevel * maxPower
}
calc def calcVolFlow (setpointPower :> ISQ::power, diffPressure :> ISQ::pressure) :> ISQMechanics::volumeFlowRate {
actPower / diffPressure
}
calc def calcFlowRate (inFlow :> ISQSpaceTime::volume, volFlow :> ISQMechanics::volumeFlowRate) :> ISQSpaceTime::volume {
// not sure how to model without time steps
}
}
part def SuctionMotor {
port suctionLevel = ~SuctionLevel;
port suctionPower = SuctionPower;
attribute parMaxPower :> ISQ::power;
calc powerOut : calcActualPower (
powerLevel = suctionLevel::suctionLevel,
maxPower = parMaxPower
) return pOut = suctionPower::suctionPower;
}
part def SuctionChamber {
port dirtyAirFlowIn = DirtyAirFlow;
port dirtyAirFlowOut = ~DirtyAirFlow;
port suctionPower : ~SuctionPower;
attribute parDiffPressure :> ISQ::pressure;
calc volFlow : calcVolFlow (
actPower = suctionPower::suctionPower,
diffPressure = parDiffPressure
) return currentFlow
calc flowRate : calcFlowRate (
inFlow = dirtyAirFlowIn::dirtyAirFlow;
volFlow = currentFlow
) return currentFlowRate = dirtyAirFlowOut::dirtyAirFlow;
}
part def suctionDevice {
part sm : SuctionMotor;
part sc : SuctionChamber {
attribute redefines parDiffPressure = 25000; // 25kPa is a common pressure difference for suction devices
}
port dirtyAirFlowIn : DirtyAirFlow;
port dirtyAirFlowOut : ~DirtyAirFlow;
port suctionLevel : ~SuctionLevel;
interface def dirtyAirFlowInPorts {
end supplierPort : DirtyAirFlow;
end consumerPort : DirtyAirFlow;
}
interface: dirtyAirFlowInPorts connect
supplierPort ::> dirtyAirFlowIn;
consumerPort ::> sc.dirtyAirFlowIn;
interface def dirtyAirFlowOutPorts {
end supplierPort : DirtyAirFlow;
end consumerPort : DirtyAirFlow;
}
interface: dirtyAirFlowOutPorts connect
supplierPort ::> sc.dirtyAirFlowOut;
consumerPort ::> dirtyAirFlowOut;
interface def suctionLevelPorts {
end supplierPort : SuctionLevel;
end consumerPort : SuctionLevel;
}
interface: suctionLevelPorts connect
supplierPort ::> suctionLevel;
consumerPort ::> sm.suctionlevel;
connect sm to sc;
interface def suctionPowerPorts {
end supplierPort : SuctionPower;
end consumerPort : SuctionPower;
}
interface: suctionPowerPorts connect
supplierPort ::> sm.suctionPower;
consumerPort ::> sc.suctionPower;
}
}