I'm trying to create State block from sflib (stateflow library) :
chart = add_block('sflib/Chart', 'autoDS/Chart'); %Create Chart Block
state = Stateflow.State(chart); %Create State in Chart Block
state.Name = 'CMD_28V_Avion';
open_system('autoDS');
It returns me "No constructor 'Stateflow.State' with matching signature found" error.
How can i fix it please ? I don't know if it's a syntax or a library error as i saw on many post.
add_block returns a handle to the added block (which for a state chart is actually a subsystem.) It does not return a handle to a chart, which is what Stateflow.State requires as its input. Hence the error.
You need,
add_block('sflib/Chart', 'autoDS/Chart'); %Create Chart Block
rt = sfroot;
m = rt.find('-isa', 'Simulink.BlockDiagram', '-and', 'Name', 'autoDS'); % block diagram
ch = m.find('-isa','Stateflow.Chart', '-and', 'Name', 'Chart'); % chart
st = Stateflow.State(ch); % state
st.Name = 'CMD_28V_Avion';
open_system('autoDS');
See the Access the Model Object and Access the Chart Object sections of Create Charts by Using the Stateflow API
Related
I have a user input function to extract 3 rows of data from a table and assigned this data to the variable 'all_sectors'. When I try to use this variable to plot the data on a bar chart it comes up with the following error message:
Unrecognized function or variable 'all_sectors'.
Error in train_fares_script (line 36)
y = all_sectors ;
My code to select the data is:
if year == 2004
all_sectors = readmatrix("train_fares.xlsx",'sheet','2004','range','A1:A3')
elseif year == 2005
year = 2005
all_sectors = readmatrix("train_fares.xlsx",'sheet','2005','range','A1:A3')
My code to plot this on a bar graph is:
x = categorical({'London and South East','Long Distance','Regional'});
y = all_sectors ;
bar(x,y)
How can I fix this so the variable is recognised?
Ive tried copying and pasting the variable name to ensure it is spelled correctly and changed the name to see if that would work but it hasn't.
I have created a very simple GUI in appdesigner (Matlab) with one dropdown menu. Additionally, I took the code that got generated (under 'Code View' tab) and pasted that in a normal .m file (because, I want to further add some more contents to this code). My question is how can I access certain variable from this self generated code, so that I can play with that value outside of the main class?
For example:
In App class, for this dropdown menu section, following line of code got generated:
app.ColorDropDown = uidropdown(app.UIFigure);
app.ColorDropDown.Items = {'Red', 'Blue', 'Yellow'};
app.ColorDropDown.Position = [277 178 140 22];
app.ColorDropDown.Value = 'Red';
Outside of this app class: Depending upon the value that was selected in this dropdown menu, I want to capture that in a normal variable, and show some other results based on the color selected
Thanks
It seems like the essence of your question is about sharing data between GUIs as you state you want to "show some other results based on the color selected".
Note: MATLAB documentation cautions: Do not use UserData property in apps you create with App Designer.
The documentation goes on to recommend approaches for sharing data among app designer apps and creating multiwindow apps in app designer.
For the sake of completeness, I'll provide a detailed example, different from the MATLAB documentation, of how this can be accomplished entirely within the App Designer.
Setup
I created 2 app designer apps, controlGUI.mlapp and plotGUI.mlapp. Running controlGUI() loads both mlapp files at once and then allows you to control aspects of the plotGUI from callbacks in the controlGUI. Of course, the plotGUI could do anything but I have it changing visual aspects of the plotted data.
Details
For simplicity, I am setting the controlGUI be the main application. I can do this be adding a property in controlGUI named PlotWindow and having it contain the output of calling plotGUI(); the other mlapp. I also have a callback function I recycle for the three dropdowns that updates a DATA property in the plotGUI. This DATA property has a listener attached that fires a callback to update the uiaxes object.
The plotGUI
The magic is really in this object. That is, I created a property named DATA and altered the access. By setting the property access SetObservable = true, we can then add a PostSet event listener, which I stored in a private property called dataChangedListener during the startupFcn.
properties (Access = public, SetObservable=true)
DATA % A struct with xdata, ydata, fields. Other line prop fields ok
end
properties (Access = private)
dataChangedListener % listener object for when DATA is changed.
end
Then the startup function, startupFcn, initializes the DATA property with some (arbitrary) data as struct then adds and enables the PostSet listener.
% Code that executes after component creation
function startupFcn(app, data)
if nargin < 2
% create a default dataset
data = struct();
data.xdata = linspace(0,1,1001);
data.ydata = sin(data.xdata.*2*pi*10);%10hz signal
data.color = app.Axes.ColorOrder(1,:);
end
app.DATA = data;
% plot the data
line(data, 'parent', app.Axes);
% add and enable PostSet event listener for the DATA property
app.dataChangedListener = addlistener(...
app,'DATA','PostSet', ...
#(s,e) app.updatePlot ...
);
app.dataChangedListener.Enabled = true;
end
The PostSet listener calls the method app.updatePlot(), so we have to add this method to our app. This method will get called whenever anything in app.DATA gets modified. So I created the "function" (as the Code Browser calls it) which simply deletes the axes children (the existing line) and uses the low-level version of line() to draw a primitive line based on the app.DATA struct object:
function updatePlot(app)
%clear plot
delete(app.Axes.Children);
% draw the new plot
line(app.DATA, 'parent', app.Axes);
end
Yes, line() will accept a struct which has field names that correspond to valid line properties but I can't seem to find the reference specifically. But if you read about the inputParser object... sorry, getting off topic.
The controlGUI
This object is simpler. It holds the plotGUI in a property, allowing direct access to the plotGUI properties and public methods.
properties (Access = public)
PlotWindow = plotGUI() % holds the reference to the plot window
end
I also created an updatePlot callback method here, different from the plotGUI method, bad naming on my part. Nonetheless, this control method takes the values from controlGUI dropdowns and then modifies the plotGUI DATA struct, stored in app.PlotWindow.DATA. So this one callback is called whenever any of the dropdowns are changed (ValueChangedFcn). Consequently, the PostSet listener for the DATA struct will fire the callback to update the plot accordingly.
% Value changed function: LineColor, LineStyle, MarkerStyle
function updatePlot(app, event)
mStyle= app.MarkerStyle.Value;
lStyle= app.LineStyle.Value;
lColor = app.LineColor.Value;
d = app.PlotWindow.DATA;
switch mStyle
case 'none'
d.marker = 'none';
case 'circle'
d.marker = 'o';
case 'diamond'
d.marker = 'diamond';
case 'point'
d.marker = '.';
end
switch lStyle
case 'none'
d.linestyle = 'none';
case 'solid'
d.linestyle = '-';
case 'dashed'
d.linestyle = '--';
case 'dotted'
d.linestyle = ':';
end
d.color = lColor;
% set the data back into the plotGUI
% The plotGUI's DATA PostSet listener will update the actual plot
app.PlotWindow.DATA = d;
end
You aren't supposed to copy/paste the code outside of the code editor with App Designer. If you want to add your own code, you should add a new function to your class using the "Function" button in App Designer. The app can also call any other matlab function so you could just pass the information from the app to another function by calling it inside the App Designer code
For example see this example from a demo I created. It uses a drop down ChartTypeDropDown to determine what type of chart it should draw. I added a new function called DrawChart which uses the data from the GUI to draw a graph depending on the values selected/entered in to the various boxes.
function results = DrawChart(app)
chartType = app.ChartTypeDropDown.Value;
chartTime = app.TimeEditField.Value;
chartA = app.AEditField.Value;
chartB = app.BEditField.Value;
chartC = app.CEditField.Value;
t = [0:0.1:chartTime];
if strcmp(chartType,'Sin')
y = chartA * sin(chartB*t)+chartC;
elseif strcmp(chartType,'Cos')
y = chartA * cos(chartB*t)+chartC;
elseif strcmp(chartType,'Exp')
y = exp(t);
else
y = x;
end
ax = app.UIAxes;
ax.Title.String = chartType;
plot(ax,t,y);
end
This function is called by the callback linked to a button
function DrawButtonPushed(app, event)
DrawChart(app);
end
Note how I call regular matlab functions such as sin/cos/exp. These could just as easily be a Matlab function that you have written.
Trying to use simulink but have some problems:
part.type = 'PB1';
part.name = ['SLibrary/PB_1_' int2str(rjoint1Count) '_Default/PB1_1' ];
part.handle = add_block(pjnt11, [sys '/' part.name], 'Position', pos, 'MakeNameUnique', 'on');
where
pjnt11 = 'SLibrary/PB_1_Default/PB1_1 ';
sys=Robot
which are defined before. Also the predefined SLibrary/PB_1_Default/PB1_1is
and
When I run the code I got the following error:
Error using startSimulation (line 134)
A new block named 'Robot/SLibrary/PB_1_1_Default/PB1_1' cannot be added
Tried to find it online but couldn't find any solution.
Thanks in advance.
You are trying to add a block, giving it the same name as an existing block. Block's must have unique names.
If you want to copy a plot through the property structure you need to filter out the read only properties (such as Annotation, BeingDeleted, Parent, Type). Is there a way to get a list of read only properties for the object?
The question arose from a related question
How can I plot from a plot handler?
I started to muck around with the previous question, trying to dynamically find out which fields were settable.
I didn't quite get it to work but I could get hold of (most of) the read only properties by using the difference between the return values of set(h) and get(h).
The only property that doesn't show up here is the Parent-property which is settable but is not supposed to be changed in the previous question.
Here is how I got the non-settable properties:
h = plot(1:0.2:10);
xx=get(h)
close all
h2 = plot(0);
settableHandles = set(h2);
settableNames = fieldnames(settableHandles);
allHandles = get(h2);
allNames = fieldnames(allHandles);
nonSettableHandles = rmfield(allHandles,settableNames);
nonSettableNames = fieldnames(nonSettableHandles)
This produces a cell of nonSettableNames:
nonSettableNames =
'Annotation'
'BeingDeleted'
'Type'
why not use something like
try
%// [set property]
catch ME
if ~isempty( regexp(ME.error, 'read only') )
continue;
else
%// [handle other error]
end
end
I am trying to implement save/load functions in a MATLAB (R2009a) UI. My object implements a layout function that generates a user interface for the object. I am trying to implement the callbacks for the save/load buttons. The save button works and save the object out to a MAT file which can be loaded later.
My problem is implementing the callback for the load button. I cannot seem to get the load to load the data from the MAT file and update the properties of the new object. Any suggestions on where I am going wrong along with suggestions on how I might proceed is greatly appreciated.
The important code is my class definition file of course my actual object implements many more properties and methods but here is a skeleton of what I have
classdef myObj<handle
properties
image % property holds a matlab image matrix
objCount % number of objects in image
end
properties(Transient=true)
parent
children
end
methods
function myObj
% empty constructor
end
function load_object(self)
% ask user for file
[fileName, pathToFile]=uigetfile('*.mat','Select .mat file');
tmp = load(fullfile(pathToFile,fileName);
if isfield(tmp,'obj')
self = tmp.obj;
end
end
LayoutFcn(self) % UI layout function
end
end
The UI layout is defined in a seperate file LayoutFcn.m which basically looks like
function LayoutFcn(self)
% create figure window and add various UI elements
...
% create load button
self.children(end+1) = uipushtool('Parent',hToolbar, ... % set parent to current toolbar
'CData',iconRead('open-document.png'), ... % read icon image from file
'Tag','uiLoad', ...
'ClickedCallback',#(hObj,event)loadingMyObject(self,hObj,event));
% create save button
self.children(end+1) = uipushtool('Parent',hToolbar, ... % set parent to current toolbar
'CData',iconRead('save-document.png'), ... % read icon image from file
'Tag','uiSave', ...
'ClickedCallback',#(hObj,event)savingMyObject(self,hObj,event));
...
end
function loadingMyObject(self,hObj,event)
self.load_object; % call load_object method defined above in class definition
end
function savingMyObject(self,hObj,event)
[fileName,pathName]=uiputfile('.mat','Save object to MAT file');
obj = self;
save(fullfile(pahtName,fileName),'obj')
end
Note: I am using MATLAB R2009a.
The code doesn't throw any errors. The way I wrote the code the parent object (represented by self) does not get updated after the call to LOAD in the method load_object. SO, this has the desired effect:
>> var = myObj;
>> var.load_object;
However, if I use the loadingMyObject callback defined in LayoutFcn.m in this fashion
>> var = myObjl
>> var.LayoutFcn
-> click Load button to call _loadingMyObject_
doesn't affect var properties. That is var will still have its default property values after clicking the Load button.
Changing the load methods to use set as suggested by gnovice throws the following error
??? Error using ==> set
Conversion to double from FujiCalibration is not possible.
even though I have set/get methods for each property; as in
method set.image(self,II)
% ... some data validation code ...
self.image = II
end
Using a loop to set each field as suggested by Mr Fooz is not really an option as my full class has public constant that throw an error when they are set.
I am looking for a solution that would avoid me having to hand code setting each field individually. Although at this point it seems like the only possibility.
I believe Mr Fooz is right. The self variable passed to load_object is an object of type "myObj", but the line:
self = tmp.obj;
is simply overwriting the self variable with the structure stored in tmp.obj. Doing:
self.image = tmp.obj.image;
should instead invoke a set operator for the image property of object self. In the MATLAB documentation there is a sample class definition with a method called "set.OfficeNumber" that illustrates this.
In addition, the following line in your function savingMyObject may be unnecessary:
obj = self;
I think it might make most sense (and make the code a little clearer) if you used the name "obj" in place of the word "self" within your class code (as the documentation tends to do). "self" doesn't appear to be any kind of special keyword in MATLAB (like it may be in other languages). It's just another variable as far as I can tell. =)
EDIT #1:
If the prospect of having to set each property individually in your load_object method doesn't sound like fun, one way around it is if you have a SET method for your object that is designed like the SET method for handle graphics. That SET command can accept a structure input where each field name is a property name and each field value is the new value for that property. Then you would have one call like:
set(self,tmp.obj);
Quite a bit shorter, especially if you have lots of properties to set. Of course, you'd then have to write the new SET method for your object, but the shortened syntax may be worth the extra work if it comes in handy elsewhere too. =)
EDIT #2:
You may be able to use the loop Mr Fooz suggested in conjunction with a try/catch block:
fn = fieldnames(tmp.obj);
for i = 1:numel(fn),
try
self.(fn{i}) = tmp.obj.(fn{i});
catch
% Throw a warning here, or potentially just do nothing.
end
end
Don't assign values to self. All that does is replace the binding to the self variable in the scope of the method call. It does not call a magical copy constructor to replace the object reference in the caller. Instead, copy the fields into self. Try something like:
if isfield(tmp,'obj')
self.image = tmp.obj.image;
self.objCount = tmp.obj.objCount;
end
Combining Mr Fooz's and gnovice's suggestions, I added a SET function with the following definition
function set(self,varargin)
if isa(varargin{1},'FujiCalibration')
tmp = varargin{1};
fns = fieldnames(self);
for i = 1:length(fns)
if strcmpi(fns{i}(1:2),'p_')
self.(fns{i}) = tmp.(fns{i});
end
end
self.calibImage = tmp.calibImage;
else
proplist=fields(self);
for n=1:2:length(varargin)
tmp = proplist(strcmpi(proplist,varargin{n}));
value = varargin{n+1};
switch length(tmp)
case 0
msg = char(strcat('There is no ''', varargin{n}, '''property'));
error('FujiCalibration:setPropertyChk',msg)
case 1
tmp = char(tmp);
self.(tmp) = value;
end
end
end
end
I then modified the load_object method as suggested by gnovice by changing
self = tmp.obj
to
set(self,tmp.obj).
I need to make sure that properties with values I want to persist are prefixed with 'p_'.
Thanks to gnovice and Mr Fooz for their answers.