@@ -303,6 +303,9 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
303303 pnh.param <bool >(" auto_packet_size" , auto_packet_size_, true );
304304 pnh.param <int >(" packet_delay" , packet_delay_, 4000 );
305305 pnh.param <int >(" throughput_limit" , throughput_limit_, 125000000 );
306+ pnh.param <bool >(" trigger" , trigger_, false );
307+ pnh.param <bool >(" sw_trigger" , sw_trigger_, false );
308+ pnh.param <double >(" max_trigger_delay" , max_trigger_delay_, 0.2 );
306309
307310 // TODO(mhosmar): Set GigE parameters:
308311 // spinnaker_.setGigEParameters(auto_packet_size_, packet_size_, packet_delay_);
@@ -356,6 +359,13 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
356359 pnh.param <double >(" min_acceptable_delay" , min_acceptable, 0.0 );
357360 double max_acceptable; // The maximum publishing delay (in seconds) before warning.
358361 pnh.param <double >(" max_acceptable_delay" , max_acceptable, 0.2 );
362+
363+ if (trigger_) {
364+ trig_sub_ = pnh.subscribe (" trigger" , 1 ,
365+ &spinnaker_camera_driver::SpinnakerCameraNodelet::triggerCallback, this );
366+ }
367+
368+
359369 ros::SubscriberStatusCallback cb2 = boost::bind (&SpinnakerCameraNodelet::connectCb, this );
360370 pub_.reset (new diagnostic_updater::DiagnosedPublisher<wfov_camera_msgs::WFOVImage>(
361371 nh.advertise <wfov_camera_msgs::WFOVImage>(" image" , queue_size, cb2, cb2),
@@ -519,6 +529,7 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
519529 NODELET_DEBUG (" Connected to camera." );
520530
521531 // Set last configuration, forcing the reconfigure level to stop
532+ ROS_INFO (" Nodelet: throughput limit to %d" ,throughput_limit_);
522533 spinnaker_.setThroughputLimit (throughput_limit_);
523534 spinnaker_.setNewConfiguration (config_, SpinnakerCamera::LEVEL_RECONFIGURE_STOP);
524535
@@ -530,6 +541,11 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
530541
531542 NODELET_DEBUG_ONCE (" Setting timeout to: %f." , timeout);
532543 spinnaker_.setTimeout (timeout);
544+
545+ NODELET_DEBUG_ONCE (" Configuring trigger: %s %s" , trigger_?" enabled" :" disabled" ,
546+ sw_trigger_?" software" :" hardware" );
547+ spinnaker_.configureTrigger (trigger_,sw_trigger_);
548+
533549 }
534550 catch (const std::runtime_error& e)
535551 {
@@ -539,8 +555,7 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
539555 // Subscribe to gain and white balance changes
540556 {
541557 std::lock_guard<std::mutex> scopedLock (connect_mutex_);
542- sub_ =
543- getMTNodeHandle ().subscribe (" image_exposure_sequence" , 10 ,
558+ sub_ = getMTNodeHandle ().subscribe (" image_exposure_sequence" , 10 ,
544559 &spinnaker_camera_driver::SpinnakerCameraNodelet::gainWBCallback, this );
545560 }
546561 state = CONNECTED;
@@ -586,6 +601,20 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
586601 NODELET_DEBUG_ONCE (" Starting a new grab from camera with serial {%d}." , spinnaker_.getSerial ());
587602 spinnaker_.grabImage (&wfov_image->image , frame_id_);
588603
604+ ros::Time time = ros::Time::now () + ros::Duration (config_.time_offset );
605+ wfov_image->header .stamp = time;
606+ wfov_image->image .header .stamp = time;
607+ if (trigger_) {
608+ double trigger_delay = (wfov_image->header .stamp - trigger_header_.stamp ).toSec ();
609+ if (trigger_delay > max_trigger_delay_) {
610+ NODELET_ERROR (" Rejecting image not attached to trigger (age %.3fs max %.3f)" ,trigger_delay,max_trigger_delay_);
611+ break ;
612+ }
613+ // replacing timestamp with trigger stamp
614+ wfov_image->header .stamp = trigger_header_.stamp ;
615+ wfov_image->image .header .stamp = trigger_header_.stamp ;
616+ }
617+
589618 // Set other values
590619 wfov_image->header .frame_id = frame_id_;
591620
@@ -595,9 +624,6 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
595624
596625 // wfov_image->temperature = spinnaker_.getCameraTemperature();
597626
598- ros::Time time = ros::Time::now () + ros::Duration (config_.time_offset );
599- wfov_image->header .stamp = time;
600- wfov_image->image .header .stamp = time;
601627
602628 // Set the CameraInfo message
603629 ci_.reset (new sensor_msgs::CameraInfo (cinfo_->getCameraInfo ()));
@@ -614,8 +640,11 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
614640
615641 wfov_image->info = *ci_;
616642
617- // Publish the full message
618- pub_->publish (wfov_image);
643+ if (pub_->getPublisher ().getNumSubscribers () > 0 )
644+ {
645+ // Publish the full message
646+ pub_->publish (wfov_image);
647+ }
619648
620649 // Publish the message using standard image transport
621650 if (it_pub_.getNumSubscribers () > 0 )
@@ -667,6 +696,14 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
667696 }
668697 }
669698
699+ void triggerCallback (const std_msgs::Header& msg)
700+ {
701+ trigger_header_ = msg;
702+ if (sw_trigger_) {
703+ spinnaker_.trigger ();
704+ } // else we just store the timestamp and assume the camera is hardware triggered
705+ }
706+
670707 /* Class Fields */
671708 std::shared_ptr<dynamic_reconfigure::Server<spinnaker_camera_driver::SpinnakerConfig> > srv_; // /< Needed to
672709 // / initialize
@@ -685,6 +722,7 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
685722 // / constructor
686723 // / requirements
687724 ros::Subscriber sub_; // /< Subscriber for gain and white balance changes.
725+ ros::Subscriber trig_sub_; // /< Subscriber for gain and white balance changes.
688726
689727 std::mutex connect_mutex_;
690728
@@ -724,6 +762,12 @@ class SpinnakerCameraNodelet : public nodelet::Nodelet
724762 // / GigE throughput limit:
725763 int throughput_limit_;
726764
765+ // Data for software trigger management
766+ std_msgs::Header trigger_header_;
767+ bool trigger_;
768+ bool sw_trigger_;
769+ double max_trigger_delay_;
770+
727771 // / Configuration:
728772 spinnaker_camera_driver::SpinnakerConfig config_;
729773};
0 commit comments