39 #if PY_MAJOR_VERSION >= 3
40 #define PyInt_AsLong PyLong_AsLong
41 #define PyString_FromString PyUnicode_FromString
46 const std::string
LOGNAME =
"handeye_solver_default";
50 solver_names_ = {
"Daniilidis1999",
"ParkBryan1994",
"TsaiLenz1989" };
66 const std::string& solver_name, std::string* error_message)
68 std::string local_error_message;
71 error_message = &local_error_message;
74 if (effector_wrt_world.size() != object_wrt_sensor.size())
76 *error_message =
"The sizes of the two input pose sample vectors are not equal: effector_wrt_world.size() = " +
77 std::to_string(effector_wrt_world.size()) +
78 " and object_wrt_sensor.size() == " + std::to_string(object_wrt_sensor.size());
86 *error_message =
"Unknown handeye solver name: " + solver_name;
91 char program_name[7] =
"python";
92 #if PY_MAJOR_VERSION >= 3
93 Py_SetProgramName(Py_DecodeLocale(program_name, NULL));
95 Py_SetProgramName(program_name);
97 static bool numpy_loaded{
false };
108 if (_import_array() < 0)
110 *error_message =
"Error importing numpy";
115 PyObject *python_name, *python_module, *python_class, *python_instance, *python_func_add_sample, *python_func_solve;
116 PyObject *python_args, *python_value;
119 python_name = PyString_FromString(
"handeye.calibrator");
120 python_module = PyImport_Import(python_name);
121 Py_DECREF(python_name);
124 *error_message =
"Failed to load python module: handeye.calibrator";
131 python_class = PyObject_GetAttrString(python_module,
"HandEyeCalibrator");
132 Py_DECREF(python_module);
133 if (!python_class || !PyCallable_Check(python_class))
135 *error_message =
"Can't find \"HandEyeCalibrator\" python class";
142 python_value = PyString_FromString(
"");
144 python_value = PyString_FromString(
"Fixed");
146 python_value = PyString_FromString(
"Moving");
149 *error_message =
"Can't create sensor mount type python value";
151 Py_DECREF(python_class);
157 python_args = PyTuple_New(1);
158 PyTuple_SetItem(python_args, 0, python_value);
161 *error_message =
"Can't build python arguments";
163 Py_DECREF(python_class);
167 python_instance = PyEval_CallObject(python_class, python_args);
168 Py_DECREF(python_args);
169 Py_DECREF(python_class);
170 if (!python_instance)
172 *error_message =
"Can't create \"HandEyeCalibrator\" python instance";
179 python_func_add_sample = PyObject_GetAttrString(python_instance,
"add_sample");
180 if (!python_func_add_sample || !PyCallable_Check(python_func_add_sample))
182 *error_message =
"Can't find 'add_sample' method";
184 Py_DECREF(python_instance);
190 size_t number_of_poses = effector_wrt_world.size();
191 PyArrayObject *numpy_arg_eef_wrt_base[number_of_poses], *numpy_arg_obj_wrt_sensor[number_of_poses];
192 PyObject *python_array_eef_wrt_base[number_of_poses], *python_array_obj_wrt_sensor[number_of_poses];
193 PyObject* python_args_sample[number_of_poses];
195 const int number_of_dims{ 2 };
199 for (
size_t i = 0; i < number_of_poses; ++i)
202 if (!
toCArray(effector_wrt_world[i], c_arr_eef_wrt_world[i]))
204 *error_message =
"Error converting Eigen::isometry3d to C array";
206 Py_DECREF(python_func_add_sample);
207 Py_DECREF(python_instance);
213 python_array_eef_wrt_base[i] =
214 PyArray_SimpleNewFromData(number_of_dims, dims, NPY_DOUBLE, (
void*)(c_arr_eef_wrt_world[i]));
215 if (!python_array_eef_wrt_base[i])
217 *error_message =
"Error creating PyArray object";
219 Py_DECREF(python_func_add_sample);
220 Py_DECREF(python_instance);
224 numpy_arg_eef_wrt_base[i] = (PyArrayObject*)(python_array_eef_wrt_base[i]);
225 if (PyArray_NDIM(numpy_arg_eef_wrt_base[i]) == 2)
227 npy_intp* py_array_dims = PyArray_DIMS(numpy_arg_eef_wrt_base[i]);
228 if (py_array_dims[0] != 4 || py_array_dims[1] != 4)
231 "Error PyArrayObject dims: " + std::to_string(py_array_dims[0]) +
"x" + std::to_string(py_array_dims[1]);
233 Py_DECREF(numpy_arg_eef_wrt_base[i]);
234 Py_DECREF(python_func_add_sample);
235 Py_DECREF(python_instance);
241 if (!
toCArray(object_wrt_sensor[i], c_arr_obj_wrt_sensor[i]))
243 *error_message =
"Error converting Eigen::isometry3d to C array";
245 Py_DECREF(python_func_add_sample);
246 Py_DECREF(python_instance);
252 python_array_obj_wrt_sensor[i] =
253 PyArray_SimpleNewFromData(number_of_dims, dims, NPY_DOUBLE, (
void*)(c_arr_obj_wrt_sensor[i]));
254 if (!python_array_obj_wrt_sensor[i])
256 *error_message =
"Error creating PyArray object";
258 Py_DECREF(python_func_add_sample);
259 Py_DECREF(python_instance);
263 numpy_arg_obj_wrt_sensor[i] = (PyArrayObject*)(python_array_obj_wrt_sensor[i]);
264 if (PyArray_NDIM(numpy_arg_obj_wrt_sensor[i]) == 2)
266 npy_intp* py_array_dims = PyArray_DIMS(numpy_arg_obj_wrt_sensor[i]);
267 if (py_array_dims[0] != 4 || py_array_dims[1] != 4)
270 "Error PyArrayObject dims: " + std::to_string(py_array_dims[0]) +
"x" + std::to_string(py_array_dims[1]);
272 Py_DECREF(numpy_arg_obj_wrt_sensor[i]);
273 Py_DECREF(python_func_add_sample);
274 Py_DECREF(python_instance);
280 python_args_sample[i] = Py_BuildValue(
"OO", numpy_arg_eef_wrt_base[i], numpy_arg_obj_wrt_sensor[i]);
281 if (!python_args_sample[i])
283 *error_message =
"Can't create argument tuple for 'add_sample' method";
285 Py_DECREF(python_func_add_sample);
286 Py_DECREF(python_instance);
290 python_value = PyEval_CallObject(python_func_add_sample, python_args_sample[i]);
293 *error_message =
"Error calling 'add_sample' method";
295 Py_DECREF(python_func_add_sample);
296 Py_DECREF(python_instance);
301 Py_DECREF(python_value);
303 Py_DECREF(python_func_add_sample);
306 for (
size_t i = 0; i < number_of_poses; i++)
308 std::stringstream ss;
309 ss <<
"\nnp_arg_eef_wrt_base";
314 ss << *(
double*)PyArray_GETPTR2(numpy_arg_eef_wrt_base[i], m, n) <<
" ";
316 ss <<
"\nnp_arg_obj_wrt_sensor";
321 ss << *(
double*)PyArray_GETPTR2(numpy_arg_obj_wrt_sensor[i], m, n) <<
" ";
327 python_name = PyString_FromString(
"handeye.solver");
328 python_module = PyImport_Import(python_name);
329 Py_DECREF(python_name);
332 *error_message =
"Failed to load python module: handeye.solver";
334 Py_DECREF(python_instance);
340 python_class = PyObject_GetAttrString(python_module, solver_name.c_str());
341 Py_DECREF(python_module);
342 if (!python_class || !PyCallable_Check(python_class))
344 *error_message =
"Can't find \"" + solver_name +
"\" python class";
346 Py_DECREF(python_instance);
352 python_func_solve = PyObject_GetAttrString(python_instance,
"solve");
353 if (!python_func_solve || !PyCallable_Check(python_func_solve))
355 *error_message =
"Can't find 'solve' method";
357 Py_DECREF(python_class);
358 Py_DECREF(python_instance);
364 python_args = Py_BuildValue(
"{s:O}",
"method", python_class);
365 Py_DECREF(python_class);
368 *error_message =
"Can't create argument tuple for 'solve' method";
370 Py_DECREF(python_instance);
376 python_value = PyEval_CallObjectWithKeywords(python_func_solve,
nullptr, python_args);
377 Py_DECREF(python_args);
378 Py_DECREF(python_func_solve);
379 for (
size_t i = 0; i < number_of_poses; ++i)
380 Py_DECREF(python_args_sample[i]);
381 Py_DECREF(python_instance);
384 *error_message =
"Error calling 'solve' method";
389 PyArrayObject* np_ret = (PyArrayObject*)python_value;
390 if (!PyArray_Check(python_value) || PyArray_NDIM(np_ret) != 2 || PyArray_NBYTES(np_ret) !=
sizeof(double) * 16)
392 *error_message =
"Did not return a valid array";
394 Py_DECREF(python_value);
399 std::stringstream ss;
400 ss <<
"\n Result camera-robot pose";
406 double item = *(
double*)PyArray_GETPTR2(np_ret, m, n);
413 Py_DECREF(python_value);
420 const Eigen::MatrixXd& mat = pose.matrix();
431 c_arr[i][j] = mat(i, j);