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 #include "openni2_camera/openni2_driver.h"
00033 #include "openni2_camera/openni2_exception.h"
00034
00035 #include <sensor_msgs/image_encodings.h>
00036 #include <sensor_msgs/distortion_models.h>
00037
00038 #include <boost/date_time/posix_time/posix_time.hpp>
00039 #include <boost/thread/thread.hpp>
00040
00041 namespace openni2_wrapper
00042 {
00043
00044 OpenNI2Driver::OpenNI2Driver(ros::NodeHandle& n, ros::NodeHandle& pnh) :
00045 nh_(n),
00046 pnh_(pnh),
00047 device_manager_(OpenNI2DeviceManager::getSingelton()),
00048 config_init_(false),
00049 data_skip_ir_counter_(0),
00050 data_skip_color_counter_(0),
00051 data_skip_depth_counter_ (0),
00052 ir_subscribers_(false),
00053 color_subscribers_(false),
00054 depth_subscribers_(false),
00055 depth_raw_subscribers_(false),
00056 enable_reconnect_(false)
00057 {
00058
00059 genVideoModeTableMap();
00060
00061 readConfigFromParameterServer();
00062
00063 initDevice();
00064
00065
00066 reconfigure_server_.reset(new ReconfigureServer(pnh_));
00067 reconfigure_server_->setCallback(boost::bind(&OpenNI2Driver::configCb, this, _1, _2));
00068
00069 while (!config_init_)
00070 {
00071 ROS_DEBUG("Waiting for dynamic reconfigure configuration.");
00072 boost::this_thread::sleep(boost::posix_time::milliseconds(100));
00073 }
00074 ROS_DEBUG("Dynamic reconfigure configuration received.");
00075
00076 advertiseROSTopics();
00077
00078 if( enable_reconnect_ )
00079 {
00080 ROS_WARN_STREAM("Reconnect has been enabled, only one camera "
00081 << "should be plugged into each bus");
00082 timer_ = nh_.createTimer(ros::Duration(1.0), &OpenNI2Driver::monitorConnection, this);
00083 }
00084 else
00085 {
00086 ROS_WARN_STREAM("Reconnect has been disabled");
00087 }
00088 }
00089
00090 void OpenNI2Driver::advertiseROSTopics()
00091 {
00092
00093
00094 ros::NodeHandle color_nh(nh_, "rgb");
00095 image_transport::ImageTransport color_it(color_nh);
00096 ros::NodeHandle ir_nh(nh_, "ir");
00097 image_transport::ImageTransport ir_it(ir_nh);
00098 ros::NodeHandle depth_nh(nh_, "depth");
00099 image_transport::ImageTransport depth_it(depth_nh);
00100 ros::NodeHandle depth_raw_nh(nh_, "depth");
00101 image_transport::ImageTransport depth_raw_it(depth_raw_nh);
00102 ros::NodeHandle projector_nh(nh_, "projector");
00103
00104
00105
00106
00107
00108
00109 boost::lock_guard<boost::mutex> lock(connect_mutex_);
00110
00111
00112 if (device_->hasColorSensor())
00113 {
00114 image_transport::SubscriberStatusCallback itssc = boost::bind(&OpenNI2Driver::colorConnectCb, this);
00115 ros::SubscriberStatusCallback rssc = boost::bind(&OpenNI2Driver::colorConnectCb, this);
00116 pub_color_ = color_it.advertiseCamera("image", 1, itssc, itssc, rssc, rssc);
00117 }
00118
00119 if (device_->hasIRSensor())
00120 {
00121 image_transport::SubscriberStatusCallback itssc = boost::bind(&OpenNI2Driver::irConnectCb, this);
00122 ros::SubscriberStatusCallback rssc = boost::bind(&OpenNI2Driver::irConnectCb, this);
00123 pub_ir_ = ir_it.advertiseCamera("image", 1, itssc, itssc, rssc, rssc);
00124 }
00125
00126 if (device_->hasDepthSensor())
00127 {
00128 image_transport::SubscriberStatusCallback itssc = boost::bind(&OpenNI2Driver::depthConnectCb, this);
00129 ros::SubscriberStatusCallback rssc = boost::bind(&OpenNI2Driver::depthConnectCb, this);
00130 pub_depth_raw_ = depth_it.advertiseCamera("image_raw", 1, itssc, itssc, rssc, rssc);
00131 pub_depth_ = depth_raw_it.advertiseCamera("image", 1, itssc, itssc, rssc, rssc);
00132 pub_projector_info_ = projector_nh.advertise<sensor_msgs::CameraInfo>("camera_info", 1, rssc, rssc);
00133 }
00134
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145 std::string serial_number = device_->getStringID();
00146 std::string color_name, ir_name;
00147
00148 color_name = "rgb_" + serial_number;
00149 ir_name = "depth_" + serial_number;
00150
00151
00152 color_info_manager_ = boost::make_shared<camera_info_manager::CameraInfoManager>(color_nh, color_name, color_info_url_);
00153 ir_info_manager_ = boost::make_shared<camera_info_manager::CameraInfoManager>(ir_nh, ir_name, ir_info_url_);
00154
00155 get_serial_server = nh_.advertiseService("get_serial", &OpenNI2Driver::getSerialCb,this);
00156
00157 }
00158
00159 bool OpenNI2Driver::getSerialCb(openni2_camera::GetSerialRequest& req, openni2_camera::GetSerialResponse& res) {
00160 res.serial = device_manager_->getSerial(device_->getUri());
00161 return true;
00162 }
00163
00164 void OpenNI2Driver::configCb(Config &config, uint32_t level)
00165 {
00166 bool stream_reset = false;
00167
00168 depth_ir_offset_x_ = config.depth_ir_offset_x;
00169 depth_ir_offset_y_ = config.depth_ir_offset_y;
00170 z_offset_mm_ = config.z_offset_mm;
00171 z_scaling_ = config.z_scaling;
00172
00173 ir_time_offset_ = ros::Duration(config.ir_time_offset);
00174 color_time_offset_ = ros::Duration(config.color_time_offset);
00175 depth_time_offset_ = ros::Duration(config.depth_time_offset);
00176
00177 if (lookupVideoModeFromDynConfig(config.ir_mode, ir_video_mode_)<0)
00178 {
00179 ROS_ERROR("Undefined IR video mode received from dynamic reconfigure");
00180 exit(-1);
00181 }
00182
00183 if (lookupVideoModeFromDynConfig(config.color_mode, color_video_mode_)<0)
00184 {
00185 ROS_ERROR("Undefined color video mode received from dynamic reconfigure");
00186 exit(-1);
00187 }
00188
00189 if (lookupVideoModeFromDynConfig(config.depth_mode, depth_video_mode_)<0)
00190 {
00191 ROS_ERROR("Undefined depth video mode received from dynamic reconfigure");
00192 exit(-1);
00193 }
00194
00195
00196
00197 ir_video_mode_.pixel_format_ = PIXEL_FORMAT_GRAY16;
00198 color_video_mode_.pixel_format_ = PIXEL_FORMAT_RGB888;
00199 depth_video_mode_.pixel_format_ = PIXEL_FORMAT_DEPTH_1_MM;
00200
00201 color_depth_synchronization_ = config.color_depth_synchronization;
00202 depth_registration_ = config.depth_registration;
00203
00204 auto_exposure_ = config.auto_exposure;
00205 auto_white_balance_ = config.auto_white_balance;
00206 exposure_ = config.exposure;
00207
00208 use_device_time_ = config.use_device_time;
00209
00210 data_skip_ = config.data_skip+1;
00211
00212 applyConfigToOpenNIDevice();
00213
00214 config_init_ = true;
00215
00216 old_config_ = config;
00217 }
00218
00219 void OpenNI2Driver::setIRVideoMode(const OpenNI2VideoMode& ir_video_mode)
00220 {
00221 if (device_->isIRVideoModeSupported(ir_video_mode))
00222 {
00223 if (ir_video_mode != device_->getIRVideoMode())
00224 {
00225 device_->setIRVideoMode(ir_video_mode);
00226 }
00227
00228 }
00229 else
00230 {
00231 ROS_ERROR_STREAM("Unsupported IR video mode - " << ir_video_mode);
00232 }
00233 }
00234 void OpenNI2Driver::setColorVideoMode(const OpenNI2VideoMode& color_video_mode)
00235 {
00236 if (device_->isColorVideoModeSupported(color_video_mode))
00237 {
00238 if (color_video_mode != device_->getColorVideoMode())
00239 {
00240 device_->setColorVideoMode(color_video_mode);
00241 }
00242 }
00243 else
00244 {
00245 ROS_ERROR_STREAM("Unsupported color video mode - " << color_video_mode);
00246 }
00247 }
00248 void OpenNI2Driver::setDepthVideoMode(const OpenNI2VideoMode& depth_video_mode)
00249 {
00250 if (device_->isDepthVideoModeSupported(depth_video_mode))
00251 {
00252 if (depth_video_mode != device_->getDepthVideoMode())
00253 {
00254 device_->setDepthVideoMode(depth_video_mode);
00255 }
00256 }
00257 else
00258 {
00259 ROS_ERROR_STREAM("Unsupported depth video mode - " << depth_video_mode);
00260 }
00261 }
00262
00263 void OpenNI2Driver::applyConfigToOpenNIDevice()
00264 {
00265
00266 data_skip_ir_counter_ = 0;
00267 data_skip_color_counter_= 0;
00268 data_skip_depth_counter_ = 0;
00269
00270 setIRVideoMode(ir_video_mode_);
00271 setColorVideoMode(color_video_mode_);
00272 setDepthVideoMode(depth_video_mode_);
00273
00274 if (device_->isImageRegistrationModeSupported())
00275 {
00276 try
00277 {
00278 if (!config_init_ || (old_config_.depth_registration != depth_registration_))
00279 device_->setImageRegistrationMode(depth_registration_);
00280 }
00281 catch (const OpenNI2Exception& exception)
00282 {
00283 ROS_ERROR("Could not set image registration. Reason: %s", exception.what());
00284 }
00285 }
00286
00287 try
00288 {
00289 if (!config_init_ || (old_config_.color_depth_synchronization != color_depth_synchronization_))
00290 device_->setDepthColorSync(color_depth_synchronization_);
00291 }
00292 catch (const OpenNI2Exception& exception)
00293 {
00294 ROS_ERROR("Could not set color depth synchronization. Reason: %s", exception.what());
00295 }
00296
00297 try
00298 {
00299 if (!config_init_ || (old_config_.auto_exposure != auto_exposure_))
00300 device_->setAutoExposure(auto_exposure_);
00301 }
00302 catch (const OpenNI2Exception& exception)
00303 {
00304 ROS_ERROR("Could not set auto exposure. Reason: %s", exception.what());
00305 }
00306
00307 try
00308 {
00309 if (!config_init_ || (old_config_.auto_white_balance != auto_white_balance_))
00310 device_->setAutoWhiteBalance(auto_white_balance_);
00311 }
00312 catch (const OpenNI2Exception& exception)
00313 {
00314 ROS_ERROR("Could not set auto white balance. Reason: %s", exception.what());
00315 }
00316
00317
00318
00319
00320
00321 if( (!auto_exposure_ && !auto_white_balance_) && exposure_ != 0 )
00322 {
00323 ROS_INFO_STREAM("Forcing exposure set, when auto exposure/white balance disabled");
00324 forceSetExposure();
00325 }
00326 else
00327 {
00328
00329 try
00330 {
00331 if (!config_init_ || (old_config_.exposure != exposure_))
00332 device_->setExposure(exposure_);
00333 }
00334 catch (const OpenNI2Exception& exception)
00335 {
00336 ROS_ERROR("Could not set exposure. Reason: %s", exception.what());
00337 }
00338 }
00339
00340 device_->setUseDeviceTimer(use_device_time_);
00341 }
00342
00343
00344
00345 void OpenNI2Driver::forceSetExposure()
00346 {
00347 int current_exposure_ = device_->getExposure();
00348 try
00349 {
00350 if( current_exposure_ == exposure_ )
00351 {
00352 if( exposure_ < 254 )
00353 {
00354 device_->setExposure(exposure_ + 1);
00355 }
00356 else
00357 {
00358 device_->setExposure(exposure_ - 1);
00359 }
00360 }
00361 device_->setExposure(exposure_);
00362 }
00363 catch (const OpenNI2Exception& exception)
00364 {
00365 ROS_ERROR("Could not set exposure. Reason: %s", exception.what());
00366 }
00367 }
00368
00369 void OpenNI2Driver::colorConnectCb()
00370 {
00371 if( !device_ )
00372 {
00373 ROS_WARN_STREAM("Callback in " << __FUNCTION__ << "failed due to null device");
00374 return;
00375 }
00376 boost::lock_guard<boost::mutex> lock(connect_mutex_);
00377
00378 color_subscribers_ = pub_color_.getNumSubscribers() > 0;
00379
00380 if (color_subscribers_ && !device_->isColorStreamStarted())
00381 {
00382
00383 if (device_->isIRStreamStarted())
00384 {
00385 ROS_ERROR("Cannot stream RGB and IR at the same time. Streaming RGB only.");
00386 ROS_INFO("Stopping IR stream.");
00387 device_->stopIRStream();
00388 }
00389
00390 device_->setColorFrameCallback(boost::bind(&OpenNI2Driver::newColorFrameCallback, this, _1));
00391
00392 ROS_INFO("Starting color stream.");
00393 device_->startColorStream();
00394
00395
00396 if( exposure_ != 0 )
00397 {
00398 ROS_INFO_STREAM("Exposure is set to " << exposure_ << ", forcing on color stream start");
00399
00400 boost::this_thread::sleep(boost::posix_time::milliseconds(100));
00401 forceSetExposure();
00402 }
00403
00404 }
00405 else if (!color_subscribers_ && device_->isColorStreamStarted())
00406 {
00407 ROS_INFO("Stopping color stream.");
00408 device_->stopColorStream();
00409
00410
00411 bool need_ir = pub_ir_.getNumSubscribers() > 0;
00412 if (need_ir && !device_->isIRStreamStarted())
00413 {
00414 device_->setIRFrameCallback(boost::bind(&OpenNI2Driver::newIRFrameCallback, this, _1));
00415
00416 ROS_INFO("Starting IR stream.");
00417 device_->startIRStream();
00418 }
00419 }
00420 }
00421
00422 void OpenNI2Driver::depthConnectCb()
00423 {
00424 if( !device_ )
00425 {
00426 ROS_WARN_STREAM("Callback in " << __FUNCTION__ << "failed due to null device");
00427 return;
00428 }
00429 boost::lock_guard<boost::mutex> lock(connect_mutex_);
00430
00431 depth_subscribers_ = pub_depth_.getNumSubscribers() > 0;
00432 depth_raw_subscribers_ = pub_depth_raw_.getNumSubscribers() > 0;
00433 projector_info_subscribers_ = pub_projector_info_.getNumSubscribers() > 0;
00434
00435 bool need_depth = depth_subscribers_ || depth_raw_subscribers_;
00436
00437 if (need_depth && !device_->isDepthStreamStarted())
00438 {
00439 device_->setDepthFrameCallback(boost::bind(&OpenNI2Driver::newDepthFrameCallback, this, _1));
00440
00441 ROS_INFO("Starting depth stream.");
00442 device_->startDepthStream();
00443 }
00444 else if (!need_depth && device_->isDepthStreamStarted())
00445 {
00446 ROS_INFO("Stopping depth stream.");
00447 device_->stopDepthStream();
00448 }
00449 }
00450
00451 void OpenNI2Driver::irConnectCb()
00452 {
00453 if( !device_ )
00454 {
00455 ROS_WARN_STREAM("Callback in " << __FUNCTION__ << "failed due to null device");
00456 return;
00457 }
00458 boost::lock_guard<boost::mutex> lock(connect_mutex_);
00459
00460 ir_subscribers_ = pub_ir_.getNumSubscribers() > 0;
00461
00462 if (ir_subscribers_ && !device_->isIRStreamStarted())
00463 {
00464
00465 if (device_->isColorStreamStarted())
00466 {
00467 ROS_ERROR("Cannot stream RGB and IR at the same time. Streaming RGB only.");
00468 }
00469 else
00470 {
00471 device_->setIRFrameCallback(boost::bind(&OpenNI2Driver::newIRFrameCallback, this, _1));
00472
00473 ROS_INFO("Starting IR stream.");
00474 device_->startIRStream();
00475 }
00476 }
00477 else if (!ir_subscribers_ && device_->isIRStreamStarted())
00478 {
00479 ROS_INFO("Stopping IR stream.");
00480 device_->stopIRStream();
00481 }
00482 }
00483
00484 void OpenNI2Driver::newIRFrameCallback(sensor_msgs::ImagePtr image)
00485 {
00486 if ((++data_skip_ir_counter_)%data_skip_==0)
00487 {
00488 data_skip_ir_counter_ = 0;
00489
00490 if (ir_subscribers_)
00491 {
00492 image->header.frame_id = ir_frame_id_;
00493 image->header.stamp = image->header.stamp + ir_time_offset_;
00494
00495 pub_ir_.publish(image, getIRCameraInfo(image->width, image->height, image->header.stamp));
00496 }
00497 }
00498 }
00499
00500 void OpenNI2Driver::newColorFrameCallback(sensor_msgs::ImagePtr image)
00501 {
00502 if ((++data_skip_color_counter_)%data_skip_==0)
00503 {
00504 data_skip_color_counter_ = 0;
00505
00506 if (color_subscribers_)
00507 {
00508 image->header.frame_id = color_frame_id_;
00509 image->header.stamp = image->header.stamp + color_time_offset_;
00510
00511 pub_color_.publish(image, getColorCameraInfo(image->width, image->height, image->header.stamp));
00512 }
00513 }
00514 }
00515
00516 void OpenNI2Driver::newDepthFrameCallback(sensor_msgs::ImagePtr image)
00517 {
00518 if ((++data_skip_depth_counter_)%data_skip_==0)
00519 {
00520
00521 data_skip_depth_counter_ = 0;
00522
00523 if (depth_raw_subscribers_||depth_subscribers_||projector_info_subscribers_)
00524 {
00525 image->header.stamp = image->header.stamp + depth_time_offset_;
00526
00527 if (z_offset_mm_ != 0)
00528 {
00529 uint16_t* data = reinterpret_cast<uint16_t*>(&image->data[0]);
00530 for (unsigned int i = 0; i < image->width * image->height; ++i)
00531 if (data[i] != 0)
00532 data[i] += z_offset_mm_;
00533 }
00534
00535 if (fabs(z_scaling_ - 1.0) > 1e-6)
00536 {
00537 uint16_t* data = reinterpret_cast<uint16_t*>(&image->data[0]);
00538 for (unsigned int i = 0; i < image->width * image->height; ++i)
00539 if (data[i] != 0)
00540 data[i] = static_cast<uint16_t>(data[i] * z_scaling_);
00541 }
00542
00543 sensor_msgs::CameraInfoPtr cam_info;
00544
00545 if (depth_registration_)
00546 {
00547 image->header.frame_id = color_frame_id_;
00548 cam_info = getColorCameraInfo(image->width,image->height, image->header.stamp);
00549 } else
00550 {
00551 image->header.frame_id = depth_frame_id_;
00552 cam_info = getDepthCameraInfo(image->width,image->height, image->header.stamp);
00553 }
00554
00555 if (depth_raw_subscribers_)
00556 {
00557 pub_depth_raw_.publish(image, cam_info);
00558 }
00559
00560 if (depth_subscribers_ )
00561 {
00562 sensor_msgs::ImageConstPtr floating_point_image = rawToFloatingPointConversion(image);
00563 pub_depth_.publish(floating_point_image, cam_info);
00564 }
00565
00566
00567 if (projector_info_subscribers_)
00568 {
00569 pub_projector_info_.publish(getProjectorCameraInfo(image->width, image->height, image->header.stamp));
00570 }
00571 }
00572 }
00573 }
00574
00575
00576 sensor_msgs::CameraInfoPtr OpenNI2Driver::getDefaultCameraInfo(int width, int height, double f) const
00577 {
00578 sensor_msgs::CameraInfoPtr info = boost::make_shared<sensor_msgs::CameraInfo>();
00579
00580 info->width = width;
00581 info->height = height;
00582
00583
00584 info->D.resize(5, 0.0);
00585 info->distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
00586
00587
00588 info->K.assign(0.0);
00589 info->K[0] = info->K[4] = f;
00590 info->K[2] = (width / 2) - 0.5;
00591
00592
00593 info->K[5] = (width * (3./8.)) - 0.5;
00594 info->K[8] = 1.0;
00595
00596
00597 info->R.assign(0.0);
00598 info->R[0] = info->R[4] = info->R[8] = 1.0;
00599
00600
00601 info->P.assign(0.0);
00602 info->P[0] = info->P[5] = f;
00603 info->P[2] = info->K[2];
00604 info->P[6] = info->K[5];
00605 info->P[10] = 1.0;
00606
00607 return info;
00608 }
00609
00611 sensor_msgs::CameraInfoPtr OpenNI2Driver::getColorCameraInfo(int width, int height, ros::Time time) const
00612 {
00613 sensor_msgs::CameraInfoPtr info;
00614
00615 if (color_info_manager_->isCalibrated())
00616 {
00617 info = boost::make_shared<sensor_msgs::CameraInfo>(color_info_manager_->getCameraInfo());
00618 if ( info->width != width )
00619 {
00620
00621 ROS_WARN_ONCE("Image resolution doesn't match calibration of the RGB camera. Using default parameters.");
00622 info = getDefaultCameraInfo(width, height, device_->getColorFocalLength(height));
00623 }
00624 }
00625 else
00626 {
00627
00628 info = getDefaultCameraInfo(width, height, device_->getColorFocalLength(height));
00629 }
00630
00631
00632 info->header.stamp = time;
00633 info->header.frame_id = color_frame_id_;
00634
00635 return info;
00636 }
00637
00638
00639 sensor_msgs::CameraInfoPtr OpenNI2Driver::getIRCameraInfo(int width, int height, ros::Time time) const
00640 {
00641 sensor_msgs::CameraInfoPtr info;
00642
00643 if (ir_info_manager_->isCalibrated())
00644 {
00645 info = boost::make_shared<sensor_msgs::CameraInfo>(ir_info_manager_->getCameraInfo());
00646 if ( info->width != width )
00647 {
00648
00649 ROS_WARN_ONCE("Image resolution doesn't match calibration of the IR camera. Using default parameters.");
00650 info = getDefaultCameraInfo(width, height, device_->getIRFocalLength(height));
00651 }
00652 }
00653 else
00654 {
00655
00656 info = getDefaultCameraInfo(width, height, device_->getDepthFocalLength(height));
00657 }
00658
00659
00660 info->header.stamp = time;
00661 info->header.frame_id = depth_frame_id_;
00662
00663 return info;
00664 }
00665
00666 sensor_msgs::CameraInfoPtr OpenNI2Driver::getDepthCameraInfo(int width, int height, ros::Time time) const
00667 {
00668
00669
00670
00671
00672 double scaling = (double)width / 640;
00673
00674 sensor_msgs::CameraInfoPtr info = getIRCameraInfo(width, height, time);
00675 info->K[2] -= depth_ir_offset_x_*scaling;
00676 info->K[5] -= depth_ir_offset_y_*scaling;
00677 info->P[2] -= depth_ir_offset_x_*scaling;
00678 info->P[6] -= depth_ir_offset_y_*scaling;
00679
00681 return info;
00682 }
00683
00684 sensor_msgs::CameraInfoPtr OpenNI2Driver::getProjectorCameraInfo(int width, int height, ros::Time time) const
00685 {
00686
00687
00688
00689 sensor_msgs::CameraInfoPtr info = getDepthCameraInfo(width, height, time);
00690
00691 info->P[3] = -device_->getBaseline() * info->P[0];
00692 return info;
00693 }
00694
00695 void OpenNI2Driver::readConfigFromParameterServer()
00696 {
00697 if (!pnh_.getParam("device_id", device_id_))
00698 {
00699 ROS_WARN ("~device_id is not set! Using first device.");
00700 device_id_ = "#1";
00701 }
00702
00703
00704 pnh_.param("ir_frame_id", ir_frame_id_, std::string("/openni_ir_optical_frame"));
00705 pnh_.param("rgb_frame_id", color_frame_id_, std::string("/openni_rgb_optical_frame"));
00706 pnh_.param("depth_frame_id", depth_frame_id_, std::string("/openni_depth_optical_frame"));
00707
00708 ROS_DEBUG("ir_frame_id = '%s' ", ir_frame_id_.c_str());
00709 ROS_DEBUG("rgb_frame_id = '%s' ", color_frame_id_.c_str());
00710 ROS_DEBUG("depth_frame_id = '%s' ", depth_frame_id_.c_str());
00711
00712 pnh_.param("rgb_camera_info_url", color_info_url_, std::string());
00713 pnh_.param("depth_camera_info_url", ir_info_url_, std::string());
00714
00715 pnh_.param("enable_reconnect", enable_reconnect_, true);
00716
00717 }
00718
00719 std::string OpenNI2Driver::resolveDeviceURI(const std::string& device_id) throw(OpenNI2Exception)
00720 {
00721
00722
00723 boost::shared_ptr<std::vector<std::string> > available_device_URIs =
00724 device_manager_->getConnectedDeviceURIs();
00725
00726
00727 if (device_id.size() > 1 && device_id[0] == '#')
00728 {
00729 std::istringstream device_number_str(device_id.substr(1));
00730 int device_number;
00731 device_number_str >> device_number;
00732 int device_index = device_number - 1;
00733 if (device_index >= available_device_URIs->size() || device_index < 0)
00734 {
00735 THROW_OPENNI_EXCEPTION(
00736 "Invalid device number %i, there are %zu devices connected.",
00737 device_number, available_device_URIs->size());
00738 }
00739 else
00740 {
00741 return available_device_URIs->at(device_index);
00742 }
00743 }
00744
00745
00746
00747
00748 else if (device_id.size() > 1 && device_id.find('@') != std::string::npos && device_id.find('/') == std::string::npos)
00749 {
00750
00751 size_t index = device_id.find('@');
00752 if (index <= 0)
00753 {
00754 THROW_OPENNI_EXCEPTION(
00755 "%s is not a valid device URI, you must give the bus number before the @.",
00756 device_id.c_str());
00757 }
00758 if (index >= device_id.size() - 1)
00759 {
00760 THROW_OPENNI_EXCEPTION(
00761 "%s is not a valid device URI, you must give the device number after the @, specify 0 for any device on this bus",
00762 device_id.c_str());
00763 }
00764
00765
00766 std::istringstream device_number_str(device_id.substr(index+1));
00767 int device_number;
00768 device_number_str >> device_number;
00769
00770
00771 std::string bus = device_id.substr(0, index);
00772 bus.insert(0, "@");
00773
00774 for (size_t i = 0; i < available_device_URIs->size(); ++i)
00775 {
00776 std::string s = (*available_device_URIs)[i];
00777 if (s.find(bus) != std::string::npos)
00778 {
00779
00780 std::ostringstream ss;
00781 ss << bus << '/' << device_number;
00782 if (device_number == 0 || s.find(ss.str()) != std::string::npos)
00783 return s;
00784 }
00785 }
00786
00787 THROW_OPENNI_EXCEPTION("Device not found %s", device_id.c_str());
00788 }
00789 else
00790 {
00791
00792 for(std::vector<std::string>::const_iterator it = available_device_URIs->begin();
00793 it != available_device_URIs->end(); ++it)
00794 {
00795 try {
00796 std::string serial = device_manager_->getSerial(*it);
00797 if (serial.size() > 0 && device_id == serial)
00798 return *it;
00799 }
00800 catch (const OpenNI2Exception& exception)
00801 {
00802 ROS_WARN("Could not query serial number of device \"%s\":", exception.what());
00803 }
00804 }
00805
00806
00807 bool match_found = false;
00808 std::string matched_uri;
00809 for (size_t i = 0; i < available_device_URIs->size(); ++i)
00810 {
00811 std::string s = (*available_device_URIs)[i];
00812 if (s.find(device_id) != std::string::npos)
00813 {
00814 if (!match_found)
00815 {
00816 matched_uri = s;
00817 match_found = true;
00818 }
00819 else
00820 {
00821
00822 THROW_OPENNI_EXCEPTION("Two devices match the given device id '%s': %s and %s.", device_id.c_str(), matched_uri.c_str(), s.c_str());
00823 }
00824 }
00825 }
00826 if (match_found)
00827 return matched_uri;
00828 else
00829 return "INVALID";
00830 }
00831 }
00832
00833 void OpenNI2Driver::initDevice()
00834 {
00835 while (ros::ok() && !device_)
00836 {
00837 try
00838 {
00839 std::string device_URI = resolveDeviceURI(device_id_);
00840 device_ = device_manager_->getDevice(device_URI);
00841 bus_id_ = extractBusID(device_->getUri() );
00842 }
00843 catch (const OpenNI2Exception& exception)
00844 {
00845 if (!device_)
00846 {
00847 ROS_INFO("No matching device found.... waiting for devices. Reason: %s", exception.what());
00848 boost::this_thread::sleep(boost::posix_time::seconds(3));
00849 continue;
00850 }
00851 else
00852 {
00853 ROS_ERROR("Could not retrieve device. Reason: %s", exception.what());
00854 exit(-1);
00855 }
00856 }
00857 }
00858
00859 while (ros::ok() && !device_->isValid())
00860 {
00861 ROS_DEBUG("Waiting for device initialization..");
00862 boost::this_thread::sleep(boost::posix_time::milliseconds(100));
00863 }
00864
00865 }
00866
00867
00868 int OpenNI2Driver::extractBusID(const std::string& uri) const
00869 {
00870
00871 unsigned first = uri.find('@');
00872 unsigned last = uri.find('/', first);
00873 std::string bus_id = uri.substr (first+1,last-first-1);
00874 int rtn = atoi(bus_id.c_str());
00875 return rtn;
00876 }
00877
00878
00879 bool OpenNI2Driver::isConnected() const
00880 {
00881
00882
00883
00884 boost::shared_ptr<std::vector<std::string> > list =
00885 device_manager_->getConnectedDeviceURIs();
00886 for (std::size_t i = 0; i != list->size(); ++i)
00887 {
00888 int uri_bus_id = extractBusID( list->at(i) );
00889 if( uri_bus_id == bus_id_ )
00890 {
00891 return true;
00892 }
00893 }
00894 return false;
00895 }
00896
00897 void OpenNI2Driver::monitorConnection(const ros::TimerEvent &event)
00898 {
00899
00900
00901 if( isConnected() )
00902 {
00903 if( !device_ )
00904 {
00905 ROS_INFO_STREAM("Detected re-connect...attempting reinit");
00906 try
00907 {
00908 {
00909 boost::lock_guard<boost::mutex> lock(connect_mutex_);
00910 std::string device_URI = resolveDeviceURI(device_id_);
00911 device_ = device_manager_->getDevice(device_URI);
00912 bus_id_ = extractBusID(device_->getUri() );
00913 while (ros::ok() && !device_->isValid())
00914 {
00915 ROS_INFO("Waiting for device initialization, before configuring and restarting publishers");
00916 boost::this_thread::sleep(boost::posix_time::milliseconds(100));
00917 }
00918 }
00919 ROS_INFO_STREAM("Re-applying configuration to camera on re-init");
00920 config_init_ = false;
00921 applyConfigToOpenNIDevice();
00922
00923
00924
00925 ROS_INFO_STREAM("Starting color stream to adjust camera");
00926 colorConnectCb();
00927
00928
00929
00930
00931
00932 if((!auto_exposure_ && !auto_white_balance_ ) && exposure_ == 0)
00933 {
00934 ROS_WARN_STREAM("Reconnection should not be enabled if auto expousre"
00935 << "/white balance are disabled. Temporarily working"
00936 << " around this issue");
00937 ROS_WARN_STREAM("Toggling exposure and white balance to auto on re-connect"
00938 << ", otherwise image will be very dark");
00939 device_->setAutoExposure(true);
00940 device_->setAutoWhiteBalance(true);
00941 ROS_INFO_STREAM("Waiting for color camera to come up and adjust");
00942
00943 boost::this_thread::sleep(boost::posix_time::milliseconds(2500));
00944 ROS_WARN_STREAM("Resetting auto exposure and white balance to previous values");
00945 device_->setAutoExposure(auto_exposure_);
00946 device_->setAutoWhiteBalance(auto_white_balance_);
00947 }
00948
00949 ROS_INFO_STREAM("Restarting publishers, if needed");
00950 irConnectCb();
00951 depthConnectCb();
00952 ROS_INFO_STREAM("Done re-initializing cameras");
00953 }
00954
00955 catch (const OpenNI2Exception& exception)
00956 {
00957 if (!device_)
00958 {
00959 ROS_INFO_STREAM("Failed to re-initialize device on bus: " << bus_id_
00960 << ", reason: " << exception.what());
00961 }
00962 }
00963 }
00964 }
00965 else if( device_ )
00966 {
00967 ROS_WARN_STREAM("Detected loss of connection. Stopping all streams and resetting device");
00968 device_->stopAllStreams();
00969 device_.reset();
00970 }
00971 }
00972
00973
00974 void OpenNI2Driver::genVideoModeTableMap()
00975 {
00976
00977
00978
00979
00980
00981
00982
00983
00984
00985
00986
00987
00988
00989
00990
00991
00992
00993 video_modes_lookup_.clear();
00994
00995 OpenNI2VideoMode video_mode;
00996
00997
00998 video_mode.x_resolution_ = 1280;
00999 video_mode.y_resolution_ = 1024;
01000 video_mode.frame_rate_ = 30;
01001
01002 video_modes_lookup_[1] = video_mode;
01003
01004
01005 video_mode.x_resolution_ = 1280;
01006 video_mode.y_resolution_ = 1024;
01007 video_mode.frame_rate_ = 15;
01008
01009 video_modes_lookup_[2] = video_mode;
01010
01011
01012 video_mode.x_resolution_ = 1280;
01013 video_mode.y_resolution_ = 720;
01014 video_mode.frame_rate_ = 30;
01015
01016 video_modes_lookup_[3] = video_mode;
01017
01018
01019 video_mode.x_resolution_ = 1280;
01020 video_mode.y_resolution_ = 720;
01021 video_mode.frame_rate_ = 15;
01022
01023 video_modes_lookup_[4] = video_mode;
01024
01025
01026 video_mode.x_resolution_ = 640;
01027 video_mode.y_resolution_ = 480;
01028 video_mode.frame_rate_ = 30;
01029
01030 video_modes_lookup_[5] = video_mode;
01031
01032
01033 video_mode.x_resolution_ = 640;
01034 video_mode.y_resolution_ = 480;
01035 video_mode.frame_rate_ = 25;
01036
01037 video_modes_lookup_[6] = video_mode;
01038
01039
01040 video_mode.x_resolution_ = 320;
01041 video_mode.y_resolution_ = 240;
01042 video_mode.frame_rate_ = 25;
01043
01044 video_modes_lookup_[7] = video_mode;
01045
01046
01047 video_mode.x_resolution_ = 320;
01048 video_mode.y_resolution_ = 240;
01049 video_mode.frame_rate_ = 30;
01050
01051 video_modes_lookup_[8] = video_mode;
01052
01053
01054 video_mode.x_resolution_ = 320;
01055 video_mode.y_resolution_ = 240;
01056 video_mode.frame_rate_ = 60;
01057
01058 video_modes_lookup_[9] = video_mode;
01059
01060
01061 video_mode.x_resolution_ = 160;
01062 video_mode.y_resolution_ = 120;
01063 video_mode.frame_rate_ = 25;
01064
01065 video_modes_lookup_[10] = video_mode;
01066
01067
01068 video_mode.x_resolution_ = 160;
01069 video_mode.y_resolution_ = 120;
01070 video_mode.frame_rate_ = 30;
01071
01072 video_modes_lookup_[11] = video_mode;
01073
01074
01075 video_mode.x_resolution_ = 160;
01076 video_mode.y_resolution_ = 120;
01077 video_mode.frame_rate_ = 60;
01078
01079 video_modes_lookup_[12] = video_mode;
01080
01081 }
01082
01083 int OpenNI2Driver::lookupVideoModeFromDynConfig(int mode_nr, OpenNI2VideoMode& video_mode)
01084 {
01085 int ret = -1;
01086
01087 std::map<int, OpenNI2VideoMode>::const_iterator it;
01088
01089 it = video_modes_lookup_.find(mode_nr);
01090
01091 if (it!=video_modes_lookup_.end())
01092 {
01093 video_mode = it->second;
01094 ret = 0;
01095 }
01096
01097 return ret;
01098 }
01099
01100 sensor_msgs::ImageConstPtr OpenNI2Driver::rawToFloatingPointConversion(sensor_msgs::ImageConstPtr raw_image)
01101 {
01102 static const float bad_point = std::numeric_limits<float>::quiet_NaN ();
01103
01104 sensor_msgs::ImagePtr new_image = boost::make_shared<sensor_msgs::Image>();
01105
01106 new_image->header = raw_image->header;
01107 new_image->width = raw_image->width;
01108 new_image->height = raw_image->height;
01109 new_image->is_bigendian = 0;
01110 new_image->encoding = sensor_msgs::image_encodings::TYPE_32FC1;
01111 new_image->step = sizeof(float)*raw_image->width;
01112
01113 std::size_t data_size = new_image->width*new_image->height;
01114 new_image->data.resize(data_size*sizeof(float));
01115
01116 const unsigned short* in_ptr = reinterpret_cast<const unsigned short*>(&raw_image->data[0]);
01117 float* out_ptr = reinterpret_cast<float*>(&new_image->data[0]);
01118
01119 for (std::size_t i = 0; i<data_size; ++i, ++in_ptr, ++out_ptr)
01120 {
01121 if (*in_ptr==0 || *in_ptr==0x7FF)
01122 {
01123 *out_ptr = bad_point;
01124 } else
01125 {
01126 *out_ptr = static_cast<float>(*in_ptr)/1000.0f;
01127 }
01128 }
01129
01130 return new_image;
01131 }
01132
01133 }