00001 #include <iostream>
00002 #include <chrono>
00003 #include <cstring>
00004 #include <csignal>
00005
00006 #include <dc1394/log.h>
00007 #include <dc1394/control.h>
00008 #include <dc1394/conversions.h>
00009
00010 #include <opencv2/imgproc/imgproc.hpp>
00011 #include <opencv2/highgui/highgui.hpp>
00012
00013 #include <boost/thread.hpp>
00014
00015 #include <ros/ros.h>
00016
00017 #include <image_transport/image_transport.h>
00018 #include <camera_info_manager/camera_info_manager.h>
00019
00020 #include <sensor_msgs/image_encodings.h>
00021
00022 #include <diagnostic_updater/diagnostic_updater.h>
00023 #include <diagnostic_updater/publisher.h>
00024
00025 #define BAYER_TILE_MAPPING_REGISTER (0x1040)
00026 #define SENSOR_BOARD_INFO_REGISTER (0x1f28)
00027 #define IMAGE_DATA_FORMAT_REGISTER (0x1048)
00028
00029 using namespace std;
00030
00031 class xb3CameraDriver
00032 {
00033 public:
00034 dc1394_t* d;
00035 unsigned int nThisCam;
00036 dc1394camera_t* camera;
00037 dc1394color_filter_t bayerTile;
00038
00039 unsigned int nBufferSize;
00040 unsigned char* pucRightRGB;
00041 unsigned char* pucLeftRGB;
00042 unsigned char* pucCenterRGB;
00043 unsigned char* pucGreenBuffer;
00044 unsigned char* pucRGBBuffer;
00045 unsigned char* pucDeInterlacedBuffer;
00046 unsigned char* pucGrabBuffer;
00047
00048 const unsigned int hardware_width;
00049 const unsigned int hardware_height;
00050 const unsigned int nBytesPerPixel;
00051
00052 unsigned int output_width;
00053 unsigned int output_height;
00054
00055
00056 string left_calibration_file;
00057 string center_calibration_file;
00058 string right_calibration_file;
00059
00060 image_transport::CameraPublisher left_publisher;
00061 image_transport::CameraPublisher center_publisher;
00062 image_transport::CameraPublisher right_publisher;
00063
00064 camera_info_manager::CameraInfoManager left_info_manager;
00065 camera_info_manager::CameraInfoManager center_info_manager;
00066 camera_info_manager::CameraInfoManager right_info_manager;
00067
00068 sensor_msgs::CameraInfo left_camera_info;
00069 sensor_msgs::CameraInfo center_camera_info;
00070 sensor_msgs::CameraInfo right_camera_info;
00071
00072 sensor_msgs::Image left;
00073 sensor_msgs::Image center;
00074 sensor_msgs::Image right;
00075
00076 cv::Mat opencv_left;
00077 cv::Mat opencv_center;
00078 cv::Mat opencv_right;
00079
00080 cv::Mat opencv_output_left;
00081 cv::Mat opencv_output_center;
00082 cv::Mat opencv_output_right;
00083
00084 boost::thread* buffer_processing_thread;
00085 boost::thread_group threads;
00086
00087 ros::NodeHandle nh;
00088 image_transport::ImageTransport it;
00089
00090
00091 diagnostic_updater::Updater updater;
00092
00093
00094 double status_max_frequency;
00095
00096
00097 double status_min_frequency;
00098
00099 diagnostic_updater::HeaderlessTopicDiagnostic frequency_diagnostics;
00100
00101 xb3CameraDriver(ros::NodeHandle nh_):
00102 nh(nh_),
00103 it(nh_),
00104 hardware_width(1280),
00105 hardware_height(960),
00106 nBytesPerPixel(3),
00107 left_info_manager(ros::NodeHandle(nh_, "left"),"left"),
00108 center_info_manager(ros::NodeHandle(nh_, "center"),"center"),
00109 right_info_manager(ros::NodeHandle(nh_, "right"),"right"),
00110 status_max_frequency(18),
00111 status_min_frequency(14),
00112 frequency_diagnostics("Xb3",updater,diagnostic_updater::FrequencyStatusParam(&status_min_frequency,&status_max_frequency, 0.01, 10)),
00113 buffer_processing_thread(NULL)
00114 {
00115 updater.setHardwareID("Xb3");
00116
00117 init();
00118
00119
00120
00121
00122
00123 nBufferSize = hardware_height*hardware_width*nBytesPerPixel;
00124 pucDeInterlacedBuffer = new unsigned char[nBufferSize];
00125 pucRGBBuffer = new unsigned char[3*nBufferSize];
00126 pucGreenBuffer = new unsigned char[nBufferSize];
00127 pucGrabBuffer = new unsigned char[3*nBufferSize];
00128
00129 opencv_left.create(cvSize(hardware_width,hardware_height),CV_8UC3);
00130 opencv_center.create(cvSize(hardware_width,hardware_height),CV_8UC3);
00131 opencv_right.create(cvSize(hardware_width,hardware_height),CV_8UC3);
00132
00133
00134 left_publisher = it.advertiseCamera("left/image_raw", 100);
00135 center_publisher = it.advertiseCamera("center/image_raw", 100);
00136 right_publisher = it.advertiseCamera("right/image_raw", 100);
00137
00138
00139 nh.param("left_calibration_file",left_calibration_file,string("package://xb3/calibrations/left_full_resolution.yaml"));
00140 nh.param("center_calibration_file",center_calibration_file,string("package://xb3/calibrations/center_full_resolution.yaml"));
00141 nh.param("right_calibration_file",right_calibration_file,string("package://xb3/calibrations/right_full_resolution.yaml"));
00142
00143
00144 left_info_manager.loadCameraInfo(left_calibration_file);
00145 center_info_manager.loadCameraInfo(center_calibration_file);
00146 right_info_manager.loadCameraInfo(right_calibration_file);
00147
00148
00149 left_camera_info = left_info_manager.getCameraInfo();
00150 center_camera_info = center_info_manager.getCameraInfo();
00151 right_camera_info = right_info_manager.getCameraInfo();
00152
00153
00154 left_camera_info.header.frame_id = ros::names::remap("/xb3_optical_frame");
00155 left_camera_info.roi.do_rectify = true;
00156
00157 center_camera_info.header.frame_id = ros::names::remap("/xb3_optical_frame");
00158 center_camera_info.roi.do_rectify = true;
00159
00160 right_camera_info.header.frame_id = ros::names::remap("/xb3_optical_frame");
00161 right_camera_info.roi.do_rectify = true;
00162
00163 output_height = left_camera_info.height;
00164 output_width = left_camera_info.width;
00165
00166 opencv_output_left.create(cvSize(output_width,output_height),CV_8UC3);
00167 opencv_output_center.create(cvSize(output_width,output_height),CV_8UC3);
00168 opencv_output_right.create(cvSize(output_width,output_height),CV_8UC3);
00169
00170
00171 left.height = left_camera_info.height;
00172 left.width = left_camera_info.width;
00173 left.encoding = sensor_msgs::image_encodings::RGB8;
00174 left.is_bigendian = 0;
00175 left.step = left.width*3;
00176 left.data.resize(left.width*left.height*3);
00177 left.header.frame_id = ros::names::remap( "/xb3_optical_frame");
00178
00179 center.height = center_camera_info.height;
00180 center.width = center_camera_info.width;
00181 center.encoding = sensor_msgs::image_encodings::RGB8;
00182 center.is_bigendian = 0;
00183 center.step = center.width*3;
00184 center.data.resize(center.width*center.height*3);
00185 center.header.frame_id = ros::names::remap( "/xb3_optical_frame");
00186
00187 right.height = right_camera_info.height;
00188 right.width = right_camera_info.width;
00189 right.encoding = sensor_msgs::image_encodings::RGB8;
00190 right.is_bigendian = 0;
00191 right.step = right.width*3;
00192 right.data.resize(right.width*right.height*3);
00193 right.header.frame_id = ros::names::remap( "/xb3_optical_frame");
00194 }
00195
00196 ~xb3CameraDriver()
00197 {
00198 cout<<"[ xb3CameraDriver]: Stopping transmission"<<endl;
00199 buffer_processing_thread->join();
00200 clean_dc1394();
00201 cout<<"[ xb3CameraDriver]: Camera closed"<<endl;
00202 }
00203
00204 void clean_dc1394(void)
00205 {
00206 dc1394_capture_stop(camera);
00207 dc1394_video_set_transmission(camera, DC1394_OFF);
00208 dc1394_camera_free(camera);
00209 }
00210
00211 dc1394error_t init()
00212 {
00213 dc1394camera_list_t* list;
00214 dc1394error_t err;
00215
00216
00217 d = dc1394_new();
00218
00219
00220 err = dc1394_camera_enumerate (d, &list);
00221 if (err != DC1394_SUCCESS )
00222 {
00223 ROS_ERROR("Unable to look for cameras\n\nPlease check \n"
00224 " - if the kernel modules `ieee1394',`raw1394' and `ohci1394' are loaded \n"
00225 " - if you have read/write access to /dev/raw1394\n\n");
00226 return err;
00227 }
00228
00229
00230 if (list->num == 0)
00231 {
00232 ROS_ERROR("No cameras found!");
00233 clean_dc1394();
00234 return DC1394_FAILURE;
00235 }
00236
00237 ROS_INFO("There were %d camera(s) found attached to your PC", list->num);
00238
00239
00240 for ( nThisCam = 0; nThisCam < list->num; nThisCam++ )
00241 {
00242 camera = dc1394_camera_new(d, list->ids[nThisCam].guid);
00243
00244 if(!camera)
00245 {
00246 ROS_ERROR("Failed to initialize camera with guid %lx", list->ids[nThisCam].guid);
00247 continue;
00248 }
00249
00250 ROS_INFO("Camera %d model = '%s'", nThisCam, camera->model );
00251
00252 if(strncmp(camera->model, "Bumblebee XB3", strlen("Bumblebee XB3")) == 0)
00253 {
00254 ROS_INFO("Found Bumblebee XB3 camera");
00255 break;
00256 }
00257
00258 dc1394_camera_free(camera);
00259 }
00260
00261
00262 ROS_INFO("Setting stereo video capture mode");
00263
00264 err = setStereoVideoCapture();
00265 if ( err != DC1394_SUCCESS )
00266 {
00267 ROS_ERROR("Could not set up video capture mode");
00268 clean_dc1394();
00269 return DC1394_FAILURE;
00270 }
00271
00272
00273 ROS_INFO("Start transmission");
00274 err = startTransmission();
00275 if ( err != DC1394_SUCCESS )
00276 {
00277 ROS_ERROR("Unable to start camera iso transmission" );
00278 clean_dc1394();
00279 }
00280
00281 err = getBayerTile(camera,&bayerTile);
00282 if ( err != DC1394_SUCCESS )
00283 {
00284 ROS_ERROR("Could not query the Bayer Tile Register!" );
00285 return DC1394_FAILURE;
00286 }
00287
00288 return DC1394_SUCCESS;
00289 }
00290
00291 dc1394error_t getBayerTile( dc1394camera_t* camera,dc1394color_filter_t* bayerPattern)
00292 {
00293 uint32_t value;
00294 dc1394error_t err;
00295
00296
00297
00298
00299 err = dc1394_get_control_register( camera, BAYER_TILE_MAPPING_REGISTER, &value );
00300 if ( err != DC1394_SUCCESS )
00301 {
00302 return err;
00303 }
00304
00305
00306 switch( value )
00307 {
00308 default:
00309 case 0x59595959:
00310
00311 *bayerPattern = (dc1394color_filter_t) 0;
00312 break;
00313 case 0x52474742:
00314 *bayerPattern = DC1394_COLOR_FILTER_RGGB;
00315 break;
00316 case 0x47425247:
00317 *bayerPattern = DC1394_COLOR_FILTER_GBRG;
00318 break;
00319 case 0x47524247:
00320 *bayerPattern = DC1394_COLOR_FILTER_GRBG;
00321 break;
00322 case 0x42474752:
00323 *bayerPattern = DC1394_COLOR_FILTER_BGGR;
00324 break;
00325 }
00326
00327 return err;
00328 }
00329
00330 dc1394error_t setStereoVideoCapture()
00331 {
00332 dc1394error_t err;
00333
00334
00335
00336 err = dc1394_memory_load(camera, 0 );
00337 if ( err != DC1394_SUCCESS )
00338 {
00339 ROS_ERROR("Can't load default memory channel" );
00340 return err;
00341 }
00342
00343
00344
00345 dc1394_video_set_operation_mode(camera, DC1394_OPERATION_MODE_1394B);
00346
00347 dc1394_video_set_iso_speed(camera, DC1394_ISO_SPEED_800 );
00348 dc1394_video_set_mode(camera, DC1394_VIDEO_MODE_FORMAT7_3 );
00349 err = dc1394_format7_set_roi(camera,
00350 DC1394_VIDEO_MODE_FORMAT7_3,
00351 DC1394_COLOR_CODING_RGB8,
00352
00353 7680,
00354 0,
00355 0,
00356 hardware_width,
00357 hardware_height);
00358 if ( err != DC1394_SUCCESS )
00359 {
00360 ROS_ERROR("Can't setup Bumblebee XB3 capture" );
00361 return err;
00362 }
00363
00364 err = dc1394_capture_setup(camera, 1, DC1394_CAPTURE_FLAGS_DEFAULT );
00365 if ( err != DC1394_SUCCESS )
00366 {
00367 ROS_ERROR("Can't setup Bumblebee capture" );
00368 return err;
00369 }
00370
00371 return DC1394_SUCCESS;
00372 }
00373
00374 dc1394error_t startTransmission()
00375 {
00376 dc1394error_t err;
00377
00378
00379 err = dc1394_video_set_transmission(camera, DC1394_ON );
00380 if ( err != DC1394_SUCCESS )
00381 {
00382 ROS_ERROR("Unable to start camera iso transmission" );
00383 return err;
00384 }
00385
00386
00387
00388 dc1394switch_t status = DC1394_OFF;
00389
00390 for ( int i = 0; i <= 5; i++ )
00391 {
00392 usleep(50000);
00393
00394
00395 err = dc1394_video_get_transmission(camera, &status );
00396 if ( err != DC1394_SUCCESS )
00397 {
00398 ROS_ERROR("Unable to get transmision status" );
00399 return err;
00400 }
00401
00402 if ( status != DC1394_OFF )
00403 break;
00404
00405 if( i == 5 )
00406 {
00407 ROS_ERROR("Camera doesn't seem to want to turn on!");
00408 return DC1394_FAILURE;
00409 }
00410 }
00411
00412 return DC1394_SUCCESS;
00413 }
00414
00415 void dc1394_deinterlace_rgb(unsigned char* src,unsigned char* dest, unsigned int width_, unsigned int height_)
00416 {
00417 register int i = (width_*height_)-1;
00418 register int r = ((width_*height_)/3)-1;
00419 register int g = ((width_*height_)*2/3)-1;
00420 register int b = (width_*height_)-1;
00421
00422 while (i >= 0)
00423 {
00424 dest[r--] = src[i--];
00425 dest[g--] = src[i--];
00426 dest[b--] = src[i--];
00427 }
00428 }
00429
00430 void getFrameAndPublish()
00431 {
00432 dc1394error_t err;
00433 dc1394video_frame_t* frame;
00434
00435 err = dc1394_capture_dequeue(camera,DC1394_CAPTURE_POLICY_WAIT,&frame);
00436 if ( err != DC1394_SUCCESS )
00437 {
00438 ROS_ERROR("extractImagesColor - cannot dequeue image!" );
00439 return;
00440 }
00441
00442 dc1394_capture_enqueue(camera,frame);
00443
00444 memcpy(pucGrabBuffer,frame->image,nBufferSize);
00445
00446
00447
00448
00449 processBuffer();
00450
00451
00452
00453 return;
00454 }
00455
00456 void processBuffer()
00457 {
00458 dc1394_deinterlace_rgb(pucGrabBuffer,pucDeInterlacedBuffer,hardware_width,3*hardware_height);
00459
00460
00461
00462 dc1394_bayer_decoding_8bit(pucDeInterlacedBuffer,pucRGBBuffer,hardware_width,3*hardware_height,bayerTile,DC1394_BAYER_METHOD_HQLINEAR);
00463
00464 if(output_height == hardware_height && output_width == hardware_width)
00465 {
00466 threads.join_all();
00467
00468 ros::Time timestamp = ros::Time::now();
00469 threads.create_thread(boost::bind(&xb3CameraDriver::processLeftImage,this,timestamp));
00470 threads.create_thread(boost::bind(&xb3CameraDriver::processCenterImage,this,timestamp));
00471 threads.create_thread(boost::bind(&xb3CameraDriver::processRightImage,this,timestamp));
00472 }else
00473 {
00475 copyToMat();
00476 resizeToOutputMat();
00477 fillRosImagesFromMat();
00478 publish();
00479 }
00480 }
00481
00482 void processLeftImage(ros::Time timestamp)
00483 {
00484
00485 unsigned char* ptr_left_buffers = pucRGBBuffer;
00486 memcpy(left.data.data(),ptr_left_buffers,left.data.size());
00487
00488 left.header.stamp = timestamp;
00489 left_camera_info.header.stamp = timestamp;
00490
00491 left_publisher.publish(left,left_camera_info,timestamp);
00492 }
00493
00494 void processCenterImage(ros::Time timestamp)
00495 {
00496
00497 unsigned char* ptr_center_buffers = pucRGBBuffer + 3 * hardware_width*hardware_height;
00498 memcpy(center.data.data(),ptr_center_buffers,center.data.size());
00499
00500 center.header.stamp = timestamp;
00501 center_camera_info.header.stamp = timestamp;
00502
00503 center_publisher.publish(center,center_camera_info,timestamp);
00504 }
00505
00506 void processRightImage(ros::Time timestamp)
00507 {
00508
00509 unsigned char* ptr_right_buffers = pucRGBBuffer + 6 * hardware_width*hardware_height;
00510 memcpy(right.data.data(),ptr_right_buffers,right.data.size());
00511
00512 right.header.stamp = timestamp;
00513 right_camera_info.header.stamp = timestamp;
00514
00515 right_publisher.publish(right,right_camera_info,timestamp);
00516 }
00517
00518 void fillRosImagesFromMat()
00519 {
00520 unsigned char* ptr_left_buffers = opencv_output_left.ptr<unsigned char>(0);
00521 unsigned char* ptr_center_buffers = opencv_output_center.ptr<unsigned char>(0);
00522 unsigned char* ptr_right_buffers = opencv_output_right.ptr<unsigned char>(0);
00523
00524 memcpy(left.data.data(),ptr_left_buffers,left.data.size());
00525 memcpy(center.data.data(),ptr_center_buffers,center.data.size());
00526 memcpy(right.data.data(),ptr_right_buffers,right.data.size());
00527 }
00528
00529 void resizeToOutputMat()
00530 {
00531 cv::resize(opencv_left,opencv_output_left,opencv_output_left.size(),0,0,CV_INTER_AREA);
00532 cv::resize(opencv_center,opencv_output_center,opencv_output_center.size(),0,0,CV_INTER_AREA);
00533 cv::resize(opencv_right,opencv_output_right,opencv_output_right.size(),0,0,CV_INTER_AREA);
00534 }
00535
00536 void copyToMat()
00537 {
00538
00539 unsigned char* ptr_left_buffers = pucRGBBuffer;
00540 unsigned char* ptr_center_buffer = pucRGBBuffer + 3 * hardware_width*hardware_height;
00541 unsigned char* ptr_right_buffers = pucRGBBuffer + 6 * hardware_width*hardware_height;
00542
00543
00544 unsigned char* ptr_left_cvMat = opencv_left.ptr<unsigned char>(0);
00545 unsigned char* ptr_center_cvMat = opencv_center.ptr<unsigned char>(0);
00546 unsigned char* ptr_right_cvMat = opencv_right.ptr<unsigned char>(0);
00547
00548 memcpy(ptr_left_cvMat,ptr_left_buffers,nBufferSize);
00549 memcpy(ptr_center_cvMat,ptr_center_buffer,nBufferSize);
00550 memcpy(ptr_right_cvMat,ptr_right_buffers,nBufferSize);
00551
00552 return;
00553 }
00554
00555 void fillRosImages()
00556 {
00557 unsigned char* ptr_left_buffers = pucRGBBuffer;
00558 unsigned char* ptr_center_buffers = pucRGBBuffer + 3 * hardware_width*hardware_height;
00559 unsigned char* ptr_right_buffers = pucRGBBuffer + 6 * hardware_width*hardware_height;
00560
00561 memcpy(left.data.data(),ptr_left_buffers,left.data.size());
00562 memcpy(center.data.data(),ptr_center_buffers,center.data.size());
00563 memcpy(right.data.data(),ptr_right_buffers,right.data.size());
00564 }
00565
00566 void publish()
00567 {
00568 ros::Time timestamp = ros::Time::now();
00569
00570 left.header.stamp = timestamp;
00571 center.header.stamp = timestamp;
00572 right.header.stamp = timestamp;
00573
00574 left_camera_info.header.stamp = timestamp;
00575 center_camera_info.header.stamp = timestamp;
00576 right_camera_info.header.stamp = timestamp;
00577
00578 left_publisher.publish(left,left_camera_info,timestamp);
00579 center_publisher.publish(center,center_camera_info,timestamp);
00580 right_publisher.publish(right,right_camera_info,timestamp);
00581 }
00582 };
00583
00584 int main(int argc,char** argv)
00585 {
00586 ros::init(argc, argv, "xb3");
00587 ros::NodeHandle nh("~");
00588
00589
00590 xb3CameraDriver xb3(nh);
00591
00592
00593
00594
00595
00596 while(ros::ok())
00597 {
00598 xb3.getFrameAndPublish();
00599
00600
00601
00602
00603
00604 }
00605
00606 return 0;
00607 }
00608