00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037 #include <openni_camera/openni_driver.h>
00038 #include <openni_camera/openni_device_kinect.h>
00039 #include <openni_camera/openni_device_primesense.h>
00040 #include <openni_camera/openni_device_xtion.h>
00041 #include <openni_camera/openni_device_oni.h>
00042 #include <sstream>
00043 #include <iostream>
00044 #include <algorithm>
00045 #include <locale>
00046 #include <cctype>
00047 #include <map>
00048
00049 #ifndef _WIN32
00050 #include <libusb-1.0/libusb.h>
00051 #else
00052 #include <boost/tokenizer.hpp>
00053 #endif
00054
00055 using namespace std;
00056 using namespace boost;
00057
00058 namespace openni_wrapper
00059 {
00060
00061 OpenNIDriver::OpenNIDriver () throw (OpenNIException)
00062 {
00063
00064 XnStatus status = context_.Init ();
00065 if (status != XN_STATUS_OK)
00066 THROW_OPENNI_EXCEPTION ("initialization failed. Reason: %s", xnGetStatusString (status));
00067
00068 updateDeviceList ();
00069 }
00070
00071 unsigned OpenNIDriver::updateDeviceList () throw ()
00072 {
00073
00074 device_context_.clear ();
00075
00076 bus_map_.clear ();
00077 serial_map_.clear ();
00078 connection_string_map_.clear ();
00079
00080
00081 static xn::NodeInfoList node_info_list;
00082 XnStatus status = context_.EnumerateProductionTrees (XN_NODE_TYPE_DEVICE, NULL, node_info_list);
00083 if (status != XN_STATUS_OK && node_info_list.Begin () != node_info_list.End ())
00084 THROW_OPENNI_EXCEPTION ("enumerating devices failed. Reason: %s", xnGetStatusString (status));
00085 else if (node_info_list.Begin () == node_info_list.End ())
00086 return 0;
00087
00088 for (xn::NodeInfoList::Iterator nodeIt = node_info_list.Begin (); nodeIt != node_info_list.End (); ++nodeIt)
00089 {
00090 connection_string_map_[(*nodeIt).GetCreationInfo ()] = device_context_.size();
00091 device_context_.push_back (DeviceContext (*nodeIt));
00092 }
00093
00094
00095 static xn::NodeInfoList depth_nodes;
00096 status = context_.EnumerateProductionTrees (XN_NODE_TYPE_DEPTH, NULL, depth_nodes, NULL);
00097 if (status != XN_STATUS_OK)
00098 THROW_OPENNI_EXCEPTION ("enumerating depth generators failed. Reason: %s", xnGetStatusString (status));
00099
00100 for (xn::NodeInfoList::Iterator nodeIt = depth_nodes.Begin (); nodeIt != depth_nodes.End (); ++nodeIt)
00101 {
00102
00103 for (xn::NodeInfoList::Iterator neededIt = (*nodeIt).GetNeededNodes ().Begin (); neededIt != (*nodeIt).GetNeededNodes ().End (); ++neededIt)
00104 {
00105 if ( connection_string_map_.count ((*neededIt).GetCreationInfo ()) )
00106 {
00107 unsigned device_index = connection_string_map_[(*neededIt).GetCreationInfo ()];
00108 device_context_[device_index].depth_node.reset (new xn::NodeInfo(*nodeIt));
00109 }
00110 }
00111 }
00112
00113
00114 static xn::NodeInfoList image_nodes;
00115 static xn::EnumerationErrors enumeration_errors;
00116 status = context_.EnumerateProductionTrees (XN_NODE_TYPE_IMAGE, NULL, image_nodes, &enumeration_errors);
00117 if (status != XN_STATUS_OK)
00118 {
00119
00120
00121
00122 if((enumeration_errors.Begin()).Error() != 65565) {
00123 XnChar strError[1024];
00124 enumeration_errors.ToString(strError, 1024);
00125 THROW_OPENNI_EXCEPTION("enumerating image nodes failed. Reason: %s", strError);
00126 }
00127 }
00128
00129 for (xn::NodeInfoList::Iterator nodeIt = image_nodes.Begin (); nodeIt != image_nodes.End (); ++nodeIt)
00130 {
00131
00132 for (xn::NodeInfoList::Iterator neededIt = (*nodeIt).GetNeededNodes ().Begin (); neededIt != (*nodeIt).GetNeededNodes ().End (); ++neededIt)
00133 {
00134 if ( connection_string_map_.count ((*neededIt).GetCreationInfo ()) )
00135 {
00136 unsigned device_index = connection_string_map_[(*neededIt).GetCreationInfo ()];
00137 device_context_[device_index].image_node.reset (new xn::NodeInfo(*nodeIt));
00138 }
00139 }
00140 }
00141
00142
00143 static xn::NodeInfoList ir_nodes;
00144 status = context_.EnumerateProductionTrees (XN_NODE_TYPE_IR, NULL, ir_nodes, NULL);
00145 if (status != XN_STATUS_OK)
00146 THROW_OPENNI_EXCEPTION ("enumerating IR generators failed. Reason: %s", xnGetStatusString (status));
00147
00148 for (xn::NodeInfoList::Iterator nodeIt = ir_nodes.Begin (); nodeIt != ir_nodes.End (); ++nodeIt)
00149 {
00150
00151 for (xn::NodeInfoList::Iterator neededIt = (*nodeIt).GetNeededNodes ().Begin (); neededIt != (*nodeIt).GetNeededNodes ().End (); ++neededIt)
00152 {
00153 if ( connection_string_map_.count ((*neededIt).GetCreationInfo ()) )
00154 {
00155 unsigned device_index = connection_string_map_[(*neededIt).GetCreationInfo ()];
00156 device_context_[device_index].ir_node.reset (new xn::NodeInfo(*nodeIt));
00157 }
00158 }
00159 }
00160
00161 #ifndef _WIN32
00162
00163 for (unsigned deviceIdx = 0; deviceIdx < device_context_.size (); ++deviceIdx)
00164 {
00165
00166 unsigned short vendor_id;
00167 unsigned short product_id;
00168 unsigned char bus;
00169 unsigned char address;
00170 sscanf (device_context_[deviceIdx].device_node.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00171 bus_map_ [bus][address] = deviceIdx;
00172 }
00173
00174
00175 getDeviceInfos ();
00176
00177 for (unsigned deviceIdx = 0; deviceIdx < device_context_.size (); ++deviceIdx)
00178 {
00179 std::string serial_number = getSerialNumber (deviceIdx);
00180 if (!serial_number.empty ())
00181 serial_map_[serial_number] = deviceIdx;
00182 }
00183
00184 #endif
00185
00186
00187 for (unsigned deviceIdx = 0; deviceIdx < device_context_.size (); ++deviceIdx)
00188 {
00189 unsigned short product_id;
00190 unsigned short vendor_id;
00191
00192 getDeviceType(device_context_[deviceIdx].device_node.GetCreationInfo (), vendor_id, product_id );
00193
00194 #if _WIN32
00195 if (vendor_id == 0x45e)
00196 {
00197 strcpy ((char*)device_context_[deviceIdx].device_node.GetDescription().strVendor, "Microsoft");
00198 strcpy ((char*)device_context_[deviceIdx].device_node.GetDescription().strName, "Xbox NUI Camera");
00199 }
00200 else
00201 #endif
00202 if (vendor_id == 0x1d27 && device_context_[deviceIdx].image_node.get () == 0)
00203 {
00204 strcpy ((char*)device_context_[deviceIdx].device_node.GetDescription().strVendor, "ASUS");
00205 strcpy ((char*)device_context_[deviceIdx].device_node.GetDescription().strName, "Xtion Pro");
00206 }
00207 }
00208 return (device_context_.size ());
00209 }
00210
00211 void OpenNIDriver::stopAll () throw (OpenNIException)
00212 {
00213 XnStatus status = context_.StopGeneratingAll ();
00214 if (status != XN_STATUS_OK)
00215 THROW_OPENNI_EXCEPTION ("stopping all streams failed. Reason: %s", xnGetStatusString (status));
00216 }
00217
00218 OpenNIDriver::~OpenNIDriver () throw ()
00219 {
00220
00221 try
00222 {
00223 stopAll ();
00224 }
00225 catch (...)
00226 {
00227 }
00228
00229 context_.Shutdown ();
00230 }
00231
00232 boost::shared_ptr<OpenNIDevice> OpenNIDriver::createVirtualDevice (const string& path, bool repeat, bool stream) const throw (OpenNIException)
00233 {
00234 return boost::shared_ptr<OpenNIDevice> (new DeviceONI (context_, path, repeat, stream));
00235 }
00236
00237 boost::shared_ptr<OpenNIDevice> OpenNIDriver::getDeviceByIndex (unsigned index) const throw (OpenNIException)
00238 {
00239 using namespace std;
00240
00241 if (index >= device_context_.size ())
00242 THROW_OPENNI_EXCEPTION ("device index out of range. only %d devices connected but device %d requested.", device_context_.size (), index);
00243 boost::shared_ptr<OpenNIDevice> device = device_context_[index].device.lock ();
00244 if (!device)
00245 {
00246 unsigned short vendor_id;
00247 unsigned short product_id;
00248 getDeviceType (device_context_[index].device_node.GetCreationInfo (), vendor_id, product_id );
00249
00250 if (vendor_id == 0x45e)
00251 {
00252 device = boost::shared_ptr<OpenNIDevice > (new DeviceKinect (context_, device_context_[index].device_node,
00253 *device_context_[index].image_node, *device_context_[index].depth_node,
00254 *device_context_[index].ir_node));
00255 device_context_[index].device = device;
00256 }
00257 else if (vendor_id == 0x1d27)
00258 {
00259 if (device_context_[index].image_node.get())
00260 device = boost::shared_ptr<OpenNIDevice > (new DevicePrimesense (context_, device_context_[index].device_node,
00261 *device_context_[index].image_node, *device_context_[index].depth_node,
00262 *device_context_[index].ir_node));
00263 else
00264 device = boost::shared_ptr<OpenNIDevice > (new DeviceXtionPro (context_, device_context_[index].device_node,
00265 *device_context_[index].depth_node, *device_context_[index].ir_node));
00266 device_context_[index].device = device;
00267 }
00268 else
00269 {
00270 THROW_OPENNI_EXCEPTION ("vendor %s (%s) known by primesense driver, but not by ros driver. Contact maintainer of the ros driver.",
00271 getVendorName (index), vendor_id);
00272 }
00273 }
00274 return (device);
00275 }
00276
00277 #ifndef _WIN32
00278 boost::shared_ptr<OpenNIDevice>
00279 OpenNIDriver::getDeviceBySerialNumber (const std::string& serial_number) const throw (OpenNIException)
00280 {
00281 std::map<std::string, unsigned>::const_iterator it = serial_map_.find (serial_number);
00282
00283 if (it != serial_map_.end ())
00284 {
00285 return getDeviceByIndex (it->second);
00286 }
00287
00288 THROW_OPENNI_EXCEPTION ("No device with serial number \'%s\' found", serial_number.c_str ());
00289
00290
00291 return (boost::shared_ptr<OpenNIDevice > ((OpenNIDevice*)NULL));
00292 }
00293
00294 boost::shared_ptr<OpenNIDevice>
00295 OpenNIDriver::getDeviceByAddress (unsigned char bus, unsigned char address) const throw (OpenNIException)
00296 {
00297 std::map<unsigned char, std::map<unsigned char, unsigned> >::const_iterator busIt = bus_map_.find (bus);
00298 if (busIt != bus_map_.end ())
00299 {
00300 std::map<unsigned char, unsigned>::const_iterator devIt;
00301
00302 if (address == 0)
00303 devIt = busIt->second.begin ();
00304 else
00305 devIt = busIt->second.find (address);
00306
00307 if (devIt != busIt->second.end ())
00308 {
00309 return getDeviceByIndex (devIt->second);
00310 }
00311 }
00312
00313 THROW_OPENNI_EXCEPTION ("No device on bus: %d @ %d found", (int)bus, (int)address);
00314
00315
00316 return (boost::shared_ptr<OpenNIDevice > ((OpenNIDevice*)NULL));
00317 }
00318
00319 void
00320 OpenNIDriver::getDeviceInfos () throw ()
00321 {
00322 libusb_context *context = NULL;
00323 int result;
00324 result = libusb_init (&context);
00325
00326 if (result < 0)
00327 return;
00328
00329 libusb_device **devices;
00330 int count = libusb_get_device_list (context, &devices);
00331 if (count < 0)
00332 return;
00333
00334 for (int devIdx = 0; devIdx < count; ++devIdx)
00335 {
00336 libusb_device* device = devices[devIdx];
00337 uint8_t busId = libusb_get_bus_number (device);
00338 std::map<unsigned char, std::map<unsigned char, unsigned> >::const_iterator busIt = bus_map_.find (busId);
00339 if (busIt == bus_map_.end ())
00340 continue;
00341
00342 uint8_t address = libusb_get_device_address (device);
00343 std::map<unsigned char, unsigned>::const_iterator addressIt = busIt->second.find (address);
00344 if (addressIt == busIt->second.end ())
00345 continue;
00346
00347 unsigned nodeIdx = addressIt->second;
00348 xn::NodeInfo& current_node = device_context_[nodeIdx].device_node;
00349 XnProductionNodeDescription& description = const_cast<XnProductionNodeDescription&>(current_node.GetDescription ());
00350
00351 libusb_device_descriptor descriptor;
00352 result = libusb_get_device_descriptor (devices[devIdx], &descriptor);
00353
00354 if (result < 0)
00355 {
00356 strcpy (description.strVendor, "unknown");
00357 strcpy (description.strName, "unknown");
00358 current_node.SetInstanceName ("");
00359 }
00360 else
00361 {
00362 libusb_device_handle* dev_handle;
00363 result = libusb_open (device, &dev_handle);
00364 if (result < 0)
00365 {
00366 strcpy (description.strVendor, "unknown");
00367 strcpy (description.strName, "unknown");
00368 current_node.SetInstanceName ("");
00369 }
00370 else
00371 {
00372 unsigned char buffer[1024];
00373 libusb_get_string_descriptor_ascii (dev_handle, descriptor.iManufacturer, buffer, 1024);
00374 strcpy (description.strVendor, (char*)buffer);
00375
00376 libusb_get_string_descriptor_ascii (dev_handle, descriptor.iProduct, buffer, 1024);
00377 strcpy (description.strName, (char*)buffer);
00378
00379 int len = libusb_get_string_descriptor_ascii (dev_handle, descriptor.iSerialNumber, buffer, 1024);
00380 if (len > 4)
00381 current_node.SetInstanceName ((char*)buffer);
00382 else
00383 current_node.SetInstanceName ("");
00384
00385 libusb_close (dev_handle);
00386 }
00387 }
00388 }
00389 libusb_free_device_list (devices, 1);
00390 libusb_exit (context);
00391 }
00392 #endif
00393
00394 const char* OpenNIDriver::getSerialNumber (unsigned index) const throw ()
00395 {
00396 #ifndef _WIN32
00397 return device_context_[index].device_node.GetInstanceName ();
00398 #else
00399 return "";
00400 #endif
00401 }
00402
00403 void OpenNIDriver::getDeviceType (const std::string& connectionString, unsigned short& vendorId, unsigned short& productId)
00404 {
00405 #if _WIN32
00406
00407 typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
00408 boost::char_separator<char> separators("#&_");
00409 tokenizer tokens(connectionString, separators);
00410
00411 unsigned int tokenIndex = 0;
00412 for (tokenizer::iterator tok_iter = tokens.begin(); tok_iter != tokens.end(); ++tok_iter, tokenIndex++)
00413 {
00414 std::string tokenValue = *tok_iter;
00415
00416 switch(tokenIndex) {
00417 case 2:
00418 sscanf(tokenValue.c_str(), "%hx", &vendorId);
00419 break;
00420 case 4:
00421 sscanf(tokenValue.c_str(), "%hx", &productId);
00422 break;
00423 }
00424 }
00425 #else
00426 unsigned char bus;
00427 unsigned char address;
00428 sscanf (connectionString.c_str(), "%hx/%hx@%hhu/%hhu", &vendorId, &productId, &bus, &address);
00429 #endif
00430 }
00431
00432 const char* OpenNIDriver::getConnectionString (unsigned index) const throw ()
00433 {
00434 return device_context_[index].device_node.GetCreationInfo ();
00435 }
00436
00437 const char* OpenNIDriver::getVendorName (unsigned index) const throw ()
00438 {
00439 return device_context_[index].device_node.GetDescription ().strVendor;
00440 }
00441
00442 const char* OpenNIDriver::getProductName (unsigned index) const throw ()
00443 {
00444 return device_context_[index].device_node.GetDescription ().strName;
00445 }
00446
00447 unsigned short OpenNIDriver::getVendorID (unsigned index) const throw ()
00448 {
00449 unsigned short vendor_id;
00450 unsigned short product_id;
00451 #ifndef _WIN32
00452 unsigned char bus;
00453 unsigned char address;
00454 sscanf (device_context_[index].device_node.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00455
00456 #else
00457 getDeviceType (device_context_[index].device_node.GetCreationInfo (), vendor_id, product_id);
00458 #endif
00459 return vendor_id;
00460 }
00461
00462 unsigned short OpenNIDriver::getProductID (unsigned index) const throw ()
00463 {
00464 unsigned short vendor_id;
00465 unsigned short product_id;
00466 #ifndef _WIN32
00467 unsigned char bus;
00468 unsigned char address;
00469 sscanf (device_context_[index].device_node.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00470
00471 #else
00472 getDeviceType (device_context_[index].device_node.GetCreationInfo (), vendor_id, product_id);
00473 #endif
00474 return product_id;
00475 }
00476
00477 unsigned char OpenNIDriver::getBus (unsigned index) const throw ()
00478 {
00479 unsigned char bus = 0;
00480 #ifndef _WIN32
00481 unsigned short vendor_id;
00482 unsigned short product_id;
00483 unsigned char address;
00484 sscanf (device_context_[index].device_node.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00485 #endif
00486 return bus;
00487 }
00488
00489 unsigned char OpenNIDriver::getAddress (unsigned index) const throw ()
00490 {
00491 unsigned char address = 0;
00492 #ifndef _WIN32
00493 unsigned short vendor_id;
00494 unsigned short product_id;
00495 unsigned char bus;
00496 sscanf (device_context_[index].device_node.GetCreationInfo (), "%hx/%hx@%hhu/%hhu", &vendor_id, &product_id, &bus, &address);
00497 #endif
00498 return address;
00499 }
00500
00501 OpenNIDriver::DeviceContext::DeviceContext (const xn::NodeInfo& device, xn::NodeInfo* image, xn::NodeInfo* depth, xn::NodeInfo* ir)
00502 : device_node (device)
00503 , image_node (image)
00504 , depth_node (depth)
00505 , ir_node (ir)
00506 {
00507 }
00508
00509 OpenNIDriver::DeviceContext::DeviceContext (const xn::NodeInfo& device)
00510 : device_node (device)
00511 , image_node ((xn::NodeInfo*)0)
00512 , depth_node ((xn::NodeInfo*)0)
00513 , ir_node ((xn::NodeInfo*)0)
00514 {
00515 }
00516
00517 OpenNIDriver::DeviceContext::DeviceContext (const DeviceContext& other)
00518 : device_node (other.device_node)
00519 , image_node (other.image_node)
00520 , depth_node (other.depth_node)
00521 , ir_node (other.ir_node)
00522 , device (other.device)
00523 {
00524 }
00525
00526 }