How to initialize Sympy python function in Simulink

6 vues (au cours des 30 derniers jours)
Ondrej Zoufaly
Ondrej Zoufaly le 28 Jan 2024
Commenté : Ondrej Zoufaly le 26 Fév 2024
Hello,
I want to solve ODE in Simulink with python function (derived in Sympy). This is just example, real Sympy equations will be larger.
Python function called Pyfun.py:
from sympy import lambdify, Matrix, symbols
t,x1,x2 = symbols('t x1 x2')
def create_symbolic_expression():
expr = Matrix([[x2], [(1-x1**2)*x2-x1]]);
return expr
def lambdify_expression(expr):
return(lambdify([t,x1,x2],expr, modules='numpy'))
Then I have MATLAB Function in Simulink that looks like this
function y = fcn(t,u)
y = [0;0];
coder.extrinsic('py.Pyfun.create_symbolic_expression')
coder.extrinsic('py.Pyfun.lambdify_expression')
expr = py.Pyfun.create_symbolic_expression();
myfunc = py.Pyfun.lambdify_expression(expr);
y = double(myfunc(t,u(1),u(2)));
Output of this function is integrated and going back as input, as it should. Everything here works well and gives right results.
My problem is, that the MATLAB Function is calling the "create" and "lambdify" symbolic expression every iteration and it makes the calculation very slow. The question is, if there is a way to initialize the python code before the Simulink simulation and only calculate with "myfunc" expression/function. I tried to call this in InitFcn in Callbacks like this
coder.extrinsic('py.Pyfun.create_symbolic_expression')
coder.extrinsic('py.Pyfun.lambdify_expression')
expr = py.Pyfun.create_symbolic_expression();
myfunc = py.Pyfun.lambdify_expression(expr);
and run MATLAB Function only like this
function y = fcn(t,u)
y = [0;0];
y = double(myfunc(t,u(1),u(2)));
but it says "Undefined function or variable 'myfunc'.". Thank you.

Réponse acceptée

Ayush Aniket
Ayush Aniket le 19 Fév 2024
Hi Ondrej,
To avoid the repeated initialization of your Python function within the Simulink model, you can use persistent variables in your MATLAB Function block to store the function handle across function calls. The persistent variable will be initialized only once when the model starts running. Refer to the documentation below to read more about it:
You can modify your MATLAB Function block as shown below:
function y = fcn(t,u)
y = [0;0];
coder.extrinsic('py.Pyfun.create_symbolic_expression')
coder.extrinsic('py.Pyfun.lambdify_expression')
persistent myfunc
if isempty(myfunc)
expr = py.Pyfun.create_symbolic_expression();
myfunc = py.Pyfun.lambdify_expression(expr);
end
y = double(myfunc(t,u(1),u(2)));
end
In the code above, 'myfunc' is declared as a persistent variable, which means that its value is retained in memory between calls to the function. The check 'isempty(myfunc)' ensures that the Python function is only created and lambdified once, when 'myfunc' is not yet initialized (i.e., during the first function call).
The InitFcn callback in the model's Callbacks is not suitable for initializing variables used within the MATLAB Function block because the scope of variables defined in the InitFcn is not shared with the MATLAB Function block.
  1 commentaire
Ondrej Zoufaly
Ondrej Zoufaly le 26 Fév 2024
Thank you, it works much faster. The only problem now is that you can only simulate the block with the discrete sample time, do you know if there is a way to use continuous time with coder.extrinsic ? Thank you.

Connectez-vous pour commenter.

Plus de réponses (0)

Catégories

En savoir plus sur Event Functions dans Help Center et File Exchange

Produits


Version

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by