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 }