-
-
Notifications
You must be signed in to change notification settings - Fork 163
/
Copy pathPythonPlugin.cpp
91 lines (70 loc) · 3.29 KB
/
PythonPlugin.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
#include "webots_ros2_driver/PythonPlugin.hpp"
static PyObject *gPyWebotsNode = NULL;
namespace webots_ros2_driver {
PythonPlugin::PythonPlugin(PyObject *pyPlugin) : mPyPlugin(pyPlugin){};
void PythonPlugin::init(webots_ros2_driver::WebotsNode *node, std::unordered_map<std::string, std::string> ¶meters) {
PyObject *pyParameters = PyDict_New();
for (const std::pair<std::string, std::string> ¶meter : parameters)
PyDict_SetItem(pyParameters, PyUnicode_FromString(parameter.first.c_str()),
PyUnicode_FromString(parameter.second.c_str()));
PyObject_CallMethod(mPyPlugin, "init", "OO", getPyWebotsNodeInstance(), pyParameters);
PyErr_Print();
}
void PythonPlugin::step() {
PyObject_CallMethod(mPyPlugin, "step", "");
PyErr_Print();
}
PyObject *PythonPlugin::getPyWebotsNodeInstance() {
if (gPyWebotsNode)
return gPyWebotsNode;
PyObject *pyWebotsExtraModuleSource = Py_CompileString(
R"EOT(
import os
import sys
# Set WEBOTS_HOME to the webots_ros2_driver installation folder
# to load the correct libController libraries from the Python API
from ament_index_python.packages import get_package_prefix
os.environ['WEBOTS_HOME'] = get_package_prefix('webots_ros2_driver')
import controller
from controller import Supervisor
# As Driver need the controller library, we extend the path here
# to avoid to load another library named "controller" when loading vehicle library
sys.path.insert(1, os.path.dirname(controller.__file__))
from vehicle import Driver
class WebotsNode:
def __init__(self):
if Driver.isInitialisationPossible():
self.robot = Driver()
else:
self.robot = Supervisor()
)EOT",
"webots_extra", Py_file_input);
if (!pyWebotsExtraModuleSource)
throw std::runtime_error("Error: The Python module with the WebotsNode class cannot be compiled.");
PyObject *pyWebotsExtraModule = PyImport_ExecCodeModule("webots_extra", pyWebotsExtraModuleSource);
if (!pyWebotsExtraModule)
throw std::runtime_error("Error: The Python module with the WebotsNode class cannot be executed.");
PyObject *pyDict = PyModule_GetDict(pyWebotsExtraModule);
PyObject *pyClass = PyDict_GetItemString(pyDict, "WebotsNode");
gPyWebotsNode = PyObject_CallObject(pyClass, nullptr);
return gPyWebotsNode;
}
std::shared_ptr<PythonPlugin> PythonPlugin::createFromType(const std::string &type) {
const std::string moduleName = type.substr(0, type.find_last_of("."));
const std::string className = type.substr(type.find_last_of(".") + 1);
Py_Initialize();
PyObject *pyName = PyUnicode_FromString(moduleName.c_str());
PyObject *pyModule = PyImport_Import(pyName);
PyErr_Print();
// If the module cannot be found the error should be handled in the upper level (e.g. try loading C++ plugin)
if (!pyModule)
return NULL;
PyObject *pyDict = PyModule_GetDict(pyModule);
PyObject *pyClass = PyDict_GetItemString(pyDict, className.c_str());
PyErr_Print();
if (!pyClass)
throw std::runtime_error("Error in plugin " + type + ": The class " + className + " cannot be found.");
PyObject *pyPlugin = PyObject_CallObject(pyClass, nullptr);
return std::shared_ptr<PythonPlugin>(new PythonPlugin(pyPlugin));
}
} // namespace webots_ros2_driver