Understanding MATLAB code for creating a wireless sensor network - matlab

I have the following MATLAB code that is used to aid in creating a wireless sensor network:
for i=1:n
S(i).xb=rand*0.5*xm;
S(i).yb=rand*0.5*ym;
S(i).E=Eo;
S(i).G=0;
S(i).type='N';
S(i).id=i;
S(i).D=dist(BS.x,BS.y,S(i).xb,S(i).yb);
S(i).Etx=Eelec*k+Eamp*k*S(i).D^2;
plot(S(i).xb,S(i).yb,'o');
end
plot(BS.x,BS.y,'rx');
In this program, why are there dots in the code? For example, S(i).xb=rand*0.5*xm;. Can anyone explain this to me?

In this code, S will be an array of structures. Each structure will contain the following member variables:
xb
yb
E
G
type
id
D
Etx
Doing S(i).xb = rand*0.5*xm; will first create a structure within the array S at location i that contains a single member xb. This will be assigned the value of rand*0.5*xm. The rest of the statements will keep appending more variables to the same structure at location i in the array.
After, if you wish to access the member variable at location i for the array S, you would still do S(i).xb, or S(i).yb, etc.
Essentially, you can think of S as having an array of elements where each element has 8 fields within the element. You'd access a field by using the ..

Related

Creating a structure within a structure with a dynamic name

I have large data sets which i want to work with in matlab.
I have a struct called Trail containing serveral structures called trail1, trail2 ...
which then contain several matrices. I now want to add another point to for instance trail1
I can do that with Trail.trail1.a2rotated(i,:) = rotpoint'; the problem is that i have to do it in a loop where the trail number as well as the a2rotated changes to e.g. a3rot...
I tired to do it like that
name ="trail"+num2str(z)+".a2rotated"+"("+i+",:)";
name = convertStringsToChars(name);
Trail.(name) = rotpoint'
But that gives me the error: Invalid field name: 'trail1.a2rotated(1,:)'.
Does someone have a solution?
The name in between brackets after the dot must be the name of a field of the struct. Other indexing operations must be done separately:
Trail.("trail"+z).a2rotated(i,:)
But you might be better off making trail(z) an array instead of separate fields with a number in the name.

Synchronize timetables stored in a structure

I am dynamically storing data from different data recorders in timetables, nested in a structure DATA, such as DATA.Motor (timetable with motor data), DATA.Actuators (timetable with actuators data) and so on.
My objective is to have a function that synchronizes and merges these timetables so I can work with one big timetable.
I am trying to use synchronize to merge and synchronize those timetables:
fields = fieldnames(DATA);
TT = synchronize(DATA.(fields{1:end}));
but get the following error:
Expected one output from a curly brace or dot indexing expression, but there were 3 results.
This confuses me because DATA.(fields{1}) return the timetable of the first field name of the DATA structure.
Any thought on how I can solve this is greatly appreciated.
The problem here is that fields{1:end} is returning a "comma-separated list", and you're not allowed to use one of those as a struct dot-index expression. I.e. it's as if you tried the following, which is not legal:
DATA.('Motor','Actuators')
One way to fix this is to pull out the values from DATA into a cell array, and then you can use {:} indexing to generate the comma-separated list as input to synchronize, like this:
DATA = struct('Motor', timetable(datetime, rand), ...
'Actuators', timetable(datetime, rand));
DATA_c = struct2cell(DATA);
TT = synchronize(DATA_c{:});

Is it possible to send global values to another model in OpenModelica?

I'm trying to create a model in OpenModelica which contains several other components (pipes, reservoirs). Currently I'm modifying a pipe in the Modelica.Fluid-library using a staggered grid, and need to determine the smallest step size dx in the entire model.
Is it possible to do the following?
Calculate dx_1 in pipe 1 and dx_2 in pipe 2.
Send dx_1 and dx_2 to an array in a global model (similar to Modelica.Fluid.System).
Determine the smallest dx = min(dx_1, dx_2) and send back to both pipe 1 and pipe 2.
I have calculated both dx_1 in pipe 1 and dx_2 in pipe 2, and created an array in a data storage model similar to Fluid.System. I am, however, struggling with sending the step sizes to the data storage model, and sending them back again after determining the smallest dx.
Is this even possible? How would one go about to do so?
Yes, there are several possibilities.
As you mention, the pipes can access variables/parameters in the data storage model if this is instantiated as inner in your global model and declared as outer in each pipe model. As with the Modelica.Fluid models referring to Fluid.System, the pipes can access dx_minin the data storage model.
This is a code example, loosely based on your question:
model Pipe
outer DataStorage dataStorage;
Real dx_min = dataStorage.dx_min;
Real dx "calculated in this model";
...
end Pipe;
model DataStorage
parameter Integer nPipes;
input Real dx_array[nPipes];
Real dx_min=min(dx_array);
...
end DataStorage;
model GlobalModel
Pipe pipe1;
Pipe pipe2;
inner DataStorage dataStorage(nPipes=2, dx_array={pipe1.dx, pipe2.dx});
...
end GlobalModel;
You should beware of the variability of the different "dx's" as you cannot assign a time-varying "dx" to a "dx" declared as a parameter.
If the only purpose of the DataStorage model is to take the minimum entry in an array then you could also put its three lines of code in GlobalModel, reducing the code to:
model Pipe
input Real dx_min;
Real dx "calculated in this model";
...
end Pipe;
model GlobalModel
parameter Integer nPipes=2;
Real dx_array[nPipes]={pipe1.dx, pipe2.dx};
Real dx_min=min(dx_array);
Pipe pipe1(dx_min=dx_min);
Pipe pipe2(dx_min=dx_min);
...
end GlobalModel;

Trouble with looping function into structure index

I'm relatively new to matlab and would really appreciate any help.
Currently, I have a function (we'll call it readf) that reads in data from a single ascii file into a struct of multiple fields (we'll call it cdata).
names = cellstr(char('A','B','C','D','E','F','G'));
cdata = readf('filestring','dataNames',names);
The function works fine and gives me the correct output of a struct with these field names, with the value of each field name being a cell array of the corresponding data.
My task is to create a for loop that uses this readf function to read in a folder of these ascii files at once. I'm trying to work it so that the for loop creates a struct with an index of the different cdata structs. After trying a few different methods, I am stumped.
This is what I have so far.
files = struct2cell(dir('folderstring')); %creates a cell array of the names of the files withing the folder
for ii=length(files);
cdata(ii) = readf([folderstring,files(1,1:ii),names],'dataName',names);
end;
This is currently giving me the following error.
"Error using horzcat
Dimensions of matrices being concatenated are not consistent."
I am not sure what is wrong. How can I fix this code so i can read in all the data from a folder at once??? Is there a better and more efficient way to do this than making an index to this struct? Perhaps a cell array of different structures or even a structure of nested structures? Thanks!
Change:
for ii=length(files);
cdata(ii) = readf([folderstring,files(1,1:ii),names],'dataName',names);
end;
To:
for ii=1:length(files); % CHECK to make sure length(files) is giving you the right number
cdata(ii) = readf([folderstring,files{ii},names],'dataName',names);
end;
% CHECK files{ii}, with 1,2,3 etc. is giving you the correct file name.

MATLAB: Referencing an element in a structure

I am trying to reference an element buried within a structure that I did not create (hence I don't know the exact way in which it was built).
Having loaded the structure, if I type:
dataFile.RECORDINGS.eye
I receive the following output:
ans =
2
ans =
2
Both of those variables will always be the same, but they could be at any time 1, 2 or 3. What I'd like to do is check with a switch statement which looks like this:
switch dataFile.RECORDINGS.eye
case {1, 2}
% action A
case 3
% action B
end
Of course, the above throws up an error because 'case' cannot check whether dataFile.RECORDINGS.eye contains a given value since there are two elements stored under that address. So, my question is: how do I reference just one of the elements? I thought it would be as simple as replacing the first line with:
switch dataFile.RECORDINGS.eye(1)
...But, this gives the error:
??? Field reference for multiple structure elements that is followed by more reference blocks is an error.
Similarly, I can't access the element like this:
switch dataFile.RECORDINGS.eye.1
...As I get the following error:
??? Dot name reference on non-scalar structure.
If the values are really always the same, you can try the following to get a scalar that can be used in the switch command:
unique([dataFile.RECORDINGS.eye])
By the way, did you try to index RECORDINGS, i.e.,
dataFile.RECORDINGS(1).eye
dataFile.RECORDINGS(2).eye
Perhaps instead of eye having multiple elements, you have multiple elements of RECORDINGS that each have a single value of eye? You might want dataFile.RECORDINGS(1).eye or dataFile.RECORDINGS(2).eye.