Array of structures in MATLAB Simulink - arrays

I am trying to create an array of structures in Simulink and got some problems with it.
first of all i tried to create it directly in Simulink using this:
function a = fcn(Dibhole, t , x, const)
%#codegen
%Output = zeros(10,10);
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
a = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
a(i,j).number = 0;
a(i,j).move = 0;
end
end
and i got this error:
Derived output was of type struct. 'Inherited type' is unsupported for this
type and a defined bus object must be used instead. Click on 'a' and
set data type for 'a' to be 'Bus: ', where '' is
the name of a bus object from the MATLAB workspace.
So i found some example how to create struct in Matlab and receive this to Simulink: http://blogs.mathworks.com/seth/2011/12/05/initializing-buses-using-a-matlab-structure/
That works perfectly but i still can't repeat this with array:
f1 = 'number';
f2 = 'move';
cube = struct(f1, 0, f2, 0);
myStruct2 = repmat(cube, 20, 10);
for i = 1:20
for j = 1:10
myStruct2(i,j).number = 1;
myStruct2(i,j).move = 1;
end
end
busInfo = Simulink.Bus.createObject(myStruct2);
Can anyone clarify to me what's the problem? Or maybe there is different way to create array of struct in Simulink?
Mihail

Simulink wants you to define the output of the function to be a bus.
As 'Bus: My_test_bus', for example.
Take a look at the Simulink Bus Editor. You can find it in any model under the menu, Edit->Bus Editor.
This would be a good start.

Rick, i think you are right!
i have tried this problem for a long time, and have got this results:
the irony is that I was never able to create array of structures BUT i did this with structure of arrays! :D
I made this steps for it:
to use structure of arrays we need to define and initialize it in some MATLAB function. Like this:
number = zeros(10,1);
move = zeros(10,1);
for i = 1:10
number(i,1) = i+1;
move(i,1) = i+2;
end
a = struct('numbers',number,'movement', move);
To work this data we must use Bus Selector.
So we have array in "numbers" and "movement".
BUT! Here we go, Rick: we must define type of output of MATLAB function like Bus! How to do this in simulink? i found this way:
in model properties in simulink Callbacks/PreLoadFcn define some function and in same folder as project create .m file named like this just defined function.
In this file create structure of array and define Bus type for it:
number = zeros(10,1);
move = zeros(10,1);
a = struct('numbers',number,'movement', move);
busInfo = Simulink.Bus.createObject(a);
Now we have Bus type for our structure at first loading of simulink model.
Last step: define MATLAB function output type directly.
in Model Explorer choose your MATLAB function. choose output variable. Set DataType for it: Bus:slBus1 (the name of this Bus type you can see in wokspace of matlab, because its a global variable).
That's all! now it works!
(tried to add pictures, but i have no enough reputation :( )
Now my program works in this way, but i also tried to create array of structures and still have the problems. i tried to create Bus for it, but can't transmit it to Bus Selector - it doesn't know what to do with structures... i also tried to add one more MATLAB function to create some data from structures and then display it, but it doesn't works too(

Related

Matlab, AppDesigner-Convert image on a good type and use it in "imread" function

I use AppDesigner inMATLAB to show photos with changed RGB. But there is the problem with character of the photo.
When I switch on my own fuction "changeRGB", finally "choosenImage" has 20bytes, class "char" and size(1x10). OK!
There is no problem in using the "function OpenButtonValueChanged". OK!
There is the problem with "function UploadButtonPushed". OK!
ABOUT THE PROBLEM:
When I click button which callback is "function UploadButtonPushed" I get the error:
"Error using imread>parse_inputs (line 502)
The file name or URL argument must be a character
vector or string scalar."
"Error in imread (line 342)
[source, fmt_s, extraArgs, was_cached_fmt_used] =
parse_inputs(cached_fmt, varargin{:});"
WHY?
Because in the "function UploadButtonPushed" my choosenImage has 1977624bytes, class "uint8" and size(681x968x3). So it's too bug for "imread".
WHAT I TRIED:
When in "function OpenButtonValueChanged" I convert a photo, adding "char": (myimage = char(app.clickedImage)); the class of the photo is changing from uint8 to char but the size.
When I use "num2cell", the claas of the photo is changing on "cell" but size and number of bytes are the same- so big. And I get the Error: "Error using imread>parse_inputs (line 502) The file name or URL argument must be a character vector or string scalar."
In my own function "changeRGB" I used "imread(image)" and here is the problem with the size of the photo. Do you know how to get the correct one?
%my own properties in AppDesigner- to use them in different functions
properties (Access = public)
clickedImage;
addR = 1;
addG = 1;
addB = 1;
end
%first function in AppDeesigner
function OpenButtonValueChanged(app, event)
value = app.OpenButton.Value;
[file, howManyFiles] = chooseImagesFromComputer; %myown function
%I load 3 images which are showed as miniatures
myFile1 = imread(file{1});
imshow(myFile1, 'Parent', app.UIAxes1_1);
myFile2 = imread(file{2});
imshow(myFile2, 'Parent', app.UIAxes1_2);
myFile3 = imread(file{3});
imshow(myFile3, 'Parent', app.UIAxes1_3);
%take values of changed RGB from the slider
app.addR = app.SliderR.Value
app.addG = app.SliderG.Value
app.addB = app.SliderB.Value
%work only on one image to change its colors. app.clickedImage, app.addR, app.addG, app.addB are properties at the beginning of the code
app.clickedImage = file{1};
app.clickedImage = changeRGB(app.clickedImage,app.addR,app.addG,app.addB); %changeRGB- my own function- here is the problem. I add it bottom
imshow(app.clickedImage,'Parent',app.UIAxesMain);
end
%second function in AppDesigner
%here is the button to upload color of the photo
function UploadButtonPushed(app, event)
myimage = app.clickedImage;
myimage = changeRGB(myimage,app.addR,app.addG,app.addB);
imshow(myimage);
end
%here is my own function in matlab, not in AppDesigner, which makes problem:
function [changedImage] = changeRGB(choosenImage, addR, addG, addB)
whos
loadedImage = imread(choosenImage);
R = loadedImage(:,:,1); %extract one of the color channels
G = loadedImage(:,:,2);
B = loadedImage(:,:,3);
RBG = cat(3,R,G,B);
R_adj2 = R + addR;
G_adj2 = G + addG;
B_adj2 = B + addB;
changedImage = cat(3,R_adj2,G_adj2,B_adj2);
end
First, you make unnecessary operations in changeRGB
function [changedImage] = changeRGB(choosenImage, addR, addG, addB)
loadedImage = imread(choosenImage);
loadedImage = bsxfun(#sum, loadedImage, reshape([addR, addG, addB], [1 1 3]);
end
Then this function return an array (the modified image) so in UploadButtonPushed(app, event) when you run myimage = app.clickedImage;, you are passing the modified array instead of the image path, that you set here app.clickedImage = changeRGB(app.clickedImage,app.addR,app.addG,app.addB);
So you have to change the design of your variables, because app.clickedImage is saving either the image path, or the image itself. Consider having 2 different variables.
A good advice also is to use matlab debugger which is really good help to find the source of this kind of problems.

How to make what function I use in c be controlled by a variable

This is my first year of vex. I am taking on the role of programmer.
I have had this idea for rapid autonomous creation, recording the driver. Instead of the usual array/debugger dump of raw streams of power levels, I had the idea of extracting functions from driver movement.
I wont go into the details, and I can code it myself, but I need some help.
There is one thing I am unable to do simply because of my lack of coding experience.
I want to create a for loop that checks every joystick button one by one.
For example:
struct button
{
bool pressed;
}
for(int i = 0; i>12; i++) //12 is number of buttons on the joystick
{
struct button button<cycle through buttons>;
}
I want there to then be:
struct button button6U;
struct button button6D;
struct button button6R;
etc.
Then, I want this:
for(int i = 0; i>12; i++) // 12 is number of buttons on the joystick
{
if(VexRT[<currentButton>])
{
button<currentButton>.pressed = true;
}
}
I have no idea how to do this, with a wildcard modifing the actual variable name I am writing to.
A couple thoughts:
A for statement would have no idea how to advance the order of joystick buttons. So something I think I might need is:
orderOfButtons
{
VexRT[6U];
VexRT[6D];
VexRT[6R];
// etc.
}
I just cant seem to figure out how to have a variable defining what VexRT[]button I am reading from.
Any help would be appreciated!
Thanks.
Sounds like you want an array:
#define NUMBER_OF_BUTTONS 12
...
struct button VexRT[NUMBER_OF_BUTTONS];
If you want to use symbolic constants to refer to specific buttons in the array, you can use an enumeration:
enum btn_id { BTN_6U, // maps to 0
BTN_6D, // maps to 1
BTN_6R, // maps to 2
...
}
Enumeration constants are represented as integers, and by default they start at 0 and increment by 1. You can initialize them to different values if you want, and multiple enumeration constants can map to the same value. I take advantage of this when I want to identify a "first" and "last" enumeration for looping, like so:
enum btn_id {
BTN_6U,
BTN_FIRST = BTN_6U, // both BTN_FIRST and BTN_6U will map to 0
BTN_6D,
BTN_6R,
...
BTN_whatever,
BTN_LAST
};
Thus, VexRT[BTN_6U] maps to VexRT[0], VexRT[BTN_6D] maps to VexRT[1], etc.
Note that this way, you don't have to loop through all the buttons just to set one:
enum btn_id currentButton = BTN_6D;
...
VexRT[currentButton].pressed = true;
If you do want to loop through the whole set, you can use
for ( enum btn_id i = BTN_FIRST; i < BTN_LAST; i++ )
{
VexRT[i].pressed = false;
}
So, what you want is to sample the user input (at some specified rate), then record it into an array, then play that back at a later time? If you have functions that drive the VEX (I'm not familiar with that), each of which are associated with an input, you can use an array of function pointers to create your output.
#define MAX_ACTION 12
#define MAX_RECORDED 200
// Declare your array of function pointers
int (*action[MAX_ACTION])(void);
// Declare your stored array of recorded actions
int recorded[MAX_RECORDED];
...
// Assign function pointers to associated functions
action[0] = go_forward;
action[1] = turn_right;
...
// Record your actions into some array
while (...)
{
// Record the action
recorded[i++] = get_action();
// Sample delay
}
...
// Playback the actions
for (i=0;i<RECORDED;i++)
{
(*action[recorded[i]])();
// delay here
}
P.S. Your for loop is backward (i<12 not i>12).
I think you are trying to access the events coming from the joystick. You can just loop through the array of values and record them. I think the channels on the joystick are simply accessed like: vexRT[x] where x is 1-12. If you just want to store the latest value from each channel you could do this:
int value[12];
for(i=0; i<12; i++)
{
value[i] = vexRT[i];
}
If you want to store all of the values so that you can map them or play them back or something then you will need a more complex data structure to store them, like a list of the value arrays.
I also have found documentation that says the values are accessed by like vexRT[Chx] where x is 1-12, so you could alternatively create a string and use it to access the joystick channels inside your loop:
string *s = (char *)malloc(5*sizeof(char)); //5 is the max length of the null terminated string
for() . . . {
sprintf(s,"Ch%d", i);
value[i] = vertRT[s];
}

Manipulating a struct which is a class property in MATLAB

I've been trying to work with MATLAB classes & structs in order to develop a traffic simulation. I have not worked actively with MATLAB classes before, so it gets a bit tricky at times. This questions involves manipulating a struct, which is a property of a class.
Top-level access
vehicles_handle = VehiclesHandle;
vehicles_handle.CreateVehicles(InitialTrafficDensity);
vehicles_handle.vehicles(1)
Class definition
classdef VehiclesHandle
%VEHICLESHANDLE Summary of this class goes here
% Detailed explanation goes here
properties
active_vehicles_count
vehicles
end
methods (Access = public)
function obj = VehiclesHandle
obj.active_vehicles_count = 0;
obj.vehicles = struct('lane',0,'position',0,'velocity',0);
end
function obj = CreateVehicles(obj,InitialTrafficDensity)
obj.active_vehicles_count = obj.active_vehicles_count + 1;
obj.vehicles(1).lane = 1;
obj.vehicles(1).position = 3;
obj.vehicles(1).velocity = 3;
obj.vehicles(2).lane = 2;
obj.vehicles(2).position = 3;
obj.vehicles(2).velocity = 3;
end
Now, I can't see the output as expected (which is vehicles_handle.vehicles(1)), I see them the properties of the vehicle 1 as 0's. The situation changes, of course, when I put then in the function VehiclesHandle, but I want to handle creation of vehicles this way.
I know that the code might not be the most efficient way to handle this, but I really do want to learn about handling a struct in this class without pain. Thanks for all the constructive comments and help in advance.
Getting rid of the problem is quite easy:
classdef VehiclesHandle
has to be
classdef VehiclesHandle < handle
And to understand why, please read Comparison of Handle and Value Classes.

How to use IDL's min() function's min_subscript argument in for loop?

I have experience in python but am new to IDL. I am trying to write a function that will return two bins. I want to use the min function to get my bin edges. My issue is that I am trying to use the min_subscript argument to denote each bin edge, and I can't figure out how to do this in a for loop. I want to write my code so that each loop has 2 different min_subscript variables (the two edges of the bin), and these variables are written into their own arrays. Here is my code:
FUNCTION DBIN, radius, data, wbin, radbin, databin
FOR i = 0, N_ELEMENTS(radius)-1 DO BEGIN
l = lonarr(N_ELEMENTS(radius))
m = lonarr(N_ELEMENTS(radius))
junk1 = min(abs(radius - radius[i]), l[i])
junk2 = min(abs(radius - (radius[i] + wbin)), m[i])
radbin = lonarr(N_ELEMENTS(radius))
radbin[i] = radius[l[i]:m[i]]
databin = lonarr(N_ELEMENTS(data))
databin[i] = total(data[l[i]:m[i]])
ENDFOR
END
wbin is the desired bin width. The junk variables only exist for the purpose of getting the min_subscripts at those locations. The min_subscripts are the l[i]'s and the m[i]'s.
I appreciate any help!!
The min_subscript argument is trying to pass a value back to you, so you must pass a "named variable" to it. Named variables have pass by reference behavior. So you have to do it in two steps, something like:
junk1 = min(abs(radius - radius[i]), li)
l[i] = li
Above, li is a named variable, so it can receive and pass back the value. Then you can put it in your storage array.

How to call an m file from another m file in MATLAB and retrieve an output?

I know this is a simple question, but for some reason I can't find a straight answer that works no matter where I look.
Basically, I have 4 values that were found in one m file, and I want to run them through a separate m file and retrieve the output from it.
I tried something like these, but none worked:
result = generate(nrow,ncol,a,b);
function result = generate(nrow,ncol,a,b);
result = #generate(nrow,ncol,a,b);
The final value in the m file "generate" is called result, and I'm trying to carry that across to my initial m file.
Any advice as to what I'm doing wrong would be greatly appreciated! Please and thank you
if your file generate.m defines a function it should have itself the following structure (which takes into account the fact that you have four returned values)
function [ret1 ret2 ret3 ret4] = generate(nrow,ncol,a,b)
.... % # Some processing of yours
ret1 = ... ; % # Returned values are eventually set
ret2 = ... ;
ret3 = ... ;
ret4 = ... ;
end
The function should be called (e.g. in your main script) as
[ret1 ret2 ret3 ret4] = generate(nrow,ncol,a,b);
now you have the variables ret1,ret2,ret3,ret4 available in the caller scope.
Be aware that the file generate.m must be in the current matlab PATH.

Resources