Advent of SysML v2 | Lesson 21 – Week 3 Recap

Hello and welcome back to the Advent of SysML v2 – a daily, hands-on mini-course designed to bring you up to speed with the new SysML v2 standard and the modern Syside tooling that makes you productive from day one.

By the end of this lesson, we’ll recap and synthesize everything we’ve learned in Week 3, showing how static models transform into computational engines, behavioral specifications, and Continuous Integration and Continuous Delivery/Deployment (CI/CD) pipelines performing automated verification.

  1. Expression Evaluation with Automator
  2. Value Rollups and Advanced Calculations
  3. Actions and Successions
  4. State-Based Behaviors
  5. State Machine Simulation
  6. CI/CD for SysML v2 Models

The Week 3 Journey

Week 3 marked a fundamental shift in how we work with SysML v2 models. In Weeks 1 and 2, you learned to describe systems: their structure, connectivity, and relationships. This week, you learned to analyze and execute them.

Your models are no longer static documents. They’re computational engines that evaluate values, behavioral specifications that can be simulated, and artifacts in automated pipelines that validate themselves on change.

The progression was deliberate:

  • Lessons 15-16 (Analyze): Transform models into computational engines
  • Lessons 17-18 (Behave): Model what systems do and how they react
  • Lessons 19-20 (Automate): Simulate, validate, and automate everything

Evaluating Models Programmatically

Week 3 began with a crucial realization: there’s a fundamental difference between viewing a model and computing its values.

It’s like the difference between reading a recipe and actually cooking the meal. A recipe says “add 2 cups of flour”, but when you cook, you’re actually measuring and mixing. The same applies to models: you can read that a sleigh has a weight attribute, but evaluating tells you the actual number.

Feature Evaluation: From Definitions to Computed Values

In Lesson 15, we learned to evaluate features programmatically using Syside Automator.

Viewing a definition tells you: “Reindeer has a weight attribute with a default value of 110 kg.”

Evaluating a usage computation tells you: “This specific reindeer, Rudolph, weighs 100 kg.”

The evaluation pattern depends on the value type. Simple values (numbers, strings) give you a direct value you can use immediately. Complex values (structures) return a model element, which means you need to evaluate its features to get the actual data. In practice, this means you sometimes need to “unwrap” complex values by evaluating their nested features.

When you get a model element back instead of a value, just call .evaluate() on its features to drill down to the actual values.

Evaluation Scope: The Key to Understanding Specialization

Imagine asking, “What does a reindeer weigh?” The answer depends on which reindeer you’re asking about. Rudolph weighs 100 kg, but a generic reindeer defaults to 110 kg. Same question, different answers.

The difference is scope. The same feature evaluated with different scopes gives different results:

1
2
3
# Same feature, different scopes
reindeer[“weight”].evaluate(scope=reindeer)  # 110 kg (default)
reindeer[“weight”].evaluate(scope=rudolph)   # 100 kg (override)

This is how SysML v2 specialization actually works at runtime. The scope tells the evaluator which specialization’s values to use.

Always ask yourself, “whose values do I want?” That’s your scope. Wrong scope = wrong values. The most common mistake when starting with programmatic evaluation is forgetting to set the scope and getting default values instead of the specialized ones.

The Syside CST Explorer helps you discover property names for your automation scripts.

Advanced Calculations: Models as Analytical Engines

Once you can evaluate individual values, the natural next question is: “What about the whole system?” Santa doesn’t just care about one reindeer’s power. He needs to know if the entire team can pull the sleigh. That’s where calculations come in.

In Lesson 16, we transformed models into computational engines with advanced calculations.

Collection functions let you ask questions about groups of things. Instead of manually adding up each reindeer’s power, you tell the model: “Give me the sum of everyone’s power.”

1
2
3
attribute reindeerCount = size(reindeer);
attribute totalPower = sum(reindeer.power);
attribute averagePower = totalPower / reindeerCount;

Three lines of SysML, and you’ve got count, total, and average. Use size() instead of hardcoding counts. When you add or remove parts, your calculations stay correct automatically.

Chained calculations are where things get powerful. In the real world, values depend on other values. You can’t calculate “load per reindeer” until you know “total weight.” And you can’t know if you’re within safety margins until you know the load. These dependencies form a chain.

You don’t have to manage this chain yourself. Just define the relationships, and Automator figures out the right order.

1
2
3
4
5
6
7
8
// Level 1: Base calculation
attribute totalWeight = sleighWeight + sum(reindeer.weight);

// Level 2: Depends on Level 1
attribute loadPerReindeer = totalWeight / reindeerCount;

// Level 3: Depends on Level 2
attribute safetyMargin = maxSafeLoad loadPerReindeer;

Conditional logic lets values adapt to the system state. Sometimes the answer isn’t a single number – it depends on circumstances. If the sleigh is heavily loaded, it should fly in “HeavyHaul” mode with a lower speed limit. If it’s light, it can fly “Agile” and go faster. The model can make this decision automatically.

1
2
attribute flightMode = if totalWeight> 2500 [kg] ? FlightMode::HeavyHaul else FlightMode::Agile;
attribute maxSpeed = if flightMode == FlightMode::Agile ? 140.4 [‘km/h’] else 70.2 [‘km/h’];

Your model is now an analytical engine – changing your model automatically updates all analyses without script maintenance.

Modeling Behavior

So far, we’ve modeled what systems are (structure) and what they calculate (values). But systems don’t just sit there – they do things. Santa’s sleigh takes off, flies to houses, delivers gifts, and lands. The reindeer controller monitors energy levels and adjusts commands. How do we model this?

With computational foundations in place, Week 3 turned to modeling what systems actually do.

Before diving into the details, here’s the key question:

  • Do I know the sequence upfront? Use actions.
  • Does my system wait for events and react? Use state machines.
  • Is it complicated? Use both: actions for what happens, states for when.

Actions and Successions: The Structure-Behavior Duality

Lesson 17 revealed a powerful insight: behavior models are built almost exactly like structure models. If you can model structure, you can model behavior — just think temporally instead of spatially. Replace “where is it?” with “when does it happen?”

Consider the parallels:

  • Parts exist in space; actions exist in time
  • A Sleigh contains a cargoBay; DeliverGifts contains steps
  • A harness connects parts; a succession orders actions
  • Part definitions create instances; action definitions create performances

Here’s what structure looks like:

1
2
3
4
part def Sleigh {
    part cargoBay : CargoBay;
    part team : ReindeerTeam;
}

And here’s the behavioral equivalent:

1
2
3
4
5
action def DeliverGifts {
    action prepareForTakeOff;
    action takeOff;
    action deliverPresents;
}

The patterns mirror each other. Once you internalize this duality, behavior modeling becomes intuitive.

Now let’s look at the building blocks.

Actions and parameters form the foundation. An action is something that happens; parameters are the data it works with:

1
2
3
4
5
6
7
action def ApproachHouse {
    in attribute address : String;
}

action def GetGift {
    out item gift;
}

Use in for inputs the action needs, out for results it produces, inout for values it modifies. Parameters are variables by default; add constant if the value shouldn’t change during execution.

Successions specify execution order. They’re how you say “do this, then do that.” Think of it like writing a checklist: first prepare for takeoff, then actually take off, then fly to the destination.

1
2
3
4
5
6
action def DeliverGifts {
    first start;
    then action prepareForTakeOff;
    then action takeOff;
    // …
}

Always start with first start; to mark where execution begins. Each then creates a succession from the previous action.

Control structures handle complexity. Real workflows aren’t always linear. You might need to repeat something for every child on the list, make a decision based on whether they were naughty or nice, or do two things at the same time. Use for loops to process collections (for child in children { ... }`), if actions for branching based on conditions, and fork/join when steps can happen concurrently. Note that concurrency ≠ parallelism. fork means threads execute independently (any ordering allowed), not necessarily at the same instant.

Sometimes you need to save a result for later. That’s where assignment comes in. Assignment actions store computed values:

1
2
ref item toGive;  // Local variable
assign toGive := selectGift.gift;  // Store result

Use ref features as local variables to store intermediate results. The assign action updates them during execution.

State Machines: Reactive Behavior

In Lesson 18, we introduced state machines for modeling how systems react to events. Many systems operate by continuously reacting to different events in their environment. The reaction is determined by the occurring event and the system’s history, encoded in its state. A state captures all the information that the system must memorize in order to decide how to react.

Use actions when you know the sequence upfront. Use state machines when the system waits for events and reacts differently based on its current state. If you’re struggling with actions, trying to figure out when things should execute, that’s a sign you need a state machine instead.

States and transitions form the core of state machines:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
state def ReindeerController {
    attribute reindeerCount : Integer;
    attribute totalPower subsets ISQ::power;
    ref port eyelet;
    ref port hmi;

    entry;
        then idle;
    state idle;
        accept StartMission via hmi
            if reindeerCount == 9 and totalPower >= 36 [SI::kW]
            do send new Command(“Gee-up!”) via eyelet
            then mission;
    state mission;
        accept EndMission via hmi
        then idle;
}

A complete transition has five parts: 

  • source state – where you are
  • trigger – accept, what event fires it
  • guard – if, the condition that must be true
  • effect – do, action to perform
  • target – then, where you end up

When a transition fires, it executes in this order: interrupt the source state’s do action, run its exit action, run the transition’s effect, run the target’s entry action, then start the target’s do action. Five steps: interrupt → exit → effect → entry → do.

Composite and parallel states enable hierarchical modeling. Real systems often do multiple things at once. While Santa’s sleigh is flying, one part of the controller monitors the reindeer’s energy levels, while another part manages the flight controls. These are separate concerns. Knowing whether reindeer energy is “nominal” or “low” doesn’t depend on whether the sleigh is “taking off” or “landing.” They change independently.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
state mission parallel {
    state monitoringReindeer {
        entry; then nominal;
        state nominal;
        state lowEnergy;
    }
    state controllingReindeer {
        entry; then takingOff;
        state takingOff;
        state flying;
        state landing;
        state waiting;
    }
}

Use parallel states when two aspects of behavior are orthogonal and change independently of each other. In the example above, reindeer energy monitoring and flight control are separate concerns that operate simultaneously.

Entry, exit, and do actions link behavior to states. When you enter a room, you might turn on the lights. While you’re in the room, you work. When you leave, you turn off the lights. States work the same way: you can define what happens when entering, what happens while you’re there, and what happens when leaving.

1
2
3
4
5
state lowEnergy {
    entry send new Status(“low energy”) via hmi;
    do action blinkLed;
    exit send new Status(“recharged”) via hmi;
}

The entry action runs when the state activates (useful for initialization and notifications). The `do` action runs while the state is active and can be interrupted. The `exit` action runs when the state deactivates (useful for cleanup).

What actually causes a transition to fire? That’s where triggers come in.

Four trigger types handle different event sources. Transitions don’t just happen. Something has to *trigger* them. Maybe it’s a command from the pilot (“start landing”). Maybe a sensor value crossed a threshold (altitude dropped below 10 meters). Maybe a timer expired (wait 60 seconds, then proceed). SysML v2 handles all of these:

  • reception triggers (`accept <Item> via <port>`) for responding to messages
  • change triggers (`accept when <condition>`) for reacting to value changes
  • relative time triggers (`accept after <duration>`) for timeouts
  • absolute time triggers (`accept at <time>`) for scheduled events

Change triggers are particularly powerful for monitoring thresholds. The transition fires automatically when the condition becomes true; no polling is needed.

With actions and state machines, you can model almost any behavior. But how do you know your model is correct?

Simulation and Automation

You’ve built a beautiful state machine. It looks right on paper. The transitions make sense. But does it actually work? Will the sleigh transition from “liftOff” to “flying” at exactly 20 meters altitude? Or did you accidentally write > instead of >= and now it never transitions at exactly 20?

There’s only one way to know for sure: run it.

The final theme of Week 3 brought everything together: making models executable and automating the entire verification workflow.

State Machine Simulation

In Lesson 19, we made behavior executable. Instead of hoping your state machine logic is correct, you can run it through scenarios and observe exactly how it behaves. Think of it like a dress rehearsal before opening night: actors don’t discover their blocking is wrong in front of a live audience.

The simulation pattern has three steps: extract the state machine structure from your SysML model using Syside Automator, load it into a simulation engine like Sismic, then run scenarios by triggering events and observing state transitions.

You play “what if?” scenarios: send a StartFlight command, set altitude to 32 meters, and check what state you’re in. Did the transition fire? If you expected flying but got liftOff, you know something’s wrong with your guard condition. The key insight: validation before implementation is vastly cheaper than debugging after.

There are two approaches:

  • Interactive mode for exploring behavior and debugging: step through manually, probe one transition at a time.
  • Scenario mode for validating complete workflows: run test sequences from a file, automated verification. Use interactive when designing, scenario when validating. Simulation results become the basis for your unit tests.

Simulation validates that command-driven transitions execute as expected, guard conditions fire at the right thresholds, composite states enter and exit correctly, and bidirectional transitions work without oscillation. Common issues it catches: wrong comparison operators (< instead of <=), missing transitions, threshold typos, and oscillation due to missing deadzones. All discovered before implementation, when they’re easy to fix.

CI/CD and Report Generation

In Lesson 20, we closed the automation loop. CI/CD (Continuous Integration and Continuous Deployment) automates quality checks on every change: validate the model, regenerate reports, update documentation.

This works because SysML v2 is textual (version-controlled with Git, processed automatically) and executable (Automator extracts any data you need). Combined with Sysand for package management, CI/CD completes your systems-as-code infrastructure.

The pipeline follows three steps:

  • Validate – check syntax and semantics
  • Generate – extract data and create reports
  • Publish – make updated docs available

If validation fails, the pipeline stops immediately. Different stakeholders get different views of the same model, all regenerated automatically from the source. Change the model, reports update on the next commit.

This is the same pattern that transformed software development, now applied to Model-Based Systems Engineering.

The Week 3 Shift: From Static to Automated

Let’s step back and see how far you’ve come.

  • Week 1 taught you what systems are: parts, features, specialization. You could describe a sleigh, its reindeer, its cargo bay.
  • Week 2 taught you how they work together: packages, connections, flows. You could show how reindeer connect to the sleigh, how gifts flow from workshop to delivery.
  • Week 3 taught you how to analyze, execute, and automate them. Now your models do things.

You started with static definitions. Now you have:

  • Computational models that evaluate values and resolve dependencies automatically
  • Behavioral specifications that define what systems do and how they react
  • Automated pipelines that validate, simulate, and report continuously

This is the shift from describing systems to engineering systems, where models become active participants in verification and validation.

Challenge

Bring together all three themes by extending your models:

  1. Computed attributes: Add weight rollups, safety margin calculations, and conditional logic to your sleigh model
  2. Action definition: Create a “PrepareForTakeOff” or “DeliverGifts” action with parameters, successions, and control structures
  3. State machine: Model sleigh operational modes (Parked, Flying, Landing) with transitions and events
  4. Automation script: Write a Python script using Syside Automator that evaluates your computed attributes, simulates your state machine, and generates a simple report

The goal is to experience the complete Analyze→ Behave → Automate workflow on your own models. This is Week 3 distilled into one hands-on exercise.

Summary

In Week 3, we transformed static models into dynamic, executable, automated systems:

  • Evaluated features programmatically with Syside Automator, understanding scope and specialization
  • Built computational models with value rollups, chained calculations, and conditional logic
  • Modeled behavior with actions, parameters, successions, and control structures
  • Created reactive systems with state machines for event-driven behavior
  • Simulated execution to validate behavior before building
  • Automated workflows with CI/CD pipelines and report generation

You now have the tools to create sophisticated SysML v2 models that don’t just describe systems, but analyze, execute, and verify them automatically. Keep practicing and happy modeling!

Cookies

Learn SysML v2 through the Advent of SysML v2 Challenge!