Here is another frequently visited page on MATLAB Answers:How can I create an impulse (delta) signal in Simulink?The ProblemLet's first look at what Wikipedia has to say about the Dirac delta... read more >>

]]>"In mathematical analysis, the Dirac delta function (or δ distribution), also known as the unit impulse,[1] is a generalized function on the real numbers, whose value is zero everywhere except at zero, and whose integral over the entire real line is equal to one.[2][3][4] Since there is no function having this property, modelling the delta "function" rigorously involves the use of limits or, as is common in mathematics, measure theory and the theory of distributions."

In its ideal form, the impulse should have an infinite amplitude at t=0

and the area under the curve should be 1:

In other words, the Dirac delta function is a theoretical concept that cannot really be simulated.

Before seeing how to implement a Dirac delta function in Simulink, let's talk a bit about why would someone need that.

If you are looking into implementing an impulse or Dirac delta function, it's very likely that you want to compute the impulse response of a system. Computing the impulse response is a common way to characterize the dynamic response of a system. This is used in many areas like vibrations and acoustics.

As an example, let’s define a system with two poles, one at 5 rad/sec and one at 50 rad/sec.

sys = tf(12,[1 0.5 25]) + tf(100,[1 2 2500]);

figure

bode(sys)

As a reference, let's start with the impulse function from the Control System Toolbox to see how the system responds to an impulse.

tFinal = 5;

[y,t] = impulse(sys,tFinal);

figure

plot(t,y)

Let's now look at how something similar could be implemented in Simulink.

The implementation of an impulse in Simulink will probably be different if implemented fixed versus variable step. Let's begin with the fixed-step case.

With a discrete signal, the Hit Crossing block outputs a value of 1 for one time step when the specified hit crossing offset is crossed. To respect the Dirac definition that the area under the curve must be equal to 1, we can divide this signal by the sample time.

mdl = "impulse_ex_discrete";

open_system(mdl);

In this example, I want to trigger the impulse to happen when the output of the Digital Clock block crosses a specific value, let's say 1 second.

Using the same transfer function as in our previous example, we can see that the results match.

out = sim(mdl);

figure;

plot(t+1,y,'LineWidth',2) % Offset the time reference by 1 second

hold on

plot(out.yout{1}.Values)

legend('MATLAB','Simulink')

With a variable-step solver, there are a few subtle things that you need to take care of.

If what you need is an impulse at t=0, I recommend using the Step block. This will allow you to control the amplitude and duration of the pulse.

mdl = "impulse_ex_1";

open_system(mdl);

The important thing to decide is the value to use for the duration and amplitude of the impulse. Since this is impossible to generate an infinitely large amplitude with an infinitely small width, we need to pick a number.

Let's simulate the model with different values for the amplitude and width of the impulse. To respect the assumption that the integral of the pulse is 1, I make the amplitude the inverse of the duration.

p = [1e-6 0.1 1];

in = repmat(Simulink.SimulationInput(mdl),length(p),1);

for i = 1:length(in)

in(i) = in(i).setVariable('impulseDuration',p(i));

in(i) = in(i).setVariable('impulseAmplitude',1/p(i));

end

out = sim(in,'ShowProgress','off');

The key thing to realize is that the longer the duration of the impulse, the more it becomes a step instead of an impulse. In the Laplace world, an ideal Diract delta function has an amplitude of 1 for all frequencies, while a step has an amplitude of $1/\mathit{s}$. The longer the impulse, the less it excites high frequencies.

Looking at the results, we can see that the second mode at 50 rad/sec is significantly less excited when the duration of the step becomes longer.

figure;hold on;

plot(t,y,'LineWidth',2)

for i = 1:length(out)

plot(out(i).yout{1}.Values)

end

legend(['Ideal' arrayfun(@num2str, p, 'UniformOutput', false)])

While the definition of the Dirac delta function says it should return a non-zero value only at t=0, it can be useful to generate an impulse at other times.

As a first attempt, it would be tempting to use a pattern similar to the one used for fixed-step. The challenge here is that with a variable-step solver, we don't have direct control on the duration of the pulse generated by the Hit Crossing block.

Based on what I know from zero-crossing detection, I guessed a gain value of 1e14 for the amplitude of the pulse, but we can see that it's not quite right.

mdl = 'impulse_ex_2';

in = Simulink.SimulationInput(mdl);

out = sim(in);

figure;hold on;

plot(t+1.23456,y,'LineWidth',2)

plot(out.yout{1}.Values)

To control the duration of the impulse, it is possible to use the Hit Scheduler block. When the time to trigger the impulse is detected by the Hit Crossing block we do two things: First, the event TrigOn is sent to the Stateflow chart to initiate the impulse. Then the Hit Scheduler schedules a second event TrigOff to be sent to the chart after a specified amount of time to terminate the impulse.

mdl1 = "impulse_ex_2c";

open_system(mdl1);

If you prefer, you can slightly simplify the logic by using the Discrete-Event Chart from SimEvents. In that case, you would configure the Hit Crossing block to output a message instead of a signal. This message will wake up the chart, and the chart will keep the impulse on for a duration specified using after.

mdl2 = "impulse_ex_2b";

open_system(mdl2);

out1 = sim(mdl1);

out2 = sim(mdl2);

figure;hold on;

plot(t+1.23456,y,'LineWidth',2)

plot(out1.yout{1}.Values)

plot(out1.yout{1}.Values)

legend("MATLAB", "Hit Scheduler", "Discrete-Event Chart");

If you took the time to read the Wikipedia page on the Dirac delta function, you might have noticed that another option is to implement the impulse as a normal distribution in the form:

To implement that, I can use the same logic as before to initiate and terminate the pulse. Instead of just outputting an on/off signal, I can use an Enabled Subsystem to "play" the normal distribution function.

mdl = "impulse_ex_3_b";

open_system(mdl);

out = sim(mdl);

In this case, we can see that the results match what we got from the impulse function.

figure;

subplot(2,1,1)

plot(out.logsout.get('u').Values)

axis([1.236 1.244 -10 600]);

subplot(2,1,2)

plot(out.logsout.get('y').Values)

hold on% compare to reference

plot(t+1.23456,y)

Have fun implementing impulses or Dirac delta functions in your Simulink model. If you have other techniques, share in the comments below.

]]>

In 2016, we published this blog post simulating a pole vault jump. I decided to revisit this topic and demonstrate how I would simulate this using the latest features in Simulink.Pole Vault ModelHere... read more >>

]]>In 2016, we published this blog post simulating a pole vault jump. I decided to revisit this topic and demonstrate how I would simulate this using the latest features in Simulink.

Here is an illustration of what a pole vault jump looks like:

To simulate this event, we can divide the jump in three phases:

- Approach: During this phase the athlete tries to maximize his speed along the runway to achieve maximum kinetic energy
- Take off and swing up: The athlete positions the pole into the “box” to convert the kinetic energy into stored potential energy in the pole and swing up.
- Fly away: The vaulter releases the pole and falls back on the mat under the influence of gravity

In 2016, the way to model that was using a series of 3 If Action Subsystems. When switching from one phase to the next, we would transfer the states from one Subsystem to the next using the Integrator block state port and GoTo and From blocks.

This semantic had multiple imitations. Let's see my preferred way to implement the same equations in MATLAB R2024a.

Here is what my new model looks like.

mdl = "poleVaultSim";

open_system(mdl);

During the Run Up phase, I integrate the motion of the athlete running at a constant speed. Compared to the 2016 implementation, I am able to use the Second Order Integrator instead of two Integrator blocks, because the Second Order Integrator does not have a state port option.

During the Take Off, the motion of the athlete is computed in polar coordinate. This makes it simpler to solve the equations for the bending of the pole.

The important part to notice is what happens in the Simulink Functions. Using State Reader blocks, I can access the states of the Integrator blocks in the previous phase and compute the initial states of the next phase. I can then use State Writer blocks to initialize the Integrator blocks in the next phase.

When simulating the model, we can follow the evolution of the simulation through the Stateflow animation and the newly revamped XY Graph block, which is just a pre-configured instance of the Record block.

Let's see the impact on the jump of two variables:

- The stiffness of the pole
- The initial angle of the pole for the take-off phase

For that, I create two multisim variables and combine them using simulink.multisim.Exhaustive.

mdl = "poleVaultSim";

k_var = simulink.multisim.Variable("k", linspace(0.1,10,5));

theta0_var = simulink.multisim.Variable("theta0", linspace(10,50,5));

MyCombination = simulink.multisim.Exhaustive([k_var, theta0_var]);

d = simulink.multisim.DesignStudy(mdl,MyCombination);

d.PostSimFcn = @(simOut, simIn) myPostSim(simOut,simIn);

out = parsim(d,'ShowProgress','off','UseFastRestart','on');

I also create a post-sim function where I do two things:

- I store the input variables in the SimulationOutput object
- I process the logged data to compute the maximum height and distance of the jump

function simOut = myPostSim(simOut,simIn)

% Transfer input variables to SimulationOutput object

for i = 1:length(simIn.Variables)

simOut.(simIn.Variables(i).Name) = simIn.Variables(i).Value;

end

% Compute key performance indicators

simOut.maxHeight = max(simOut.logsout.get('y').Values.Data);

simOut.distance = abs(simOut.logsout.get('x').Values.Data(end));

Once the simulations complete, we can visualize results in multiple ways. Let's try a few things.

Let's begin by plotting all x-y timeseries:

figure;hold on;

for i = 1:length(out)

plot(out(i).logsout.get('x').Values.Data,out(i).logsout.get('y').Values.Data)

legendText{i} = ['k = ' num2str(out(i).k) ', theta0 = ' num2str(out(i).theta0)];

end

legend(legendText,'Location','northeastoutside');

Maybe a matrix of scatter plots would help visualize this data?

u = [[out.k]' [out.theta0]'];

y = [[out.maxHeight]' [out.distance]'];

figure;

plotmatrix(u,y);

or a 3d bar plot?

height = reshape([out.maxHeight],5,5);

figure

bar3(height);

In the end, this seems pretty clear that the lower stiffness and initial angle result in the higher jump.

Don't miss the actual pole vault competition at the Paris Olympic:

How would you simulate the pole vault competition? Let us know in the comments below.

]]>

With the Paris Olympics going on, I decided to revisit the simulation of the shot put event that we published in 2016. BackgroundI recommend visiting the 2016 blog post for more background on how we... read more >>

]]>With the Paris Olympics going on, I decided to revisit the simulation of the shot put event that we published in 2016.

I recommend visiting the 2016 blog post for more background on how we put decided to simulate this Olympic event. In short, at the shot put event the athlete needs to throw a "shot", a round weight, a far as they can within a specific zone. This is typically done by first spinning to generate momentum and then unwind and push the weight.

To implement that in Simulink, we used a series of solids and joints from Simscape Multibody. Here is what it looks like in the Mechanics Explorer:

Let's see how I started with the 2016 model and improved it using new features available in MATLAB R2024a.

The first thing I did when opening the model from R2016 is to run the Upgrade Advisor. The Upgrade Advisor is a useful tool that can identify potential enhancements to a model to take advantage of new features. In this case, it flagged 3 items:

The Upgrade Advisor was able to automatically apply the following changes:

- Configure the model to use the solver "daessc" for Simscape models with differential algebraic equations. This new solver is more robust to solve the type of equations produced by Simscape.
- Change the Solver Configuration block to use state-based absolute and relative consistency tolerances during initialization. Introduced in R2022b, this provides better robustness and efficiency during the initialization, especially when using Simscape nominal values.

- Update Simscape physical signal blocks to propagate units, which was not possible in 2016. In my case, for example, it set the unit of the PS Constant block to "rad/s" because that's what the Revolute Joint downstream expects.

After just a few clicks, the model was ready to use in MATLAB R2024a.

In 2016, in order to keep the shot in the hand of the athlete, we had to implement a custom force rule that would be disabled at the time of releasing the shot. This was not ideal because this force rule was computationally expensive and making the simulation slow.

So the first improvement I did to the model is leveraging the "mode" property of Simscape Multibody joints. This feature, introduced a few releases ago, allows any joint to be locked or unlocked based on an input signal.

This adds an input port to the Joint block that I can control from my Stateflow chart.

Another feature added to Simscape Multibody that I like is the possibility to add additional frames to the Solid blocks. For each section of the arm, I defined frames at both ends of the limb.

That way, I can get rid of the Rigid Transform blocks that had to be used before. There is nothing fundamentally wrong with using Rigid Transform, but I find adding frames to the Body block makes the model easier to understand at first look.

With those changes, here is what the model looks like:

The last change I made to the model is in the Sensing subsystem. In 2016, we had to use Transform Sensor blocks and PS-Simulink blocks to get the information we needed out of Simscape Multibody. In R2024a, we added the possibility to directly log Simscape variables as if they were Simulink signals.

When selecting a Simscape block, go to the Simscape Block tab in the toolstrip and enable Log Variables. In the Model Data Editor, you will see a Simscape Variables tab appear where you can select which variables to log and give them the name you desire.

When simulating the model, they will show up in the "logsout".

mdl = "ShotPut";

out = sim(mdl);

out.logsout

With those changes done, I decided to study the impact of some parameters on the simulation results. For that, I can use the new Design Study introduced in R2024a.

First, I specified a variable shoulderAngle in the Rigid Transform block controlling the shoulder angle and marked it as Run-Time tunable, so I can tune it when the model is simulated in Fast Restart mode.

I created a design study with an array of 10 values from 45 degrees to 135 degrees.

ShoulderAngleVar = simulink.multisim.Variable("shoulderAngle", linspace(45,135,10));

d = simulink.multisim.DesignStudy(mdl,ShoulderAngleVar);

out = parsim(d,'ShowProgress','off','UseFastRestart','on');

figure

hold on

for i = 1:length(out)

plot3(out(i).logsout.get('x').Values.Data,...

out(i).logsout.get('y').Values.Data,...

out(i).logsout.get('z').Values.Data)

end

view([-95.14 19.80])

axis equal

Don't miss the shot put events at the Paris Olympics:

Are you using the Upgrade Advisor when upgrading to new MATLAB releases? Are you taking advantage of the new features add to Simscape and Simulink? Have you tried the new Design Study? Let us know in the comments below.

]]>

Let's look at another frequently visited MATLAB Answers page:Derivative of state '1' in block 'X/Y/Integrator' at time 0.55 is not finite.The ProblemHere is a simple model similar to the one I have... read more >>

]]>Here is a simple model similar to the one I have been using recently in multiple posts.

mdl = "suspension";

open_system(mdl);

When simulating the model, we get the same error as reported in MATLAB Answers:

in = Simulink.SimulationInput(mdl);

in = in.setModelParameter('Stoptime','500');

in = in.setModelParameter('CaptureErrors','on');

out= sim(in);

out.ErrorMessage

This error can be triggered by multiple reasons. Before diving into the reasons, I would like to highlight the tools that are the most likely to help you diagnose this type of issue.

In the Explore Gallery, launch the States Explorer.

This will allow you to quickly scan all the states in the model and identify which states are diverging:

Another useful tool is to Highlight Signal to Source the signal entering the block reported in the error message:

Once enabled, use the arrow keys to highlight the upstream blocks feeding the integrator and try understanding the logic making the equations unstable.

The Simulink Debugger allows you to step block by block during a simulation, which can be useful to diagnose this kind of issue.

First, select the blocks upstream of the block listed in the error message and enable Port Value Display.

Select the signal entering the problematic block and add a breakpoint. You have the option to break on Inf or NaN, but I recommend breaking earlier to better observe what happens before the error.

Click Run and when the breakpoint is hit, you will be able to step block by block to try identifying the problem with the equations in your model.

Let's now look at the most common situations leading to this error.

The most common reason for this error is that equations in the model are unstable. This usually happens if the algorithm has been implemented incorrectly, or if you are simulating a system that is truly unstable.

It can be useful to plot the state mentioned in the error message to see that it diverges toward infinity:

plot(out.xout.get('dx').Values)

In this simulation, the size of the model makes it easy to identify the problem. Here is an animation where I enabled port value display for all blocks and I am slowly stepping the model forward so we can see the evolution of each signal. Notice how the values are increasing at each time step:

The implementation mistake here is that signs specified in the Sum block result in a positive feedback loop. To solve the problem and make this simulation behave as the mass-spring-damper it is trying to model, we need to make the signs of the feedback signals entering the Sum block negative.

in = Simulink.SimulationInput(mdl);

in = in.setBlockParameter('suspension/Sum','Inputs','+--');

out = sim(in);

plot(out.xout.get('dx').Values)

As described in the error message, one possible reason for this error is the solver taking too large steps. This typically happens when using fixed-step solver, which is necessary to generate code and deploy to real-time systems.

Here is a slightly different version of the model.

mdl = "suspensionFixedStep";

open_system(mdl);

I fixed the signs of the Sum block to make the equations stable, but I changed the solver to ode3 with a step size of 1 second.

I will simulate the model with larger values for k and c, making the system dynamic fast and impossible to capture properly with the step sized of 1 seconds.

in = Simulink.SimulationInput(mdl);

in = in.setModelParameter('CaptureErrors','on');

in = in.setVariable('k',1e5);

in = in.setVariable('c',100);

out = sim(in);

out.ErrorMessage

There are multiple ways to analyze the system and decide how to deal with this error.

A first approach is to analyze the equations in the model. This is obviously easier if the model is small. In this example, we have a mass-spring-damper system. The natural frequency of this system can be computed analytically using:

omega_n = sqrt(k/m)

This means that the system will oscillate with a period of:

T = 2*pi/omega_n % oscillation period in seconds

To capture this oscillation accurately, we need at least a minimum number of points per oscillation.

Another approach to study the dynamics of the equations in your system is to linearize it using Simulink Control Design.

linsys = linearize(mdl);

We can then extract the natural frequency using damp. Thanks to MATLAB GPT for reminding me the existence of damp.

[wn, zeta, p] = damp(linsys);

T_lin = 2*pi/max(wn) % oscillation period in seconds

When getting this error with a fixed-step solver, one option is simulating the model with a variable-step solver. First, this gives you a good reference in terms of accuracy.

in = Simulink.SimulationInput(mdl);

in = in.setModelParameter('SolverType','Variable-step');

in = in.setModelParameter('StopTime','0.2');

in = in.setVariable('k',1e5);

in = in.setVariable('c',100);

outVarStep = sim(in);

figure

plot(outVarStep.xout.get('dx').Values);

Second, seeing what time steps the variable-step solver is taking can be useful to pick a fixed step-size. The Solver Profiler has a Step Size plot that can help with that. In this case, we can see that the variable-step solver needs to take steps slightly smaller than 0.01 second.

Once you better understand the system dynamic, it's time to look into solutions.

Let's try simulating the model with different fixed-step size and see what the results look like.

ts = [0.0005 0.001 0.002 0.005 0.01];

clear in

in(1:length(ts)) = Simulink.SimulationInput(mdl);

for i = 1:length(ts)

in(i) = in(i).setModelParameter('FixedStep',num2str(ts(i)));

in(i) = in(i).setModelParameter('StopTime','0.2');

in(i) = in(i).setVariable('k',1e5);

in(i) = in(i).setVariable('c',100);

end

out = sim(in,'ShowProgress','off');

Looking at the results, we can see that they become less and less accurate as the step size increase. If simulated for a larger stop time, the last step size of 0.01 would eventually error out with the infinite derivative error.

figure;hold on

plot(outVarStep.xout.get('dx').Values,'linewidth',2);

for i = 1:length(ts)

plot(out(i).xout.get('dx').Values)

legendLabel{i} = ['Ts = ' num2str(ts(i))]; %#ok<SAGROW>

end

axis([0 0.2 -2e-3 2e-3])

legend([ 'Variable-Step' legendLabel]);

The solver being used can also impact the accuracy of the results. The higher the order, the more computationally expensive, but also the more accurate a solver is.

solvers = {'ode1','ode3','ode5','ode1be'};

clear in

in(1:length(solvers)) = Simulink.SimulationInput(mdl);

for i = 1:length(solvers)

in(i) = in(i).setModelParameter('FixedStep','0.005');

in(i) = in(i).setModelParameter('StopTime','0.5');

in(i) = in(i).setModelParameter('Solver',solvers{i});

in(i) = in(i).setVariable('k',1e5);

in(i) = in(i).setVariable('c',100);

end

out = sim(in,'ShowProgress','off');

Here we can see that ode1 is unstable while ode5 gives results close to the variable-step solver. Ode1be is an implicit solver that is especially good at remaining stable when solving stiff systems.

figure;hold on

plot(outVarStep.xout.get('dx').Values,'linewidth',2);

for i = 1:length(solvers)

plot(out(i).xout.get('dx').Values)

end

axis([0 0.2 -2.5e-3 2.5e-3])

legend([' Variable-Step' solvers]);

In some cases, real-time constraints can make it impossible to use a larger step-size or a more accurate solver. In such case, the solution is most likely to try simplifying the system equations or to soften the dynamics.

The Simscape documentation has an extensive section on techniques to adapt a model for real-time simulation: Real-Time Simulation. Many of those techniques are not Simscape-specific and also apply to any Simulink model.

This one might sound obvious, but if the equations in the model return Inf and this Inf is passed to an Integrator block, you will get this error. One common reason for that is a division by zero.

mdl = "example3";

open_system(mdl);

in = Simulink.SimulationInput(mdl);

in = in.setModelParameter('CaptureErrors','on');

out = sim(in);

out.ErrorMessage

To diagnose this, I recommend using the Simulink Debugger. Setting a breakpoint on Inf or NaN will stop the simulation at the first block where the Inf is generated.

In this case, the solution is to modify the equations to avoid feeding Inf to Integrator blocks.

Have you run into problems with infinite derivative error? Let us know in the comments below.

]]>

I recently ran into a report of the most visited entries on MATLAB Answers. I looked at the ones involving Simulink and thought it would be interesting to cover some of those on this blog. While most... read more >>

]]>I recently ran into a report of the most visited entries on MATLAB Answers. I looked at the ones involving Simulink and thought it would be interesting to cover some of those on this blog.

While most questions have direct answers, I think this is a good opportunity to provide additional background and cover some subtleties not addressed on MATLAB Answers.

This week, I am starting with the most visited:

Before giving you my answer to this question, I want to encourage you to visit the documentation page Run Simulations Programmatically. It covers in details into all the options available and their implications.

Now, let's go with my shorter informal version.

To me, simulating a model programmatically boils down to the four following options:

- Sim with model name: Passing the model name to the sim command. It's simple and works for many use cases.
- Sim with Simulation Input object: Passing a Simulink.SimulationInput object to the sim command. The most versatile and scalable approach.
- Simulation object: Introduced in R2024a, the Simulation object provides an interface to control the simulation execution: start, step, stop and tune parameters
- Old and Discouraged: Older syntaxes that are still available for backward compatibility, but that you should avoid

If you have a Simulink model that simulates using the Run button, the quickest and simplest way to simulate it from MATLAB is probably to call the sim command and pass it the model name.

For example, I have a model saved as suspension.slx.

mdl = 'suspension';

open_system(mdl)

I can simulate it by first defining the data it needs in the MATLAB workspace and then calling sim:

out = sim(mdl)

All the logged data is contained within the variable out, which is a Simulink.SimulationOutput object. For example, if I want to plot the velocity computed by the Integrator block, I can execute:

plot(out.yout.get('dx').Values)

If you try this with your model and sim returns a vector instead of a Simulation Output object, see the Old and Discouraged section below.

While the above approach works in many cases, I recommend a slightly different approach. As described by Reid Spence in this comment, specifying a Simulink.SimulationInput object and passing it to the sim command offers a lot of advantages:

- Explicitly specify variables, signals, states and parameters used for the simulation
- Straightforward transition to parallel simulations using parsim, batchsim and Simulink Compiler

I expect that additional features to be released in future versions of Simulink will also be based on use of the Simulation Input object, so I encourage you to start using it today.

In its simplest form, using a Simulation Input object adds only one line of code to the previous approach:

in = Simulink.SimulationInput(mdl)

You can then pass this to the sim command:

out = sim(in);

The main advantage of the Simulation Input object is that it explicitly specifies what is being passed to the sim function. For example, let's modify the previously created object by specifying:

- A different stop time:

in = in.setModelParameter('StopTime','20');

- A different value for the variable k:

in = in.setVariable('k',20);

- A signal for the root-level Inport block:

ds = createInputDataset(mdl);

ds{1} = timeseries([0 0 1 1],[0 10 10 20]);

in = in.setExternalInput(ds);

- The initial states of the Integrator block:

x0 = Simulink.BlockDiagram.getInitialState(mdl);

x0{1}.Values.Data(2) = 0.1;

in = in.setInitialState(x0);

I can then simulate the model and plot the results:

out = sim(in);

plot(out.yout.get('dx').Values)

In R2024a, we introduced the Simulation object. This object allows you to programmatically start, pause, step and tune block parameters in the same way as you would do while interacting with the Simulink editor.

Here is an example that runs the simulation between 0 and 5 seconds with variable c set to 0, and then runs it between 5 and 10 seconds with c equal to 10:

sm = simulation(mdl);

setVariable(sm,'c',0);

step(sm,PauseTime=5);

setVariable(sm,'c',10);

step(sm,PauseTime=10);

out = stop(sm);

plot(out.yout.get('dx').Values);

At this point, I need to cover approaches that we want to discourage. We are providing those for backward compatibility, but we discourage using them because they come with many limitations and usability issues.

If you see one of those being used, I strongly encourage you to convert your code to use the Simulation Input object as described above.

Programmatically, this option can be disabled using:

set_param(mdl,'ReturnWorkspaceOutputs','off');

Once this is done, you can call the sim command without output arguments:

sim(mdl)

Once the simulation complete, you will see the individual parameters specified in the Data Import/Export section of the configset magically appear in the MATLAB base workspace.

logsout

Another even older syntax that still exists only for backward incompatibility is this one, where the sim command returns 3 outputs for time, states, and outputs:

[t,x,y] = sim(mdl);

Once again, I recommend avoiding those and use the Simulation Input object instead.

If you are planning to run multiple simulations, I recommend creating an array of Simulation Input object and passing it to the sim command. Let's run our example for multiple damping values:

% Setup an array of SimulationInput objects

in(1:5) = Simulink.SimulationInput(mdl);

for i = 1:length(in)

in(i) = in(i).setVariable('c',i);

end

% Simulating

out = sim(in,'ShowProgress','off');

% Visualizing results

figure;hold on

for i = 1:length(out)

plot(out(i).yout.get('dx').Values);

end

To run this code in parallel, all you need to do is replace the call to sim with parsim or batchsim.

Simulations can be launched from multiple contexts: MATLAB Scripts, MATLAB Functions, MATLAB Classes, App Designer apps, etc. For your model to be easily run from any context, I recommend associating with your model a set of default values for all the parameters. This is typically done in two ways:

For more details on this topic, I recommend visiting: Determine Where to Store Variables and Objects for Simulink Models.

With that setup, it makes it easy to simply open the model and hit Ctrl+D to do an update diagram, or click Run to simulate it without the need to run any code. This also makes it easy to run functions like Simulink.BlockDiagram.buildRapidAcceleratorTarget or slbuild.

When times come to simulate the model, you can create Simulation Input objects to specify the data that needs to change from the default values associated with the model as illustrated above.

Have you adopted the Simulink.Simulation object? What's your preferred way to run simulations from MATLAB? Which challenges are you encountering when simulating models form MATLAB?

Let us know in the comments below.

]]>MATLAB R2024a is now available, and a lot of new important features have been added to Simulink. Here are my top 5.Simulation objectUsing the Simulation object, you can programmatically run a... read more >>

]]>MATLAB R2024a is now available, and a lot of new important features have been added to Simulink. Here are my top 5.

Using the Simulation object, you can programmatically run a simulation step by step. You can execute the simulation one step at a time, for a specified number of steps or up to a specific time. Here is an example where I simulate the model up to t=18.5 seconds, then I change the value of variable k and continue the simulation until the stop time:

mdl = 'vdpX';

sm = simulation(mdl);

% Run the first part of the simulation with k=0.2

sm.setVariable('k',0.2);

step(sm,PauseTime=18.5);

% Run the second half with k=1.5

sm.setVariable('k',1.5);

step(sm,PauseTime=40);

out = terminate(sm);

The new Design Study API provides a layer on top of parsim and batchsim to improve scalability. Instead of creating an array of Simulink.SimulationInput objects, you specify arrays of values to be simulated, and how they should be combined. Here is a simple example where I simulate a mass-spring-damper system for different mass and damping values.

I specify 5 mass values and 5 damping values, and simulate an exhaustive combination for a total of 25 simulation

mdl = 'simple_system';

kVar = simulink.multisim.Variable('c',1:5);

cVar = simulink.multisim.Variable('m',1:5);

fullSpace = simulink.multisim.Exhaustive([kVar cVar]);

myDesignStudy = simulink.multisim.DesignStudy(mdl, fullSpace);

outH = parsim(myDesignStudy,'ShowProgress','Off','UseFastRestart','on');

out = fetchOutputs(outH);

A new VariantConfiguration property has been added to the Simulink.SimulationInput object. Here is an example code where I get the variant configuration data for a model and run one simulation per available configuration:

mdl = 'sldemo_variant_subsystems';

load_system(mdl);

load('variantConfigs.mat'); % load pre-saved variant configuration data

vcd = Simulink.VariantManager.getConfigurationData(mdl);

N = length(vcd.Configurations);

in(1:N) = Simulink.SimulationInput(mdl);

for i = 1:N

in(i) = in(i).setVariantConfiguration(vcd.Configurations(i).Name);

end

out = sim(in,'ShowProgress','off');

Before R2024a, if you wanted to programmatically change the value of a parameter stored in a data dictionary, you had to write code like this:

myDictionaryObj = Simulink.data.dictionary.open('simplesystemDD.sldd');

dDataSectObj = getSection(myDictionaryObj,'Design Data');

kObj = getEntry(dDataSectObj,'k');

k = getValue(kObj);

k = k+1;

setValue(kObj,k);

h = Simulink.data.connect('simplesystemDD.sldd');

h.k = h.k+1;

Let's close this list with a simple quality-of-life editing improvement. This is not a game-changer like some of the previous highlights but will hopefully improve your editing experience.

When selecting a block, you might notice a light green highlighting on connections and blocks around it. This means that we have detected that those connections and blocks should likely move with the blocks.

Same works with resizing:

Have a look at the Simulink release notes for R2024a. Let us know your favorite feature and which ones you would like to see highlighted on this blog.

]]>MATLAB R2024a has been released recently, so I thought I should share my favorite new addition to Simulink: The ability to add emojis everywhere!As you probably know, it has been possible for many... read more >>

]]>MATLAB R2024a has been released recently, so I thought I should share my favorite new addition to Simulink: The ability to add emojis everywhere!

As you probably know, it has been possible for many releases now to include emojis in the comments of MATLAB code:

It is now possible to use emojis in Simulink too!

When you are editing the name of a block or an annotation, try hitting the shortcut "Win+." (or Cmd-Ctrl-Space for Mac OS) to launch the emoji dialog:

Those will not only show up in the editor canvas, they will follow along through your entire workflow.

Stateflow also supports emojis in comments:

Let's look at simulation results in the Simulation Data Inspector:

If you generate code using Embedded Coder, emojis will show up in the generated comments:

The Finder also supports searching for emojis in a model:

If you end up using emojis incorrectly, you will get a clear error. For example, I tried using the "automobile" emoji instead of typing "auto" for a configuration parameter. (Unfortunately we are not evaluating emojis yet... )

I get a clear error:

Obviously, emojis are not the greatest addition in Simulink in R2024a... I will follow up in a few days with a post covering my real favorites of R2024a.

Final disclaimer for Simulink Check users: Before you start adding emojis everywhere in your Simulink models, you might want to know that they are not yet approved by the MathWorks Advisory Board Guidelines for blocks and signals names. Let us know in the comments below if you think they should!

]]>On this π day 2024, I decided to tag along with Mike Croucher from The MATLAB Blog and show one way to compute π.While Mike went for advanced maneuvers involving the MATLAB AI Chat Playground,... read more >>

]]>On this π day 2024, I decided to tag along with Mike Croucher from The MATLAB Blog and show one way to compute π.

While Mike went for advanced maneuvers involving the MATLAB AI Chat Playground, Parallel Computing Toolbox, and even Quantum Computing, I decided to go with the way our ancestors would have done thousands of years ago: by rolling a cylinder. See method 1 in this WikiHow article for more details.

Using Simscape Multibody, I connected a Planar Joint and a Cylinder Solid together. I let the Cylinder fall on an Infinite Plane and used the Spatial Contact Force block to compute the contact dynamic between those two:

mdl = 'ComputePi';

open_system(mdl);

I used Motion Actuation to roll the cylinder by 360 degrees and sensed by how much it had translated. I was then able to compute π using:

$$\pi =\frac{\mathit{d}}{2\mathit{r}}$$

where d is the distance travelled and r is the radius of the cylinder.

in = Simulink.SimulationInput(mdl);

out = sim(in);

r = 1; % Cylinder radius;

d = out.yout{1}.Values.Data(end); % final distance

pi_estimate = d/(2*r)

Because the cylinder slipped a bit on the ground, I did not get a very accurate result, but it's probably representative of the result you would get if you had tried computing π that way a few thousand years ago.

Hopefully, you can find more accurate ways to compute π.

If you need to model cylinders rolling on the ground, try opening the model used for this blog post in MATLAB Online by clicking on this banner:

]]>The MathWorks Certification Program recently released a new certification: Simulink Associate.With this certification, you will be able to demonstrate your Simulink proficiency to colleagues,... read more >>

]]>With this certification, you will be able to demonstrate your Simulink proficiency to colleagues, industry peers and potential employers.

We carefully designed the certification such that it validates the skills most organizations seek in successful and productive Simulink users.

To be certified, you will need to register and pass an online test with 42 multiple-choice questions. If you want to get a feeling of what those questions look like, see the sample exam questions. Here is one example:

Before taking the test, I also recommend looking at the list of topics covered in the test. This will help you determine if you need to learn new features and maybe sign up for training before taking the test.

Once you are done, you will be able to show off your achievement through a digital credential. Anyone earning the certification will receive this credential through Credly, which can then be shared with employers or on your LinkedIn profile.

Give a look at the exam information and recommended preparation on the MathWorks Certification Program page and register for the certification once you think you are ready.

]]>A few weeks ago I published this blog post: Getting the most out of Rapid Accelerator mode – Version R2023b, where I described how to simulate a model multiple times in Rapid Accelerator mode for... read more >>

]]>A few weeks ago I published this blog post: Getting the most out of Rapid Accelerator mode – Version R2023b, where I described how to simulate a model multiple times in Rapid Accelerator mode for maximum performance using the parameter RapidAcceleratorUpToDateCheck='off'.

In this previous post, I was tuning the value of a Gain block. This week I received the question: Can I do the same for a parameter of type popup?

I have this model with a masked subsystem that has a popup parameter. Under the mask, the variable associated with the popup, choice, is used to control what type of noise is added to the signal:

If I try to simulate the model as described in the previous blog post, I get an error saying that it's not possible to use setBlockParameters and RapidAcceleratorUpToDateCheck='off' at the same time:

mdl = 'testNoise';

blk = [mdl '/AddNoise'];

in(1:3) = Simulink.SimulationInput(mdl);

for i = 1:3

in(i) = in(i).setModelParameter(SimulationMode='Rapid');

in(i) = in(i).setModelParameter(RapidAcceleratorUpToDateCheck='off');

end

try

in(1) = in(1).setBlockParameter(blk,'choice','Random');

catch ME

ME.message

end

The solution to this is described in the documentation page Tune Mask Enumeration Parameters - Popup and Radio Button. I find this page is a bit long and complex, so I will try to summarize the process here.

The first thing you need to do is associate an enumeration with the popup parameter. For this example, the enumeration is:

classdef noise < Simulink.Mask.EnumerationBase

enumeration

Random (1,'Random')

Pulse (2,'Pulse')

Sequence (3,'Sequence')

end

end

I then associate it with the parameter in the Mask Editor by double-clicking on the Type options field:

In the Subsystem under the mask, I need to modify how the variable is specified in the block dialog. For this example, instead of using the variable choice directly, I need to specify noiseValues(choice). The documentation explains the syntax, but in short you begin with the enumeration name (noise in this example) and you append "Values" to it. Then you pass to it, between parenthesis, the popup variable (choice in this example):

If you create the masked Subsystem that way, you will notice that the dialog has a new "Associate Variable" option:

This will open a dialog to specify the variable and optionally create it if it does not exist. For this example, I will create it myself:

noiseType = noise.Random;

Once you click ok, in the block dialog, you will see the variable name and the enumeration type next to it:

And that's it, now it's time to simulate the model:

mdl = 'testNoiseTunable';

in(1:3) = Simulink.SimulationInput(mdl);

for i = 1:3

in(i) = in(i).setModelParameter(SimulationMode='Rapid');

in(i) = in(i).setModelParameter(RapidAcceleratorUpToDateCheck='off');

end

in(1) = in(1).setVariable('noiseType',noise.Random);

in(2) = in(2).setVariable('noiseType',noise.Pulse);

in(3) = in(3).setVariable('noiseType',noise.Sequence);

out = sim(in,'ShowProgress','off');

Once the simulation completes, we can plot the results and confirm that the parameter has been tuned:

plot(out(1).yout{1}.Values);

hold on

plot(out(2).yout{1}.Values);

plot(out(3).yout{1}.Values);

hold off

legend({'Random','Pulse','Sequence'});

If you are creating masked library blocks with parameters of type popups, be nice to your users and associate the popup with an enumeration type. This will enable them to tune it in Rapid Accelerator optimally. This will also enable the parameter to be tuned if the model is deployed with Simulink Compiler.

]]>