I need to use an object among several functions on a Matlab S-Function.
The object is used as a library and it is needed to set the conection with a server, get data from it in each loop and close it at the end of simulation. The use of the object its something like this:
ClassX ObjectX;
[Handle clientID]=ObjectX.setConnection(...);
while(coonection)
[result]=ObjectX.getPosition(Handle ClientID,...);
[result]=ObjectX.getAngle(Handle ClientID,...);
...
end
[result]=ObjectX.CloseConnection(...);
Its not convinient to instance and close the comunication in every loop. So I whant to create the object and set the conection on "function setup(block)", update data on "function Update(block)" and close the conection on "function Terminate(block)" but to do this I need to share the "ObjectX" an "clientID" among the functions.
I hope you can help me.
You can use a Singleton class, which is instantiated once and returns the same instance everytime you ask for it.
classdef (Sealed) SingleInstance < handle
methods (Access = private)
function obj = SingleInstance
end
end
methods (Static)
function singleObj = getInstance
persistent localObj
if isempty(localObj) || ~isvalid(localObj)
localObj = SingleInstance;
end
singleObj = localObj;
end
end
method (Access = public)
function setup(obj, block)
end
function update(obj, block)
end
function terminate(obj, block)
end
end
end
More information is available here
Related
I like the OO programming style that matlabs App Designer uses (or at least the way I'm using it). Now I'm wondering if I can use the same style in my "normal" matlab class.
What I have now:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
obj = DoSomething(obj);
disp(obj.myVar) % outputs "c"
end
function obj = DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
Which can be called externally using:
myClassInst = myClass;
myClassInst.Main()
I would like to get rid of all the "obj = " in the classdef, as is possible in App Designer. So something that would look like this:
classdef myClass
properties
myVar;
end
methods
function Main(obj)
obj.myVar = "a";
DoSomething(obj); % Just call the function without "obj = "
disp(obj.myVar) % outputs "a" because I didn't overwrite obj
end
function DoSomething(obj)
if(obj.myVar == "a")
obj.myVar="c";
else
obj.myVar = "b";
end
end
end
end
The equivalent of this seems to work in App Designer. So it appears you can modify variables in a class (instance?) in App Designer, while also being able to access the modified variable without explicitly overwriting your old class instance.
I noticed App Designer has all methods an properties set to (Access = private), though I'm not sure that has anything to do with it. Of course if I set everything to private, then I can't access the Main() method from outside anymore.
So my question is, how can I program in "normal" matlab, the same way as is possible in App Designer?
EDIT:
The following works in App Designer (I left out the methods/properties for the GUI elements):
classdef tmp < matlab.apps.AppBase
properties (Access = private)
myVar; % Description
end
methods (Access = private)
function doSomething(app)
if app.myVar == "a"
app.myVar = "c";
else
app.myVar = "b";
end
end
end
% Callbacks that handle component events
methods (Access = private)
% Code that executes after component creation
function startupFcn(app)
app.myVar = "a";
doSomething(app);
disp(app.myVar); % outputs "c"
end
end
end
You definitely can! All you have to do is inherit from the handle class, as opposed to a value class which is the default for matlab. You can also define private and public methods as in other languages.
The only thing you have to do is:
classdef myclass < handle % this is how you inherit from base class
properties
public_property
end
properties (Access=private)
private_property
end
methods
function obj = myclass() % class constructor
...
end
function public_function()
...
end
end
methods (Access=private)
function private_function()
...
end
end
end
Now every time you pass an object of this class to a function, you are not passing it by value, you are passing by reference (as you might be used to from python) and modifying it's properties modifies them also in the original object.
You need to inherit (< at the top of the class) from a handle class
classdef myClass < handle
properties
var
end
methods
function obj = myClass( varargin )
% Constructor function, called automatically when object is created
end
function someFunction( obj )
obj.randomizeVar(); % Equivalent to randomizeVar( obj );
end
function randomizeVar( obj )
obj.var = rand();
end
end
end
See the documentation for the difference between a "handle" and "value" class:
A value class constructor returns an object that is associated with the variable to which it is assigned. If you reassign this variable, MATLABĀ® creates an independent copy of the original object. If you pass this variable to a function to modify it, the function must return the modified object as an output argument. For information on value-class behavior, see Avoid Unnecessary Copies of Data.
A handle class constructor returns a handle object that is a reference to the object created. You can assign the handle object to multiple variables or pass it to functions without causing MATLAB to make a copy of the original object. A function that modifies a handle object passed as an input argument does not need to return the object.
Moreover, if you edit matlab.apps.AppBase, the class which you app designer code inherits, you can see that the first line is
classdef AppBase < handle
So you are literally doing the same thing, without the AppBase middle-man.
I am working on a MATLAB class which stores an interface object created with tcpip and includes a callback function for the interface object to use, as per the following example:
classdef wsg50_mini2 < handle
properties
TCPIP
end
%PUBLIC METHODS
methods
%CONSTRUCTOR
function obj = wsg50_mini2(varargin)
fprintf('################# I am created #################\n')
obj.TCPIP = tcpip('localhost',1000);
obj.TCPIP.OutputBufferSize = 3000;
obj.TCPIP.InputBufferSize = 3000;
obj.TCPIP.ByteOrder = 'littleEndian';
obj.TCPIP.Timeout = 1;
%Setting up Callbackfunction
obj.TCPIP.BytesAvailableFcnMode = 'byte';
obj.TCPIP.BytesAvailableFcnCount = 1;
obj.TCPIP.BytesAvailableFcn = {#obj.TCP_Callback, obj};
end
end
%PRIVATE METHODS
methods (Access = private)
%DESTRUCTOR
function delete(obj)
fprintf('################# Hey I am called! #################\n')
instrreset
end
end
%STATIC METHODS
methods (Static)
%TCP Callback
%This function will be called if one Byte is available at the TCPIP
%buffer.
function TCP_Callback(tcpsocket,event,obj)
fprintf('Loading 1 Byte Data From Buffer.\n')
end
end
end
When I clear my class the variable will be cleaned from the workspace, but the delete destructor function is not called. Why not?
I realized, that my Instruments are still active in the Instrument Control app. If I delete my Instruments from there, my delete destructor is be called.
I think it is some strange behaviour of the tcpip-class.
It sounds very much like you have the wsg50 variable reference in your Instrument Control App class, in that case when you clear the variable from the workspace because it is still referenced elsewhere it is not deleted.
Lets look at a simple example:
classdef myClass < handle
properties
name = '';
end
methods
function delete ( obj )
fprintf ( '%s being deleted\n', obj.name );
end
end
end
Right lets run some code:
var = basicClass;
var.name = '123';
If we clear this variable then you can see the delete is called:
>> clear var
being deleted
If we re run this code and make a reference elsewhere:
var = basicClass;
var.name = '123';
otherReference.var = var;
Looking at both variables they are the same (as expected):
>> var
var =
myClass with properties:
name: '123'
>> otherReference.var
ans =
myClass with properties:
name: '123'
So what happens if we clear var and look at the other reference
clear var
otherReference.var.name
>> otherReference.var
ans =
myClass with properties:
name: '123'
We can see that the class variable is alive, as it should be as this is no difference than a class being an input to a function and when that function finishes the local copy of that variable is cleared from scope.
If we really want to delete the variable then you can do the following, where you explicitly run the destructor method:
var = basicClass;
var.name = '123';
otherReference.var = var;
delete(var);
otherReference.var.name
The delete line give us:
123 being deleted
While if we look at the otherReference.var we get:
Invalid or deleted object.
This will actually delete the variable and you will see that the otherReference is now a pointer to an invalid handle.
The problem is the line obj.TCPIP.BytesAvailableFcn = {#obj.TCP_Callback, obj};. The reference #obj.TCP_Callback creates a instance of the class inside the tcpip object, which is a property of the class itself.
the most easiest solution is to clear obj.TCPIP.BytesAvailableFcn = '' inside the destructor and call the destructor manualy. This is okayish if the code is only used by its creator.
To keep the object-oriented code intact, a Wrapper-Class works for the callback-function. The main file is updated with the Wrapper Class and a Listener as shown below. The Setup of the Callback is replaced with a combination of both of them. The Destructor needs then to call the destructors of the Wrapper (Which removes the instance of itself from the Callback) and of the Listener:
classdef wsg50_mini2 < handle
properties
TCPIP
TCPIPWrapper
LH
end
%PUBLIC METHODS
methods
%CONSTRUCTOR
function obj = wsg50_mini2(varargin)
fprintf('################# I am created #################\n')
% Create TCPIP Object
obj.TCPIP = tcpip('localhost',1000);
% Create TCPIP Wrapper
obj.TCPIPWrapper = TCPIPWrapper(obj.TCPIP)
% Add Listener
obj.LH = listener(obj.TCPIPWrapper,'BytesAvailableFcn',#obj.onBytes);
obj.TCPIP.OutputBufferSize = 3000;
obj.TCPIP.InputBufferSize = 3000;
obj.TCPIP.ByteOrder = 'littleEndian';
obj.TCPIP.Timeout = 1;
end
end
%PRIVATE METHODS
methods (Access = private)
%DESTRUCTOR
function delete(obj)
fprintf('################# Hey I am called! #################\n')
% Destroy Listener
delete(obj.LH);
% destroy Wrapper
delete(obj.TCPIPWrapper);
instrreset
end
end
%STATIC METHODS
methods (Private)
function onBytes(obj,~,~)
fprintf('Loading 1 Byte Data From Buffer.\n')
end
end
end
Additional the Wrapper looks as following:
classdef TCPIPWrapper < handle
properties(Access=private)
tcpip
end
events
BytesAvailableFcn
end
methods
% tcpipCallbackWrapper Constructor
function obj = tcpipCallbackWrapper(tcpip)
disp 'CONSTRUCTED tcpipCallbackWrapper'
% Keep a reference to the tcpip object
obj.tcpip = tcpip;
% Adding this listener will result in the destructor not being
% called automatically anymore; but luckily we have myClass
% which will explicitly call it for us
obj.tcpip.BytesAvailableFcnMode = 'byte';
obj.tcpip.BytesAvailableFcnCount = 1;
obj.tcpip.BytesAvailableFcn = #obj.bytesAvailableFcn;
end
% tcpipCallbackWrapper Destructor
function delete(obj)
disp 'DESTRUCTED tcpipCallbackWrapper'
% Overwrite the callback with a new empty one, removing the
% reference from the callback to our class instance, allowing
% the instance to truly be destroyed
obj.tcpip.BytesAvailableFcn = '';
end
end
methods (Access=private)
% Callback for BytesAvailableFcn
function bytesAvailableFcn(obj,~,~)
notify(obj, 'BytesAvailableFcn');
end
end
end
Dear lovely community,
I already looked in Google and in the forum and also found some interesting posts. But in the end I still didn't get it worked. So, I am going to post the question here. I know in Matlab are already get/ Set methods implemented, but I am using objects and therefore I didn't understand where to implement them.
Overall Structure:
+Measurement\MeasurerIF
+Measurement\MeasurerComponent
In my Interface I declare my functions I want to implement and this Interface is furthermore abstract. It looks like this:
classdef MeasuererIF < handle
methods (Abstract=true)
getStatus(cObj) ;
setStatus(cObj,iStatus) ;
getInfo(cObj) ;
setInfo(cObj,sInfo) ;
end
end
Then I created the other class MeasurerComponent in which I implemented the methods and also the constructor:
classdef MeasurerComponent < PerformanceMeasurement.MeasuererIF
%% MeasurerComponent: Evaluates which model is used and contains them as childs.
% Detailed explanation goes here
properties (Access=protected)
miStatus;
msInfo;
mcData;
end
methods
%constructor
function cObj = PerformanceMeasurement.MeasurerComponent ;
cObj.miStatus = -1 ;
cObj.msInfo = 'Import' ;
cObj.mcData = [] ;
end
%Status
function setStatus(cObj,iStatus)
cObj.miStatus = iStatus;
end
function iStatus = getStatus(cObj)
iStatus = cObj.miStatus;
end
%Info
function setInfo(cObj,sInfo)
cObj.msInfo = sInfo;
end
function sInfo = getInfo(cObj)
sInfo = cObj.msInfo ;
end
end
end
Earlier I just used the getMethods and recently added the setMethods and now it doesn't work anymore. The Problem is that when I create an object
obj = Measurement.MeasurerComponent
the programm doesn't initialize the values anymore.
For a = obj.getInfo;
I receive just []
Does someone has an idea why it doesn't get initialized anymore? After I received a tip I changed the initialization process to the constructor due to the handle class.
I am really thankful and glad about each hint and tip!
Cheers
Your constructor should be defined by function cObj = MeasurerComponent, without the PerformanceMeasurement prefix. This is just the way that packages are defined and used in Matlab - you add the prefix if using the class from outside the package, but not within the package (explained here: "Note that definitions do not use the package prefix" -
http://uk.mathworks.com/help/matlab/matlab_oop/scoping-classes-with-packages.html?refresh=true).
Also, you have a typo - your abstract parent class file is called +Measurement\MeasurerIF but in the definition you spell it MeasuererIF. It doesn't matter which one it is called, but the name of the class does have to match the filename!
If I correct both of these issues, then your code becomes
+Measurement\MeasurerIF
classdef MeasurerIF < handle
methods (Abstract=true)
getStatus(cObj)
setStatus(cObj,iStatus)
getInfo(cObj)
setInfo(cObj,sInfo)
end
end
+Measurement\MeasurerIF
classdef MeasurerComponent < Measurement.MeasurerIF
%% MeasurerComponent: Evaluates which model is used and contains them
%% as childs.
properties (Access=protected)
miStatus
msInfo
mcData
end
methods
%constructor
function cObj = MeasurerComponent
cObj.miStatus = -1 ;
cObj.msInfo = 'Import' ;
cObj.mcData = [] ;
end
%Status
function setStatus(cObj,iStatus)
cObj.miStatus = iStatus;
end
function iStatus = getStatus(cObj)
iStatus = cObj.miStatus;
end
%Info
function setInfo(cObj,sInfo)
cObj.msInfo = sInfo;
end
function sInfo = getInfo(cObj)
sInfo = cObj.msInfo ;
end
end
end
and if I type the following:
obj = Measurement.MeasurerComponent;
obj.getInfo
then I get back
ans =
Import
which is what I expect.
This is the error it returns:
You cannot get the 't' property of Planet.
Error in Problem4dot10 (line 12)
name=mercury.t(mercury);
I created getter functions to return properties of the class planet:
methods %for getter functions
function t=get.t(obj)
t=obj.t;
end
function r=get.r(obj)
r=obj.r;
end
function x=get.x(obj)
x=obj.x;
end
function y=get.y(obj)
y=obj.y;
end
function vx=get.vx(obj)
vx=obj.vx;
end
function vy=get.vy(obj)
vy=obj.vy;
end
function n=get.n(obj)
n=obj.n;
end
function n=get.Name(obj)
n=obj.Name;
end
end
And I called the getter from the file Problem4dot10.m:
mercury=Planet(1,0.002,0,2*pi,1,0,'Mercury');
mercury.sett(60);
name=mercury.t(mercury);
I looked at the documentation to try to figure out it out. What I'm trying to do is create a planet class that keeps track of the position of the planet, and also calculates where the planet is in the next time step. It then assumes that new state.
It seems to me that the t property is private. You can make it public using, e.g.:
properties(SetAccess = public, GetAccess = public)
t = 0;
end
or
properties(Access = public)
t = 0;
end
Also you don't need to pass mercury into t getter method. name=mercury.t; should be enough.
It seems MATLAB handles will not respond to more than one notification from the same source at a time. Unfortunately this is a big problem for me. Here's an example of what I'm talking about:
classdef testClass < handle
events
testevent
end
methods
function obj = testClass
obj.addlistener('testevent', #obj.respond);
end
function raise(obj)
obj.notify('testevent');
end
function respond(obj, varargin)
fprintf('Responded!\n');
obj.raise();
end
end
end
when I execute the code
c = testClass;
c.raise();
The result is
Responded!
But I really want the recursion to work, though obviously in this simple example it would recurse infinitely. Is there any way to get this behavior?
You can make the listener recursive by setting the listener handle's Recursive property to true. Listener handle properties are in the event.listener help page. You just need to specify an output argument to obj.addlistener to retrieve the handle.
Here's the code I used to make it work:
classdef testClass < handle
events
testevent
end
methods
function obj = testClass
lh = obj.addlistener('testevent', #obj.respond);
lh.Recursive = true;
end
function raise(obj)
notify(obj,'testevent');
end
function respond(obj, varargin)
fprintf('Responded!\n');
obj.raise();
end
end
end
Also note that there is a default recursion limit of 500 calls, so naively the code won't infinitely recur; use set(0, 'RecursionLimit', N) to change that. I would think setting N=inf is a bad idea.