3

I need to control a Simulink control scheme from an external application, written in Python. What I need to do is to step through the simulation and, at each step, retrieve the output and let the Python application determine the new set of inputs. This for a fixed time period. Is there any way at all to do this? I admit I am having a hard time trying to achieve this using a matlab script, let alone Python. Is this doable? If not, is there a way to insert the Python module into the simulink scheme?

Thanks


EDIT: THIS IS HOW I MANAGED TO SOLVE IT

In order to run the simulation step-by-step, I created this block structure with a clock, a relational operator and an Assertion block

Simulation stepper in simulink

where Tmp is the timestamp of each pause

Tmp=get_param(bdroot,'SimulationTime')

The assertion block contains the following instructions:

set_param(bdroot,'SimulationCommand','pause')

This way, the simulation pauses after each step, i.e. (clockTime-Tmp)=timeStep.

Now, I create a Python script that launches the simulation (see accepted answer) and iterates through like this:

#While the simulation is running
while eng.get_param('simpleTest','SimulationStatus')!=('stopped' or 'terminating'):
    if eng.get_param('simpleTest','SimulationStatus')=='paused':
        #do your evaluations and operations 
        eng.set_param('simpleTest','SimulationCommand','update',nargout=0) #if you have updated any simulation parameters
        eng.set_param('simpleTest','SimulationCommand','continue',nargout=0)

This seems to work fine for me, but if there are better options, please let me know.

jd95
  • 404
  • 6
  • 14
Bianca
  • 149
  • 2
  • 10

1 Answers1

3

Using the matlab.engine bindings in Python you can start a MATLAB engine instance and send individual commands to MATLAB as a string (if you aren't already using this). This technique will let you enter in strings as if you were entering them on the MATLAB command line. For example:

 >>>import matlab.engine # load engine functionality
 >>>eng = matlab.engine.start_matlab() # init instance of engine
 >>>eng.sim("simulinkModelName") # start a simulink model by calling it through the engine instance

This also lets you pass data to MATLAB from Python, according to the documentation. From what you have stated this should be enough to achieve what you were asking.


However, another approach comes to mind which is using TCP/IP connections to communicate between the two processes (Python GUI to Simulink). This would let you send messages from one program to the next and then you could parse them accordingly. (Simulink, Matlab & Python all have TCP/IP options with them!)

In this idea I would have the GUI acting as a server and listening/sending messages to the client (simulink) in a background asynchronous thread. You could send a command to start the simulation, then stop at a certain point and wait to receive data from Python for example.

This may require a more complex understanding of the threading processes and I would recommend looking up threading in Python, as well as using sockets in Python.

If you did then want to move to another language for GUI development the TCP/IP commands would also be the same for future implementations.


I hope this can help and you get your task completed!

WoodyDev
  • 1,386
  • 1
  • 9
  • 19
  • Thank you for the reply. This is very helpful, however it still doesn't seem to solve my step by step simulation issue. I'm able to launch a Simulink module from python, but I cannot find any way to iterate through the simulation one step at a time. – Bianca Feb 20 '18 at 16:26
  • 1
    No problem! I guess the way I would go about this would be to start a TCP/IP connection in the Python GUI & the simulink model, and then have matlab functions in the Simulink model that are just something like `while(!continueMessageReceived)` so that the simulink model is stuck at a specific block until it receives the message you have chosen. This would give the same sense as iterating through the simulation one step at a time. You could then pass the necessary data to/from Simulink again before breaking from the blocking while loop. Good luck! – WoodyDev Feb 20 '18 at 16:38
  • 1
    Thank you very much for your input. Eventually, the solution was much simpler and did not involve a TCP/IP connection: what I did was creating a block that synchs with the simulation time and pauses the simulation whenever (currentTime-previousTime)=timeStep. Then, I created an if statement in python such that 'if paused, then update parameters and resume simulation', using the get_param('modelName', 'SimulationStatus') and set_param('modelName', 'SimulationCommand', 'continue') from the matlab api imported in Python. This works fine for me. – Bianca Feb 21 '18 at 22:54