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;	
	}
}