I have created a class in Python. In my application this class is a kind of lookup table.
Here is a sample class to illustrate the topic :
class ExampleClass:
def __init__(self, var1):
self.prop1 = var1
def get_property(self):
return self.prop1
Matlab offers the ability to call Python modules directly within the Matlab environment (see Matlab docs)
One calls Python like :
>>> py.importlib.import_module("ExampleClass")
>>> x = py.ExampleClass.ExampleClass(1)
>>> x.get_property()
ans =
1
What I would like to do is to make x
available in Simulink m-function blocks in order to call get_property()
from all the m-function blocks. Note that the creation of x
is computationally expensive, therefore I want to load it in the workspace once when initializing the simulation.
What I tried so far :
I tried passing my ExampleClass
to the m-functions via a mask parameter, but I get an error :
Error:Expression 'object name' for type of data 'x' did not evaluate to a valid type.
Which is understandable because Simulink does not allow to use datatypes other than int
, double
and other standard data types.
Is there a way around to be able to call x.get_property()
from my m-functions ?
To date, there is no efficient way to access those variables. For other ways to access them, see below.
coder.extrinsic
and evalin
Note : This workaround works so I share it here but the performance is not satisfactory due to the
evalin
andcoder.extrinsic
calls.
It is possible to use objects within the base workspace from a Simulink m-function block with the following functions:
Object creation in the base workspace
>>> py.importlib.import_module("ExampleClass")
>>> x = py.ExampleClass.ExampleClass(1)
In the Simulink m-function block :
function out = fcn()
coder.extrinsic('get_property_in_matlab') % goes outside of Simulink
out = 0; % Initialize output type for Simulink
out = get_property_in_matlab();
end
In Matlab we define a function to call x
function [res] = get_property_in_matlab()
x_in_matlab = evalin('base', 'x'); % Get the object from base workspace
res = x_in_matlab.get_property(); % Use the get property method
end
This workaround works but the penalty of using coder.extrinsic
and evalin
renders this solution unusable performance-wise in my case.
See documentation.
This yields the same performance as previous try with coder.extrinsic
and evalin
.
Create a Simulink object : New
--> System Object --> Simulink Extension
Then create a property for the object
% Public, tunable properties
properties
ex_class_obj
end
In the constructor add the object value :
methods
% Constructor
function obj = example_class_caller(varargin)
% Support name-value pair arguments when constructing object
setProperties(obj,nargin,varargin{:})
obj.ex_class_obj = evalin('base', 'x');
end
end
...
Make sure to choose Interpreted execution
.
Finally perform your computation in stepImpl
:
function y = stepImpl(obj)
% Implement algorithm. Calculate y as a function of input u and
% discrete states.
y= obj.ex_class_obj.get_property();
end