Module 4: Behaviour Modelling
How to describe what a system does — actions, data flow, control flow, and state machines — and how every behavioural keyword maps to a KerML Occurrence layer construct underneath.
KerML → SysML: Behaviour Modelling Concepts
SysML v2 behaviour modelling is built on KerML’s Occurrence layer — the part of the language that describes things that happen over time, in contrast to the Structure layer which describes things that exist. Every behavioural keyword in this module is a SysML L2 application of a KerML L1 construct from that Occurrence layer.
| SysML v2 concept (L2) | Underlying KerML construct (L1) | What SysML adds |
|---|---|---|
action def | Behavior (a Classifier — KerML Occurrence layer) | Keyword implies something that happens over a time interval; instances are occurrences, not persistent objects |
action (usage) | Feature typed by a Behavior | Composite by default [1..1]; executes within the owning action's lifetime |
perform action | FeatureMembership referencing a Behavior | Shorthand to invoke a behaviour by name without declaring a sub-action body |
in / out / inout parameters | Directed Feature on a Behavior | Direction restricts who supplies or receives the value; typed by any classifier |
flow (item flow on action) | ItemFlow (an Interaction specialisation) | Declares what items pass between two action parameter endpoints |
succession | Succession (a Connector with temporal semantics) | The source must finish before the target may start; encodes temporal ordering |
first / then | Shorthand for Succession | Pairs of succession constraints; can be chained into an action sequence |
if / else / merge | Decision / merge ControlNode pattern | Conditional routing: one branch executes based on a guard; merge recombines branches |
loop | Loop ControlNode pattern | Repeats the body while a condition holds; KerML models this as a guarded succession cycle |
fork / join | Fork / join ControlNode pattern | Fork activates multiple concurrent actions; join waits for all to complete |
state def / state | StateDefinition (specialises ActionDefinition / BehaviorDefinition) | Adds entry/do/exit semantics and triggered transitions to a behaviour |
transition | TransitionUsage (a Succession) | Adds a trigger, guard, and effect to a temporal succession between states |
accept | AcceptActionUsage | Waits for a message or signal to arrive before proceeding |
send | SendActionUsage | Sends a message or signal to another part or action |
occurrence def | Occurrence (the root Classifier of the KerML Occurrence layer) | Names a reusable type of thing-that-happens; base for action def, state def, etc. |
In KerML, the Occurrence layer sits above the Core layer. Occurrence specialises Class and adds the concept of happening over a time interval. Behavior further specialises Occurrence to add the notion of being performed. Every SysML v2 behavioural keyword — action def, state def, transition — is ultimately a specialisation of Behavior or Occurrence at the KerML layer.
Actions & Behaviours
KerML origin: action def → Behavior (Occurrence layer); action → Feature typed by Behavior
An action describes something the system does over a time interval. This is the fundamental shift from Module 3: parts exist, actions happen. At the KerML level, Behavior specialises Occurrence which specialises Class — so all the mechanisms you know from structure modelling (specialisation, features, multiplicity, chaining) apply equally to behaviours.
A car exists continuously. Starting the engine is an action — it happens over a time interval, has inputs (key, fuel), produces outputs (running engine), and terminates. The car (structure) and the start sequence (behaviour) are two different kinds of model element, but both are Classifiers in KerML.
Defining and using actions
The definition/usage split from Module 1 applies here too. action def defines the template; action uses it in a specific context:
1 action def FuelPump { 2 in item fuelRequest : FuelRequest; // input: what is being requested 3 out item fuelDelivery : Fuel; // output: fuel delivered 4 } 5 6 action def EngineStart { 7 // sub-actions: each is a Feature typed by its action def 8 action primeSystem : PrimeFuelSystem; 9 action crankEngine : CrankEngine; 10 action fireIgnition : FireIgnition; 11 }
Nesting and decomposition
Actions can be nested to any depth. Each sub-action is a composite Feature whose execution occurs within the lifetime of its parent action — exactly as a composite part is owned by its parent part in the structural domain:
1 action def MissionProfile { 2 action takeOff : TakeOff; 3 action cruise : CruiseSegment; 4 action land : Landing; 5 // Without explicit succession, execution order is unspecified. 6 // Use succession / then to impose ordering (see Section 3). 7 }
action def maps to KerML Behavior. An action usage maps to a Feature typed by that Behavior. Because Behavior is itself a Class, action definitions can specialise each other (specializes), and action usages can use subsets and redefines exactly as structural features do.
Performing an existing action definition
Use perform action to invoke a pre-defined action by name, without re-declaring its body. This is a membership reference, not a new definition:
1 action def SystemTest { 2 perform action runDiagnostics : Diagnostics; // references Diagnostics by type 3 perform action logResults : Logger; 4 }
An action is not a function call in the programming sense. It is a Feature typed by a Behavior — it has a lifetime, can have sub-actions executing concurrently within it, and participates in the full type system. Thinking of it as a method call will lead to confusion when ordering, concurrency, and data flow are introduced.
Action Parameters & Data Flow
KerML origin: Parameters → directed Features on a Behavior; Item flows → ItemFlow
Actions communicate by passing items through parameters. A parameter is a directed Feature on the action definition — the same in / out / inout mechanism as port features in Module 3, but applied to actions. The KerML origin is the same: a directed Feature on a Classifier.
Declaring parameters
1 action def ComputeTrajectory { 2 in attribute startPos : GeoCoordinate; // input: starting position 3 in attribute targetPos : GeoCoordinate; // input: target position 4 in attribute windSpeed : ISQ::SpeedValue; // input: environmental data 5 out attribute trajectory : Trajectory; // output: computed path 6 out attribute flightTime : ISQ::TimeValue; // output: estimated duration 7 }
Item flows between sub-actions
Inside a composite action, item flows connect one sub-action’s output parameter to another’s input parameter. This is the behavioural analogue of the structural flow statement from Module 3, mapping to KerML ItemFlow:
1 action 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 // Item flows: output of one action feeds into input of next 8 flow sense.data to plan.data; 9 flow plan.cmd to execute.cmd; 10 }
Think of a production line. The welding station (sense) hands its output to the painting station (plan), which hands its output to the assembly station (execute). Item flows are the conveyor belts between stations.
Binding parameters through the hierarchy
Outer action parameters can be bound to inner sub-action parameters using bind. This propagates values across the action boundary without creating a separate item flow object:
1 action def MissionPlan { 2 in attribute origin : GeoCoordinate; 3 out attribute path : Trajectory; 4 5 action compute : ComputeTrajectory { 6 bind compute.startPos = origin; // outer in binds to inner in 7 bind compute.trajectory = path; // inner out binds to outer out 8 } 9 }
Parameters are Features, so they obey all Feature rules: they carry multiplicity, can be typed by any Classifier (including DataType for value parameters and Class for object parameters), and can be subsetted or redefined in specialisations of the action definition.
Control Flow & Sequencing
KerML origin: succession → Succession (a Connector); if/else → decision / merge ControlNode; fork/join → fork / join ControlNode
By default, sub-actions within a composite action have no defined execution order. They may run concurrently, in any sequence, or only once their data dependencies are satisfied. To impose explicit ordering, SysML v2 provides succession and higher-level control flow constructs that map to KerML Succession connectors and control node patterns.
Succession: explicit ordering
A succession between two actions means: the first action must finish before the second may start. This is the behavioural analogue of a connector in structure modelling — it is a KerML Succession, itself a specialisation of Connector:
1 action def EngineStart { 2 action prime : PrimeFuelSystem; 3 action crank : CrankEngine; 4 action fire : FireIgnition; 5 6 succession prime then crank; // prime must finish before crank starts 7 succession crank then fire; // crank must finish before fire starts 8 }
The first / then shorthand chains successions compactly:
1 action def EngineStart { 2 action prime : PrimeFuelSystem; 3 action crank : CrankEngine; 4 action fire : FireIgnition; 5 6 first prime then crank then fire; // equivalent to two succession statements 7 }
Conditional branching: if / else
An if block declares a decision node: a guard expression is evaluated, and exactly one branch executes. The KerML model is a DecisionNode control node with guarded outgoing successions:
1 action 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 node implicitly recombines the two branches 14 then respond; 15 }
The merge keyword recombines multiple incoming branches into a single outgoing flow. It is necessary whenever two or more branches converge before a shared continuation — without it, the continuation would require all branches to complete (a join), not any one.
Parallel execution: fork / join
A fork activates multiple sub-actions simultaneously. A join waits until all forked actions have completed before proceeding. These map to KerML fork/join control node patterns:
1 action def SystemInitialise { 2 action loadFirmware : LoadFirmware; 3 action selfTest : RunSelfTest; 4 action calibrateSensors : Calibrate; 5 action connectNetwork : ConnectNetwork; 6 action reportReady : ReportReady; 7 8 // All four initialisation tasks run in parallel 9 fork { 10 then loadFirmware; 11 then selfTest; 12 then calibrateSensors; 13 then connectNetwork; 14 } 15 // Wait for all four to complete, then report 16 join then reportReady; 17 }
Loops
A loop repeats its body while a condition holds. At the KerML level this is a guarded succession cycle — a Succession whose source is the loop body and whose target is a DecisionNode that re-evaluates the condition:
1 action def PollSensor { 2 action read : ReadSensorValue; 3 action process : ProcessReading; 4 5 loop { 6 first read then process; 7 } while process.shouldContinue; 8 }
Succession and fork/join model completion ordering, not timing. A succession does not say "start the next action 100 ms later" — it says the first must finish before the second may begin. For real-time timing constraints, use requirement constraints on action durations, not succession.
State Machines
KerML origin: state def → StateMachine (specialises Behavior); transition → TransitionUsage (a Succession)
A state machine models a system whose behaviour depends on its current state. In SysML v2, state def maps to a KerML StateMachine, which is itself a specialisation of Behavior. This means state machines are behaviours — they can appear as action usages, accept parameters, and be composed into larger action networks.
Think of a traffic light controller. It does not execute a sequential algorithm — instead it is always in one of three states (RED, AMBER, GREEN) and changes state in response to events (a timer firing, a sensor trigger). The state machine captures exactly this kind of reactive, event-driven behaviour.
Defining states
Each state can have optional entry, do, and exit actions:
1 state def TrafficLightController { 2 entry; // initial pseudo-state β execution begins here 3 4 state RED { 5 entry action activateRed : ActivateRedLight; // runs when entering 6 do action holdRed : HoldRedSignal; // runs while in state 7 exit action deactivateRed : DeactivateLight; // runs when leaving 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 }
Transitions
A transition is a TransitionUsage — a KerML Succession that adds a trigger, an optional guard, and an optional effect action:
1 // Syntax: transition <source> accept <trigger> if <guard> do <effect> then <target> 2 3 state def TrafficLightController { 4 state RED; 5 state AMBER; 6 state GREEN; 7 8 entry; then RED; // initial transition: start in RED 9 10 // RED -> GREEN when timer expires 11 transition RED 12 accept TimerExpired 13 then GREEN; 14 15 // GREEN -> AMBER when timer expires or pedestrian button pressed 16 transition GREEN 17 accept TimerExpired | PedestrianRequest 18 then AMBER; 19 20 // AMBER -> RED unconditionally after short delay 21 transition AMBER 22 accept TimerExpired 23 then RED; 24 }
Guard conditions and effects
1 state def SafetyController { 2 state NORMAL; 3 state DEGRADED; 4 state SAFE_SHUTDOWN; 5 6 entry; then NORMAL; 7 8 transition NORMAL 9 accept HealthCheck // trigger: fired by a HealthCheck event 10 if systemHealth < 0.5 // guard: only fires when health is low 11 do action log : LogDegradation // effect: executed during the transition 12 then DEGRADED; 13 14 transition DEGRADED 15 accept HealthCheck 16 if systemHealth < 0.1 17 then SAFE_SHUTDOWN; 18 }
Accept and send inside states
accept waits for an incoming message or signal. send dispatches one. They map to KerML AcceptActionUsage and SendActionUsage respectively:
1 state def CommandProcessor { 2 state IDLE; 3 state PROCESSING; 4 5 entry; then IDLE; 6 7 transition IDLE 8 accept CommandReceived // waits for a CommandReceived event 9 then PROCESSING; 10 11 state PROCESSING { 12 do action work : ProcessCommand; 13 exit action notify { 14 send : CompletionSignal; // sends a CompletionSignal on exit 15 } 16 } 17 18 transition PROCESSING 19 accept work.done 20 then IDLE; 21 }
In SysML v2, state machines are first-class behaviours. A state def can be used as the type of an action usage inside a larger action sequence. This means you can compose state machines with sequential and parallel action flows — something that was awkward in SysML v1.
Occurrences & Snapshots
KerML origin: occurrence def → Occurrence (KerML Occurrence layer root); snapshot → structural projection of an occurrence at a time instant
KerML’s Occurrence layer introduces two fundamental concepts that underpin everything in this module: occurrences (things that happen over a time interval) and snapshots (what an occurrence looks like at a single instant). Every action, state, and message in SysML v2 is ultimately an occurrence.
Occurrence definitions
occurrence def names a reusable type of happening — the most general form before you specialise it into an action or state machine. It is useful when you want to describe events or interactions without immediately committing to whether they are actions, states, or messages:
1 occurrence def SystemEvent; 2 occurrence def FaultEvent specializes SystemEvent { 3 attribute severity : Integer; 4 attribute component : String; 5 } 6 7 occurrence def RecoveryAction specializes SystemEvent { 8 attribute targetComponent : String; 9 }
Snapshots — structural slices through time
A snapshot captures the state of a part at a specific moment within an occurrence. It is a structural projection — a view of what attribute values and sub-part configurations hold at that instant. Snapshots are used in behavioural models to assert preconditions, postconditions, and invariants:
1 action def ChargeBattery { 2 in part battery : Battery; 3 4 // Precondition: what battery looks like when charging begins 5 snapshot startState { 6 assert constraint { battery.stateOfCharge < 0.9 } 7 } 8 9 action doCharge : Charge; 10 11 // Postcondition: what battery looks like when charging ends 12 snapshot endState { 13 assert constraint { battery.stateOfCharge >= 0.99 } 14 } 15 }
Snapshots are not checkpoints inserted into an action sequence. They describe structural conditions that must hold at the beginning and end of an occurrence. Tooling uses them for verification: if a simulation or formal analysis shows the postcondition is not reachable, there is a modelling defect.
Time slices and temporal ordering
Every occurrence has a time slice — its span from start to finish. SysML v2 inherits from KerML the ability to reference startShot and endShot projections of any occurrence, enabling constraints that span multiple actions:
1 requirement def ResponseTime { 2 subject mission : MissionAction; 3 require constraint { 4 // The end of the mission must occur within 60 seconds of its start 5 mission.endShot.time - mission.startShot.time <= 60[s] 6 } 7 }
An occurrence is like a film clip: it spans a period of time. A snapshot is a single frame of that clip. A time slice is the subset of the clip from one moment to another. SysML v2 lets you make assertions about individual frames (snapshots) or the whole clip (the occurrence).
Complete Worked Example
The following model integrates all four sections: a UAV autopilot behaviour combining sequential actions, data flow, a decision, concurrency, and a state machine for flight mode management.
1 package UAVBehaviour { 2 private import ISQ::*; 3 private import SI::*; 4 private import ScalarValues::*; 5 private import UAVSystem::*; // parts from Module 3 worked example 6 7 // ββ Occurrences (shared event vocabulary) βββββββββββββββ 8 occurrence def FlightEvent; 9 occurrence def TakeoffCleared specializes FlightEvent; 10 occurrence def LandingCleared specializes FlightEvent; 11 occurrence def FaultDetected specializes FlightEvent { 12 attribute severity : Integer; 13 } 14 15 // ββ State machine: flight mode βββββββββββββββββββββββββββ 16 state def FlightModeController { 17 state GROUND; 18 state TAKEOFF; 19 state CRUISE; 20 state LANDING; 21 state EMERGENCY; 22 23 entry; then GROUND; 24 25 transition GROUND 26 accept TakeoffCleared 27 then TAKEOFF; 28 29 transition TAKEOFF 30 accept AltitudeReached 31 if altitude >= 50[m] 32 then CRUISE; 33 34 transition CRUISE 35 accept LandingCleared 36 then LANDING; 37 38 transition LANDING 39 accept TouchdownDetected 40 then GROUND; 41 42 // From each state: fault triggers emergency 43 transition GROUND 44 accept FaultDetected 45 if severity >= 2 46 do action log : LogEmergency 47 then EMERGENCY; 48 transition TAKEOFF 49 accept FaultDetected 50 if severity >= 2 51 then EMERGENCY; 52 transition CRUISE 53 accept FaultDetected 54 if severity >= 2 55 then EMERGENCY; 56 transition LANDING 57 accept FaultDetected 58 if severity >= 2 59 then EMERGENCY; 60 } 61 62 // ββ Action: sensor fusion (produces navigation estimate) β 63 action def SensorFusion { 64 in item gpsData : GPSReading; 65 in item imuData : IMUReading; 66 out attribute navEstimate : NavigationState; 67 } 68 69 // ββ Action: guidance (consumes nav, produces command) ββββ 70 action def GuidanceLaw { 71 in attribute navEstimate : NavigationState; 72 in attribute targetWP : Waypoint; 73 out attribute motorCmds : MotorCommandSet; 74 } 75 76 // ββ Top-level autopilot loop βββββββββββββββββββββββββββββ 77 action def AutopilotLoop { 78 in part uav : UAV; 79 80 // State machine runs concurrently with the guidance loop 81 action modeCtrl : FlightModeController; 82 83 // Sensor fusion and guidance execute in sequence, in a loop 84 action fuse : SensorFusion; 85 action guide : GuidanceLaw; 86 action actuate: ActuateMotors; 87 88 // Data flow: fusion output feeds guidance input 89 flow fuse.navEstimate to guide.navEstimate; 90 flow guide.motorCmds to actuate.motorCmds; 91 92 // Control flow: sequence within each iteration 93 loop { 94 first fuse then guide then actuate; 95 } while uav.flightMode != FlightMode::GROUND; 96 97 // Precondition snapshot 98 snapshot preCheck { 99 assert constraint { uav.battery.health >= 0.2 } 100 } 101 } 102 }
This model demonstrates: occurrence def (shared event vocabulary), state def with triggers and guards, action parameters and item flows (sensor fusion pipeline), succession with first/then, loop with a termination condition, concurrent state machine alongside a sequential loop, and a snapshot precondition.
Module Summary
| SysML v2 concept | KerML origin | Key rule |
|---|---|---|
action def | Behavior (Occurrence layer) | Instances are occurrences, not persistent objects; they happen over a time interval |
action (usage) | Feature typed by Behavior | Composite [1..1] by default; executes within the owning action's lifetime |
Parameters (in/out/inout) | Directed Features on a Behavior | Same mechanism as port features; typed by any Classifier |
Item flow (flow X to Y) | ItemFlow | Connects output parameter of one sub-action to input of another |
bind X = Y | BindingConnector | Propagates a value across an action boundary without a separate flow object |
succession / first/then | Succession (a Connector) | Source must finish before target may start; models temporal ordering |
if / else / merge | Decision / merge ControlNode | Conditional branching; merge recombines branches into shared continuation |
fork / join | Fork / join ControlNode | Fork: activate all simultaneously; join: wait for all to complete |
loop | Guarded Succession cycle | Repeats body while condition holds |
state def | StateDefinition (specialises ActionDefinition / BehaviorDefinition) | Reactive, event-driven behaviour; entry/do/exit actions per state |
transition | TransitionUsage (a Succession) | Adds trigger, guard, and effect to a succession between states |
accept | AcceptActionUsage | Waits for a signal or message before proceeding |
send | SendActionUsage | Dispatches a signal or message to another element |
occurrence def | Occurrence (KerML Occurrence layer root) | Most general type of happening; base for action def, state def, etc. |
snapshot | Structural projection at a time instant | Asserts structural conditions (pre/postconditions) on an occurrence |