In today’s video blog I am going to cover the often overlooked Stateflow Super Step semantic and how it interacts with Stateflow function calls and Simulink subsystems. This is the first in a two part series, in the second part I will show how I validate the behavior of the chart.
Many of my posts are prompted by questions from readers or issues that have arisen from my clients over the years. This one one comes from an engineering student, “What should I study if I want to go into Model-Based Design?”
One “post video” thought. Strictly speaking, the study of puns is not required to work in the field of Model-Based Design but study of the polymorphic nature of language can help you for the polymorphic behavior of models.
Over time the current best practices if unexamined run the risk of becoming “okay practices.” This is one of the reasons why the majority of MathWorks customers update their software roughly every 2.5 years.(1) While there are many metaphors for doing this the one I would choose for you will depend on where you are at…(2)
- Bootcamp: Are you new to Model-Based Design? In this case the review is an intensive ‘hit all the major areas’ to bring you up to speed as quickly as possible.
- Tune up: If you have been following a Model-Based Design process for a number of years then it is reviewing the major processes as well as focusing on any rough spots you may have detected.
- Refresh: Like the tune up, you are experienced with Model-Based Design but you are starting a new project. This gives you a ‘clean slate’ to bring new processes into play.
Before you get started, define a set of objectives (the “must have” and the “nice to have” improvements) as well as a time line(3) to complete the changes. From here, there are multiple paths forward.
Once you are done
Ok, really, once you are done
Before starting, the baseline objectives were set. Once those have been achieved, work should focus on the development of your product. Incremental improvements should be made over time but the focus should be on your core product. Rest assured when the next 2.5 year cycle comes around you can make your next round of improvements.
- There are two primary reasons for software updates; getting access to the latest version of tools (including new and improved features) and the chance to review existing workflows.
- One of the aspects of working as a consultant is that you are in a constant state of learning; every new customer brings new challenges and gives you another chance to examine how and what you recommend.
- Generally 3 months to complete the main work of a version migration is common; there will be some lingering tasks that involve the use of new technology which could push the total time out to 6 months.
- In reading this blog you are already doing this one!
- Note, as a general best practice when an outside person comes in this is a great chance to learn what other companies are doing (though take everything with a grain of salt, the other companies process may or may not have been good)
With this post I’m going to walk through a sample project demonstrating how Units in Simulink Models can be validated. Demonstrating each stage of the project development, providing insight into how and what I was thinking at each step along the way.
Stages of project development
There are 5 stages to project development
- Identification of need: What is the problem you are trying to solve?
- Review of existing solutions: Is there an existing solution that meets needs?
- Task identification/estimation: What are the tasks / steps that need to be completed and what is the effort (risk) to complete them?
- Implementation and testing: Following a ‘test as you go’ strategy develop the modules that you need
- Validation of solution: Does what you did in 4 solve what you needed in 1?
Stage 1: Identification of need
As of release 2019A Simulink provides
- Unit specification at the boundaries and through Simulink.Signal and Simulink.Parameter objects
- Unit checking at the boundaries of models (inports and outports)
While this is very useful (and you should always define your boundary conditions) for large models knowing what the units of interior signals would be beneficial.
Problem to be solved: determine the unit of all blocks internal to the model and use that information to validate the units at the boundaries / internal to the model.
What I wanted to be able to do was specify the unit types on the inports and outports and propagate the units through the model.
At this stage, depending on the complexity of the project, the high level requirements should be written; derived requirements will be written at the start of task 3.
Stage 2: Review of existing solutions
There are two classes of “existing solutions”. The first are solutions to “base” problem you are trying to solve; the second are solutions to the sub-tasks in the problem. In this instance we have already identified the extent of the solution to the “base” problem, the ability to check units at the boundaries of the model; for what we want this is insufficient.
For the sub-tasks the Simulink API’s provide the interface required to “decode” the model to propagate the information through the model.
Stage 3: Task identification/estimation
Depending on the size of the project task identification can be decomposed to a “function” based level or lower. For large projects the “function” may in fact be a collection of functions. As you start to identify the functions required reuse of the components should be taken into account. My first pass (almost always on paper) is in a “operation required / issues” format.
- Propagate unit information in the model:
- How to determine data/unit flow
- How to handle data merging blocks (buses and mux blocks)
- How to handle subsystems
- Calculate output units based on inputs:
- Define categories of block transformations
- Integration / derivative
- Handle effects of Parameter data types
- Define categories of block transformations
- Apply information to the blocks
- Units (note most blocks don’t have a “unit” field
- Status of block (assigned, unsigned, invalid)
- Check calculated units against assigned
- Simulink Signal objects
Having identified the tasks I now think about what goes into each step and if I have experience or near experience in coding it; in this case all of the tasks involved are close to things I have done before so I have faith in my estimates…. (For the record, I estimated 8 hours and it ended up taking me 7)
Step 4: Implementation and Testing
Step 4.1: Unit propagation
My first question was how to propagate the units through the model. I decided that a first, reasonable requirement was that all of the inports must have units defined. If I enforced that I could simple “walk forward” from the inports to the outport of the system.
The once that approach was selected it the implementation becomes clear; create an array of inports and trace outwards from them. As each new block is found tack it onto the end of the array removing the most recent from the list.
(Note: Since this is a demo project I am not, currently, doing anything with Mux or Bus blocks).
Step 4.2: Calculating units
The key to calculating the units is to realize that there are really only 3 fundmental operations.
- Cancellation: through either multiplication or division units are canceled.
- Matching: the operation (addition or subtraction) requires the input units to match
- Integration / derivation: a “cancellation” of time.
As you look at the code you will see that I have created “num” and “den” variables, these are for the numerator and denominators of the inputs. Additional, for the sake of a demo, I have restricted the number of block inputs to 2.
- In hindsight I didn’t actually need to find the numerator and denominator since much of what happens is through string clean up. However, conceptually, it was a required task).
- In this example I am not handling feedback loops through unit delays, however they could be treated as a special case of a “sum” or matching required block.
As I developed the code I also wrote some basic test points to validate that the behavior was correct. The most basic tests were to determine if the units, stored as strings by Simulink, could be converted to the num/den strings
In this case you can see that I tried to cover all of the ways in which data could be encoded. One thing to note, I did not implement “compound units”. E.g. if you put in N (for Newtons) I do not cancel that in the same way you would kg*m/s^2. To do that I would, I think, first expand all the compound units to their fundamental components and then cancel.
The final step in this process will be to validate the units at the outports. To indicate passing / failing outports I color code them “green” for pass and “red” for failed.
Step 5: Validation of the solution
The code, as implemented, provides a “taste” of the final solution. However, the way in which it was code is modular so as I want to add in new capabilities (support for additional blocks, muxs, buses, subsystems) the extensions will be easy to add. If you are interested I have included a copy of the code and sample model here.