Suppose I have variable ii entering into the SIMULINK simulation from workspace and I would like to assign a new value for it after some condition is satisfied and save the value into a workspace. The values of variable could be defined in array, however, array length is not predefined. I see the block "MATLAB Function" could be useful, but is it proper way to evaluate just one simple command like ii=ii+1?
On the picture below started with ii=0, I expected the value of ii to be increased by one until tout>2 and its value to be saved accordingly. But I only got two values of ii: 1 till time of 2 seconds and 0 from time > 2 seconds on.
simulink_scheme
Usually you can use simple operations avoiding use of MATLAB Function Block. In your case there are different solutions. For example this way:
I load ii variable from workspace, check the condition in Switch block, and return new variable with the same name ii to workspace.
But! Important moment here is: to load data into Simulink with From Workspace block loaded data must be in special format: timeseries, matrix or structure. So you can't load just ii=1. And the same thing about To Workspace block - it returns data to workspace in timeseries, array or structure. This mean you take values of ii for every timestep of your simulation.
You can solve this problem using Decimation parameter in To Workspace block, then you can get only last value of ii. To get only value of ii without time column use Save format: Array in To Workspace block options. This let you get just 1 value as you wish. But, now you can simulate your program only 1 time: you load ii with time column (as it necessary for From Workspace block) and save just one value. Simulink can't load now ii because now it hasn't time column!
So the solutions depends on what you want.
P.S. One more advice to you: do not use just i variable! MATLAB has predefined variable i = 0.0000 + 1.0000i - imaginary unit.
I made some workaround this problem and get this example:
Where subsystem is:
Attention: To Workspace block save result as Array (avoiding time column). How it works: create ii=0 in workspace. Start simulation. While subsystem is enabled (t<=2) it will modify ii value in this way: increase ii at every timestep by 1. I mean:
t = 0, ii = 1
t = 1, ii = 2
t = 2, ii = 3
t = 3, ii = 3 ...
at the next simulation we load last value of ii array - ii(end) and continue simulation in the same way.
Related
For reading time-based data of variables from the Matlab workspace in Simulink (for time-based inter- and extrapolation), a typical solution is the use of the From Workspace block, by e.g. providing variable input data var in the following structure format:
var.time=[nx1]
var.signals.dimensions=m
var.signals.values=[nxm]
for providing the data of m variables with n time-based samples. Since variables' data is stored in a single matrix, it is implied that all variables are required to have the same (number of) time stamps.
If this is not the case, a solution could be the use of multiple From Workspace blocks, and corresponding variable input data structs (e.g. varA, varB, varC, etc.), like so:
However, this solution requires the number of variables to be fixed for all simulations. In my case, variables are numbered (rather than named) and the number of variables might not be the same from one simulation to the next. As such, for generalization purposes, I would like to find a solution without having to change the simulation file. A first step in this direction is the use of a struct array (i.e. var(1), var(2), var(3), etc.), which works:
A candidate next step is then to use a For Iterator to loop over N variables (and then to assign and concatenate the output in some output array, which I know can be done and is not the focus here):
The problem here is that the index id can't be fed to the From Workspace block! I ran into an identical issue when trying to solve the problem with a lookup table block. How to solve this problem of reading multiple but varying number of data variables from the workspace with different (number of) time stamps? Solutions that don't use a From Workspace or lookup table block are welcome too.
Here is equivalent code for running the whole thing in Matlab instead of Simulink:
% DEFINED IN MATLAB:
% Examplary input of variable data with different time stamps, according to
% Simulink structure conventions (.time, .signals etc)
N=3; % number of variables
for id=N:-1:1
var(id).time = linspace(0,2,id*2+2)';
var(id).signals.dimensions = 1;
var(id).signals.values = sin((var(id).time-id)*pi/2)';
end
% TO BE EXECUTED IN SIMULINK:
% the simulink clock time:
t = 1.234; % random time
for id=N:-1:1
var_t(id) = interp1(var(id).time,var(id).signals.values,t);
end
And here a figure to illustrate the results:
% Figure code:
figure(1),clf
colors=lines(N);
for id=1:N
plot(var(id).time,var(id).signals.values,'*-','color',colors(id,:)),hold on
plot(t,var_t(id),'o','color',colors(id,:))
end
xlabel('time'),ylabel('variable data')
Hello I'm building a exe from a simulink model and in order to do that I pass the inputs to it through a .mat file.
My question is, since in my model is present a "for each" block, how can I store the data in the .mat file? Normally (without the for each block) I would store the input as a constant vector in the workspace (see the upper part of the simulink model) and it will handle automatically how to pass the data during the simulation time. But in my case, since I want to export as .exe and pass the input programmatically, I need the input as .mat file and the presence of the "for each" block screw up the building the vector time (since is unclear how to combine time vector with data vector inside the .mat file because is unclear to simulink which data take at a given simulation time.
Thank you for any help!
It's not really clear what the specific problem you are having is.
In your upper diagram, the model will run when you have a variable
>> input = 1:3;
If you turn on Display->Signals & Ports->Signal Dimensions then you'll see that the signal coming out of the Constant block has a dimension of 3.
For the lower diagram, create a variable in MATLAB, that since it will be used in a From File block, must adhere to the specifications required for that block, which means the first row is a time vector, so
>> t = [0 10]
t =
0 10
>> u = [1 1;2 2;3 3]
u =
1 1
2 2
3 3
>> tu = [t;u]
tu =
0 10
1 1
2 2
3 3
And then save this variable to your file,
>> save input tu
Now the signal coming out of the From File block will also be of dimension 3.
Change the values of t and u to suit your specific problem.
I'm a super beginner in Simulink models and control systems.
I have .slx Simulink model for drone dynamics system.
It takes in two inputs (roll cmd, pitch cmd) and outputs velocity x, velocity y, position x, and position y.
From here, it seems like I can open the system by calling
open_system('myModel.slx', 'loadable');
But how do I put inputs and get output values?
Is there a way I can do this in a gui?
EDIT:
Here is the full layout of my model:
When I did
roll_CMD=10;
pitch_CMD=20;
I got a warning saying:
Input port 1 of 'SimpleDroneDynamics/...' is not connected.
How do I feed inputs using port numbers?
How do I get outputs with port numbers? I tried
[vx, vy, px, py] = sim('SimpleDroneDynamics.slx');
and got an error saying
Number of left-hand side argument doesn't match block diagram...
Is there a way to continuously feed inputs at every time step? This being controller module, I think I'm supposed to feed in different values based on output position and velocity.
EDIT2:
I'm using Matlab2017a
About the first two points of your question:
In simulink:
For the inputs you can use a constant block and when you double click the input block you can assign a value, which can be a workspace variable.
To get the outputs to your workspace you can use the simout block (make sure to put Save format to array).
Connect inputs to your simulink model
Connect outputs of your simulink model to the simout blocks.
MATLAB script
clc;
clear all;
roll = 10;
pitch = 20;
sim('/path_to_simulinkmodel.slx')
time = simout(:,1);
velocity_X = simout(:,2);
velocity_Y = simout(:,3);
position_X = simout(:,4);
position_Y = simout(:,5);
About the third point of your question
You can define the duration of your simulation in the block diagram editor. You can put a variable which is defined in the calling script. There are multiple ways of achieving time dependent input variables:
One option I personally don't recommend is using a for-loop and calling the simulink model with a different value of roll and pitch
for i = 1:numberOfTimesteps
roll = ...
...
sim('simulinkModel.slx')
end
A second and more efficient approach is changing the constant blocks to other source blocks like ramp signals or sinusoid signals
First of all Simulink model use main Matlab workspace. So you can change your variables values at command window (or just at your script) and run Simulink model.
There are several ways to initialize this constants for Simulink. One more useful way is to create script containing all your variables and load it at Simulink model starts. You can do it by adding script name in Simulink/Model Explorer/Callbacks. (There are different callbacks - on Loading, on Starting and etc.). Read more about this: here.
Now you can run your simulation using sim function:
sim('name_of_model')
name_of_model must contain path if model is not in the active MATLAB folder (active folder you can see in your matlab window just under the main menu).
There are different properties of sim function, read about them in help this can be useful for you. By the way: you can change some parameters of your model using sim. You even can find any block in your model and change it's properties. Read more about sim and about finding current blocks. Interesting that the last solution give you ability to change parameters during the simulation!
About getting output. After you run simulation you get tout variable in main workspace. It is an array of timesteps. But if you add outport block (like at my image) you also get another variable in workspace yout. yout is an Datasets. It contain all your outports values. For 2 outports for example:
yout
yout =
Simulink.SimulationData.Dataset
Package: Simulink.SimulationData
Characteristics:
Name: 'yout'
Total Elements: 2
Elements:
1 : ''
2 : ''
Get the values of any of outports:
yout.get(1).Values
it is a timeseries data type, so:
yout.get(1).Values.Time - give you times
yout.get(2).Values.Data - give you values of this outport at each time
We have one more method to take output values:
[t,x,y] = sim('model_name')
it returns double arrays. t- time array, y - matrix of all outports values (it already double and contain only values without times, but for each simulation time!)
So now you can create common Matlab GUI and work at this variables! There is no any difficulties. You can read more about GUI for Simulink here.
I have a .mat file which has a structure loaded into the Workspace. I have created a simulink model and want to Import the signals from the Workspace. What should be the Input value for the Data Parameter of the 'From Workspace' block. The Name of the structure is Measurements, the Signal Name is B_cal and it has further elements as time,name, Units and value. I know that the structures can be accessed by somewhat like this command :
Measurements.B_cal.value
But i am unable to set the Input Parameters. Could anyone help me with this ?
There are some limitation to use structures through the FromWorkspace block:
A MATLAB expression that evaluates to one of the following:
A MATLAB timeseries object
A structure of MATLAB timeseries objects
A two-dimensional matrix:
The first element of each matrix row is a time stamp.
The rest of each row is a scalar or vector of signal values.
A structure, with or without time, which contains:
1) A signals.values field, which contains a vector of signal values
2) An optional signals.dimensions array, which contains the dimensions of the signal
3) An optional time vector, which contains time stamps
More useful information you can find in help.
So in your case you can use different methods. I'll give some examples:
1) define your struct in necessary format:
t = (1:10)'; %'
v = [6 9 3 1 7 0 7 3 8 1]'; %'
measure.time = t;
measure.signals.values = v;
Important moment here: t andv must be a columns! rows will not work!
If you need to use several rows of data use multidimensional v and add
measure.signals.dimentions = size(v,2);
2) You can see ths time field is an optional. If you do not have it you need to set Sample time in block other than 0 and, clear Interpolate Data, Set Form output after final data value by to a value other than Extrapolation. Furthermore, you need to define time field:
mystruct.time = [];
3) If you don't want to change your structure, you can use next:
t = (1:10)'; %'
and set this in Data of FromWorkspace block: [t, Measurements.B_cal.value].
4) There are some useful methods: use timeseries or just matrix. But it's not really your case if you need to use your structure.
I have recently started learning MatLab, and wrote the following script today as part of my practice to see how we can generate a vector:
x = [];
n = 4;
for i = i:n
x = [x,i^2];
end
x
When I run this script I get what I expect, namely the following vector:
x = 0 1 4 9 16
However, if I run the script a second time right afterwards I only get the following output:
x = 16
What is the reason for this? How come I only get the last vector entry as output the second time I run the script, and not the vector in its entirety? If anyone can explain this to me, I would greatly appreciate it.
Beginning with a fresh workspace, i will simply be the complex number 1i (as in x^2=-1). I imagine you got this warning on the first run:
Warning: Colon operands must be real scalars.
So the for statement basically loops over for i = real(1i):4. Note that real(1i)=0.
When you rerun the script again with the variables already initialized (assuming you didn't clear the workspace), i will refer to a variable containing the last value of 4, shadowing the builtin function i with the same name, and the for-loop executes:
x=[];
for i=4:4
x = [x, i^2]
end
which iterates only one time, thus you end up with x=16
you forget to initialize i.
after first execution i is 4 and remains 4.
then you initialize x as an empty vector but because i is 4 the loop runs only once.
clear your workspace and inspect it before and after first execution.
Is it possibly a simple typo?
for i = i:n
and should actually mean
for i = 1:n
as i is (probably) uninitialized in the first run, and therefore 0, it works just fine.
The second time, i is still n (=4), and only runs once.
Also, as a performance-tip: in every iteration of your loop you increase the size of your vector, the more efficient (and more matlaboid) way would be to create the vector with the basevalues first, for example with
x = 1:n
and then square each value by
x = x^2
In Matlab, using vector-operations (or matrix-operations on higher dimensions) should be prefered over iterative loop approaches, as it gives matlab the opportunity to do optimised operations. It is also often more readable that way.