00001 #include <Python.h>
00002
00003 #include <tf2/buffer_core.h>
00004 #include <tf2/exceptions.h>
00005
00006
00007
00008 #define WRAP(x) \
00009 do { \
00010 try \
00011 { \
00012 x; \
00013 } \
00014 catch (const tf2::ConnectivityException &e) \
00015 { \
00016 PyErr_SetString(tf2_connectivityexception, e.what()); \
00017 return NULL; \
00018 } \
00019 catch (const tf2::LookupException &e) \
00020 { \
00021 PyErr_SetString(tf2_lookupexception, e.what()); \
00022 return NULL; \
00023 } \
00024 catch (const tf2::ExtrapolationException &e) \
00025 { \
00026 PyErr_SetString(tf2_extrapolationexception, e.what()); \
00027 return NULL; \
00028 } \
00029 catch (const tf2::InvalidArgumentException &e) \
00030 { \
00031 PyErr_SetString(tf2_invalidargumentexception, e.what()); \
00032 return NULL; \
00033 } \
00034 catch (const tf2::TimeoutException &e) \
00035 { \
00036 PyErr_SetString(tf2_timeoutexception, e.what()); \
00037 return NULL; \
00038 } \
00039 catch (const tf2::TransformException &e) \
00040 { \
00041 PyErr_SetString(tf2_exception, e.what()); \
00042 return NULL; \
00043 } \
00044 } while (0)
00045
00046 static PyObject *pModulerospy = NULL;
00047 static PyObject *pModulegeometrymsgs = NULL;
00048 static PyObject *tf2_exception = NULL;
00049 static PyObject *tf2_connectivityexception = NULL, *tf2_lookupexception = NULL, *tf2_extrapolationexception = NULL,
00050 *tf2_invalidargumentexception = NULL, *tf2_timeoutexception = NULL;
00051
00052 struct buffer_core_t {
00053 PyObject_HEAD
00054 tf2::BufferCore *bc;
00055 };
00056
00057 static PyTypeObject buffer_core_Type = {
00058 PyObject_HEAD_INIT(&PyType_Type)
00059 0,
00060 "_tf2.BufferCore",
00061 sizeof(buffer_core_t),
00062 };
00063
00064 static PyObject *PyObject_BorrowAttrString(PyObject* o, const char *name)
00065 {
00066 PyObject *r = PyObject_GetAttrString(o, name);
00067 if (r != NULL)
00068 Py_DECREF(r);
00069 return r;
00070 }
00071
00072 static PyObject *transform_converter(const geometry_msgs::TransformStamped* transform)
00073 {
00074 PyObject *pclass, *pargs, *pinst = NULL;
00075 pclass = PyObject_GetAttrString(pModulegeometrymsgs, "TransformStamped");
00076 if(pclass == NULL)
00077 {
00078 printf("Can't get geometry_msgs.msg.TransformedStamped\n");
00079 return NULL;
00080 }
00081
00082 pargs = Py_BuildValue("()");
00083 if(pargs == NULL)
00084 {
00085 printf("Can't build argument list\n");
00086 return NULL;
00087 }
00088
00089 pinst = PyEval_CallObject(pclass, pargs);
00090 Py_DECREF(pclass);
00091 Py_DECREF(pargs);
00092 if(pinst == NULL)
00093 {
00094 printf("Can't create class\n");
00095 return NULL;
00096 }
00097
00098
00099 PyObject *rospy_time = PyObject_GetAttrString(pModulerospy, "Time");
00100 PyObject *args = Py_BuildValue("ii", transform->header.stamp.sec, transform->header.stamp.nsec);
00101 PyObject *time_obj = PyObject_CallObject(rospy_time, args);
00102 Py_DECREF(args);
00103 Py_DECREF(rospy_time);
00104
00105 PyObject* pheader = PyObject_GetAttrString(pinst, "header");
00106 PyObject_SetAttrString(pheader, "stamp", time_obj);
00107 Py_DECREF(time_obj);
00108
00109 PyObject_SetAttrString(pheader, "frame_id", PyString_FromString((transform->header.frame_id).c_str()));
00110 Py_DECREF(pheader);
00111
00112 PyObject *ptransform = PyObject_GetAttrString(pinst, "transform");
00113 PyObject *ptranslation = PyObject_GetAttrString(ptransform, "translation");
00114 PyObject *protation = PyObject_GetAttrString(ptransform, "rotation");
00115 Py_DECREF(ptransform);
00116
00117 PyObject_SetAttrString(pinst, "child_frame_id", PyString_FromString((transform->child_frame_id).c_str()));
00118
00119 PyObject_SetAttrString(ptranslation, "x", PyFloat_FromDouble(transform->transform.translation.x));
00120 PyObject_SetAttrString(ptranslation, "y", PyFloat_FromDouble(transform->transform.translation.y));
00121 PyObject_SetAttrString(ptranslation, "z", PyFloat_FromDouble(transform->transform.translation.z));
00122 Py_DECREF(ptranslation);
00123
00124 PyObject_SetAttrString(protation, "x", PyFloat_FromDouble(transform->transform.rotation.x));
00125 PyObject_SetAttrString(protation, "y", PyFloat_FromDouble(transform->transform.rotation.y));
00126 PyObject_SetAttrString(protation, "z", PyFloat_FromDouble(transform->transform.rotation.z));
00127 PyObject_SetAttrString(protation, "w", PyFloat_FromDouble(transform->transform.rotation.w));
00128 Py_DECREF(protation);
00129
00130 return pinst;
00131 }
00132
00133 static int rostime_converter(PyObject *obj, ros::Time *rt)
00134 {
00135 PyObject *tsr = PyObject_CallMethod(obj, (char*)"to_sec", NULL);
00136 if (tsr == NULL) {
00137 PyErr_SetString(PyExc_TypeError, "time must have a to_sec method, e.g. rospy.Time or rospy.Duration");
00138 return 0;
00139 } else {
00140 (*rt).fromSec(PyFloat_AsDouble(tsr));
00141 Py_DECREF(tsr);
00142 return 1;
00143 }
00144 }
00145
00146 static int rosduration_converter(PyObject *obj, ros::Duration *rt)
00147 {
00148 PyObject *tsr = PyObject_CallMethod(obj, (char*)"to_sec", NULL);
00149 if (tsr == NULL) {
00150 PyErr_SetString(PyExc_TypeError, "time must have a to_sec method, e.g. rospy.Time or rospy.Duration");
00151 return 0;
00152 } else {
00153 (*rt).fromSec(PyFloat_AsDouble(tsr));
00154 Py_DECREF(tsr);
00155 return 1;
00156 }
00157 }
00158
00159 static int BufferCore_init(PyObject *self, PyObject *args, PyObject *kw)
00160 {
00161 ros::Duration cache_time;
00162
00163 cache_time.fromSec(tf2::BufferCore::DEFAULT_CACHE_TIME);
00164
00165 if (!PyArg_ParseTuple(args, "|O&", rosduration_converter, &cache_time))
00166 return -1;
00167
00168 ((buffer_core_t*)self)->bc = new tf2::BufferCore(cache_time);
00169
00170 return 0;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183 static PyObject *allFramesAsYAML(PyObject *self, PyObject *args)
00184 {
00185 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00186 return PyString_FromString(bc->allFramesAsYAML().c_str());
00187 }
00188
00189 static PyObject *allFramesAsString(PyObject *self, PyObject *args)
00190 {
00191 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00192 return PyString_FromString(bc->allFramesAsString().c_str());
00193 }
00194
00195 static PyObject *canTransformCore(PyObject *self, PyObject *args, PyObject *kw)
00196 {
00197 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00198 char *target_frame, *source_frame;
00199 ros::Time time;
00200 static const char *keywords[] = { "target_frame", "source_frame", "time", NULL };
00201
00202 if (!PyArg_ParseTupleAndKeywords(args, kw, "ssO&", (char**)keywords, &target_frame, &source_frame, rostime_converter, &time))
00203 return NULL;
00204 std::string error_msg;
00205 bool can_transform = bc->canTransform(target_frame, source_frame, time, &error_msg);
00206
00207 return Py_BuildValue("bs", can_transform, error_msg.c_str());
00208 }
00209
00210 static PyObject *canTransformFullCore(PyObject *self, PyObject *args, PyObject *kw)
00211 {
00212 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00213 char *target_frame, *source_frame, *fixed_frame;
00214 ros::Time target_time, source_time;
00215 static const char *keywords[] = { "target_frame", "target_time", "source_frame", "source_time", "fixed_frame", NULL };
00216
00217 if (!PyArg_ParseTupleAndKeywords(args, kw, "sO&sO&s", (char**)keywords,
00218 &target_frame,
00219 rostime_converter,
00220 &target_time,
00221 &source_frame,
00222 rostime_converter,
00223 &source_time,
00224 &fixed_frame))
00225 return NULL;
00226 std::string error_msg;
00227 bool can_transform = bc->canTransform(target_frame, target_time, source_frame, source_time, fixed_frame, &error_msg);
00228
00229 return Py_BuildValue("bs", can_transform, error_msg.c_str());
00230 }
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289 static PyObject *lookupTransformCore(PyObject *self, PyObject *args, PyObject *kw)
00290 {
00291 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00292 char *target_frame, *source_frame;
00293 ros::Time time;
00294 static const char *keywords[] = { "target_frame", "source_frame", "time", NULL };
00295
00296 if (!PyArg_ParseTupleAndKeywords(args, kw, "ssO&", (char**)keywords, &target_frame, &source_frame, rostime_converter, &time))
00297 return NULL;
00298 geometry_msgs::TransformStamped transform;
00299 WRAP(transform = bc->lookupTransform(target_frame, source_frame, time));
00300 geometry_msgs::Vector3 origin = transform.transform.translation;
00301 geometry_msgs::Quaternion rotation = transform.transform.rotation;
00302
00303 return Py_BuildValue("O&", transform_converter, &transform);
00304
00305
00306
00307 }
00308
00309 static PyObject *lookupTransformFullCore(PyObject *self, PyObject *args, PyObject *kw)
00310 {
00311 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00312 char *target_frame, *source_frame, *fixed_frame;
00313 ros::Time target_time, source_time;
00314 static const char *keywords[] = { "target_frame", "target_time", "source_frame", "source_time", "fixed_frame", NULL };
00315
00316 if (!PyArg_ParseTupleAndKeywords(args, kw, "sO&sO&s", (char**)keywords,
00317 &target_frame,
00318 rostime_converter,
00319 &target_time,
00320 &source_frame,
00321 rostime_converter,
00322 &source_time,
00323 &fixed_frame))
00324 return NULL;
00325 geometry_msgs::TransformStamped transform;
00326 WRAP(transform = bc->lookupTransform(target_frame, target_time, source_frame, source_time, fixed_frame));
00327 geometry_msgs::Vector3 origin = transform.transform.translation;
00328 geometry_msgs::Quaternion rotation = transform.transform.rotation;
00329
00330 return Py_BuildValue("O&", transform_converter, &transform);
00331 }
00332
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377 static PyObject *setTransform(PyObject *self, PyObject *args)
00378 {
00379 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00380 PyObject *py_transform;
00381 char *authority;
00382
00383 if (!PyArg_ParseTuple(args, "Os", &py_transform, &authority))
00384 return NULL;
00385
00386 geometry_msgs::TransformStamped transform;
00387 PyObject *header = PyObject_BorrowAttrString(py_transform, "header");
00388 transform.child_frame_id = PyString_AsString(PyObject_BorrowAttrString(py_transform, "child_frame_id"));
00389 transform.header.frame_id = PyString_AsString(PyObject_BorrowAttrString(header, "frame_id"));
00390 if (rostime_converter(PyObject_BorrowAttrString(header, "stamp"), &transform.header.stamp) != 1)
00391 return NULL;
00392
00393 PyObject *mtransform = PyObject_BorrowAttrString(py_transform, "transform");
00394 PyObject *translation = PyObject_BorrowAttrString(mtransform, "translation");
00395 transform.transform.translation.x = PyFloat_AsDouble(PyObject_BorrowAttrString(translation, "x"));
00396 transform.transform.translation.y = PyFloat_AsDouble(PyObject_BorrowAttrString(translation, "y"));
00397 transform.transform.translation.z = PyFloat_AsDouble(PyObject_BorrowAttrString(translation, "z"));
00398 PyObject *rotation = PyObject_BorrowAttrString(mtransform, "rotation");
00399 transform.transform.rotation.x = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "x"));
00400 transform.transform.rotation.y = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "y"));
00401 transform.transform.rotation.z = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "z"));
00402 transform.transform.rotation.w = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "w"));
00403
00404 bc->setTransform(transform, authority);
00405 Py_RETURN_NONE;
00406 }
00407
00408 static PyObject *setTransformStatic(PyObject *self, PyObject *args)
00409 {
00410 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00411 PyObject *py_transform;
00412 char *authority;
00413
00414 if (!PyArg_ParseTuple(args, "Os", &py_transform, &authority))
00415 return NULL;
00416
00417 geometry_msgs::TransformStamped transform;
00418 PyObject *header = PyObject_BorrowAttrString(py_transform, "header");
00419 transform.child_frame_id = PyString_AsString(PyObject_BorrowAttrString(py_transform, "child_frame_id"));
00420 transform.header.frame_id = PyString_AsString(PyObject_BorrowAttrString(header, "frame_id"));
00421 if (rostime_converter(PyObject_BorrowAttrString(header, "stamp"), &transform.header.stamp) != 1)
00422 return NULL;
00423
00424 PyObject *mtransform = PyObject_BorrowAttrString(py_transform, "transform");
00425 PyObject *translation = PyObject_BorrowAttrString(mtransform, "translation");
00426 transform.transform.translation.x = PyFloat_AsDouble(PyObject_BorrowAttrString(translation, "x"));
00427 transform.transform.translation.y = PyFloat_AsDouble(PyObject_BorrowAttrString(translation, "y"));
00428 transform.transform.translation.z = PyFloat_AsDouble(PyObject_BorrowAttrString(translation, "z"));
00429 PyObject *rotation = PyObject_BorrowAttrString(mtransform, "rotation");
00430 transform.transform.rotation.x = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "x"));
00431 transform.transform.rotation.y = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "y"));
00432 transform.transform.rotation.z = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "z"));
00433 transform.transform.rotation.w = PyFloat_AsDouble(PyObject_BorrowAttrString(rotation, "w"));
00434
00435
00436 bc->setTransform(transform, authority, true);
00437 Py_RETURN_NONE;
00438 }
00439
00440 static PyObject *clear(PyObject *self, PyObject *args)
00441 {
00442 tf2::BufferCore *bc = ((buffer_core_t*)self)->bc;
00443 bc->clear();
00444 Py_RETURN_NONE;
00445 }
00446
00447
00448
00449
00450
00451
00452
00453
00454
00455
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466 static struct PyMethodDef buffer_core_methods[] =
00467 {
00468 {"all_frames_as_yaml", allFramesAsYAML, METH_VARARGS},
00469 {"all_frames_as_string", allFramesAsString, METH_VARARGS},
00470 {"set_transform", setTransform, METH_VARARGS},
00471 {"set_transform_static", setTransformStatic, METH_VARARGS},
00472 {"can_transform_core", (PyCFunction)canTransformCore, METH_KEYWORDS},
00473 {"can_transform_full_core", (PyCFunction)canTransformFullCore, METH_KEYWORDS},
00474
00475 {"clear", (PyCFunction)clear, METH_KEYWORDS},
00476
00477
00478
00479 {"lookup_transform_core", (PyCFunction)lookupTransformCore, METH_KEYWORDS},
00480 {"lookup_transform_full_core", (PyCFunction)lookupTransformFullCore, METH_KEYWORDS},
00481
00482
00483
00484 {NULL, NULL}
00485 };
00486
00487 static PyMethodDef module_methods[] = {
00488
00489 {0, 0, 0},
00490 };
00491
00492 extern "C" void init_tf2()
00493 {
00494 PyObject *item, *m, *d;
00495
00496 #if PYTHON_API_VERSION >= 1007
00497 tf2_exception = PyErr_NewException((char*)"tf2.TransformException", NULL, NULL);
00498 tf2_connectivityexception = PyErr_NewException((char*)"tf2.ConnectivityException", tf2_exception, NULL);
00499 tf2_lookupexception = PyErr_NewException((char*)"tf2.LookupException", tf2_exception, NULL);
00500 tf2_extrapolationexception = PyErr_NewException((char*)"tf2.ExtrapolationException", tf2_exception, NULL);
00501 tf2_invalidargumentexception = PyErr_NewException((char*)"tf2.InvalidArgumentException", tf2_exception, NULL);
00502 tf2_timeoutexception = PyErr_NewException((char*)"tf2.TimeoutException", tf2_exception, NULL);
00503 #else
00504 tf2_exception = PyString_FromString("tf2.error");
00505 tf2_connectivityexception = PyString_FromString("tf2.ConnectivityException");
00506 tf2_lookupexception = PyString_FromString("tf2.LookupException");
00507 tf2_extrapolationexception = PyString_FromString("tf2.ExtrapolationException");
00508 tf2_invalidargumentexception = PyString_FromString("tf2.InvalidArgumentException");
00509 tf2_timeoutexception = PyString_FromString("tf2.TimeoutException");
00510 #endif
00511
00512 pModulerospy = PyImport_Import(item= PyString_FromString("rospy")); Py_DECREF(item);
00513 pModulegeometrymsgs = PyImport_ImportModule("geometry_msgs.msg");
00514
00515 if(pModulegeometrymsgs == NULL)
00516 {
00517 printf("Cannot load geometry_msgs module");
00518 return;
00519 }
00520
00521 buffer_core_Type.tp_alloc = PyType_GenericAlloc;
00522 buffer_core_Type.tp_new = PyType_GenericNew;
00523 buffer_core_Type.tp_init = BufferCore_init;
00524 buffer_core_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE;
00525 buffer_core_Type.tp_methods = buffer_core_methods;
00526 if (PyType_Ready(&buffer_core_Type) != 0)
00527 return;
00528
00529 m = Py_InitModule("_tf2", module_methods);
00530 PyModule_AddObject(m, "BufferCore", (PyObject *)&buffer_core_Type);
00531 d = PyModule_GetDict(m);
00532 PyDict_SetItemString(d, "TransformException", tf2_exception);
00533 PyDict_SetItemString(d, "ConnectivityException", tf2_connectivityexception);
00534 PyDict_SetItemString(d, "LookupException", tf2_lookupexception);
00535 PyDict_SetItemString(d, "ExtrapolationException", tf2_extrapolationexception);
00536 PyDict_SetItemString(d, "InvalidArgumentException", tf2_invalidargumentexception);
00537 PyDict_SetItemString(d, "TimeoutException", tf2_timeoutexception);
00538 }