Using MATLAB Engine API for Python

I have a variable A= 25 (1X1 double) in my MATLAB workspace and I am using the MATLAB Engine API to call it in python by using the following code.
import matlab.engine
eng = matlab.engine.start_matlab()
var = eng.workspace['A']
print(var)
I am getting the following error message:
Error using matlab.internal.engine.getVariable
Undefined variable 'A'.
Traceback (most recent call last):
File "readingdata.py", line 20, in <module>
test = eng.workspace['A']
File "/usr/local/lib/python3.8/dist-packages/matlab/engine/matlabengine.py", line 120, in __getitem__
future = _method(attr)
File "/usr/local/lib/python3.8/dist-packages/matlab/engine/matlabengine.py", line 70, in __call__
return FutureResult(self._engine(), future, nargs, _stdout,
File "/usr/local/lib/python3.8/dist-packages/matlab/engine/futureresult.py", line 67, in result
return self.__future.result(timeout)
File "/usr/local/lib/python3.8/dist-packages/matlab/engine/fevalfuture.py", line 82, in result
self._result = pythonengine.getFEvalResult(self._future,self._nargout, None, out=self._out, err=self._err)
matlab.engine.MatlabExecutionError:
File /usr/local/MATLAB/R2022a/toolbox/matlab/external/engines/engine_api/+matlab/+internal/+engine/getVariable.m, line 27, in getVariable
Undefined variable 'A'.
I could do the same using scipy.io
Is there something I am missing?

回答 (1 件)

Kojiro Saito
Kojiro Saito 2022 年 3 月 28 日

2 投票

It's because engine.start_matlab launches a new MATALB session and there's no variable in workspace.
You need to create a session to a running MATLAB as described in this document.
In MATLAB, you need to call matlab.engine.shareEngine.
[MATLAB side]
A = 25;
matlab.engine.shareEngine
Then, you need to create a session from Python using engine.connect_matlab not engine.start_matlab.
[Python side]
import matlab.engine
eng = matlab.engine.connect_matlab()
var = eng.workspace['A']
print(var)

11 件のコメント

Ankita Tondwalkar
Ankita Tondwalkar 2022 年 3 月 28 日
Thank you for the answer. SInce I was already sharing my MATLAB session I could do without including the matlab.engine.shareEngine command.
I have a follow up question. The whole idea behind using matlab engine API was to load a predfined environment of MATLAB BAsicGridWorld in python.
When I simply load env in python it displays <matlab.object object at 0x7f2488eaa5f0>
The env is of the class rl.env.rlMDPEnv.I need to access env. Model.States and for which I have to parse differently. Is that correct?
I am currently refering https://gist.github.com/mbauman/9121961. I hope that is a correct way to go about. If not any reference would be highly appreciated.
Once again, thanks for the prompt response.
BR,
Ankita
Kojiro Saito
Kojiro Saito 2022 年 3 月 28 日
You can use eval function for accesing the element of MATLAB object.
[Python side]
import matlab.engine
eng = matlab.engine.connect_matlab()
states = eng.eval('env.Model.States')
print(states)
result:
['[1,1]', '[2,1]', '[3,1]', '[4,1]', '[5,1]', '[1,2]', '[2,2]', '[3,2]', '[4,2]', '[5,2]', '[1,3]', '[2,3]', '[3,3]', '[4,3]', '[5,3]', '[1,4]', '[2,4]', '[3,4]', '[4,4]', '[5,4]', '[1,5]', '[2,5]', '[3,5]', '[4,5]', '[5,5]']
[MATLAB side]
Based on this document's Example.
% Make MATLAB to be sharable
matlab.engine.shareEngine;
% rlMDPEnv shipping demo
GW = createGridWorld(5,5);
GW.CurrentState = '[2,1]';
GW.TerminalStates = '[5,5]';
GW.ObstacleStates = ["[3,3]";"[3,4]";"[3,5]";"[4,3]"];
updateStateTranstionForObstacles(GW)
GW.T(state2idx(GW,"[2,4]"),:,:) = 0;
GW.T(state2idx(GW,"[2,4]"),state2idx(GW,"[4,4]"),:) = 1;
nS = numel(GW.States);
nA = numel(GW.Actions);
GW.R = -1*ones(nS,nS,nA);
GW.R(state2idx(GW,"[2,4]"),state2idx(GW,"[4,4]"),:) = 5;
GW.R(:,state2idx(GW,GW.TerminalStates),:) = 10;
env = rlMDPEnv(GW);
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 3 月 28 日
Thnak you for your quick response.
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 4 月 3 日
編集済み: Ankita Tondwalkar 2022 年 4 月 3 日
@Kojiro Saito When I am trying to import the MATLAB environment in python it gives the following error:
File /usr/local/MATLAB/R2022a/toolbox/rl/rl/rlMDPEnv.m, line 31, in rlMDPEnv
Input must be a MDP model.
Line 31 of rlMDPEnv.m is env = rl.env.rlMDPEnv(MDP);
MATLAB part of the code:
GW = createGridWorld(5,5);
GW.CurrentState = '[2,1]';
GW.TerminalStates = '[5,5]';
nS = numel(GW.States);
nA = numel(GW.Actions);
GW.R = -1*ones(nS,nS,nA);
GW.R(state2idx(GW,"[2,4]"),state2idx(GW,"[4,4]"),:) = 5;
GW.R(:,state2idx(GW,GW.TerminalStates),:) = 10;
env = rlMDPEnv(GW);
Python part of the code:
import matlab.engine
eng = matlab.engine.connect_matlab()
env = eng.rlMDPEnv("GW")
model = PPO(env))
model.learn(100)
However, when I try with rlPredefinedEnv("BasicGridWorld") it does not throw any error.
Any thoughts?
Kojiro Saito
Kojiro Saito 2022 年 4 月 4 日
I think you need to import GW from MATLAB workspace to Python first.
import matlab.engine
eng = matlab.engine.connect_matlab()
#env = eng.rlMDPEnv("GW")
gw = eng.workspace['GW']
env = eng.rlMDPEnv(gw)
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 4 月 4 日
編集済み: Ankita Tondwalkar 2022 年 4 月 4 日
Thank you for the reply.
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 4 月 7 日
編集済み: Ankita Tondwalkar 2022 年 4 月 8 日
Hello @Kojiro Saito . Please find a snippet of my python code which is trying to import environment from MATLAB.
import numpy as np
eng = matlab.engine.connect_matlab()
env = eng.rlPredefinedEnv("BasicGridWorld")
action = np.array([1]) (This is because my action is a np array in my code)
action = matlab.int64(action.tolist())
obs,rew = eng.step(env,action)
obs,rew = eng.step(env,action)
TypeError: cannot unpack non-iterable float object
Basically it just returning states and not rewards, whereas when I do the same in MATLAB it returns both observation and rewards. What could be the reson for it?
Thanks,
Ankita
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 4 月 8 日
Hello Kojiro,
I found the solution to it. Instead of using, obs,rew = eng.step(env,action) , I used
t = eng.step(env, action, nargout=2) and it returned me the next observaton and reward.
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 4 月 9 日
編集済み: Ankita Tondwalkar 2022 年 4 月 9 日
The action space in BasicGridWorld environment is N-1, S-2, E-3 and W-4. While sampling an action from distribution in python, the four possible actions are 0 , 1, 2 and 3.
Whenever action 0 is selected to obtain the next observation and reward I get the following error:
File /usr/local/MATLAB/R2022a/toolbox/rl/rl/+rl/+env/rlMDPEnv.m, line 76, in rlMDPEnv.step
Invalid index specified.
This is my python code where I am generating an action which is a np array, since matlab does not support np array as is, I first convert it to matlab matrix and then pass it to the step function.
action = argmax(action.tolist())
action = matlab.int64(action.tolist())
output = self.eng.step(self.env,action,nargout=4)
Is this an indexing error or is it because step function can takeonly 2 arguments and I have passed 3?
Any leads will be very helpful.
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 5 月 4 日
This problem resulted from that fact how indexing works differenty in MATLAB and Python. I made sure while callig in Python I followed the indexing rule for Python.
Ankita Tondwalkar
Ankita Tondwalkar 2022 年 9 月 26 日
Hello,
I am trying to access predefined enviromen ("BasicGridWorld") variable, obsInfo and actInfo present in MATLAB workspace in Python.
While doing so, I am able to find my MATLAB session but unable to connect to it.
In my Python terminal I am getting the following error:
matlab.engine.EngineError: Unable to connect to MATLAB session 'MATLAB_3052'.
In MATLAB I am using the share engine command (but I get the error that "The current MATLAB session is shared already")while in Python I have the matlab.engine.connect_matlab(). Can anyone let me know if I am missing something?
Thanks,
Ankita

サインインしてコメントする。

カテゴリ

質問済み:

2022 年 3 月 27 日

コメント済み:

2022 年 9 月 26 日

Community Treasure Hunt

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

Start Hunting!

Translated by