In simulink model I have a matlab function block. Inside the function I would like to create an array of objects in a way it is compatible with code generation.
My question is similar to the one answered here: Construct an array of objects in MATLAB
The problem is "compatible with code generation" part.
When I try to do it with repmatmatlab returns:
Arrays of objects are not supported for code generation.
When I try to do it with array of objects I see:
Recursive calls are not allowed. Function 'dummyClass.dummyClass'
participated in a recursive call.
Please find below the code I run:
embedded matlab function
function y = fcn(u)
%#codegen
x = [1 2 3];
% %% repmat way
% aa = dummyClass(x(1));
% aaArray = repmat(aa,1,3);
%% array of objects
aa = dummyClass(x);
y = u;
class file
classdef dummyClass
properties
value
end
methods
function obj = dummyClass(value)
%% array of objects
if nargin~=0
m = size(value,1);
n = size(value,2);
obj(m,n) = dummyClass;
for i = 1:m
for j = 1:n
obj(a,b).value = value(a,b);
end
end
end
% %% repmat
% obj.value = value;
end
end
end
Uncomment
As of MATLAB R2017a, there's no way to create arrays of objects that is compatible with code generation using MATLAB Coder or Simulink Coder.
As the first error message says, "arrays of objects are not supported for code generation" - it's not a problem with any specific way you're attempting to create them, they're just not supported at all.
MathWorks may introduce this feature in a future version, but it's not there right now.
Related
I'm trying to dynamically fill a property in a Matlab class.
I pass vectors to a method function and then compute various parameters. I would like to fill the properties in a for loop, see code example. The OwnClassFunction is just an example of a further function in the class, but is not implemented in the code example. How can I do this correctly?
classdef Sicherung < handle
properties
x = ([],1)
end
methods
function examplefunction(object,...
single_parameter_vector) % (n,1) n can be any size
for i=1:length(param_vector)
[object.x(i,1)] = object.OwnClassFunction(single_parameter_vector(i,1));
end
end
end
end
If i try something like that
...
properties
x = []
end
...
function ...(object,parameter)
for i=1:length(parameter)
[object.x(i)] = function(parameter(i));
end
I get the error message Subscripted assignment dimension mismatch.
I don’t have MATLAB in hand to test, but the following should work.
Your code is pretty close to a correctly functioning method. Change it as follows:
classdef Sicherung < handle
properties
x = [] % initialize to empty array
end
methods
function examplefunction(object,param_vector)
if ~isvector(param_vector)
error('vector expected') % check input
end
n = numel(param_vector)
object.x = zeros(n,1); % preallocate
for i=1:n
object.x(i) = object.OwnClassFunction(param_vector(i));
end
end
end
end
I am working on a simple System Object in Matlab/Simulink.
It looks like this :
classdef realtime_header_detectorSO < matlab.System & matlab.system.mixin.Propagates
% correlateHeader
%
% This template includes the minimum set of functions required
% to define a System object with discrete state.
properties
Header
%nrOfBitsInPreviousStep=0;
s=100;
d=zeros(1,s);
end
properties (DiscreteState)
end
properties (Access = private)
max_nr_of_packets=20;
max_packet_length_in_bytes=300;
current_packet=1;
% Pre-computed constants.
% h = commsrc.pn('GenPoly', [9 5 0],'NumBitsOut', 8,'InitialStates',ones(1,9));
% data=logical(zeros(max_nr_of_packets,max_packet_length_in_bytes*8));
end
methods (Access = protected)
function setupImpl(obj,u)
% Implement tasks that need to be performed only once,
% such as pre-computed constants.
end
function [maxCorr]= stepImpl(obj,u)
eml.extrinsic('num2str');
coder.extrinsic('sprintf');
% Implement algorithm. Calculate y as a function of
% input u and discrete states.
%y = size(u,1);
symbols=sign(u);
c=abs(conv(flipud(obj.Header),[symbols; symbols]));
maxCorr=max(c);
% maxCorr
if(maxCorr==36)
idx36=find(c(1:size(symbols,1))==36);
disp('header(s) detected at the following location(s) in bytes:');
disp(sprintf('%15.4f \n',idx36/8));
nrOfSymbols=size(symbols,1);
disp(['out of nr. of total symbols: ' num2str(nrOfSymbols)]);
disp('------');
% maxCorr
end
% y=obj.pBufferIdx;
end
function resetImpl(obj)
% Initialize discrete-state properties.
end
function varargout = isOutputFixedSizeImpl(~)
varargout = {true};
end
function varargout = getOutputSizeImpl(obj)
varargout = {[1 1]};
end
end
end
However when I compile/run it I get the following error:
The System object name 'realtime_header_detectorSO' specified in MATLAB System block 'freqScanningRT/Sync and
Find Header/detect header' is invalid.
Caused by:
Undefined function or variable 's'.
However (!) the following code compiles and runs just fine :
classdef realtime_header_detectorSO < matlab.System & matlab.system.mixin.Propagates
% correlateHeader
%
% This template includes the minimum set of functions required
% to define a System object with discrete state.
properties
Header
%nrOfBitsInPreviousStep=0;
s=100;
% d=zeros(1,s);
end
properties (DiscreteState)
end
properties (Access = private)
max_nr_of_packets=20;
max_packet_length_in_bytes=300;
current_packet=1;
% Pre-computed constants.
% h = commsrc.pn('GenPoly', [9 5 0],'NumBitsOut', 8,'InitialStates',ones(1,9));
% data=logical(zeros(max_nr_of_packets,max_packet_length_in_bytes*8));
end
methods (Access = protected)
function setupImpl(obj,u)
% Implement tasks that need to be performed only once,
% such as pre-computed constants.
end
function [maxCorr]= stepImpl(obj,u)
eml.extrinsic('num2str');
coder.extrinsic('sprintf');
% Implement algorithm. Calculate y as a function of
% input u and discrete states.
%y = size(u,1);
disp(obj.s);
symbols=sign(u);
c=abs(conv(flipud(obj.Header),[symbols; symbols]));
maxCorr=max(c);
% maxCorr
if(maxCorr==36)
idx36=find(c(1:size(symbols,1))==36);
disp('header(s) detected at the following location(s) in bytes:');
disp(sprintf('%15.4f \n',idx36/8));
nrOfSymbols=size(symbols,1);
disp(['out of nr. of total symbols: ' num2str(nrOfSymbols)]);
disp('------');
% maxCorr
end
% y=obj.pBufferIdx;
end
function resetImpl(obj)
% Initialize discrete-state properties.
end
function varargout = isOutputFixedSizeImpl(~)
varargout = {true};
end
function varargout = getOutputSizeImpl(obj)
varargout = {[1 1]};
end
end
end
So I can access s in the stepImpl(obj,u) as obj.s but I cannot access s inside the properties block, where it is defined !
Now this is confusing.
Is there way to access s inside the properties block ?
The problem is that I have to use the properties block because if I try this :
function setupImpl(obj,u)
% Implement tasks that need to be performed only once,
% such as pre-computed constants.
d=zeros(1,obj.s);
end
then I get :
Error due to multiple causes.
Caused by:
Problem creating simulation target MEX-file for model 'freqScanningRT'.
Simulink detected an error
'Computed maximum size is not bounded.
Static memory allocation requires all sizes to be bounded.
The computed size is [1 x :?].'.
The error occurred for MATLAB System block 'freqScanningRT/Sync and Find Header/detect header'. See line
34, column 15 in file
'path/realtime_header_detectorSO.m'.
The error was detected during code generation phase.
Start code generation report.
To prevent this error, use one of the following:
* Modify the System object to avoid code that does not support code generation.
* Change 'Simulate using' parameter to 'Interpreted Execution'.
Any idea how to refer to variables in the properties blocks ?
There must be a way to do this.
You should be able to use
properties
s = 100;
d = zeros(1,100);
end
right? If you already have the 100 as a default for s, you should also be able to provide this as part of the default for d.
I'm guessing that you're trying to avoid doing that because you feel uncomfortable repeating the "100". But I'd also guess that really, "100" is some sort of magic number that your system depends on; so really, you should try to pull it out as a constant in any case, whether it's repeated or not.
So in that case, you might improve things with
properties (Constant)
MYCONSTANT = 100;
end
properties
% Reference Constant class properties with the class name
s = realtime_header_detectorSO.MYCONSTANT;
d = zeros(1, realtime_header_detectorSO.MYCONSTANT);
end
You're not going to be able to do what you're originally trying to do - it's not possible to reference the name of one property within the property definition block when defining another property (even though you can perfectly well reference it within a method). I guess I understand why you find that confusing - but to clear up your confusion, note that you have no guarantee over the order in which MATLAB instantiates default values for properties. If it tried to create d before it had created s, it would obviously fail.
You can avoid this problem all together by initializing the properties in the constructor.
I get the following error while using MATLAB coder for generating a c++ code from m file with a call to a c function ompmex.c
C function calls always return scalar values but a non-scalar value is expected here.
My code is:
function [D,gamma] = DSGD2(X,H) %#codegen
[Xr,Xc]=size(X);
[Hr,Hc]=size(H);
D=zeros(Hr,Hc,'double');
D=X(:,11:210);
d1=sqrt(sum(D.*D)); D=D./repmat(d1,Xr,1);
beta=zeros(Xr,Xc,'double');
beta=coder.ceval('ompmex',H,X,H'*H,200);
Can anybody help on this. I am not getting a working answer online
function [D,gamma] = DSGD2(X,H) %#codegen
[Xr,Xc] = size(X);
[Hr,Hc] = size(H);
D = zeros(Hr,Hc,'double');
D = X(:,11:210);
d1 = sqrt(sum(D.*D));
D = D./repmat(d1,Xr,1);
% coder.ceval is tricky. I recommand to use it only if the function is
% created by c-coder too (and not as mex function!)! you need a c executable
% or a c library (generated before you trigger codegen for DSGD2).
% further more, ceval can not handle multiple
% outputs. as a workaround, always use structs for output - and for
% input too!
s = struct('beta',(zeros(Xr,Xc,'double')));
% make it work in matlab too and call ompmex function
if coder.target('MATLAB')
s = ompmex(H,X,H'*H,200);
else
coder.ceval('ompmex_initialize')
s = coder.ceval('ompmex',H,X,H'*H,200);
coder.ceval('ompmex_terminate')
end
% read out stuct value
beta = zeros(Xr,Xc,'double');
beta = s.beta;
gamma = 0; % not given by you, but c-coder needs it. so change to what ever you need
end
I am having some difficulty designing a subclass of dataset in Matlab (R2010b). I am experienced programming Matlab, but new to using its OOP features. My constructor seems to be fine, but when I try to build some methods that access data in the dataset, I can't seem to get it to work. Here is an example:
classdef mydataset < dataset
properties
end
methods
function [obj] = mydataset(obs,array)
% obs is N x 1 cell array of strings
% array is N x 2 double array
obj = obj#dataset({array,'Field1','Field2'},'ObsNames',obs)
end
function [val] = computeValue(obj)
col = obj.Field1;
% I get an error above regardless of how I try to access the dataset.
% e.g. col = double(obj(obs,'Field1')) also does not work.
% Some more code using col to determine val
end
end
end
In my method computeValue, I am trying to access the data in the dataset using dataset syntax, i.e. on the command line I could access Field1 using ".". It complains there is no method, property, or field Field1 for class mydataset. If I try the alternate syntax
col = double(obj(:,'Field1'));
it complains about the size of obj, e.g. "Index exceeds matrix dimensions".
I found a workaround using subsref:
methods
function [val] = computeValue(obj)
s.type = '.';
s.subs = 'Field1';
col = subsref(obj,s);
% Some more code using col to determine val
end
end
Although the workaround works, it is not very convenient and largely defeats the purpose of wanting a subclass of dataset. Is there some attribute or something simple I am missing?
Thank you very much.
Eric
Can you post the complete code of your class. I suppose you didn't declare your property "factor" and try to access it.
Your class should look like this :
classdef MyClass
properties
factor;
end
methods
function obj = MyClass(factor)
% The constructor set the property factor
obj.factor = factor;
end
function val = computeValue(obj)
col = obj.factor;
% ...
end
end
end
Look at the code snippet here in the mathworks documentation,
Digital Servo Control of a Hard-Disk Drive
Gf1 = tf(w1*[a1 b1*w1],[1 2*z1*w1 w1^2]); % first resonance
Gf2 = tf(w2*[a2 b2*w2],[1 2*z2*w2 w2^2]); % second resonance
Gf3 = tf(w3*[a3 b3*w3],[1 2*z3*w3 w3^2]); % third resonance
Gf4 = tf(w4*[a4 b4*w4],[1 2*z4*w4 w4^2]); % fourth resonance
my question is, how can I implement the above statements within a loop like,
% pseudo code
for i = 1:4
Gf%d = tf(w%d*[a%d b%d*w%d],[1 2*z%d*w%d w%d^2]); i
and then execute the result in matlab?
Here's one option:
w = [w1 w2 w3 w4];
%# same thing for a, b, d...
for i=1:4
Gf(i) = tf(w(i)*[a(i) b(i)*w(i)],[1 2*z(i)*w(i) w(i)^2]); % ith resonance
end
You could either use eval:
for i = 1:4
eval(sprintf('Gf%d = tf(w%d*[a%d b%d*w%d],[1 2*z%d*w%d w%d^2]);', i));
end
or you could turn your parameters into arrays. Arrays would be more efficient, if you have control over how you format your data.
The best way to do this is to use arrays.
for i = 1:n
trans(i) = % your stuff here %
end
Then just replace the different variables with the correct array indexes.