How to access nested values from Python

11 次查看(过去 30 天)
Hello,
i found this old tutorial about controlling a simulink model from python:
For future reference i copy the code to here (in hopes not to infrige his copyright).
import matlab.engine
import matplotlib.pyplot as plt
class SimulinkPlant:
def __init__(self,modelName = 'plant'):
self.modelName = modelName #The name of the Simulink Model (To be placed in the same directory as the Python Code)
#Logging the variables
self.yHist = 0
self.tHist = 0
def setControlAction(self,u):
#Helper Function to set value of control action
self.eng.set_param('{}/u'.format(self.modelName),'value',str(u),nargout=0)
def getHistory(self):
#Helper Function to get Plant Output and Time History
return self.eng.workspace['output'],self.eng.workspace['tout']
def connectToMatlab(self):
print("Starting matlab")
self.eng = matlab.engine.start_matlab()
print("Connected to Matlab")
#Load the model
self.eng.eval("model = '{}'".format(self.modelName),nargout=0)
self.eng.eval("load_system(model)",nargout=0)
#Initialize Control Action to 0
self.setControlAction(0)
print("Initialized Model")
#Start Simulation and then Instantly pause
self.eng.set_param(self.modelName,'SimulationCommand','start','SimulationCommand','pause',nargout=0)
self.yHist,self.tHist = self.getHistory()
def connectController(self,controller):
self.controller = controller
self.controller.initialize()
def simulate(self):
# Control Loop
while(self.eng.get_param(self.modelName,'SimulationStatus') != ('stopped' or 'terminating')):
#Generate the Control action based on the past outputs
u = self.controller.getControlEffort(self.yHist,self.tHist)
#Set that Control Action
self.setControlAction(u)
#Pause the Simulation for each timestep
self.eng.set_param(self.modelName,'SimulationCommand','continue','SimulationCommand','pause',nargout=0)
self.yHist,self.tHist = self.getHistory()
def disconnect(self):
self.eng.set_param(self.modelName,'SimulationCommand','stop',nargout=0)
self.eng.quit()
class PIController:
def __init__(self):
#Maintain a History of Variables
self.yHist = []
self.tHist = []
self.uHist = []
self.eSum = 0
def initialize(self):
#Initialize the graph
self.fig, = plt.plot(self.tHist,self.yHist)
plt.xlim(0,10)
plt.ylim(0,20)
plt.ylabel("Plant Output")
plt.xlabel("Time(s)")
plt.title("Plant Response")
def updateGraph(self):
# Update the Graph
self.fig.set_xdata(self.tHist)
self.fig.set_ydata(self.yHist)
plt.pause(0.1)
plt.show()
def getControlEffort(self,yHist,tHist):
# Returns control action based on past outputs
self.yHist = yHist
self.tHist = tHist
self.updateGraph()
if(type(self.yHist) == float):
y = self.yHist
else:
y = self.yHist[-1][0]
# Set Point is 10
e = 10-y
self.eSum += e
u = 1*e + 0.001*self.eSum
print(y)
self.uHist.append(u)
return u
plant = SimulinkPlant(modelName="plant")
#Establishes a Connection
plant.connectToMatlab()
#Instantiates the controller
controller = PIController()
plant.connectController(controller)
#Control Loop
plant.simulate()
#Closes Connection to MATLAB
plant.disconnect()
However it seems, that the API changed and Simulink now saves it's data in out.output.
How do i access such nested values from python.
It doesn't work to just write in python:
output = self.eng.workspace['out'].output

回答(1 个)

surya venu
surya venu 2024-4-19
Hi,
You're right, trying to access "self.eng.workspace['out'].output" directly won't work because it treats 'out' as a key in the workspace dictionary and tries to access another dictionary named 'output' within it.
Here's how you can access the nested values from Python in the given scenario:
Using a Subscript
Since out seems to be a variable in the MATLAB workspace that holds a list or array, you can access its elements using a subscript. Here's the updated code:
output = self.eng.workspace['out'](1)
Hope it helps.

类别

Help CenterFile Exchange 中查找有关 Python Client Programming 的更多信息

标签

Community Treasure Hunt

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

Start Hunting!

Translated by