00001
00034 #include <multisense_ros/camera.h>
00035 #include <multisense_ros/RawCamConfig.h>
00036 #include <multisense_ros/RawCamCal.h>
00037 #include <multisense_ros/DeviceInfo.h>
00038 #include <multisense_ros/Histogram.h>
00039
00040 #include <sensor_msgs/distortion_models.h>
00041 #include <sensor_msgs/image_encodings.h>
00042
00043 #include <multisense_lib/MultiSenseChannel.hh>
00044
00045 #include <opencv2/opencv.hpp>
00046 #include <arpa/inet.h>
00047 #include <fstream>
00048 #include <turbojpeg.h>
00049
00050 using namespace crl::multisense;
00051
00052 namespace multisense_ros {
00053
00054 namespace {
00055
00056
00057
00058
00059 const DataSource allImageSources = (Source_Luma_Left |
00060 Source_Luma_Right |
00061 Source_Luma_Rectified_Left |
00062 Source_Luma_Rectified_Right |
00063 Source_Chroma_Left |
00064 Source_Disparity |
00065 Source_Disparity_Right |
00066 Source_Disparity_Cost |
00067 Source_Jpeg_Left);
00068
00069
00070
00071
00072 const uint32_t luma_cloud_step = 16;
00073 const uint32_t color_cloud_step = 16;
00074
00075
00076
00077
00078 void monoCB(const image::Header& header, void* userDataP)
00079 { reinterpret_cast<Camera*>(userDataP)->monoCallback(header); }
00080 void rectCB(const image::Header& header, void* userDataP)
00081 { reinterpret_cast<Camera*>(userDataP)->rectCallback(header); }
00082 void depthCB(const image::Header& header, void* userDataP)
00083 { reinterpret_cast<Camera*>(userDataP)->depthCallback(header); }
00084 void pointCB(const image::Header& header, void* userDataP)
00085 { reinterpret_cast<Camera*>(userDataP)->pointCloudCallback(header); }
00086 void rawCB(const image::Header& header, void* userDataP)
00087 { reinterpret_cast<Camera*>(userDataP)->rawCamDataCallback(header); }
00088 void colorCB(const image::Header& header, void* userDataP)
00089 { reinterpret_cast<Camera*>(userDataP)->colorImageCallback(header); }
00090 void dispCB(const image::Header& header, void* userDataP)
00091 { reinterpret_cast<Camera*>(userDataP)->disparityImageCallback(header); }
00092 void jpegCB(const image::Header& header, void* userDataP)
00093 { reinterpret_cast<Camera*>(userDataP)->jpegImageCallback(header); }
00094 void histCB(const image::Header& header, void* userDataP)
00095 { reinterpret_cast<Camera*>(userDataP)->histogramCallback(header); }
00096
00097
00098
00099
00100 bool isValidPoint(const cv::Vec3f& pt,
00101 const float& maxRange)
00102 {
00103
00104
00105
00106
00107
00108 if (image_geometry::StereoCameraModel::MISSING_Z != pt[2] && std::isfinite(pt[2])) {
00109
00110
00111
00112
00113 const float mag = std::sqrt((pt[0]*pt[0])+(pt[1]*pt[1])+(pt[2]*pt[2]));
00114
00115 if (mag < maxRange)
00116 return true;
00117 }
00118
00119 return false;
00120 }
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133 boost::mutex point_cloud_mutex;
00134
00135 bool publishPointCloud(int64_t imageFrameId,
00136 int64_t pointsFrameId,
00137 int64_t& cloudFrameId,
00138 ros::Publisher& pub,
00139 sensor_msgs::PointCloud2& cloud,
00140 const uint32_t width,
00141 const uint32_t height,
00142 const uint32_t timeSeconds,
00143 const uint32_t timeMicroSeconds,
00144 const uint32_t cloudStep,
00145 const std::vector<cv::Vec3f>& points,
00146 const uint8_t* imageP,
00147 const uint32_t colorChannels,
00148 const float maxRange,
00149 bool writeColorPacked,
00150 bool organized)
00151 {
00152 boost::mutex::scoped_lock lock(point_cloud_mutex);
00153
00154 if (0 == pub.getNumSubscribers() ||
00155 imageFrameId != pointsFrameId ||
00156 cloudFrameId >= imageFrameId) {
00157 return false;
00158 }
00159
00160 cloudFrameId = imageFrameId;
00161 const uint32_t imageSize = height * width;
00162
00163 if (points.size() != imageSize)
00164 return false;
00165
00166 cloud.data.resize(imageSize * cloudStep);
00167
00168 uint8_t *cloudP = reinterpret_cast<uint8_t*>(&cloud.data[0]);
00169 const uint32_t pointSize = 3 * sizeof(float);
00170 uint32_t validPoints = 0;
00171
00172 cv::Vec3f nanPoint(std::numeric_limits<float>::quiet_NaN(),
00173 std::numeric_limits<float>::quiet_NaN(),
00174 std::numeric_limits<float>::quiet_NaN());
00175
00176
00177 for(uint32_t i=0; i<height; ++i)
00178 for(uint32_t j=0; j<width; ++j) {
00179
00180 const uint32_t index = i * width + j;
00181
00182 const uint32_t* pointP = reinterpret_cast<const uint32_t*>(&points[index]);
00183 uint32_t* targetCloudP = reinterpret_cast<uint32_t*>(cloudP);
00184
00185
00186
00187
00188
00189
00190 if (false == isValidPoint(points[index], maxRange))
00191 {
00192 if (organized)
00193 {
00194 pointP = reinterpret_cast<const uint32_t*>(&nanPoint[0]);
00195 }
00196 else
00197 {
00198 continue;
00199 }
00200 }
00201
00202
00203
00204
00205
00206 targetCloudP[0] = pointP[0];
00207 targetCloudP[1] = pointP[1];
00208 targetCloudP[2] = pointP[2];
00209
00210
00211 const uint8_t *sourceColorP = &(imageP[colorChannels * index]);
00212 uint8_t *cloudColorP = (cloudP + pointSize);
00213
00214
00215
00216
00217
00218
00219 if (writeColorPacked || colorChannels > 2)
00220 {
00221 switch(colorChannels)
00222 {
00223 case 4:
00224 cloudColorP[3] = sourceColorP[3];
00225 case 3:
00226 cloudColorP[2] = sourceColorP[2];
00227 case 2:
00228 cloudColorP[1] = sourceColorP[1];
00229 case 1:
00230 cloudColorP[0] = sourceColorP[0];
00231 }
00232
00233 } else {
00234 union
00235 {
00236 uint32_t value;
00237 char bytes[sizeof(uint32_t)];
00238 } color;
00239
00240 color.value = 0;
00241
00242
00243
00244
00245
00246 color.bytes[0] = sourceColorP[0];
00247 color.bytes[1] = sourceColorP[1] & ((colorChannels > 1) * 255);
00248
00249 float* floatCloudColorP = reinterpret_cast<float*>(cloudColorP);
00250 floatCloudColorP[0] = static_cast<float>(color.value);
00251 }
00252
00253 cloudP += cloudStep;
00254 validPoints ++;
00255 }
00256
00257 if (!organized) {
00258 cloud.row_step = validPoints * cloudStep;
00259 cloud.width = validPoints;
00260 cloud.height = 1;
00261 } else {
00262 cloud.width = width;
00263 cloud.height = height;
00264 cloud.row_step = width * cloudStep;
00265 }
00266
00267 cloud.header.stamp = ros::Time(timeSeconds, 1000 * timeMicroSeconds);
00268 cloud.data.resize(validPoints * cloudStep);
00269 pub.publish(cloud);
00270
00271 return true;
00272 }
00273
00274 bool savePgm(const std::string& fileName,
00275 uint32_t width,
00276 uint32_t height,
00277 uint32_t bitsPerPixel,
00278 const void *dataP)
00279 {
00280 std::ofstream outputStream(fileName.c_str(), std::ios::binary | std::ios::out);
00281
00282 if (false == outputStream.good()) {
00283 fprintf(stderr, "failed to open \"%s\"\n", fileName.c_str());
00284 return false;
00285 }
00286
00287 const uint32_t imageSize = height * width;
00288
00289 switch(bitsPerPixel) {
00290 case 8:
00291 {
00292
00293 outputStream << "P5\n"
00294 << width << " " << height << "\n"
00295 << 0xFF << "\n";
00296
00297 outputStream.write(reinterpret_cast<const char*>(dataP), imageSize);
00298
00299 break;
00300 }
00301 case 16:
00302 {
00303 outputStream << "P5\n"
00304 << width << " " << height << "\n"
00305 << 0xFFFF << "\n";
00306
00307 const uint16_t *imageP = reinterpret_cast<const uint16_t*>(dataP);
00308
00309 for (uint32_t i=0; i<imageSize; ++i) {
00310 uint16_t o = htons(imageP[i]);
00311 outputStream.write(reinterpret_cast<const char*>(&o), sizeof(uint16_t));
00312 }
00313
00314 break;
00315 }
00316 }
00317
00318 outputStream.close();
00319 return true;
00320 }
00321
00322 };
00323
00324 Camera::Camera(Channel* driver,
00325 const std::string& tf_prefix) :
00326 driver_(driver),
00327 device_nh_(""),
00328 left_nh_(device_nh_, "left"),
00329 right_nh_(device_nh_, "right"),
00330 left_mono_transport_(left_nh_),
00331 right_mono_transport_(right_nh_),
00332 left_rect_transport_(left_nh_),
00333 right_rect_transport_(right_nh_),
00334 left_rgb_transport_(left_nh_),
00335 left_rgb_rect_transport_(left_nh_),
00336 depth_transport_(device_nh_),
00337 ni_depth_transport_(device_nh_),
00338 disparity_left_transport_(left_nh_),
00339 disparity_right_transport_(right_nh_),
00340 disparity_cost_transport_(left_nh_),
00341 left_mono_cam_info_(),
00342 right_mono_cam_info_(),
00343 left_rect_cam_info_(),
00344 right_rect_cam_info_(),
00345 left_rgb_rect_cam_info_(),
00346 left_disp_cam_info_(),
00347 right_disp_cam_info_(),
00348 left_cost_cam_info_(),
00349 left_rgb_cam_info_(),
00350 depth_cam_info_(),
00351 left_mono_cam_pub_(),
00352 right_mono_cam_pub_(),
00353 left_rect_cam_pub_(),
00354 right_rect_cam_pub_(),
00355 depth_cam_pub_(),
00356 ni_depth_cam_pub_(),
00357 left_rgb_cam_pub_(),
00358 left_rgb_rect_cam_pub_(),
00359 left_mono_cam_info_pub_(),
00360 right_mono_cam_info_pub_(),
00361 left_rect_cam_info_pub_(),
00362 right_rect_cam_info_pub_(),
00363 left_disp_cam_info_pub_(),
00364 right_disp_cam_info_pub_(),
00365 left_cost_cam_info_pub_(),
00366 left_rgb_cam_info_pub_(),
00367 left_rgb_rect_cam_info_pub_(),
00368 depth_cam_info_pub_(),
00369 luma_point_cloud_pub_(),
00370 color_point_cloud_pub_(),
00371 luma_organized_point_cloud_pub_(),
00372 color_organized_point_cloud_pub_(),
00373 left_disparity_pub_(),
00374 right_disparity_pub_(),
00375 left_disparity_cost_pub_(),
00376 left_stereo_disparity_pub_(),
00377 right_stereo_disparity_pub_(),
00378 raw_cam_data_pub_(),
00379 raw_cam_config_pub_(),
00380 raw_cam_cal_pub_(),
00381 device_info_pub_(),
00382 histogram_pub_(),
00383 left_mono_image_(),
00384 right_mono_image_(),
00385 left_rect_image_(),
00386 right_rect_image_(),
00387 depth_image_(),
00388 luma_point_cloud_(),
00389 color_point_cloud_(),
00390 luma_organized_point_cloud_(),
00391 color_organized_point_cloud_(),
00392 left_luma_image_(),
00393 left_rgb_image_(),
00394 left_rgb_rect_image_(),
00395 left_disparity_image_(),
00396 left_disparity_cost_image_(),
00397 right_disparity_image_(),
00398 left_stereo_disparity_(),
00399 right_stereo_disparity_(),
00400 got_raw_cam_left_(false),
00401 got_left_luma_(false),
00402 left_luma_frame_id_(0),
00403 left_rect_frame_id_(0),
00404 left_rgb_rect_frame_id_(-1),
00405 luma_point_cloud_frame_id_(-1),
00406 luma_organized_point_cloud_frame_id_(-1),
00407 color_point_cloud_frame_id_(-1),
00408 color_organized_point_cloud_frame_id_(-1),
00409 raw_cam_data_(),
00410 version_info_(),
00411 device_info_(),
00412 image_config_(),
00413 image_calibration_(),
00414 cal_lock_(),
00415 calibration_map_left_1_(NULL),
00416 calibration_map_left_2_(NULL),
00417 frame_id_left_(),
00418 frame_id_right_(),
00419 disparity_buff_(),
00420 points_buff_(),
00421 points_buff_frame_id_(-1),
00422 q_matrix_(4, 4, 0.0),
00423 pc_max_range_(15.0f),
00424 pc_color_frame_sync_(true),
00425 disparities_(0),
00426 stream_lock_(),
00427 stream_map_(),
00428 last_frame_id_(-1),
00429 luma_color_depth_(1),
00430 write_pc_color_packed_(false),
00431 border_clip_type_(0),
00432 border_clip_value_(0.0),
00433 border_clip_lock_()
00434 {
00435
00436
00437
00438 Status status = driver_->getVersionInfo(version_info_);
00439 if (Status_Ok != status) {
00440 ROS_ERROR("Camera: failed to query version info: %s",
00441 Channel::statusString(status));
00442 return;
00443 }
00444 status = driver_->getDeviceInfo(device_info_);
00445 if (Status_Ok != status) {
00446 ROS_ERROR("Camera: failed to query device info: %s",
00447 Channel::statusString(status));
00448 return;
00449 }
00450
00451
00452
00453
00454 frame_id_left_ = tf_prefix + "/left_camera_optical_frame";
00455 frame_id_right_ = tf_prefix + "/right_camera_optical_frame";
00456 ROS_INFO("camera frame id: %s", frame_id_left_.c_str());
00457
00458
00459
00460
00461 ros::NodeHandle calibration_nh(device_nh_, "calibration");
00462 device_info_pub_ = calibration_nh.advertise<multisense_ros::DeviceInfo>("device_info", 1, true);
00463 raw_cam_cal_pub_ = calibration_nh.advertise<multisense_ros::RawCamCal>("raw_cam_cal", 1, true);
00464 raw_cam_config_pub_ = calibration_nh.advertise<multisense_ros::RawCamConfig>("raw_cam_config", 1, true);
00465 histogram_pub_ = device_nh_.advertise<multisense_ros::Histogram>("histogram", 5);
00466
00467
00468
00469
00470 if (system::DeviceInfo::HARDWARE_REV_MULTISENSE_ST21 == device_info_.hardwareRevision) {
00471
00472
00473
00474
00475
00476 luma_color_depth_ = 2;
00477 }
00478
00479
00480
00481
00482 if (system::DeviceInfo::HARDWARE_REV_BCAM == device_info_.hardwareRevision) {
00483
00484 left_mono_cam_pub_ = left_mono_transport_.advertise("image_mono", 5,
00485 boost::bind(&Camera::connectStream, this, Source_Luma_Left),
00486 boost::bind(&Camera::disconnectStream, this, Source_Luma_Left));
00487
00488 left_rgb_cam_pub_ = left_rgb_transport_.advertise("image_color", 5,
00489 boost::bind(&Camera::connectStream, this, Source_Jpeg_Left),
00490 boost::bind(&Camera::disconnectStream, this, Source_Jpeg_Left));
00491
00492 left_rgb_rect_cam_pub_ = left_rgb_rect_transport_.advertiseCamera("image_rect_color", 5,
00493 boost::bind(&Camera::connectStream, this, Source_Jpeg_Left),
00494 boost::bind(&Camera::disconnectStream, this, Source_Jpeg_Left));
00495
00496 left_mono_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_mono/camera_info", 1, true);
00497 left_rgb_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_color/camera_info", 1, true);
00498 left_rgb_rect_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_rect_color/camera_info", 1, true);
00499
00500
00501 } else if (system::DeviceInfo::HARDWARE_REV_MULTISENSE_M == device_info_.hardwareRevision) {
00502
00503
00504
00505 left_mono_cam_pub_ = left_mono_transport_.advertise("image_mono", 5,
00506 boost::bind(&Camera::connectStream, this, Source_Luma_Left),
00507 boost::bind(&Camera::disconnectStream, this, Source_Luma_Left));
00508 left_rect_cam_pub_ = left_rect_transport_.advertiseCamera("image_rect", 5,
00509 boost::bind(&Camera::connectStream, this, Source_Luma_Rectified_Left),
00510 boost::bind(&Camera::disconnectStream, this, Source_Luma_Rectified_Left));
00511 left_rgb_cam_pub_ = left_rgb_transport_.advertise("image_color", 5,
00512 boost::bind(&Camera::connectStream, this, Source_Luma_Left | Source_Chroma_Left),
00513 boost::bind(&Camera::disconnectStream, this, Source_Luma_Left | Source_Chroma_Left));
00514 left_rgb_rect_cam_pub_ = left_rgb_rect_transport_.advertiseCamera("image_rect_color", 5,
00515 boost::bind(&Camera::connectStream, this, Source_Luma_Left | Source_Chroma_Left),
00516 boost::bind(&Camera::disconnectStream, this, Source_Luma_Left | Source_Chroma_Left));
00517
00518 left_mono_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_mono/camera_info", 1, true);
00519 left_rect_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_rect/camera_info", 1, true);
00520 left_rgb_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_color/camera_info", 1, true);
00521 left_rgb_rect_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_rect_color/camera_info", 1, true);
00522
00523 } else {
00524
00525
00526 left_mono_cam_pub_ = left_mono_transport_.advertise("image_mono", 5,
00527 boost::bind(&Camera::connectStream, this, Source_Luma_Left),
00528 boost::bind(&Camera::disconnectStream, this, Source_Luma_Left));
00529 right_mono_cam_pub_ = right_mono_transport_.advertise("image_mono", 5,
00530 boost::bind(&Camera::connectStream, this, Source_Luma_Right),
00531 boost::bind(&Camera::disconnectStream, this, Source_Luma_Right));
00532 left_rect_cam_pub_ = left_rect_transport_.advertiseCamera("image_rect", 5,
00533 boost::bind(&Camera::connectStream, this, Source_Luma_Rectified_Left),
00534 boost::bind(&Camera::disconnectStream, this, Source_Luma_Rectified_Left));
00535 right_rect_cam_pub_ = right_rect_transport_.advertiseCamera("image_rect", 5,
00536 boost::bind(&Camera::connectStream, this, Source_Luma_Rectified_Right),
00537 boost::bind(&Camera::disconnectStream, this, Source_Luma_Rectified_Right));
00538 depth_cam_pub_ = depth_transport_.advertise("depth", 5,
00539 boost::bind(&Camera::connectStream, this, Source_Disparity),
00540 boost::bind(&Camera::disconnectStream, this, Source_Disparity));
00541 ni_depth_cam_pub_ = ni_depth_transport_.advertise("openni_depth", 5,
00542 boost::bind(&Camera::connectStream, this, Source_Disparity),
00543 boost::bind(&Camera::disconnectStream, this, Source_Disparity));
00544
00545 if (system::DeviceInfo::HARDWARE_REV_MULTISENSE_ST21 != device_info_.hardwareRevision) {
00546
00547 left_rgb_cam_pub_ = left_rgb_transport_.advertise("image_color", 5,
00548 boost::bind(&Camera::connectStream, this, Source_Luma_Left | Source_Chroma_Left),
00549 boost::bind(&Camera::disconnectStream, this, Source_Luma_Left | Source_Chroma_Left));
00550 left_rgb_rect_cam_pub_ = left_rgb_rect_transport_.advertiseCamera("image_rect_color", 5,
00551 boost::bind(&Camera::connectStream, this, Source_Luma_Left | Source_Chroma_Left),
00552 boost::bind(&Camera::disconnectStream, this, Source_Luma_Left | Source_Chroma_Left));
00553 color_point_cloud_pub_ = device_nh_.advertise<sensor_msgs::PointCloud2>("image_points2_color", 5,
00554 boost::bind(&Camera::connectStream, this,
00555 Source_Disparity | Source_Luma_Left | Source_Chroma_Left),
00556 boost::bind(&Camera::disconnectStream, this,
00557 Source_Disparity | Source_Luma_Left | Source_Chroma_Left));
00558 color_organized_point_cloud_pub_ = device_nh_.advertise<sensor_msgs::PointCloud2>("organized_image_points2_color", 5,
00559 boost::bind(&Camera::connectStream, this,
00560 Source_Disparity | Source_Luma_Left | Source_Chroma_Left),
00561 boost::bind(&Camera::disconnectStream, this,
00562 Source_Disparity | Source_Luma_Left | Source_Chroma_Left));
00563
00564 left_rgb_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_color/camera_info", 1, true);
00565 left_rgb_rect_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_rect_color/camera_info", 1, true);
00566
00567 }
00568
00569 luma_point_cloud_pub_ = device_nh_.advertise<sensor_msgs::PointCloud2>("image_points2", 5,
00570 boost::bind(&Camera::connectStream, this, Source_Luma_Rectified_Left | Source_Disparity),
00571 boost::bind(&Camera::disconnectStream, this, Source_Luma_Rectified_Left | Source_Disparity));
00572
00573 luma_organized_point_cloud_pub_ = device_nh_.advertise<sensor_msgs::PointCloud2>("organized_image_points2", 5,
00574 boost::bind(&Camera::connectStream, this, Source_Luma_Rectified_Left | Source_Disparity),
00575 boost::bind(&Camera::disconnectStream, this, Source_Luma_Rectified_Left | Source_Disparity));
00576
00577 raw_cam_data_pub_ = calibration_nh.advertise<multisense_ros::RawCamData>("raw_cam_data", 5,
00578 boost::bind(&Camera::connectStream, this, Source_Luma_Rectified_Left | Source_Disparity),
00579 boost::bind(&Camera::disconnectStream, this, Source_Luma_Rectified_Left | Source_Disparity));
00580
00581 left_disparity_pub_ = disparity_left_transport_.advertise("disparity", 5,
00582 boost::bind(&Camera::connectStream, this, Source_Disparity),
00583 boost::bind(&Camera::disconnectStream, this, Source_Disparity));
00584
00585 left_stereo_disparity_pub_ = left_nh_.advertise<stereo_msgs::DisparityImage>("disparity_image", 5,
00586 boost::bind(&Camera::connectStream, this, Source_Disparity),
00587 boost::bind(&Camera::disconnectStream, this, Source_Disparity));
00588
00589 if (version_info_.sensorFirmwareVersion >= 0x0300) {
00590
00591 right_disparity_pub_ = disparity_right_transport_.advertise("disparity", 5,
00592 boost::bind(&Camera::connectStream, this, Source_Disparity_Right),
00593 boost::bind(&Camera::disconnectStream, this, Source_Disparity_Right));
00594
00595 right_stereo_disparity_pub_ = right_nh_.advertise<stereo_msgs::DisparityImage>("disparity_image", 5,
00596 boost::bind(&Camera::connectStream, this, Source_Disparity_Right),
00597 boost::bind(&Camera::disconnectStream, this, Source_Disparity_Right));
00598
00599 left_disparity_cost_pub_ = disparity_cost_transport_.advertise("cost", 5,
00600 boost::bind(&Camera::connectStream, this, Source_Disparity_Cost),
00601 boost::bind(&Camera::disconnectStream, this, Source_Disparity_Cost));
00602
00603 right_disp_cam_info_pub_ = right_nh_.advertise<sensor_msgs::CameraInfo>("disparity/camera_info", 1, true);
00604 left_cost_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("cost/camera_info", 1, true);
00605 }
00606
00607
00608
00609 left_mono_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_mono/camera_info", 1, true);
00610 right_mono_cam_info_pub_ = right_nh_.advertise<sensor_msgs::CameraInfo>("image_mono/camera_info", 1, true);
00611 left_rect_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("image_rect/camera_info", 1, true);
00612 right_rect_cam_info_pub_ = right_nh_.advertise<sensor_msgs::CameraInfo>("image_rect/camera_info", 1, true);
00613 left_disp_cam_info_pub_ = left_nh_.advertise<sensor_msgs::CameraInfo>("disparity/camera_info", 1, true);
00614 depth_cam_info_pub_ = device_nh_.advertise<sensor_msgs::CameraInfo>("depth/camera_info", 1, true);
00615 }
00616
00617
00618
00619
00620
00621 stop();
00622
00623
00624
00625
00626 multisense_ros::DeviceInfo msg;
00627
00628 msg.deviceName = device_info_.name;
00629 msg.buildDate = device_info_.buildDate;
00630 msg.serialNumber = device_info_.serialNumber;
00631 msg.deviceRevision = device_info_.hardwareRevision;
00632
00633 msg.numberOfPcbs = device_info_.pcbs.size();
00634 std::vector<system::PcbInfo>::const_iterator it = device_info_.pcbs.begin();
00635 for(; it != device_info_.pcbs.end(); ++it) {
00636 msg.pcbSerialNumbers.push_back((*it).revision);
00637 msg.pcbNames.push_back((*it).name);
00638 }
00639
00640 msg.imagerName = device_info_.imagerName;
00641 msg.imagerType = device_info_.imagerType;
00642 msg.imagerWidth = device_info_.imagerWidth;
00643 msg.imagerHeight = device_info_.imagerHeight;
00644
00645 msg.lensName = device_info_.lensName;
00646 msg.lensType = device_info_.lensType;
00647 msg.nominalBaseline = device_info_.nominalBaseline;
00648 msg.nominalFocalLength = device_info_.nominalFocalLength;
00649 msg.nominalRelativeAperture = device_info_.nominalRelativeAperture;
00650
00651 msg.lightingType = device_info_.lightingType;
00652 msg.numberOfLights = device_info_.numberOfLights;
00653
00654 msg.laserName = device_info_.laserName;
00655 msg.laserType = device_info_.laserType;
00656
00657 msg.motorName = device_info_.motorName;
00658 msg.motorType = device_info_.motorType;
00659 msg.motorGearReduction = device_info_.motorGearReduction;
00660
00661 msg.apiBuildDate = version_info_.apiBuildDate;
00662 msg.apiVersion = version_info_.apiVersion;
00663 msg.firmwareBuildDate = version_info_.sensorFirmwareBuildDate;
00664 msg.firmwareVersion = version_info_.sensorFirmwareVersion;
00665 msg.bitstreamVersion = version_info_.sensorHardwareVersion;
00666 msg.bitstreamMagic = version_info_.sensorHardwareMagic;
00667 msg.fpgaDna = version_info_.sensorFpgaDna;
00668
00669 device_info_pub_.publish(msg);
00670
00671
00672
00673
00674 status = driver_->getImageCalibration(image_calibration_);
00675 if (Status_Ok != status)
00676 ROS_ERROR("Camera: failed to query image calibration: %s",
00677 Channel::statusString(status));
00678 else {
00679
00680 multisense_ros::RawCamCal cal;
00681 const float *cP;
00682
00683 cP = reinterpret_cast<const float *>(&(image_calibration_.left.M[0][0]));
00684 for(uint32_t i=0; i<9; i++) cal.left_M[i] = cP[i];
00685 cP = reinterpret_cast<const float *>(&(image_calibration_.left.D[0]));
00686 for(uint32_t i=0; i<8; i++) cal.left_D[i] = cP[i];
00687 cP = reinterpret_cast<const float *>(&(image_calibration_.left.R[0][0]));
00688 for(uint32_t i=0; i<9; i++) cal.left_R[i] = cP[i];
00689 cP = reinterpret_cast<const float *>(&(image_calibration_.left.P[0][0]));
00690 for(uint32_t i=0; i<12; i++) cal.left_P[i] = cP[i];
00691
00692 cP = reinterpret_cast<const float *>(&(image_calibration_.right.M[0][0]));
00693 for(uint32_t i=0; i<9; i++) cal.right_M[i] = cP[i];
00694 cP = reinterpret_cast<const float *>(&(image_calibration_.right.D[0]));
00695 for(uint32_t i=0; i<8; i++) cal.right_D[i] = cP[i];
00696 cP = reinterpret_cast<const float *>(&(image_calibration_.right.R[0][0]));
00697 for(uint32_t i=0; i<9; i++) cal.right_R[i] = cP[i];
00698 cP = reinterpret_cast<const float *>(&(image_calibration_.right.P[0][0]));
00699 for(uint32_t i=0; i<12; i++) cal.right_P[i] = cP[i];
00700
00701 raw_cam_cal_pub_.publish(cal);
00702 }
00703
00704
00705
00706
00707 q_matrix_(0,0) = q_matrix_(1,1) = 1.0;
00708 queryConfig();
00709
00710
00711
00712
00713 luma_point_cloud_.is_bigendian = (htonl(1) == 1);
00714 luma_point_cloud_.is_dense = true;
00715 luma_point_cloud_.point_step = luma_cloud_step;
00716 luma_point_cloud_.height = 1;
00717 luma_point_cloud_.header.frame_id = frame_id_left_;
00718 luma_point_cloud_.fields.resize(4);
00719 luma_point_cloud_.fields[0].name = "x";
00720 luma_point_cloud_.fields[0].offset = 0;
00721 luma_point_cloud_.fields[0].count = 1;
00722 luma_point_cloud_.fields[0].datatype = sensor_msgs::PointField::FLOAT32;
00723 luma_point_cloud_.fields[1].name = "y";
00724 luma_point_cloud_.fields[1].offset = 4;
00725 luma_point_cloud_.fields[1].count = 1;
00726 luma_point_cloud_.fields[1].datatype = sensor_msgs::PointField::FLOAT32;
00727 luma_point_cloud_.fields[2].name = "z";
00728 luma_point_cloud_.fields[2].offset = 8;
00729 luma_point_cloud_.fields[2].count = 1;
00730 luma_point_cloud_.fields[2].datatype = sensor_msgs::PointField::FLOAT32;
00731 luma_point_cloud_.fields[3].name = "luminance";
00732 luma_point_cloud_.fields[3].offset = 12;
00733 luma_point_cloud_.fields[3].count = 1;
00734 luma_point_cloud_.fields[3].datatype = sensor_msgs::PointField::FLOAT32;
00735
00736 color_point_cloud_.is_bigendian = (htonl(1) == 1);
00737 color_point_cloud_.is_dense = true;
00738 color_point_cloud_.point_step = color_cloud_step;
00739 color_point_cloud_.height = 1;
00740 color_point_cloud_.header.frame_id = frame_id_left_;
00741 color_point_cloud_.fields.resize(4);
00742 color_point_cloud_.fields[0].name = "x";
00743 color_point_cloud_.fields[0].offset = 0;
00744 color_point_cloud_.fields[0].count = 1;
00745 color_point_cloud_.fields[0].datatype = sensor_msgs::PointField::FLOAT32;
00746 color_point_cloud_.fields[1].name = "y";
00747 color_point_cloud_.fields[1].offset = 4;
00748 color_point_cloud_.fields[1].count = 1;
00749 color_point_cloud_.fields[1].datatype = sensor_msgs::PointField::FLOAT32;
00750 color_point_cloud_.fields[2].name = "z";
00751 color_point_cloud_.fields[2].offset = 8;
00752 color_point_cloud_.fields[2].count = 1;
00753 color_point_cloud_.fields[2].datatype = sensor_msgs::PointField::FLOAT32;
00754 color_point_cloud_.fields[3].name = "rgb";
00755 color_point_cloud_.fields[3].offset = 12;
00756 color_point_cloud_.fields[3].count = 1;
00757 color_point_cloud_.fields[3].datatype = sensor_msgs::PointField::FLOAT32;
00758
00759 luma_organized_point_cloud_.is_bigendian = (htonl(1) == 1);
00760 luma_organized_point_cloud_.is_dense = false;
00761 luma_organized_point_cloud_.point_step = luma_cloud_step;
00762 luma_organized_point_cloud_.header.frame_id = frame_id_left_;
00763 luma_organized_point_cloud_.fields.resize(4);
00764 luma_organized_point_cloud_.fields[0].name = "x";
00765 luma_organized_point_cloud_.fields[0].offset = 0;
00766 luma_organized_point_cloud_.fields[0].count = 1;
00767 luma_organized_point_cloud_.fields[0].datatype = sensor_msgs::PointField::FLOAT32;
00768 luma_organized_point_cloud_.fields[1].name = "y";
00769 luma_organized_point_cloud_.fields[1].offset = 4;
00770 luma_organized_point_cloud_.fields[1].count = 1;
00771 luma_organized_point_cloud_.fields[1].datatype = sensor_msgs::PointField::FLOAT32;
00772 luma_organized_point_cloud_.fields[2].name = "z";
00773 luma_organized_point_cloud_.fields[2].offset = 8;
00774 luma_organized_point_cloud_.fields[2].count = 1;
00775 luma_organized_point_cloud_.fields[2].datatype = sensor_msgs::PointField::FLOAT32;
00776 luma_organized_point_cloud_.fields[3].name = "luminance";
00777 luma_organized_point_cloud_.fields[3].offset = 12;
00778 luma_organized_point_cloud_.fields[3].count = 1;
00779 luma_organized_point_cloud_.fields[3].datatype = sensor_msgs::PointField::FLOAT32;
00780
00781 color_organized_point_cloud_.is_bigendian = (htonl(1) == 1);
00782 color_organized_point_cloud_.is_dense = false;
00783 color_organized_point_cloud_.point_step = color_cloud_step;
00784 color_organized_point_cloud_.header.frame_id = frame_id_left_;
00785 color_organized_point_cloud_.fields.resize(4);
00786 color_organized_point_cloud_.fields[0].name = "x";
00787 color_organized_point_cloud_.fields[0].offset = 0;
00788 color_organized_point_cloud_.fields[0].count = 1;
00789 color_organized_point_cloud_.fields[0].datatype = sensor_msgs::PointField::FLOAT32;
00790 color_organized_point_cloud_.fields[1].name = "y";
00791 color_organized_point_cloud_.fields[1].offset = 4;
00792 color_organized_point_cloud_.fields[1].count = 1;
00793 color_organized_point_cloud_.fields[1].datatype = sensor_msgs::PointField::FLOAT32;
00794 color_organized_point_cloud_.fields[2].name = "z";
00795 color_organized_point_cloud_.fields[2].offset = 8;
00796 color_organized_point_cloud_.fields[2].count = 1;
00797 color_organized_point_cloud_.fields[2].datatype = sensor_msgs::PointField::FLOAT32;
00798 color_organized_point_cloud_.fields[3].name = "rgb";
00799 color_organized_point_cloud_.fields[3].offset = 12;
00800 color_organized_point_cloud_.fields[3].count = 1;
00801 color_organized_point_cloud_.fields[3].datatype = sensor_msgs::PointField::FLOAT32;
00802
00803
00804
00805
00806
00807
00808
00809
00810 if (system::DeviceInfo::HARDWARE_REV_BCAM == device_info_.hardwareRevision) {
00811
00812 driver_->addIsolatedCallback(monoCB, Source_Luma_Left, this);
00813 driver_->addIsolatedCallback(jpegCB, Source_Jpeg_Left, this);
00814
00815 } else {
00816
00817 driver_->addIsolatedCallback(monoCB, Source_Luma_Left | Source_Luma_Right, this);
00818 driver_->addIsolatedCallback(rectCB, Source_Luma_Rectified_Left | Source_Luma_Rectified_Right, this);
00819 driver_->addIsolatedCallback(depthCB, Source_Disparity, this);
00820 driver_->addIsolatedCallback(pointCB, Source_Disparity, this);
00821 driver_->addIsolatedCallback(rawCB, Source_Disparity | Source_Luma_Rectified_Left, this);
00822 driver_->addIsolatedCallback(colorCB, Source_Luma_Left | Source_Chroma_Left, this);
00823 driver_->addIsolatedCallback(dispCB, Source_Disparity | Source_Disparity_Right | Source_Disparity_Cost, this);
00824 }
00825
00826
00827
00828
00829 driver_->addIsolatedCallback(histCB, allImageSources, this);
00830
00831
00832
00833
00834
00835 const char *pcColorFrameSyncEnvStringP = getenv("MULTISENSE_ROS_PC_COLOR_FRAME_SYNC_OFF");
00836 if (NULL != pcColorFrameSyncEnvStringP) {
00837 pc_color_frame_sync_ = false;
00838 ROS_INFO("color point cloud frame sync is disabled");
00839 }
00840 }
00841
00842 Camera::~Camera()
00843 {
00844 stop();
00845
00846 if (system::DeviceInfo::HARDWARE_REV_BCAM == device_info_.hardwareRevision) {
00847
00848 driver_->removeIsolatedCallback(monoCB);
00849 driver_->removeIsolatedCallback(jpegCB);
00850
00851 } else {
00852
00853 driver_->removeIsolatedCallback(monoCB);
00854 driver_->removeIsolatedCallback(rectCB);
00855 driver_->removeIsolatedCallback(depthCB);
00856 driver_->removeIsolatedCallback(pointCB);
00857 driver_->removeIsolatedCallback(rawCB);
00858 driver_->removeIsolatedCallback(colorCB);
00859 driver_->removeIsolatedCallback(dispCB);
00860 }
00861 }
00862
00863 void Camera::histogramCallback(const image::Header& header)
00864 {
00865 if (last_frame_id_ >= header.frameId)
00866 return;
00867
00868 last_frame_id_ = header.frameId;
00869
00870 if (histogram_pub_.getNumSubscribers() > 0) {
00871 multisense_ros::Histogram rh;
00872 image::Histogram mh;
00873
00874 Status status = driver_->getImageHistogram(header.frameId, mh);
00875 if (Status_Ok == status) {
00876 rh.frame_count = header.frameId;
00877 rh.time_stamp = ros::Time(header.timeSeconds,
00878 1000 * header.timeMicroSeconds);
00879 rh.width = header.width;
00880 rh.height = header.height;
00881 switch(header.source) {
00882 case Source_Chroma_Left:
00883 case Source_Chroma_Right:
00884 rh.width *= 2;
00885 rh.height *= 2;
00886 }
00887
00888 rh.exposure_time = header.exposure;
00889 rh.gain = header.gain;
00890 rh.fps = header.framesPerSecond;
00891 rh.channels = mh.channels;
00892 rh.bins = mh.bins;
00893 rh.data = mh.data;
00894 histogram_pub_.publish(rh);
00895 }
00896 }
00897 }
00898
00899 void Camera::jpegImageCallback(const image::Header& header)
00900 {
00901 if (Source_Jpeg_Left != header.source)
00902 return;
00903
00904 const uint32_t height = header.height;
00905 const uint32_t width = header.width;
00906 const uint32_t rgbLength = height * width * 3;
00907
00908 left_rgb_image_.header.frame_id = frame_id_left_;
00909 left_rgb_image_.height = height;
00910 left_rgb_image_.width = width;
00911 left_rgb_image_.encoding = "rgb8";
00912 left_rgb_image_.is_bigendian = false;
00913 left_rgb_image_.step = 3 * width;
00914 left_rgb_image_.header.stamp = ros::Time(header.timeSeconds,
00915 1000 * header.timeMicroSeconds);
00916
00917 left_rgb_image_.data.resize(rgbLength);
00918
00919 tjhandle jpegDecompressor = tjInitDecompress();
00920 tjDecompress2(jpegDecompressor,
00921 reinterpret_cast<unsigned char*>(const_cast<void*>(header.imageDataP)),
00922 header.imageLength,
00923 &(left_rgb_image_.data[0]),
00924 width, 0, height, TJPF_RGB, 0);
00925 tjDestroy(jpegDecompressor);
00926
00927 left_rgb_cam_pub_.publish(left_rgb_image_);
00928 left_rgb_cam_info_.header = left_rgb_image_.header;
00929 left_rgb_cam_info_pub_.publish(left_rgb_cam_info_);
00930
00931 if (left_rgb_rect_cam_pub_.getNumSubscribers() > 0) {
00932 boost::mutex::scoped_lock lock(cal_lock_);
00933
00934 if (width != image_config_.width() ||
00935 height != image_config_.height()){
00936
00937
00938 cal_lock_.unlock();
00939 queryConfig();
00940 }
00941 else if (NULL == calibration_map_left_1_ || NULL == calibration_map_left_2_)
00942 ROS_ERROR("Camera: undistort maps not initialized");
00943 else {
00944
00945 const CvScalar outlierColor = {{0.0}};
00946
00947 left_rgb_rect_image_.data.resize(rgbLength);
00948
00949 IplImage *sourceImageP = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 3);
00950 sourceImageP->imageData = reinterpret_cast<char*>(&(left_rgb_image_.data[0]));
00951 IplImage *destImageP = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 3);
00952 destImageP->imageData = reinterpret_cast<char*>(&(left_rgb_rect_image_.data[0]));
00953
00954 cvRemap(sourceImageP, destImageP,
00955 calibration_map_left_1_,
00956 calibration_map_left_2_,
00957 CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
00958 outlierColor);
00959
00960 cvReleaseImageHeader(&sourceImageP);
00961 cvReleaseImageHeader(&destImageP);
00962
00963 left_rgb_rect_image_.header.frame_id = frame_id_left_;
00964 left_rgb_rect_image_.header.stamp = ros::Time(header.timeSeconds,
00965 1000 * header.timeMicroSeconds);
00966 left_rgb_rect_image_.height = height;
00967 left_rgb_rect_image_.width = width;
00968 left_rgb_rect_image_.encoding = "rgb8";
00969 left_rgb_rect_image_.is_bigendian = false;
00970 left_rgb_rect_image_.step = 3 * width;
00971 left_rgb_rect_cam_info_.header = left_rgb_rect_image_.header;
00972 left_rgb_rect_frame_id_ = header.frameId;
00973 left_rgb_rect_cam_pub_.publish(left_rgb_rect_image_, left_rgb_rect_cam_info_);
00974 left_rgb_rect_cam_info_pub_.publish(left_rgb_rect_cam_info_);
00975 }
00976 }
00977 }
00978
00979 void Camera::disparityImageCallback(const image::Header& header)
00980 {
00981 if (!((Source_Disparity == header.source &&
00982 left_disparity_pub_.getNumSubscribers() > 0) ||
00983 (Source_Disparity_Right == header.source &&
00984 right_disparity_pub_.getNumSubscribers() > 0) ||
00985 (Source_Disparity_Cost == header.source &&
00986 left_disparity_cost_pub_.getNumSubscribers() > 0) ||
00987 (Source_Disparity == header.source &&
00988 left_stereo_disparity_pub_.getNumSubscribers() > 0) ||
00989 (Source_Disparity_Right == header.source &&
00990 right_stereo_disparity_pub_.getNumSubscribers() > 0) ))
00991 return;
00992
00993 const uint32_t imageSize = (header.width * header.height * header.bitsPerPixel) / 8;
00994
00995 ros::Time t = ros::Time(header.timeSeconds,
00996 1000 * header.timeMicroSeconds);
00997
00998 switch(header.source) {
00999 case Source_Disparity:
01000 case Source_Disparity_Right:
01001 {
01002 sensor_msgs::Image *imageP = NULL;
01003 sensor_msgs::CameraInfo *camInfoP = NULL;
01004 image_transport::Publisher *pubP = NULL;
01005 ros::Publisher *camInfoPubP = NULL;
01006 ros::Publisher *stereoDisparityPubP = NULL;
01007 stereo_msgs::DisparityImage *stereoDisparityImageP = NULL;
01008
01009
01010 if (Source_Disparity == header.source) {
01011 pubP = &left_disparity_pub_;
01012 imageP = &left_disparity_image_;
01013 imageP->header.frame_id = frame_id_left_;
01014 camInfoP = &left_disp_cam_info_;
01015 camInfoPubP = &left_disp_cam_info_pub_;
01016 stereoDisparityPubP = &left_stereo_disparity_pub_;
01017 stereoDisparityImageP = &left_stereo_disparity_;
01018 stereoDisparityImageP->header.frame_id = frame_id_left_;
01019 } else {
01020 pubP = &right_disparity_pub_;
01021 imageP = &right_disparity_image_;
01022 imageP->header.frame_id = frame_id_right_;
01023 camInfoP = &right_disp_cam_info_;
01024 camInfoPubP = &right_disp_cam_info_pub_;
01025 stereoDisparityPubP = &right_stereo_disparity_pub_;
01026 stereoDisparityImageP = &right_stereo_disparity_;
01027 stereoDisparityImageP->header.frame_id = frame_id_right_;
01028 }
01029
01030
01031
01032 if (pubP->getNumSubscribers() > 0)
01033 {
01034 imageP->data.resize(imageSize);
01035 memcpy(&imageP->data[0], header.imageDataP, imageSize);
01036
01037 imageP->header.stamp = t;
01038 imageP->height = header.height;
01039 imageP->width = header.width;
01040 imageP->is_bigendian = false;
01041
01042 switch(header.bitsPerPixel) {
01043 case 8:
01044 imageP->encoding = sensor_msgs::image_encodings::TYPE_8UC1;
01045 imageP->step = header.width;
01046 break;
01047 case 16:
01048 imageP->encoding = sensor_msgs::image_encodings::TYPE_16UC1;
01049 imageP->step = header.width * 2;
01050 break;
01051 }
01052
01053 pubP->publish(*imageP);
01054 }
01055
01056 if (stereoDisparityPubP->getNumSubscribers() > 0)
01057 {
01058
01059
01060
01061
01062
01063 if (right_rect_cam_info_.P[0] != right_rect_cam_info_.P[5])
01064 {
01065 std::stringstream warning;
01066 warning << "Current camera configuration has non-square pixels (fx != fy).";
01067 warning << "The stereo_msgs/DisparityImage does not account for";
01068 warning << " this. Be careful when reprojecting to a pointcloud.";
01069 ROS_WARN("%s", warning.str().c_str());
01070 }
01071
01072
01073
01074
01075
01076 uint32_t floatingPointImageSize = header.width * header.height * 4;
01077 stereoDisparityImageP->image.data.resize(floatingPointImageSize);
01078
01079 stereoDisparityImageP->header.stamp = t;
01080
01081 stereoDisparityImageP->image.height = header.height;
01082 stereoDisparityImageP->image.width = header.width;
01083 stereoDisparityImageP->image.is_bigendian = false;
01084 stereoDisparityImageP->image.header.stamp = t;
01085 stereoDisparityImageP->image.header.frame_id = stereoDisparityImageP->header.frame_id;
01086 stereoDisparityImageP->image.encoding = "32FC1";
01087 stereoDisparityImageP->image.step = 4 * header.width;
01088
01089
01090
01091
01092
01093 stereoDisparityImageP->f = right_rect_cam_info_.P[0];
01094
01095
01096
01097
01098
01099 stereoDisparityImageP->T = fabs(right_rect_cam_info_.P[3] /
01100 right_rect_cam_info_.P[0]);
01101 stereoDisparityImageP->min_disparity = 0;
01102 stereoDisparityImageP->max_disparity = disparities_;
01103 stereoDisparityImageP->delta_d = 1./16.;
01104
01105
01106
01107
01108
01109
01110
01111 cv::Mat_<uint16_t> tmpImage(header.height,
01112 header.width,
01113 reinterpret_cast<uint16_t*>(
01114 const_cast<void*>(header.imageDataP)));
01115
01116
01117
01118
01119 cv::Mat_<float> floatingPointImage(header.height,
01120 header.width,
01121 reinterpret_cast<float*>(&stereoDisparityImageP->image.data[0]));
01122
01123
01124
01125
01126
01127 floatingPointImage = tmpImage / 16.0;
01128
01129 stereoDisparityPubP->publish(*stereoDisparityImageP);
01130 }
01131
01132 camInfoP->header = imageP->header;
01133 camInfoP->header.stamp = t;
01134 camInfoPubP->publish(*camInfoP);
01135
01136 break;
01137 }
01138 case Source_Disparity_Cost:
01139
01140 left_disparity_cost_image_.data.resize(imageSize);
01141 memcpy(&left_disparity_cost_image_.data[0], header.imageDataP, imageSize);
01142
01143 left_disparity_cost_image_.header.frame_id = frame_id_left_;
01144 left_disparity_cost_image_.header.stamp = t;
01145 left_disparity_cost_image_.height = header.height;
01146 left_disparity_cost_image_.width = header.width;
01147
01148 left_disparity_cost_image_.encoding = sensor_msgs::image_encodings::TYPE_8UC1;
01149 left_disparity_cost_image_.is_bigendian = false;
01150 left_disparity_cost_image_.step = header.width;
01151
01152 left_disparity_cost_pub_.publish(left_disparity_cost_image_);
01153
01154 left_cost_cam_info_.header = left_disparity_cost_image_.header;
01155 left_cost_cam_info_pub_.publish(left_cost_cam_info_);
01156
01157 break;
01158 }
01159 }
01160
01161 void Camera::monoCallback(const image::Header& header)
01162 {
01163 if (Source_Luma_Left != header.source &&
01164 Source_Luma_Right != header.source) {
01165
01166 ROS_ERROR("Camera: unexpected image source: 0x%x", header.source);
01167 return;
01168 }
01169
01170 ros::Time t = ros::Time(header.timeSeconds,
01171 1000 * header.timeMicroSeconds);
01172
01173 switch(header.source) {
01174 case Source_Luma_Left:
01175
01176 left_mono_image_.data.resize(header.imageLength);
01177 memcpy(&left_mono_image_.data[0], header.imageDataP, header.imageLength);
01178
01179 left_mono_image_.header.frame_id = frame_id_left_;
01180 left_mono_image_.header.stamp = t;
01181 left_mono_image_.height = header.height;
01182 left_mono_image_.width = header.width;
01183
01184 switch(header.bitsPerPixel) {
01185 case 8:
01186 left_mono_image_.encoding = sensor_msgs::image_encodings::TYPE_8UC1;
01187 left_mono_image_.step = header.width;
01188 break;
01189 case 16:
01190 left_mono_image_.encoding = sensor_msgs::image_encodings::TYPE_16UC1;
01191 left_mono_image_.step = header.width * 2;
01192 break;
01193 }
01194
01195 left_mono_image_.is_bigendian = false;
01196
01197 left_mono_cam_pub_.publish(left_mono_image_);
01198
01199
01200
01201 left_mono_cam_info_.header= left_mono_image_.header;
01202 left_mono_cam_info_pub_.publish(left_mono_cam_info_);
01203
01204 break;
01205 case Source_Luma_Right:
01206
01207 right_mono_image_.data.resize(header.imageLength);
01208 memcpy(&right_mono_image_.data[0], header.imageDataP, header.imageLength);
01209
01210 right_mono_image_.header.frame_id = frame_id_right_;
01211 right_mono_image_.header.stamp = t;
01212 right_mono_image_.height = header.height;
01213 right_mono_image_.width = header.width;
01214
01215 switch(header.bitsPerPixel) {
01216 case 8:
01217 right_mono_image_.encoding = sensor_msgs::image_encodings::TYPE_8UC1;
01218 right_mono_image_.step = header.width;
01219 break;
01220 case 16:
01221 right_mono_image_.encoding = sensor_msgs::image_encodings::TYPE_16UC1;
01222 right_mono_image_.step = header.width * 2;
01223 break;
01224 }
01225 right_mono_image_.is_bigendian = false;
01226
01227 right_mono_cam_pub_.publish(right_mono_image_);
01228
01229
01230
01231 right_mono_cam_info_.header= right_mono_image_.header;
01232 right_mono_cam_info_pub_.publish(right_mono_cam_info_);
01233
01234 break;
01235 }
01236 }
01237
01238 void Camera::rectCallback(const image::Header& header)
01239 {
01240 if (Source_Luma_Rectified_Left != header.source &&
01241 Source_Luma_Rectified_Right != header.source) {
01242
01243 ROS_ERROR("Camera: unexpected image source: 0x%x", header.source);
01244 return;
01245 }
01246
01247
01248 ros::Time t = ros::Time(header.timeSeconds,
01249 1000 * header.timeMicroSeconds);
01250
01251 switch(header.source) {
01252 case Source_Luma_Rectified_Left:
01253
01254 left_rect_image_.data.resize(header.imageLength);
01255 memcpy(&left_rect_image_.data[0], header.imageDataP, header.imageLength);
01256
01257 left_rect_image_.header.frame_id = frame_id_left_;
01258 left_rect_image_.header.stamp = t;
01259 left_rect_image_.height = header.height;
01260 left_rect_image_.width = header.width;
01261
01262 left_rect_frame_id_ = header.frameId;
01263
01264
01265 switch(header.bitsPerPixel) {
01266 case 8:
01267 left_rect_image_.encoding = sensor_msgs::image_encodings::TYPE_8UC1;
01268 left_rect_image_.step = header.width;
01269
01270 break;
01271 case 16:
01272 left_rect_image_.encoding = sensor_msgs::image_encodings::TYPE_16UC1;
01273 left_rect_image_.step = header.width * 2;
01274
01275 break;
01276 }
01277
01278 left_rect_image_.is_bigendian = false;
01279
01280 left_rect_cam_info_.header = left_rect_image_.header;
01281
01282
01283
01284
01285
01286 left_rect_cam_pub_.publish(left_rect_image_, left_rect_cam_info_);
01287
01288 left_rect_cam_info_pub_.publish(left_rect_cam_info_);
01289
01290 publishPointCloud(left_rect_frame_id_,
01291 points_buff_frame_id_,
01292 luma_point_cloud_frame_id_,
01293 luma_point_cloud_pub_,
01294 luma_point_cloud_,
01295 header.width,
01296 header.height,
01297 header.timeSeconds,
01298 header.timeMicroSeconds,
01299 luma_cloud_step,
01300 points_buff_,
01301 &(left_rect_image_.data[0]), luma_color_depth_,
01302 pc_max_range_,
01303 write_pc_color_packed_,
01304 false);
01305
01306 publishPointCloud(left_rect_frame_id_,
01307 points_buff_frame_id_,
01308 luma_organized_point_cloud_frame_id_,
01309 luma_organized_point_cloud_pub_,
01310 luma_organized_point_cloud_,
01311 header.width,
01312 header.height,
01313 header.timeSeconds,
01314 header.timeMicroSeconds,
01315 luma_cloud_step,
01316 points_buff_,
01317 &(left_rect_image_.data[0]), luma_color_depth_,
01318 pc_max_range_,
01319 write_pc_color_packed_,
01320 true);
01321
01322 break;
01323 case Source_Luma_Rectified_Right:
01324
01325 right_rect_image_.data.resize(header.imageLength);
01326 memcpy(&right_rect_image_.data[0], header.imageDataP, header.imageLength);
01327
01328 right_rect_image_.header.frame_id = frame_id_left_;
01329 right_rect_image_.header.stamp = t;
01330 right_rect_image_.height = header.height;
01331 right_rect_image_.width = header.width;
01332
01333 switch(header.bitsPerPixel) {
01334 case 8:
01335 right_rect_image_.encoding = sensor_msgs::image_encodings::TYPE_8UC1;
01336 right_rect_image_.step = header.width;
01337 break;
01338 case 16:
01339 right_rect_image_.encoding = sensor_msgs::image_encodings::TYPE_16UC1;
01340 right_rect_image_.step = header.width * 2;
01341 break;
01342 }
01343
01344 right_rect_image_.is_bigendian = false;
01345
01346 right_rect_cam_info_.header = right_rect_image_.header;
01347
01348
01349
01350
01351
01352 right_rect_cam_pub_.publish(right_rect_image_, right_rect_cam_info_);
01353
01354 right_rect_cam_info_pub_.publish(right_rect_cam_info_);
01355
01356 break;
01357 }
01358 }
01359
01360 void Camera::depthCallback(const image::Header& header)
01361 {
01362 if (Source_Disparity != header.source) {
01363
01364 ROS_ERROR("Camera: unexpected image source: 0x%x", header.source);
01365 return;
01366 }
01367
01368 uint32_t niDepthSubscribers = ni_depth_cam_pub_.getNumSubscribers();
01369 uint32_t depthSubscribers = depth_cam_pub_.getNumSubscribers();
01370 if (0 == niDepthSubscribers &&
01371 0 == depthSubscribers)
01372 return;
01373
01374 const float bad_point = std::numeric_limits<float>::quiet_NaN();
01375 const uint32_t depthSize = header.height * header.width * sizeof(float);
01376 const uint32_t niDepthSize = header.height * header.width * sizeof(uint16_t);
01377 const uint32_t imageSize = header.width * header.height;
01378
01379 depth_image_.header.stamp = ros::Time(header.timeSeconds,
01380 1000 * header.timeMicroSeconds);
01381 depth_image_.header.frame_id = frame_id_left_;
01382 depth_image_.height = header.height;
01383 depth_image_.width = header.width;
01384 depth_image_.is_bigendian = (htonl(1) == 1);
01385
01386 ni_depth_image_ = depth_image_;
01387
01388 ni_depth_image_.encoding = "16UC1";
01389 ni_depth_image_.step = header.width * 2;
01390
01391 depth_image_.encoding = "32FC1";
01392 depth_image_.step = header.width * 4;
01393
01394 depth_image_.data.resize(depthSize);
01395 ni_depth_image_.data.resize(niDepthSize);
01396
01397 float *depthImageP = reinterpret_cast<float*>(&depth_image_.data[0]);
01398 uint16_t *niDepthImageP = reinterpret_cast<uint16_t*>(&ni_depth_image_.data[0]);
01399
01400
01401
01402
01403 if (32 == header.bitsPerPixel) {
01404
01405
01406
01407
01408
01409
01410
01411
01412
01413
01414 const double scale = (-right_rect_cam_info_.P[3]);
01415
01416 const float *disparityImageP = reinterpret_cast<const float*>(header.imageDataP);
01417
01418 for (uint32_t i = 0 ; i < imageSize ; ++i)
01419 {
01420 if (0.0 >= disparityImageP[i])
01421 {
01422 depthImageP[i] = bad_point;
01423 niDepthImageP[i] = 0;
01424 }
01425 else
01426 {
01427 depthImageP[i] = scale / disparityImageP[i];
01428 niDepthImageP[i] = static_cast<uint16_t>(depthImageP[i] * 1000);
01429 }
01430 }
01431
01432
01433
01434
01435 } else if (16 == header.bitsPerPixel) {
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448 const float scale = (right_rect_cam_info_.P[3] * -16.0f);
01449
01450 const uint16_t *disparityImageP = reinterpret_cast<const uint16_t*>(header.imageDataP);
01451
01452 for (uint32_t i = 0 ; i < imageSize ; ++i)
01453 {
01454 if (0 == disparityImageP[i])
01455 {
01456 depthImageP[i] = bad_point;
01457 niDepthImageP[i] = 0;
01458 }
01459 else
01460 {
01461 depthImageP[i] = scale / disparityImageP[i];
01462 niDepthImageP[i] = static_cast<uint16_t>(depthImageP[i] * 1000);
01463 }
01464 }
01465
01466 } else {
01467 ROS_ERROR("Camera: unsupported disparity bpp: %d", header.bitsPerPixel);
01468 return;
01469 }
01470
01471 if (0 != niDepthSubscribers)
01472 {
01473 ni_depth_cam_pub_.publish(ni_depth_image_);
01474 }
01475
01476 if (0 != depthSubscribers)
01477 {
01478 depth_cam_pub_.publish(depth_image_);
01479 }
01480
01481 depth_cam_info_.header = depth_image_.header;
01482 depth_cam_info_pub_.publish(depth_cam_info_);
01483 }
01484
01485 void Camera::pointCloudCallback(const image::Header& header)
01486 {
01487 if (Source_Disparity != header.source) {
01488
01489 ROS_ERROR("Camera: unexpected image source: 0x%x", header.source);
01490 return;
01491 }
01492
01493 if (0 == luma_point_cloud_pub_.getNumSubscribers() &&
01494 0 == color_point_cloud_pub_.getNumSubscribers() &&
01495 0 == luma_organized_point_cloud_pub_.getNumSubscribers() &&
01496 0 == color_organized_point_cloud_pub_.getNumSubscribers())
01497 return;
01498
01499 boost::mutex::scoped_lock lock(border_clip_lock_);
01500
01501 const bool handle_missing = true;
01502 const uint32_t imageSize = header.height * header.width;
01503
01504
01505
01506
01507 points_buff_.resize(imageSize);
01508 disparity_buff_.resize(imageSize);
01509
01510
01511
01512
01513 cv::Mat_<cv::Vec3f> points(header.height, header.width, &(points_buff_[0]));
01514
01515
01516
01517
01518 if (32 == header.bitsPerPixel) {
01519
01520 cv::Mat_<float> disparity(header.height, header.width,
01521 const_cast<float*>(reinterpret_cast<const float*>(header.imageDataP)));
01522
01523 cv::reprojectImageTo3D(disparity, points, q_matrix_, handle_missing);
01524
01525
01526
01527
01528 } else if (16 == header.bitsPerPixel) {
01529
01530 cv::Mat_<uint16_t> disparityOrigP(header.height, header.width,
01531 const_cast<uint16_t*>(reinterpret_cast<const uint16_t*>(header.imageDataP)));
01532 cv::Mat_<float> disparity(header.height, header.width, &(disparity_buff_[0]));
01533 disparity = disparityOrigP / 16.0f;
01534
01535 cv::reprojectImageTo3D(disparity, points, q_matrix_, handle_missing);
01536
01537 } else {
01538 ROS_ERROR("Camera: unsupported disparity bpp: %d", header.bitsPerPixel);
01539 return;
01540 }
01541
01542
01543
01544
01545
01546 if ( border_clip_value_ > 0)
01547 {
01548 points.setTo(cv::Vec3f(10000.0, 10000.0, 10000.0), border_clip_mask_);
01549 }
01550
01551
01552
01553
01554
01555 points_buff_frame_id_ = header.frameId;
01556
01557
01558
01559
01560 publishPointCloud(left_rect_frame_id_,
01561 points_buff_frame_id_,
01562 luma_point_cloud_frame_id_,
01563 luma_point_cloud_pub_,
01564 luma_point_cloud_,
01565 header.width,
01566 header.height,
01567 header.timeSeconds,
01568 header.timeMicroSeconds,
01569 luma_cloud_step,
01570 points_buff_,
01571 &(left_rect_image_.data[0]), luma_color_depth_,
01572 pc_max_range_,
01573 write_pc_color_packed_,
01574 false);
01575
01576 publishPointCloud(left_rgb_rect_frame_id_,
01577 points_buff_frame_id_,
01578 color_point_cloud_frame_id_,
01579 color_point_cloud_pub_,
01580 color_point_cloud_,
01581 header.width,
01582 header.height,
01583 header.timeSeconds,
01584 header.timeMicroSeconds,
01585 color_cloud_step,
01586 points_buff_,
01587 &(left_rgb_rect_image_.data[0]), 3,
01588 pc_max_range_,
01589 write_pc_color_packed_,
01590 false);
01591
01592 publishPointCloud(left_rect_frame_id_,
01593 points_buff_frame_id_,
01594 luma_organized_point_cloud_frame_id_,
01595 luma_organized_point_cloud_pub_,
01596 luma_organized_point_cloud_,
01597 header.width,
01598 header.height,
01599 header.timeSeconds,
01600 header.timeMicroSeconds,
01601 luma_cloud_step,
01602 points_buff_,
01603 &(left_rect_image_.data[0]), luma_color_depth_,
01604 pc_max_range_,
01605 write_pc_color_packed_,
01606 true);
01607
01608 publishPointCloud(left_rgb_rect_frame_id_,
01609 points_buff_frame_id_,
01610 color_organized_point_cloud_frame_id_,
01611 color_organized_point_cloud_pub_,
01612 color_organized_point_cloud_,
01613 header.width,
01614 header.height,
01615 header.timeSeconds,
01616 header.timeMicroSeconds,
01617 color_cloud_step,
01618 points_buff_,
01619 &(left_rgb_rect_image_.data[0]), 3,
01620 pc_max_range_,
01621 write_pc_color_packed_,
01622 true);
01623 }
01624
01625 void Camera::rawCamDataCallback(const image::Header& header)
01626 {
01627 if (0 == raw_cam_data_pub_.getNumSubscribers()) {
01628 got_raw_cam_left_ = false;
01629 return;
01630 }
01631
01632 const uint32_t imageSize = header.width * header.height;
01633
01634
01635
01636
01637
01638 if (false == got_raw_cam_left_) {
01639
01640 if (Source_Luma_Rectified_Left == header.source) {
01641
01642 raw_cam_data_.gray_scale_image.resize(imageSize);
01643 memcpy(&(raw_cam_data_.gray_scale_image[0]),
01644 header.imageDataP,
01645 imageSize * sizeof(uint8_t));
01646
01647 raw_cam_data_.frames_per_second = header.framesPerSecond;
01648 raw_cam_data_.gain = header.gain;
01649 raw_cam_data_.exposure_time = header.exposure;
01650 raw_cam_data_.frame_count = header.frameId;
01651 raw_cam_data_.time_stamp = ros::Time(header.timeSeconds,
01652 1000 * header.timeMicroSeconds);
01653 raw_cam_data_.width = header.width;
01654 raw_cam_data_.height = header.height;
01655
01656 got_raw_cam_left_ = true;
01657 }
01658
01659 } else if (Source_Disparity == header.source) {
01660
01661 const uint32_t imageSize = header.width * header.height;
01662
01663 if (header.frameId == raw_cam_data_.frame_count) {
01664
01665 raw_cam_data_.disparity_image.resize(imageSize);
01666 memcpy(&(raw_cam_data_.disparity_image[0]),
01667 header.imageDataP, imageSize * sizeof(uint16_t));
01668
01669 raw_cam_data_pub_.publish(raw_cam_data_);
01670 }
01671
01672 got_raw_cam_left_ = false;
01673 }
01674 }
01675
01676 void Camera::colorImageCallback(const image::Header& header)
01677 {
01678 if (0 == left_rgb_cam_pub_.getNumSubscribers() &&
01679 0 == left_rgb_rect_cam_pub_.getNumSubscribers() &&
01680 0 == color_point_cloud_pub_.getNumSubscribers() &&
01681 0 == color_organized_point_cloud_pub_.getNumSubscribers()) {
01682 got_left_luma_ = false;
01683 return;
01684 }
01685
01686
01687
01688
01689
01690 if (false == got_left_luma_) {
01691
01692 if (Source_Luma_Left == header.source) {
01693
01694 const uint32_t imageSize = header.width * header.height;
01695
01696 left_luma_image_.data.resize(imageSize);
01697 memcpy(&left_luma_image_.data[0], header.imageDataP, imageSize);
01698
01699 left_luma_image_.height = header.height;
01700 left_luma_image_.width = header.width;
01701
01702 left_luma_frame_id_ = header.frameId;
01703 got_left_luma_ = true;
01704 }
01705
01706 } else if (Source_Chroma_Left == header.source) {
01707
01708 if (header.frameId == left_luma_frame_id_) {
01709
01710 const uint32_t height = left_luma_image_.height;
01711 const uint32_t width = left_luma_image_.width;
01712 const uint32_t imageSize = 3 * height * width;
01713
01714 left_rgb_image_.data.resize(imageSize);
01715
01716 left_rgb_image_.header.frame_id = frame_id_left_;
01717 left_rgb_image_.header.stamp = ros::Time(header.timeSeconds,
01718 1000 * header.timeMicroSeconds);
01719 left_rgb_image_.height = height;
01720 left_rgb_image_.width = width;
01721
01722 left_rgb_image_.encoding = "bgr8";
01723 left_rgb_image_.is_bigendian = false;
01724 left_rgb_image_.step = 3 * width;
01725
01726
01727
01728
01729
01730 const uint8_t *lumaP = reinterpret_cast<const uint8_t*>(&(left_luma_image_.data[0]));
01731 const uint8_t *chromaP = reinterpret_cast<const uint8_t*>(header.imageDataP);
01732 uint8_t *bgrP = reinterpret_cast<uint8_t*>(&(left_rgb_image_.data[0]));
01733 const uint32_t rgbStride = width * 3;
01734
01735 for(uint32_t y=0; y<height; y++) {
01736 for(uint32_t x=0; x<width; x++) {
01737
01738 const uint32_t lumaOffset = (y * width) + x;
01739 const uint32_t chromaOffset = 2 * (((y/2) * (width/2)) + (x/2));
01740
01741 const float px_y = static_cast<float>(lumaP[lumaOffset]);
01742 const float px_cb = static_cast<float>(chromaP[chromaOffset+0]) - 128.0f;
01743 const float px_cr = static_cast<float>(chromaP[chromaOffset+1]) - 128.0f;
01744
01745 float px_r = px_y + 1.402f * px_cr;
01746 float px_g = px_y - 0.34414f * px_cb - 0.71414f * px_cr;
01747 float px_b = px_y + 1.772f * px_cb;
01748
01749 if (px_r < 0.0f) px_r = 0.0f;
01750 else if (px_r > 255.0f) px_r = 255.0f;
01751 if (px_g < 0.0f) px_g = 0.0f;
01752 else if (px_g > 255.0f) px_g = 255.0f;
01753 if (px_b < 0.0f) px_b = 0.0f;
01754 else if (px_b > 255.0f) px_b = 255.0f;
01755
01756 const uint32_t rgbOffset = (y * rgbStride) + (3 * x);
01757
01758 bgrP[rgbOffset + 0] = static_cast<uint8_t>(px_b);
01759 bgrP[rgbOffset + 1] = static_cast<uint8_t>(px_g);
01760 bgrP[rgbOffset + 2] = static_cast<uint8_t>(px_r);
01761 }
01762 }
01763
01764 if (0 != left_rgb_cam_pub_.getNumSubscribers()) {
01765 left_rgb_cam_pub_.publish(left_rgb_image_);
01766
01767 left_rgb_cam_info_.header = left_rgb_image_.header;
01768 left_rgb_cam_info_pub_.publish(left_rgb_cam_info_);
01769 }
01770
01771 if (left_rgb_rect_cam_pub_.getNumSubscribers() > 0 ||
01772 color_point_cloud_pub_.getNumSubscribers() > 0 ||
01773 color_organized_point_cloud_pub_.getNumSubscribers() > 0) {
01774 boost::mutex::scoped_lock lock(cal_lock_);
01775
01776 if (width != image_config_.width() ||
01777 height != image_config_.height())
01778
01779
01780 ;
01781 else if (NULL == calibration_map_left_1_ || NULL == calibration_map_left_2_)
01782 ROS_ERROR("Camera: undistort maps not initialized");
01783 else {
01784
01785 const CvScalar outlierColor = {{0.0}};
01786
01787 left_rgb_rect_image_.data.resize(imageSize);
01788
01789 IplImage *sourceImageP = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 3);
01790 sourceImageP->imageData = reinterpret_cast<char*>(&(left_rgb_image_.data[0]));
01791 IplImage *destImageP = cvCreateImageHeader(cvSize(width, height), IPL_DEPTH_8U, 3);
01792 destImageP->imageData = reinterpret_cast<char*>(&(left_rgb_rect_image_.data[0]));
01793
01794 cvRemap(sourceImageP, destImageP,
01795 calibration_map_left_1_,
01796 calibration_map_left_2_,
01797 CV_INTER_LINEAR+CV_WARP_FILL_OUTLIERS,
01798 outlierColor);
01799
01800 cvReleaseImageHeader(&sourceImageP);
01801 cvReleaseImageHeader(&destImageP);
01802
01803 left_rgb_rect_image_.header.frame_id = frame_id_left_;
01804 left_rgb_rect_image_.header.stamp = ros::Time(header.timeSeconds,
01805 1000 * header.timeMicroSeconds);
01806 left_rgb_rect_image_.height = height;
01807 left_rgb_rect_image_.width = width;
01808
01809 left_rgb_rect_image_.encoding = "bgr8";
01810 left_rgb_rect_image_.is_bigendian = false;
01811 left_rgb_rect_image_.step = 3 * width;
01812
01813 left_rgb_rect_cam_info_.header = left_rgb_rect_image_.header;
01814 left_rgb_rect_frame_id_ = header.frameId;
01815
01816 if (left_rgb_rect_cam_pub_.getNumSubscribers() > 0) {
01817 left_rgb_rect_cam_pub_.publish(left_rgb_rect_image_, left_rgb_rect_cam_info_);
01818
01819 left_rgb_rect_cam_info_.header = left_rgb_rect_image_.header;
01820 left_rgb_rect_cam_info_pub_.publish(left_rgb_rect_cam_info_);
01821 }
01822
01823
01824
01825
01826 publishPointCloud(left_rgb_rect_frame_id_,
01827 points_buff_frame_id_,
01828 color_point_cloud_frame_id_,
01829 color_point_cloud_pub_,
01830 color_point_cloud_,
01831 left_luma_image_.width,
01832 left_luma_image_.height,
01833 header.timeSeconds,
01834 header.timeMicroSeconds,
01835 color_cloud_step,
01836 points_buff_,
01837 &(left_rgb_rect_image_.data[0]), 3,
01838 pc_max_range_,
01839 write_pc_color_packed_,
01840 false);
01841
01842 publishPointCloud(left_rgb_rect_frame_id_,
01843 points_buff_frame_id_,
01844 color_organized_point_cloud_frame_id_,
01845 color_organized_point_cloud_pub_,
01846 color_organized_point_cloud_,
01847 left_luma_image_.width,
01848 left_luma_image_.height,
01849 header.timeSeconds,
01850 header.timeMicroSeconds,
01851 color_cloud_step,
01852 points_buff_,
01853 &(left_rgb_rect_image_.data[0]), 3,
01854 pc_max_range_,
01855 write_pc_color_packed_,
01856 true);
01857 }
01858 }
01859 }
01860
01861 got_left_luma_ = false;
01862 }
01863 }
01864
01865 void Camera::queryConfig()
01866 {
01867 boost::mutex::scoped_lock lock(cal_lock_);
01868
01869
01870
01871
01872 Status status = driver_->getImageConfig(image_config_);
01873 if (Status_Ok != status) {
01874 ROS_ERROR("Camera: failed to query sensor configuration: %s",
01875 Channel::statusString(status));
01876 return;
01877 }
01878
01879
01880
01881
01882 const image::Config& c = image_config_;
01883
01884 disparities_ = c.disparities();
01885
01886
01887
01888
01889 left_rect_cam_info_.header.frame_id = frame_id_left_;
01890 left_rect_cam_info_.header.stamp = ros::Time::now();
01891 right_rect_cam_info_.header = left_rect_cam_info_.header;
01892
01893 left_rect_cam_info_.width = c.width();
01894 left_rect_cam_info_.height = c.height();
01895
01896 right_rect_cam_info_.width = c.width();
01897 right_rect_cam_info_.height = c.height();
01898
01899
01900
01901
01902 image::Calibration cal = image_calibration_;
01903
01904 const float x_scale = 1.0f / ((static_cast<float>(device_info_.imagerWidth) /
01905 static_cast<float>(c.width())));
01906 const float y_scale = 1.0f / ((static_cast<float>(device_info_.imagerHeight) /
01907 static_cast<float>(c.height())));
01908
01909
01910
01911
01912 updateCameraInfo(left_rect_cam_info_, cal.left.M, cal.left.R, cal.left.P, cal.left.D, x_scale, y_scale);
01913 updateCameraInfo(right_rect_cam_info_, cal.right.M, cal.right.R, cal.right.P, cal.right.D, x_scale, y_scale);
01914
01915
01916
01917
01918 left_disp_cam_info_ = left_rect_cam_info_;
01919 left_cost_cam_info_ = left_rect_cam_info_;
01920 left_rgb_rect_cam_info_ = left_rect_cam_info_;
01921 left_mono_cam_info_ = left_rect_cam_info_;
01922 left_rgb_cam_info_ = left_rect_cam_info_;
01923 depth_cam_info_ = left_rect_cam_info_;
01924
01925 right_mono_cam_info_ = right_rect_cam_info_;
01926 right_disp_cam_info_ = right_rect_cam_info_;
01927
01928
01929
01930
01931 right_mono_cam_info_.header.frame_id = frame_id_right_;
01932 right_disp_cam_info_.header.frame_id = frame_id_right_;
01933
01934
01935
01936
01937
01938
01939
01940
01941
01942
01943 q_matrix_(0,0) = c.fy() * c.tx();
01944 q_matrix_(1,1) = c.fx() * c.tx();
01945 q_matrix_(0,3) = -c.fy() * c.cx() * c.tx();
01946 q_matrix_(1,3) = -c.fx() * c.cy() * c.tx();
01947 q_matrix_(2,3) = c.fx() * c.fy() * c.tx();
01948 q_matrix_(3,2) = -c.fy();
01949 q_matrix_(3,3) = c.fy() * (right_rect_cam_info_.P[2] - left_rect_cam_info_.P[2]);
01950
01951
01952
01953
01954 if (calibration_map_left_1_)
01955 cvReleaseMat(&calibration_map_left_1_);
01956 if (calibration_map_left_2_)
01957 cvReleaseMat(&calibration_map_left_2_);
01958
01959 calibration_map_left_1_ = cvCreateMat(c.height(), c.width(), CV_32F);
01960 calibration_map_left_2_ = cvCreateMat(c.height(), c.width(), CV_32F);
01961
01962 cal.left.M[0][0] *= x_scale; cal.left.M[1][1] *= y_scale;
01963 cal.left.M[0][2] *= x_scale; cal.left.M[1][2] *= y_scale;
01964 cal.right.M[0][0] *= x_scale; cal.right.M[1][1] *= y_scale;
01965 cal.right.M[0][2] *= x_scale; cal.right.M[1][2] *= y_scale;
01966 cal.left.P[0][0] *= x_scale; cal.left.P[1][1] *= y_scale;
01967 cal.left.P[0][2] *= x_scale; cal.left.P[1][2] *= y_scale;
01968 cal.left.P[0][3] *= x_scale; cal.left.P[1][3] *= y_scale;
01969
01970 CvMat M1 = cvMat(3, 3, CV_32F, &cal.left.M);
01971 CvMat D1 = cvMat(1, 8, CV_32F, &cal.left.D);
01972 CvMat R1 = cvMat(3, 3, CV_32F, &cal.left.R);
01973 CvMat P1 = cvMat(3, 4, CV_32F, &cal.left.P);
01974
01975 cvInitUndistortRectifyMap(&M1, &D1, &R1, &P1,
01976 calibration_map_left_1_,
01977 calibration_map_left_2_);
01978
01979
01980
01981
01982
01983 multisense_ros::RawCamConfig cfg;
01984
01985 cfg.width = c.width();
01986 cfg.height = c.height();
01987 cfg.frames_per_second = c.fps();
01988 cfg.gain = c.gain();
01989 cfg.exposure_time = c.exposure();
01990
01991 cfg.fx = c.fx();
01992 cfg.fy = c.fy();
01993 cfg.cx = c.cx();
01994 cfg.cy = c.cy();
01995 cfg.tx = c.tx();
01996 cfg.ty = c.ty();
01997 cfg.tz = c.tz();
01998 cfg.roll = c.roll();
01999 cfg.pitch = c.pitch();
02000 cfg.yaw = c.yaw();
02001
02002 raw_cam_config_pub_.publish(cfg);
02003
02004
02005
02006
02007 generateBorderClip(border_clip_type_, border_clip_value_, c.height(), c.width());
02008
02009
02010
02011
02012 publishAllCameraInfo();
02013 }
02014
02015 void Camera::updateCameraInfo(sensor_msgs::CameraInfo& cameraInfo,
02016 const float M[3][3],
02017 const float R[3][3],
02018 const float P[3][4],
02019 const float D[8],
02020 double xScale,
02021 double yScale
02022 )
02023 {
02024 cameraInfo.P[0] = P[0][0] * xScale; cameraInfo.P[1] = P[0][1];
02025 cameraInfo.P[2] = P[0][2] * xScale; cameraInfo.P[3] = P[0][3] * xScale;
02026 cameraInfo.P[4] = P[1][0]; cameraInfo.P[5] = P[1][1] * yScale;
02027 cameraInfo.P[6] = P[1][2] * yScale; cameraInfo.P[7] = P[1][3];
02028 cameraInfo.P[8] = P[2][0]; cameraInfo.P[9] = P[2][1];
02029 cameraInfo.P[10] = P[2][2]; cameraInfo.P[11] = P[2][3];
02030
02031 cameraInfo.K[0] = M[0][0] * xScale; cameraInfo.K[1] = M[0][1];
02032 cameraInfo.K[2] = M[0][2] * xScale; cameraInfo.K[3] = M[1][0];
02033 cameraInfo.K[4] = M[1][1] * yScale; cameraInfo.K[5] = M[1][2] * yScale;
02034 cameraInfo.K[6] = M[2][0]; cameraInfo.K[7] = M[2][1];
02035 cameraInfo.K[8] = M[2][2];
02036
02037 cameraInfo.R[0] = R[0][0]; cameraInfo.R[1] = R[0][1];
02038 cameraInfo.R[2] = R[0][2]; cameraInfo.R[3] = R[1][0];
02039 cameraInfo.R[4] = R[1][1]; cameraInfo.R[5] = R[1][2];
02040 cameraInfo.R[6] = R[2][0]; cameraInfo.R[7] = R[2][1];
02041 cameraInfo.R[8] = R[2][2];
02042
02043
02044
02045
02046
02047 cameraInfo.D.resize(8);
02048 for (uint8_t i=0 ; i < 8 ; ++i) {
02049 cameraInfo.D[i] = D[i];
02050 }
02051
02052
02053
02054
02055
02056
02057
02058 if (D[7] == 0.0 && D[6] == 0.0 && D[5] == 0.0) {
02059 cameraInfo.distortion_model = sensor_msgs::distortion_models::PLUMB_BOB;
02060 } else {
02061 cameraInfo.distortion_model = sensor_msgs::distortion_models::RATIONAL_POLYNOMIAL;
02062 }
02063
02064 }
02065
02066
02067 void Camera::publishAllCameraInfo()
02068 {
02069
02070
02071
02072
02073
02074
02075
02076
02077 if (system::DeviceInfo::HARDWARE_REV_BCAM == device_info_.hardwareRevision) {
02078
02079 left_mono_cam_info_pub_.publish(left_mono_cam_info_);
02080 left_rgb_cam_info_pub_.publish(left_rgb_cam_info_);
02081 left_rgb_rect_cam_info_pub_.publish(left_rgb_rect_cam_info_);
02082
02083 } else if (system::DeviceInfo::HARDWARE_REV_MULTISENSE_M == device_info_.hardwareRevision) {
02084
02085 left_mono_cam_info_pub_.publish(left_mono_cam_info_);
02086 left_rect_cam_info_pub_.publish(left_rect_cam_info_);
02087 left_rgb_cam_info_pub_.publish(left_rgb_cam_info_);
02088 left_rgb_rect_cam_info_pub_.publish(left_rgb_rect_cam_info_);
02089
02090 } else {
02091
02092 if (system::DeviceInfo::HARDWARE_REV_MULTISENSE_ST21 != device_info_.hardwareRevision) {
02093
02094 left_rgb_cam_info_pub_.publish(left_rgb_cam_info_);
02095 left_rgb_rect_cam_info_pub_.publish(left_rgb_rect_cam_info_);
02096 }
02097
02098 if (version_info_.sensorFirmwareVersion >= 0x0300) {
02099
02100 right_disp_cam_info_pub_.publish(right_disp_cam_info_);
02101 left_cost_cam_info_pub_.publish(left_cost_cam_info_);
02102 }
02103
02104 left_mono_cam_info_pub_.publish(left_mono_cam_info_);
02105 left_rect_cam_info_pub_.publish(left_rect_cam_info_);
02106 right_mono_cam_info_pub_.publish(right_mono_cam_info_);
02107 right_rect_cam_info_pub_.publish(right_rect_cam_info_);
02108 left_disp_cam_info_pub_.publish(left_disp_cam_info_);
02109 depth_cam_info_pub_.publish(depth_cam_info_);
02110
02111 }
02112 }
02113
02114 void Camera::borderClipChanged(int borderClipType, double borderClipValue)
02115 {
02116
02117
02118
02119
02120 generateBorderClip(borderClipType, borderClipValue, border_clip_mask_.rows, border_clip_mask_.cols);
02121
02122 }
02123
02124 void Camera::generateBorderClip(int borderClipType, double borderClipValue, uint32_t height, uint32_t width)
02125 {
02126
02127 boost::mutex::scoped_lock lock(border_clip_lock_);
02128
02129 border_clip_type_ = borderClipType;
02130 border_clip_value_ = borderClipValue;
02131
02132
02133
02134
02135 border_clip_mask_ = cv::Mat_<uint8_t>(height, width, static_cast<uint8_t>(255));
02136
02137
02138
02139
02140
02141
02142 double halfWidth = static_cast<double>(width)/2.0;
02143 double halfHeight = static_cast<double>(height)/2.0;
02144
02145
02146
02147
02148
02149 double radius = sqrt( pow( halfWidth, 2) + pow( halfHeight, 2) );
02150 radius -= borderClipValue;
02151
02152 for (uint32_t u = 0 ; u < width ; ++u)
02153 {
02154 for (uint32_t v = 0 ; v < height ; ++v)
02155 {
02156 switch (borderClipType)
02157 {
02158 case RECTANGULAR:
02159 {
02160 if ( u >= borderClipValue && u <= width - borderClipValue &&
02161 v >= borderClipValue && v <= height - borderClipValue)
02162 {
02163 border_clip_mask_(v, u) = 0;
02164 }
02165
02166 break;
02167 }
02168 case CIRCULAR:
02169 {
02170 double vector = sqrt( pow( halfWidth - u, 2) +
02171 pow( halfHeight - v, 2) );
02172
02173 if ( vector < radius)
02174 {
02175 border_clip_mask_(v, u) = 0;
02176 }
02177
02178 break;
02179 }
02180 default:
02181 {
02182 ROS_WARN("Unknown border clip type.");
02183 return;
02184 }
02185 }
02186 }
02187 }
02188 }
02189
02190 void Camera::stop()
02191 {
02192 boost::mutex::scoped_lock lock(stream_lock_);
02193
02194 stream_map_.clear();
02195
02196 Status status = driver_->stopStreams(allImageSources);
02197 if (Status_Ok != status)
02198 ROS_ERROR("Camera: failed to stop all streams: %s",
02199 Channel::statusString(status));
02200 }
02201
02202 void Camera::connectStream(DataSource enableMask)
02203 {
02204 boost::mutex::scoped_lock lock(stream_lock_);
02205
02206 DataSource notStarted = 0;
02207
02208 for(uint32_t i=0; i<32; i++)
02209 if ((1<<i) & enableMask && 0 == stream_map_[(1<<i)]++)
02210 notStarted |= (1<<i);
02211
02212 if (0 != notStarted) {
02213
02214 Status status = driver_->startStreams(notStarted);
02215 if (Status_Ok != status)
02216 ROS_ERROR("Camera: failed to start streams 0x%x: %s",
02217 notStarted, Channel::statusString(status));
02218 }
02219 }
02220
02221 void Camera::disconnectStream(DataSource disableMask)
02222 {
02223 boost::mutex::scoped_lock lock(stream_lock_);
02224
02225 DataSource notStopped = 0;
02226
02227 for(uint32_t i=0; i<32; i++)
02228 if ((1<<i) & disableMask && 0 == --stream_map_[(1<<i)])
02229 notStopped |= (1<<i);
02230
02231 if (0 != notStopped) {
02232 Status status = driver_->stopStreams(notStopped);
02233 if (Status_Ok != status)
02234 ROS_ERROR("Camera: failed to stop streams 0x%x: %s\n",
02235 notStopped, Channel::statusString(status));
02236 }
02237 }
02238
02239
02240
02241 }