00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033 #include <avt_vimba_camera/stereo_camera.h>
00034 #include <driver_base/SensorLevels.h>
00035
00036 namespace avt_vimba_camera {
00037
00038 StereoCamera::StereoCamera(ros::NodeHandle nh, ros::NodeHandle nhp)
00039 :nh_(nh), nhp_(nhp), it_(nh), left_cam_("left"), right_cam_("right"),
00040 desired_freq_(7.5), left_init_(false), right_init_(false), check_timer_(io_, boost::posix_time::seconds(1)), sync_timer_(io_, boost::posix_time::seconds(0.1)) {
00041
00042
00043 nhp_.param("left_ip", left_ip_, std::string(""));
00044 nhp_.param("right_ip", right_ip_, std::string(""));
00045 nhp_.param("left_guid", left_guid_, std::string(""));
00046 nhp_.param("right_guid", right_guid_, std::string(""));
00047 nhp_.param("left_camera_info_url", left_camera_info_url_, std::string(""));
00048 nhp_.param("right_camera_info_url", right_camera_info_url_, std::string(""));
00049 nhp_.param("show_debug_prints", show_debug_prints_, false);
00050 nhp_.param("r_imgs_buffer_size", imgs_buffer_size_, 3);
00051 nhp_.param("max_sec_diff", max_sec_diff_, 0.05);
00052 nhp_.param("sync_timer_step", sync_timer_step_, 0.1);
00053 }
00054
00055 StereoCamera::~StereoCamera() {
00056 left_cam_.stop();
00057 right_cam_.stop();
00058 updater_.broadcast(0, "Device is closed.");
00059 left_pub_.shutdown();
00060 right_pub_.shutdown();
00061 }
00062
00063 void StereoCamera::run() {
00064
00065
00066 api_.start();
00067
00068
00069 left_pub_ = it_.advertiseCamera("/stereo_down/left/image_raw", 1);
00070 right_pub_ = it_.advertiseCamera("/stereo_down/right/image_raw", 1);
00071
00072
00073 left_cam_.setCallback(boost::bind(&avt_vimba_camera::StereoCamera::leftFrameCallback, this, _1));
00074 right_cam_.setCallback(boost::bind(&avt_vimba_camera::StereoCamera::rightFrameCallback, this, _1));
00075
00076
00077 updater_.setHardwareID("Stereo-"+left_guid_+"-"+right_guid_);
00078 updater_.broadcast(0, "Device is closed.");
00079 double min_freq = 2.0;
00080 double max_freq = 20.0;
00081 diagnostic_updater::FrequencyStatusParam freq_params(&min_freq, &max_freq, 0.1, 10);
00082 double min_stamp = 0.001;
00083 double max_stamp = 1.0;
00084 diagnostic_updater::TimeStampStatusParam stamp_params(min_stamp, max_stamp);
00085
00086 updater_.update();
00087
00088
00089 left_info_man_ = boost::shared_ptr<camera_info_manager::CameraInfoManager>(new camera_info_manager::CameraInfoManager(ros::NodeHandle(nhp_, "left"),"left_optical",left_camera_info_url_));
00090 right_info_man_ = boost::shared_ptr<camera_info_manager::CameraInfoManager>(new camera_info_manager::CameraInfoManager(ros::NodeHandle(nhp_, "right"),"right_optical",right_camera_info_url_));
00091
00092 pub_left_temp_ = nhp_.advertise<std_msgs::Float64>("left_temp", 1, true);
00093 pub_right_temp_ = nhp_.advertise<std_msgs::Float64>("right_temp", 1, true);
00094
00095
00096 reconfigure_server_.setCallback(boost::bind(&StereoCamera::configure, this, _1, _2));
00097
00098
00099 sync_timer_.async_wait( boost::bind(&StereoCamera::syncCallback, this) );
00100 check_timer_.async_wait( boost::bind(&StereoCamera::checkCallback, this) );
00101 io_.run();
00102
00103 }
00104
00105 void StereoCamera::leftFrameCallback(const FramePtr& vimba_frame_ptr) {
00106 left_init_ = true;
00107 ros::Time ros_time = ros::Time::now();
00108 l_last_time_ = ros_time.toSec();
00109 if(left_pub_.getNumSubscribers() > 0){
00110 sensor_msgs::Image img;
00111 if (api_.frameToImage(vimba_frame_ptr, img)){
00112
00113 sensor_msgs::CameraInfo lci = left_info_man_->getCameraInfo();
00114 lci.header.stamp = ros_time;
00115 img.header.stamp = ros_time;
00116 img.header.frame_id = lci.header.frame_id;
00117 if (right_pub_.getNumSubscribers() == 0) {
00118 left_pub_.publish(img, lci);
00119 }
00120 else {
00121
00122 mutex::scoped_lock lock(l_sync_mutex_);
00123 if (l_imgs_buffer_.size() >= imgs_buffer_size_) {
00124 l_imgs_buffer_.erase(l_imgs_buffer_.begin(), l_imgs_buffer_.begin() + 1);
00125 }
00126 l_imgs_buffer_.push_back(img);
00127 }
00128 }
00129 else {
00130 ROS_WARN_STREAM("Function frameToImage returned 0. No image published.");
00131 }
00132 }
00133
00134
00135 if (pub_left_temp_.getNumSubscribers() > 0) {
00136 std_msgs::Float64 msg;
00137 msg.data = left_cam_.getDeviceTemp();
00138 pub_left_temp_.publish(msg);
00139 }
00140
00141 updater_.update();
00142 }
00143
00144 void StereoCamera::rightFrameCallback(const FramePtr& vimba_frame_ptr) {
00145 right_init_ = true;
00146 ros::Time ros_time = ros::Time::now();
00147 r_last_time_ = ros_time.toSec();
00148 if(right_pub_.getNumSubscribers() > 0){
00149 sensor_msgs::Image img;
00150 if (api_.frameToImage(vimba_frame_ptr, img)){
00151
00152 sensor_msgs::CameraInfo rci = right_info_man_->getCameraInfo();
00153 rci.header.stamp = ros_time;
00154 img.header.stamp = ros_time;
00155 img.header.frame_id = rci.header.frame_id;
00156
00157
00158 if (left_pub_.getNumSubscribers() == 0) {
00159 right_pub_.publish(img, rci);
00160 }
00161 else {
00162
00163 mutex::scoped_lock lock(r_sync_mutex_);
00164 if (r_imgs_buffer_.size() >= imgs_buffer_size_) {
00165 r_imgs_buffer_.erase(r_imgs_buffer_.begin(), r_imgs_buffer_.begin() + 1);
00166 }
00167 r_imgs_buffer_.push_back(img);
00168 }
00169 }
00170 else {
00171 ROS_WARN_STREAM("Function frameToImage returned 0. No image published.");
00172 }
00173 }
00174
00175
00176 if (pub_right_temp_.getNumSubscribers() > 0) {
00177 std_msgs::Float64 msg;
00178 msg.data = right_cam_.getDeviceTemp();
00179 pub_right_temp_.publish(msg);
00180 }
00181 }
00182
00183 void StereoCamera::syncCallback() {
00184
00185 if(left_pub_.getNumSubscribers() > 0 && right_pub_.getNumSubscribers() > 0) {
00186
00187 std::vector<sensor_msgs::Image> l_imgs_buffer, r_imgs_buffer;
00188 {
00189 mutex::scoped_lock l_lock(l_sync_mutex_);
00190 mutex::scoped_lock r_lock(r_sync_mutex_);
00191 l_imgs_buffer = l_imgs_buffer_;
00192 r_imgs_buffer = r_imgs_buffer_;
00193 }
00194
00195
00196 if (l_imgs_buffer.size() == 0 || r_imgs_buffer.size() == 0) {
00197 sync_timer_.expires_at(sync_timer_.expires_at() + boost::posix_time::seconds(sync_timer_step_));
00198 sync_timer_.async_wait(boost::bind(&StereoCamera::syncCallback, this));
00199 return;
00200 }
00201
00202
00203 sensor_msgs::CameraInfo lci = left_info_man_->getCameraInfo();
00204 sensor_msgs::CameraInfo rci = right_info_man_->getCameraInfo();
00205
00206 bool synced = false;
00207 for (uint i=0; i<l_imgs_buffer.size(); i++) {
00208 double l_stamp = l_imgs_buffer[i].header.stamp.toSec();
00209
00210 for (uint j=0; j<r_imgs_buffer.size(); j++) {
00211 double r_stamp = r_imgs_buffer[j].header.stamp.toSec();
00212
00213 if (fabs(l_stamp - r_stamp) < max_sec_diff_) {
00214
00215 r_imgs_buffer[j].header.stamp = l_imgs_buffer[i].header.stamp;
00216 lci.header.stamp = l_imgs_buffer[i].header.stamp;
00217 rci.header.stamp = l_imgs_buffer[i].header.stamp;
00218 left_pub_.publish(l_imgs_buffer[i], lci);
00219 right_pub_.publish(r_imgs_buffer[j], rci);
00220
00221
00222 {
00223 mutex::scoped_lock l_lock(l_sync_mutex_);
00224 l_imgs_buffer_.erase(l_imgs_buffer_.begin(), l_imgs_buffer_.begin() + i + 1);
00225 }
00226 {
00227 mutex::scoped_lock r_lock(r_sync_mutex_);
00228 r_imgs_buffer_.erase(r_imgs_buffer_.begin(), r_imgs_buffer_.begin() + j + 1);
00229 }
00230
00231 synced = true;
00232 break;
00233 }
00234 }
00235 if (synced) break;
00236 }
00237 }
00238
00239 sync_timer_.expires_at(sync_timer_.expires_at() + boost::posix_time::seconds(sync_timer_step_));
00240 sync_timer_.async_wait(boost::bind(&StereoCamera::syncCallback, this));
00241 }
00242
00252 void StereoCamera::configure(StereoConfig& newconfig, uint32_t level) {
00253
00254 try {
00255
00256
00257 if (!left_cam_.isOpened()) {
00258 left_cam_.start(left_ip_, left_guid_, show_debug_prints_);
00259 }
00260 if (!right_cam_.isOpened()) {
00261 right_cam_.start(right_ip_, right_guid_, show_debug_prints_);
00262 if (left_cam_.isOpened() && right_cam_.isOpened()){
00263 left_cam_.resetTimestamp();
00264 right_cam_.resetTimestamp();
00265 }
00266 }
00267 Config left_config, right_config;
00268 copyConfig(newconfig, left_config, right_config);
00269 left_cam_.updateConfig(left_config);
00270 right_cam_.updateConfig(right_config);
00271 updateCameraInfo(newconfig);
00272 } catch (const std::exception& e) {
00273 ROS_ERROR_STREAM("Error reconfiguring avt_vimba_camera node : " << e.what());
00274 }
00275 }
00276
00277 void StereoCamera::copyConfig(StereoConfig& sc, Config& lc, Config& rc) {
00278
00279 lc.frame_id = sc.left_frame_id;
00280 lc.trig_timestamp_topic = sc.left_trig_timestamp_topic;
00281 lc.acquisition_mode = sc.left_acquisition_mode;
00282 lc.acquisition_rate = sc.left_acquisition_rate;
00283 lc.trigger_source = sc.left_trigger_source;
00284 lc.trigger_mode = sc.left_trigger_mode;
00285 lc.trigger_selector = sc.left_trigger_selector;
00286 lc.trigger_activation = sc.left_trigger_activation;
00287 lc.trigger_delay = sc.left_trigger_delay;
00288 lc.exposure = sc.exposure;
00289 lc.exposure_auto = sc.exposure_auto;
00290 lc.exposure_auto_alg = sc.exposure_auto_alg;
00291 lc.exposure_auto_tol = sc.exposure_auto_tol;
00292 lc.exposure_auto_max = sc.exposure_auto_max;
00293 lc.exposure_auto_min = sc.exposure_auto_min;
00294 lc.exposure_auto_outliers = sc.exposure_auto_outliers;
00295 lc.exposure_auto_rate = sc.exposure_auto_rate;
00296 lc.exposure_auto_target = sc.exposure_auto_target;
00297 lc.gain = sc.gain;
00298 lc.gain_auto = sc.gain_auto;
00299 lc.gain_auto_tol = sc.gain_auto_tol;
00300 lc.gain_auto_max = sc.gain_auto_max;
00301 lc.gain_auto_min = sc.gain_auto_min;
00302 lc.gain_auto_outliers = sc.gain_auto_outliers;
00303 lc.gain_auto_rate = sc.gain_auto_rate;
00304 lc.gain_auto_target = sc.gain_auto_target;
00305 lc.balance_ratio_abs = sc.balance_ratio_abs;
00306 lc.balance_ratio_selector = sc.balance_ratio_selector;
00307 lc.whitebalance_auto = sc.whitebalance_auto;
00308 lc.whitebalance_auto_tol = sc.whitebalance_auto_tol;
00309 lc.whitebalance_auto_rate = sc.whitebalance_auto_rate;
00310 lc.binning_x = sc.binning_x;
00311 lc.binning_y = sc.binning_y;
00312 lc.decimation_x = sc.decimation_x;
00313 lc.decimation_y = sc.decimation_y;
00314 lc.width = sc.width;
00315 lc.height = sc.height;
00316 lc.roi_width = sc.roi_width;
00317 lc.roi_height = sc.roi_height;
00318 lc.roi_offset_x = sc.roi_offset_x;
00319 lc.roi_offset_y = sc.roi_offset_y;
00320 lc.pixel_format = sc.pixel_format;
00321 lc.stream_bytes_per_second = sc.stream_bytes_per_second;
00322 lc.ptp_mode = sc.left_ptp_mode;
00323 lc.sync_in_selector = sc.left_sync_in_selector;
00324 lc.sync_out_polarity = sc.left_sync_out_polarity;
00325 lc.sync_out_selector = sc.left_sync_out_selector;
00326 lc.sync_out_source = sc.left_sync_out_source;
00327
00328 rc.frame_id = sc.right_frame_id;
00329 rc.trig_timestamp_topic = sc.right_trig_timestamp_topic;
00330 rc.acquisition_mode = sc.right_acquisition_mode;
00331 rc.acquisition_rate = sc.right_acquisition_rate;
00332 rc.trigger_source = sc.right_trigger_source;
00333 rc.trigger_mode = sc.right_trigger_mode;
00334 rc.trigger_selector = sc.right_trigger_selector;
00335 rc.trigger_activation = sc.right_trigger_activation;
00336 rc.trigger_delay = sc.right_trigger_delay;
00337 rc.exposure = sc.exposure;
00338 rc.exposure_auto = sc.exposure_auto;
00339 rc.exposure_auto_alg = sc.exposure_auto_alg;
00340 rc.exposure_auto_tol = sc.exposure_auto_tol;
00341 rc.exposure_auto_max = sc.exposure_auto_max;
00342 rc.exposure_auto_min = sc.exposure_auto_min;
00343 rc.exposure_auto_outliers = sc.exposure_auto_outliers;
00344 rc.exposure_auto_rate = sc.exposure_auto_rate;
00345 rc.exposure_auto_target = sc.exposure_auto_target;
00346 rc.gain = sc.gain;
00347 rc.gain_auto = sc.gain_auto;
00348 rc.gain_auto_tol = sc.gain_auto_tol;
00349 rc.gain_auto_max = sc.gain_auto_max;
00350 rc.gain_auto_min = sc.gain_auto_min;
00351 rc.gain_auto_outliers = sc.gain_auto_outliers;
00352 rc.gain_auto_rate = sc.gain_auto_rate;
00353 rc.gain_auto_target = sc.gain_auto_target;
00354 rc.balance_ratio_abs = sc.balance_ratio_abs;
00355 rc.balance_ratio_selector = sc.balance_ratio_selector;
00356 rc.whitebalance_auto = sc.whitebalance_auto;
00357 rc.whitebalance_auto_tol = sc.whitebalance_auto_tol;
00358 rc.whitebalance_auto_rate = sc.whitebalance_auto_rate;
00359 rc.binning_x = sc.binning_x;
00360 rc.binning_y = sc.binning_y;
00361 rc.decimation_x = sc.decimation_x;
00362 rc.decimation_y = sc.decimation_y;
00363 rc.width = sc.width;
00364 rc.height = sc.height;
00365 rc.roi_width = sc.roi_width;
00366 rc.roi_height = sc.roi_height;
00367 rc.roi_offset_x = sc.roi_offset_x;
00368 rc.roi_offset_y = sc.roi_offset_y;
00369 rc.pixel_format = sc.pixel_format;
00370 rc.stream_bytes_per_second = sc.stream_bytes_per_second;
00371 rc.ptp_mode = sc.right_ptp_mode;
00372 rc.sync_in_selector = sc.right_sync_in_selector;
00373 rc.sync_out_polarity = sc.right_sync_out_polarity;
00374 rc.sync_out_selector = sc.right_sync_out_selector;
00375 rc.sync_out_source = sc.right_sync_out_source;
00376 }
00377
00378 void StereoCamera::updateCameraInfo(const StereoConfig& config) {
00379
00380 sensor_msgs::CameraInfo left_ci = left_info_man_->getCameraInfo();
00381 sensor_msgs::CameraInfo right_ci = right_info_man_->getCameraInfo();
00382
00383
00384 left_ci.header.frame_id = config.left_frame_id;
00385 right_ci.header.frame_id = config.right_frame_id;
00386
00387
00388 int binning_or_decimation_x = std::max(config.binning_x, config.decimation_x);
00389 int binning_or_decimation_y = std::max(config.binning_y, config.decimation_y);
00390
00391 left_ci.height = config.height/binning_or_decimation_x;
00392 left_ci.width = config.width/binning_or_decimation_y;
00393 left_ci.binning_x = 1;
00394 left_ci.binning_y = 1;
00395
00396 right_ci.height = config.height/binning_or_decimation_x;
00397 right_ci.width = config.width/binning_or_decimation_y;
00398 right_ci.binning_x = 1;
00399 right_ci.binning_y = 1;
00400
00401
00402 left_ci.roi.x_offset = config.roi_offset_x/binning_or_decimation_x;
00403 left_ci.roi.y_offset = config.roi_offset_y/binning_or_decimation_y;
00404 left_ci.roi.height = config.roi_height/binning_or_decimation_x;
00405 left_ci.roi.width = config.roi_width/binning_or_decimation_y;
00406
00407 right_ci.roi.x_offset = config.roi_offset_x/binning_or_decimation_x;
00408 right_ci.roi.y_offset = config.roi_offset_y/binning_or_decimation_y;
00409 right_ci.roi.height = config.roi_height/binning_or_decimation_x;
00410 right_ci.roi.width = config.roi_width/binning_or_decimation_y;
00411
00412 std::string left_camera_info_url, right_camera_info_url;
00413 nhp_.getParamCached("left_camera_info_url", left_camera_info_url);
00414 nhp_.getParamCached("right_camera_info_url", right_camera_info_url);
00415
00416
00417 if (left_camera_info_url != left_camera_info_url_) {
00418 left_info_man_->setCameraName(config.left_frame_id);
00419 if (left_info_man_->validateURL(left_camera_info_url)) {
00420 left_info_man_->loadCameraInfo(left_camera_info_url);
00421 left_ci = left_info_man_->getCameraInfo();
00422 } else {
00423 ROS_WARN_STREAM("Camera info URL not valid: " << left_camera_info_url);
00424 }
00425 }
00426
00427 if (right_camera_info_url != right_camera_info_url_) {
00428 right_info_man_->setCameraName(config.right_frame_id);
00429 if (right_info_man_->validateURL(right_camera_info_url)) {
00430 right_info_man_->loadCameraInfo(right_camera_info_url);
00431 right_ci = right_info_man_->getCameraInfo();
00432 } else {
00433 ROS_WARN_STREAM("Camera info URL not valid: " << right_camera_info_url);
00434 }
00435 }
00436
00437 bool lRoiMatchesCalibration = (left_ci.height == config.roi_height
00438 && left_ci.width == config.roi_width);
00439 bool lResolutionMatchesCalibration = (left_ci.width == config.width
00440 && left_ci.height == config.height);
00441
00442 left_ci.roi.do_rectify = lRoiMatchesCalibration || lResolutionMatchesCalibration;
00443
00444 bool rRoiMatchesCalibration = (right_ci.height == config.roi_height
00445 && right_ci.width == config.roi_width);
00446 bool rResolutionMatchesCalibration = (right_ci.width == config.width
00447 && right_ci.height == config.height);
00448
00449 right_ci.roi.do_rectify = rRoiMatchesCalibration || rResolutionMatchesCalibration;
00450
00451
00452 left_info_man_->setCameraInfo(left_ci);
00453 right_info_man_->setCameraInfo(right_ci);
00454 }
00455
00456
00457 void StereoCamera::checkCallback() {
00458 if (left_init_) {
00459 double now = ros::Time::now().toSec();
00460 if (now - l_last_time_ > 10/desired_freq_) {
00461 ROS_WARN("Left camera not publishing. Reseting...");
00462 left_init_ = false;
00463 left_cam_.stop();
00464 ROS_INFO("DBGL 1");
00465 ros::WallDuration(2.0).sleep();
00466 ROS_INFO("DBGL 2");
00467 left_cam_.start(left_ip_, left_guid_, show_debug_prints_);
00468 ROS_INFO("Left camera reset!");
00469 }
00470 }
00471 if (right_init_) {
00472 double now = ros::Time::now().toSec();
00473 if (now - r_last_time_ > 10/desired_freq_) {
00474 ROS_WARN("Right camera not publishing. Reseting...");
00475 right_init_ = false;
00476 right_cam_.stop();
00477 ROS_INFO("DBGR 1");
00478 ros::WallDuration(2.0).sleep();
00479 ROS_INFO("DBGR 2");
00480 right_cam_.start(right_ip_, right_guid_, show_debug_prints_);
00481 ROS_INFO("Right camera reset!");
00482 }
00483 }
00484
00485 check_timer_.expires_at(check_timer_.expires_at() + boost::posix_time::seconds(1));
00486 check_timer_.async_wait(boost::bind(&StereoCamera::checkCallback, this));
00487 }
00488
00489 };