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 #include <algorithm>
00032 #include <assert.h>
00033 #include <boost/thread/thread.hpp>
00034 #include <boost/bind.hpp>
00035
00036 #include <gazebo_plugins/gazebo_ros_depth_camera.h>
00037
00038 #include "sensors/Sensor.hh"
00039 #include "sdf/interface/SDF.hh"
00040 #include "sensors/SensorTypes.hh"
00041
00042
00043 #include "pcl/ros/conversions.h"
00044
00045 #include "tf/tf.h"
00046
00047 namespace gazebo
00048 {
00049
00051
00052 GazeboRosDepthCamera::GazeboRosDepthCamera()
00053 {
00054 this->point_cloud_connect_count_ = 0;
00055 }
00056
00058
00059 GazeboRosDepthCamera::~GazeboRosDepthCamera()
00060 {
00061 }
00062
00064
00065 void GazeboRosDepthCamera::InfoConnect()
00066 {
00067 this->info_connect_count_++;
00068 }
00070
00071 void GazeboRosDepthCamera::InfoDisconnect()
00072 {
00073 this->info_connect_count_--;
00074 }
00075
00077
00078 void GazeboRosDepthCamera::Load(sensors::SensorPtr _parent, sdf::ElementPtr _sdf)
00079 {
00080 DepthCameraPlugin::Load(_parent, _sdf);
00081
00082
00083 this->parentSensor_ = this->parentSensor;
00084 this->width_ = this->width;
00085 this->height_ = this->height;
00086 this->depth_ = this->depth;
00087 this->format_ = this->format;
00088 this->camera_ = this->depthCamera;
00089
00090 GazeboRosCameraUtils::Load(_parent, _sdf);
00091
00092
00093 if (!_sdf->GetElement("imageTopicName"))
00094 this->image_topic_name_ = "ir/image_raw";
00095 if (!_sdf->HasElement("cameraInfoTopicName"))
00096 this->camera_info_topic_name_ = "ir/camera_info";
00097
00098
00099 if (!_sdf->GetElement("pointCloudTopicName"))
00100 this->point_cloud_topic_name_ = "points";
00101 else
00102 this->point_cloud_topic_name_ = _sdf->GetElement("pointCloudTopicName")->GetValueString();
00103
00104
00105 if (!_sdf->GetElement("depthImageTopicName"))
00106 this->depth_image_topic_name_ = "depth/image_raw";
00107 else
00108 this->depth_image_topic_name_ = _sdf->GetElement("depthImageTopicName")->GetValueString();
00109
00110 if (!_sdf->GetElement("depthImageCameraInfoTopicName"))
00111 this->depth_image_camera_info_topic_name_ = "depth/camera_info";
00112 else
00113 this->depth_image_camera_info_topic_name_ = _sdf->GetElement("depthImageCameraInfoTopicName")->GetValueString();
00114
00115 if (!_sdf->GetElement("pointCloudCutoff"))
00116 this->point_cloud_cutoff_ = 0.4;
00117 else
00118 this->point_cloud_cutoff_ = _sdf->GetElement("pointCloudCutoff")->GetValueDouble();
00119
00120 ros::AdvertiseOptions point_cloud_ao =
00121 ros::AdvertiseOptions::create<sensor_msgs::PointCloud2 >(
00122 this->point_cloud_topic_name_,1,
00123 boost::bind( &GazeboRosDepthCamera::PointCloudConnect,this),
00124 boost::bind( &GazeboRosDepthCamera::PointCloudDisconnect,this),
00125 ros::VoidPtr(), &this->camera_queue_);
00126 this->point_cloud_pub_ = this->rosnode_->advertise(point_cloud_ao);
00127
00128 ros::AdvertiseOptions depth_image_ao =
00129 ros::AdvertiseOptions::create< sensor_msgs::Image >(
00130 this->depth_image_topic_name_,1,
00131 boost::bind( &GazeboRosDepthCamera::PointCloudConnect,this),
00132 boost::bind( &GazeboRosDepthCamera::PointCloudDisconnect,this),
00133 ros::VoidPtr(), &this->camera_queue_);
00134 this->depth_image_pub_ = this->rosnode_->advertise(depth_image_ao);
00135
00136 ros::AdvertiseOptions depth_image_camera_info_ao =
00137 ros::AdvertiseOptions::create<sensor_msgs::CameraInfo>(
00138 this->depth_image_camera_info_topic_name_,1,
00139 boost::bind( &GazeboRosDepthCamera::InfoConnect,this),
00140 boost::bind( &GazeboRosDepthCamera::InfoDisconnect,this),
00141 ros::VoidPtr(), &this->camera_queue_);
00142 this->depth_image_camera_info_pub_ = this->rosnode_->advertise(depth_image_camera_info_ao);
00143
00144 }
00145
00147
00148 void GazeboRosDepthCamera::PointCloudConnect()
00149 {
00150 this->point_cloud_connect_count_++;
00151 this->image_connect_count_++;
00152 this->parentSensor->SetActive(true);
00153 }
00155
00156 void GazeboRosDepthCamera::PointCloudDisconnect()
00157 {
00158 this->point_cloud_connect_count_--;
00159 this->image_connect_count_--;
00160 if (this->point_cloud_connect_count_ <= 0)
00161 this->parentSensor->SetActive(false);
00162 }
00163
00165
00166 void GazeboRosDepthCamera::OnNewDepthFrame(const float *_image,
00167 unsigned int _width, unsigned int _height, unsigned int _depth,
00168 const std::string &_format)
00169 {
00170 this->depth_sensor_update_time_ = this->parentSensor->GetLastUpdateTime();
00171 if (!this->parentSensor->IsActive())
00172 {
00173 if (this->point_cloud_connect_count_ > 0)
00174
00175 this->parentSensor->SetActive(true);
00176 }
00177 else
00178 {
00179 if (this->point_cloud_connect_count_ > 0)
00180 this->FillPointdCloud(_image);
00181 }
00182 }
00183
00185
00186 void GazeboRosDepthCamera::OnNewRGBPointCloud(const float *_pcd,
00187 unsigned int _width, unsigned int _height, unsigned int _depth,
00188 const std::string &_format)
00189 {
00190 this->depth_sensor_update_time_ = this->parentSensor->GetLastUpdateTime();
00191 if (!this->parentSensor->IsActive())
00192 {
00193 if (this->point_cloud_connect_count_ > 0)
00194
00195 this->parentSensor->SetActive(true);
00196 }
00197 else
00198 {
00199 if (this->point_cloud_connect_count_ > 0)
00200 {
00201 this->lock_.lock();
00202 this->point_cloud_msg_.header.frame_id = this->frame_name_;
00203 this->point_cloud_msg_.header.stamp.sec = this->depth_sensor_update_time_.sec;
00204 this->point_cloud_msg_.header.stamp.nsec = this->depth_sensor_update_time_.nsec;
00205 this->point_cloud_msg_.width = this->width;
00206 this->point_cloud_msg_.height = this->height;
00207 this->point_cloud_msg_.row_step = this->point_cloud_msg_.point_step * this->width;
00208
00209 pcl::PointCloud<pcl::PointXYZRGB> point_cloud;
00210 point_cloud.points.resize(0);
00211 point_cloud.is_dense = true;
00212
00213 for (unsigned int i = 0; i < _width; i++)
00214 {
00215 for (unsigned int j = 0; j < _height; j++)
00216 {
00217 unsigned int index = (j * _width) + i;
00218 pcl::PointXYZRGB point;
00219 point.x = _pcd[4 * index];
00220 point.y = _pcd[4 * index + 1];
00221 point.z = _pcd[4 * index + 2];
00222 point.rgb = _pcd[4 * index + 3];
00223 point_cloud.points.push_back(point);
00224 if (i == _width /2 && j == _height / 2)
00225 {
00226 uint32_t rgb = *reinterpret_cast<int*>(&point.rgb);
00227 uint8_t r = (rgb >> 16) & 0x0000ff;
00228 uint8_t g = (rgb >> 8) & 0x0000ff;
00229 uint8_t b = (rgb) & 0x0000ff;
00230 std::cerr << (int)r << " " << (int)g << " " << (int)b << "\n";
00231 }
00232 }
00233 }
00234 point_cloud.header = this->point_cloud_msg_.header;
00235 pcl::toROSMsg(point_cloud, this->point_cloud_msg_);
00236
00237 this->point_cloud_pub_.publish(this->point_cloud_msg_);
00238 this->lock_.unlock();
00239 }
00240 }
00241 }
00242
00244
00245 void GazeboRosDepthCamera::OnNewImageFrame(const unsigned char *_image,
00246 unsigned int _width, unsigned int _height, unsigned int _depth,
00247 const std::string &_format)
00248 {
00249
00250 this->sensor_update_time_ = this->parentSensor->GetLastUpdateTime();
00251
00252 if (!this->parentSensor->IsActive())
00253 {
00254 if (this->image_connect_count_ > 0)
00255
00256 this->parentSensor->SetActive(true);
00257 }
00258 else
00259 {
00260 if (this->image_connect_count_ > 0)
00261 this->PutCameraData(_image);
00262 }
00263 }
00264
00266
00267 void GazeboRosDepthCamera::FillPointdCloud(const float *_src)
00268 {
00269 this->lock_.lock();
00270
00271 this->point_cloud_msg_.header.frame_id = this->frame_name_;
00272 this->point_cloud_msg_.header.stamp.sec = this->depth_sensor_update_time_.sec;
00273 this->point_cloud_msg_.header.stamp.nsec = this->depth_sensor_update_time_.nsec;
00274 this->point_cloud_msg_.width = this->width;
00275 this->point_cloud_msg_.height = this->height;
00276 this->point_cloud_msg_.row_step = this->point_cloud_msg_.point_step * this->width;
00277
00279 FillPointCloudHelper(this->point_cloud_msg_,
00280 this->height,
00281 this->width,
00282 1,
00283 (void*)_src );
00284
00285 this->point_cloud_pub_.publish(this->point_cloud_msg_);
00286
00287
00288 this->depth_image_msg_.header.frame_id = this->frame_name_;
00289 this->depth_image_msg_.header.stamp.sec = this->depth_sensor_update_time_.sec;
00290 this->depth_image_msg_.header.stamp.nsec = this->depth_sensor_update_time_.nsec;
00291
00293 FillDepthImageHelper(this->depth_image_msg_,
00294 this->height,
00295 this->width,
00296 1,
00297 (void*)_src );
00298
00299 this->depth_image_pub_.publish(this->depth_image_msg_);
00300
00301 this->lock_.unlock();
00302 }
00303
00304
00305
00306 bool GazeboRosDepthCamera::FillPointCloudHelper(
00307 sensor_msgs::PointCloud2 &point_cloud_msg,
00308 uint32_t rows_arg, uint32_t cols_arg,
00309 uint32_t step_arg, void* data_arg)
00310 {
00311 pcl::PointCloud<pcl::PointXYZRGB> point_cloud;
00312
00313 point_cloud.points.resize(0);
00314 point_cloud.is_dense = true;
00315
00316 float* toCopyFrom = (float*)data_arg;
00317 int index = 0;
00318
00319 double hfov = this->parentSensor->GetDepthCamera()->GetHFOV().GetAsRadian();
00320 double fl = ((double)this->width) / (2.0 *tan(hfov/2.0));
00321
00322
00323 for (uint32_t j=0; j<rows_arg; j++)
00324 {
00325 double pAngle;
00326 if (rows_arg>1) pAngle = atan2( (double)j - 0.5*(double)(rows_arg-1), fl);
00327 else pAngle = 0.0;
00328
00329 for (uint32_t i=0; i<cols_arg; i++)
00330 {
00331 double yAngle;
00332 if (cols_arg>1) yAngle = atan2( (double)i - 0.5*(double)(cols_arg-1), fl);
00333 else yAngle = 0.0;
00334
00335 double depth = toCopyFrom[index++];
00336
00337
00338
00339
00340
00341 pcl::PointXYZRGB point;
00342 point.x = depth * tan(yAngle);
00343 point.y = depth * tan(pAngle);
00344 if(depth > this->point_cloud_cutoff_)
00345 {
00346 point.z = depth;
00347 }
00348 else
00349 {
00350 point.x = point.y = point.z = std::numeric_limits<float>::quiet_NaN ();
00351 point_cloud.is_dense = false;
00352 }
00353
00354
00355 uint8_t* image_src = (uint8_t*)(&(this->image_msg_.data[0]));
00356 if (this->image_msg_.data.size() == rows_arg*cols_arg*3)
00357 {
00358
00359 point.r = image_src[i*3+j*cols_arg*3+0];
00360 point.g = image_src[i*3+j*cols_arg*3+1];
00361 point.b = image_src[i*3+j*cols_arg*3+2];
00362 }
00363 else if (this->image_msg_.data.size() == rows_arg*cols_arg)
00364 {
00365
00366 point.r = image_src[i+j*cols_arg];
00367 point.g = image_src[i+j*cols_arg];
00368 point.b = image_src[i+j*cols_arg];
00369 }
00370 else
00371 {
00372
00373 point.r = 0;
00374 point.g = 0;
00375 point.b = 0;
00376 }
00377
00378 point_cloud.points.push_back(point);
00379 }
00380 }
00381
00382 point_cloud.header = point_cloud_msg.header;
00383 pcl::toROSMsg(point_cloud, point_cloud_msg);
00384 return true;
00385 }
00386
00387
00388 bool GazeboRosDepthCamera::FillDepthImageHelper(
00389 sensor_msgs::Image& image_msg,
00390 uint32_t rows_arg, uint32_t cols_arg,
00391 uint32_t step_arg, void* data_arg)
00392 {
00393 image_msg.encoding = sensor_msgs::image_encodings::TYPE_32FC1;
00394 image_msg.height = rows_arg;
00395 image_msg.width = cols_arg;
00396 image_msg.step = 1;
00397 image_msg.data.resize(rows_arg * cols_arg * sizeof(float));
00398 image_msg.is_bigendian = 0;
00399
00400 const float bad_point = std::numeric_limits<float>::quiet_NaN();
00401
00402 float* dest = (float*)(&(image_msg.data[0]));
00403 float* toCopyFrom = (float*)data_arg;
00404 int index = 0;
00405
00406
00407 for (uint32_t j = 0; j < rows_arg; j++)
00408 {
00409 for (uint32_t i = 0; i < cols_arg; i++)
00410 {
00411 float depth = 0;
00412 for (uint32_t s = 0; s < step_arg; s++)
00413 depth += toCopyFrom[index++];
00414 depth = depth / (float)step_arg;
00415
00416 if (depth > this->point_cloud_cutoff_)
00417 {
00418 dest[i + j * cols_arg] = depth;
00419 }
00420 else
00421 {
00422 dest[i + j * cols_arg] = bad_point;
00423 }
00424 }
00425 }
00426 return true;
00427 }
00428
00429 void GazeboRosDepthCamera::PublishCameraInfo()
00430 {
00431 ROS_DEBUG("publishing depth camera info, then camera info");
00432 GazeboRosCameraUtils::PublishCameraInfo();
00433 this->PublishCameraInfo(this->depth_image_camera_info_pub_);
00434 }
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451
00452
00453
00454
00456
00457
00458
00459
00460
00461
00462
00463
00464
00465
00466
00467 GZ_REGISTER_SENSOR_PLUGIN(GazeboRosDepthCamera)
00468
00469 }