GCC Code Coverage Report | |||||||||||||||||||||
|
|||||||||||||||||||||
Line | Branch | Exec | Source |
1 |
/* |
||
2 |
* Copyright 2016, |
||
3 |
* Olivier Stasse, |
||
4 |
* |
||
5 |
* CNRS |
||
6 |
* |
||
7 |
*/ |
||
8 |
/* -------------------------------------------------------------------------- */ |
||
9 |
/* --- INCLUDES ------------------------------------------------------------- */ |
||
10 |
/* -------------------------------------------------------------------------- */ |
||
11 |
|||
12 |
// POSIX.1-2001 |
||
13 |
#include <dlfcn.h> |
||
14 |
|||
15 |
// C++ includes |
||
16 |
#include <iostream> |
||
17 |
#include <sstream> |
||
18 |
|||
19 |
// Boost includes |
||
20 |
#include <boost/program_options.hpp> |
||
21 |
|||
22 |
// Dynamic Graph includes |
||
23 |
#include <dynamic-graph/pool.h> |
||
24 |
|||
25 |
// Local includes |
||
26 |
#include <sot/core/sot-loader.hh> |
||
27 |
|||
28 |
namespace po = boost::program_options; |
||
29 |
|||
30 |
namespace dynamicgraph { |
||
31 |
namespace sot { |
||
32 |
|||
33 |
✓✗ | 13 |
SotLoader::SotLoader() { |
34 |
13 |
dynamic_graph_stopped_ = true; |
|
35 |
13 |
sot_external_interface_ = nullptr; |
|
36 |
✓✗ | 13 |
sot_dynamic_library_filename_ = ""; |
37 |
13 |
sot_dynamic_library_ = nullptr; |
|
38 |
✓✗ | 13 |
device_name_ = ""; |
39 |
13 |
} |
|
40 |
|||
41 |
13 |
SotLoader::~SotLoader() { cleanUp(); } |
|
42 |
|||
43 |
2 |
int SotLoader::parseOptions(int argc, char *argv[]) { |
|
44 |
✓✗✓✗ |
6 |
po::options_description desc("Allowed options"); |
45 |
✓✗✓✗ |
2 |
desc.add_options()("help", "produce help message")( |
46 |
✓✗✓✗ |
2 |
"sot-dynamic-library", po::value<std::string>(), "Library to load"); |
47 |
✓✗✓✗ |
2 |
desc.add_options()("help", "produce help message")( |
48 |
✓✗✓✗ |
2 |
"input-file", po::value<std::string>(), "Library to load"); |
49 |
|||
50 |
// Input variable map from the command line (int argc, char* argv[]). |
||
51 |
✓✗ | 4 |
po::variables_map vm; |
52 |
✓✗✓✗ |
2 |
po::store(po::parse_command_line(argc, argv, desc), vm); |
53 |
✓✗ | 2 |
po::notify(vm); |
54 |
|||
55 |
✓✗✓✗ ✗✓ |
2 |
if (vm.count("help")) { |
56 |
std::cout << desc << "\n"; |
||
57 |
return -1; |
||
58 |
} |
||
59 |
✓✗✓✗ ✓✓ |
2 |
if (vm.count("sot-dynamic-library")) { |
60 |
✓✗✓✗ ✓✗✓✗ |
1 |
sot_dynamic_library_filename_ = vm["sot-dynamic-library"].as<std::string>(); |
61 |
✓✗✓✗ ✓✗ |
1 |
} else if (vm.count("input-file")) { |
62 |
✓✗✓✗ ✓✗✓✗ |
1 |
sot_dynamic_library_filename_ = vm["input-file"].as<std::string>(); |
63 |
} else { |
||
64 |
std::cout << "No filename specified\n"; |
||
65 |
return -1; |
||
66 |
} |
||
67 |
2 |
return 0; |
|
68 |
} |
||
69 |
|||
70 |
12 |
bool SotLoader::initialization() { |
|
71 |
// Load the library containing the AbstractSotExternalInterface. |
||
72 |
12 |
sot_dynamic_library_ = |
|
73 |
12 |
dlopen(sot_dynamic_library_filename_.c_str(), RTLD_LAZY | RTLD_GLOBAL); |
|
74 |
✗✓ | 12 |
if (!sot_dynamic_library_) { |
75 |
std::cerr << "Cannot load library: " << dlerror() << '\n'; |
||
76 |
return false; |
||
77 |
} |
||
78 |
|||
79 |
// reset errors |
||
80 |
12 |
dlerror(); |
|
81 |
|||
82 |
// Load the symbols. |
||
83 |
createSotExternalInterface_t *createSotExternalInterface = |
||
84 |
reinterpret_cast<createSotExternalInterface_t *>(reinterpret_cast<long>( |
||
85 |
12 |
dlsym(sot_dynamic_library_, "createSotExternalInterface"))); |
|
86 |
12 |
const char *dlsym_error = dlerror(); |
|
87 |
✓✓ | 12 |
if (dlsym_error) { |
88 |
✓✗✓✗ ✓✗ |
2 |
std::cerr << "Cannot load symbol create: " << dlsym_error << '\n'; |
89 |
2 |
return false; |
|
90 |
} |
||
91 |
|||
92 |
// Create robot-controller |
||
93 |
✓✗ | 10 |
sot_external_interface_ = createSotExternalInterface(); |
94 |
✗✓ | 10 |
assert(sot_external_interface_ && "Fail to create the sotExternalInterface"); |
95 |
✓✗✓✗ |
10 |
std::cout << "SoT loaded at address [" << &sot_external_interface_ |
96 |
✓✗✓✗ ✓✗✓✗ |
10 |
<< "] from " << sot_dynamic_library_filename_ << "." << std::endl; |
97 |
|||
98 |
// Init the python interpreter. |
||
99 |
20 |
std::string result, out, err; |
|
100 |
// Debug print. |
||
101 |
✓✗✓✗ |
10 |
runPythonCommand("print(\"Executing python interpreter prologue...\")", |
102 |
result, out, err); |
||
103 |
// make sure that the current environment variable are setup in the current |
||
104 |
// python interpreter. |
||
105 |
✓✗✓✗ |
10 |
runPythonCommand("import sys, os", result, out, err); |
106 |
✓✗✓✗ |
10 |
runPythonCommand("print(\"python version:\", sys.version)", result, out, err); |
107 |
✓✗✓✗ |
10 |
runPythonCommand("pythonpath = os.environ.get('PYTHONPATH', '')", result, out, |
108 |
err); |
||
109 |
✓✗✓✗ |
10 |
runPythonCommand("path = []", result, out, err); |
110 |
✓✗✓✗ |
10 |
runPythonCommand( |
111 |
"for p in pythonpath.split(':'):\n" |
||
112 |
" if p not in sys.path:\n" |
||
113 |
" path.append(p)", |
||
114 |
result, out, err); |
||
115 |
✓✗✓✗ |
10 |
runPythonCommand("path.extend(sys.path)", result, out, err); |
116 |
✓✗✓✗ |
10 |
runPythonCommand("sys.path = path", result, out, err); |
117 |
// used to be able to invoke rospy |
||
118 |
✓✗✓✗ |
10 |
runPythonCommand( |
119 |
"if not hasattr(sys, \'argv\'):\n" |
||
120 |
" sys.argv = ['sot']", |
||
121 |
result, out, err); |
||
122 |
// help setting signals |
||
123 |
✓✗✓✗ |
10 |
runPythonCommand("import numpy as np", result, out, err); |
124 |
// Debug print. |
||
125 |
✓✗✓✗ |
10 |
runPythonCommand("print(\"Executing python interpreter prologue... Done\")", |
126 |
result, out, err); |
||
127 |
|||
128 |
10 |
return true; |
|
129 |
} |
||
130 |
|||
131 |
15 |
void SotLoader::cleanUp() { |
|
132 |
// Unregister the device first if it exists to avoid a double destruction from |
||
133 |
// the pool of entity and the class that handle the Device pointer. |
||
134 |
✓✓ | 15 |
if (device_name_ != "") { |
135 |
1 |
PoolStorage::getInstance()->deregisterEntity(device_name_); |
|
136 |
} |
||
137 |
|||
138 |
// We do not destroy the FactoryStorage singleton because the module will not |
||
139 |
// be reloaded at next initialization (because Python C API cannot safely |
||
140 |
// unload a module...). |
||
141 |
// SignalCaster singleton could probably be destroyed. |
||
142 |
15 |
dynamicgraph::PoolStorage::destroy(); |
|
143 |
|||
144 |
// Load the symbols. |
||
145 |
✓✓✓✓ |
15 |
if (sot_dynamic_library_ != nullptr && sot_external_interface_ != nullptr) { |
146 |
destroySotExternalInterface_t *destroySotExternalInterface = |
||
147 |
reinterpret_cast<destroySotExternalInterface_t *>( |
||
148 |
reinterpret_cast<long>( |
||
149 |
10 |
dlsym(sot_dynamic_library_, "destroySotExternalInterface"))); |
|
150 |
10 |
const char *dlsym_error = dlerror(); |
|
151 |
✗✓ | 10 |
if (dlsym_error) { |
152 |
std::cerr << "Cannot load symbol destroy: " << dlsym_error << '\n'; |
||
153 |
return; |
||
154 |
} |
||
155 |
|||
156 |
10 |
destroySotExternalInterface(sot_external_interface_); |
|
157 |
10 |
sot_external_interface_ = nullptr; |
|
158 |
|||
159 |
/// Uncount the number of access to this library. |
||
160 |
10 |
dlclose(sot_dynamic_library_); |
|
161 |
10 |
sot_dynamic_library_ = nullptr; |
|
162 |
} |
||
163 |
} |
||
164 |
|||
165 |
118 |
void SotLoader::runPythonCommand(const std::string &command, |
|
166 |
std::string &result, std::string &out, |
||
167 |
std::string &err) { |
||
168 |
118 |
embeded_python_interpreter_.python(command, result, out, err); |
|
169 |
118 |
} |
|
170 |
|||
171 |
2 |
void SotLoader::oneIteration( |
|
172 |
std::map<std::string, SensorValues> &sensors_in, |
||
173 |
std::map<std::string, ControlValues> &control_values) { |
||
174 |
✓✓ | 2 |
if (!dynamic_graph_stopped_) { |
175 |
try { |
||
176 |
✓✗ | 1 |
sot_external_interface_->nominalSetSensors(sensors_in); |
177 |
✓✗ | 1 |
sot_external_interface_->getControl(control_values); |
178 |
} catch (std::exception &e) { |
||
179 |
std::cout << "Exception while running the graph:\n" |
||
180 |
<< e.what() << std::endl; |
||
181 |
throw e; |
||
182 |
} |
||
183 |
} |
||
184 |
2 |
} |
|
185 |
|||
186 |
1 |
void SotLoader::loadDeviceInPython(const std::string &device_name) { |
|
187 |
2 |
std::string result, out, err; |
|
188 |
// Debug print. |
||
189 |
✓✗✓✗ |
1 |
runPythonCommand("print(\"Load device from C++ to Python...\")", result, out, |
190 |
err); |
||
191 |
|||
192 |
// Import the Device entity declaration |
||
193 |
✓✗✓✗ |
1 |
runPythonCommand("from dynamic_graph.sot.core import Device", result, out, |
194 |
err); |
||
195 |
|||
196 |
// Get the existing C++ entity pointer in the Python interpreter. |
||
197 |
✓✗✓✗ ✓✗ |
1 |
runPythonCommand("loaded_device_name = \"" + device_name + "\"", result, out, |
198 |
err); |
||
199 |
✓✗✓✗ |
1 |
runPythonCommand("device_cpp_object = Device(loaded_device_name)", result, |
200 |
out, err); |
||
201 |
|||
202 |
// Debug print. |
||
203 |
✓✗✓✗ |
1 |
runPythonCommand("print(\"Load device from C++ to Python... Done!!\")", |
204 |
result, out, err); |
||
205 |
|||
206 |
// strore the device name to unregister it upon cleanup. |
||
207 |
✓✗ | 1 |
device_name_ = device_name; |
208 |
1 |
} |
|
209 |
|||
210 |
} /* namespace sot */ |
||
211 |
} /* namespace dynamicgraph */ |
Generated by: GCOVR (Version 4.2) |