Go to the documentation of this file.00001
00062
00063
00064
00065
00066
00067
00068
00069
00070 #include <ros/ros.h>
00071 #include <tf/transform_listener.h>
00072 #include <tf_conversions/tf_eigen.h>
00073
00074
00075 #include <sensor_msgs/CameraInfo.h>
00076 #include <cob_srvs/Trigger.h>
00077
00078 #include <dynamic_reconfigure/server.h>
00079 #include <cob_keyframe_detector/keyframe_detectorConfig.h>
00080
00081 using namespace tf;
00082
00083
00084
00085 class KeyframeDetector
00086 {
00087
00088 public:
00089
00090 KeyframeDetector()
00091 : first_(true),
00092 trigger_always_(false)
00093 {
00094 config_server_.setCallback(boost::bind(&KeyframeDetector::dynReconfCallback, this, _1, _2));
00095 camera_info_sub_ = n_.subscribe("camera_info", 1, &KeyframeDetector::cameraInfoSubCallback, this);
00096 transform_sub_ = n_.subscribe("/tf", 1, &KeyframeDetector::transformSubCallback, this);
00097 keyframe_trigger_client_ = n_.serviceClient<cob_srvs::Trigger>("trigger_keyframe");
00098 }
00099
00100
00101
00102 ~KeyframeDetector()
00103 {
00105 }
00106
00107 void dynReconfCallback(cob_keyframe_detector::keyframe_detectorConfig &config, uint32_t level)
00108 {
00109 r_limit_ = config.r_limit;
00110 p_limit_ = config.p_limit;
00111 y_limit_ = config.y_limit;
00112 distance_limit_ = config.distance_limit;
00113 trigger_always_ = config.trigger_always;
00114 }
00115
00116 void
00117 cameraInfoSubCallback(sensor_msgs::CameraInfo::ConstPtr pc_in)
00118 {
00119 frame_id_ = pc_in->header.frame_id;
00120 }
00121
00122 void
00123 transformSubCallback(const tf::tfMessageConstPtr& msg)
00124 {
00125 boost::mutex::scoped_lock l(m_mutex_pointCloudSubCallback);
00126
00127 if(frame_id_.size() < 1) {
00128 ROS_WARN("KeyframeDetector: Frame id is missing, no key frame detected");
00129 return;
00130 }
00131 StampedTransform transform;
00132 try
00133 {
00134 tf_listener_.waitForTransform("/map", frame_id_, ros::Time(0), ros::Duration(0.1));
00135 tf_listener_.lookupTransform("/map", frame_id_, ros::Time(0), transform);
00136
00137 Eigen::Affine3d trf_eigen, trf_eigen_old;
00138 tf::transformTFToEigen(transform, trf_eigen);
00139 tf::transformTFToEigen(transform_old_, trf_eigen_old);
00140 Eigen::Vector3d rpy = trf_eigen.rotation().eulerAngles(2,1,0);
00141 Eigen::Vector3d rpy_old = trf_eigen_old.rotation().eulerAngles(2,1,0);
00142
00143 if(trigger_always_ || first_ || fabs(rpy(0) - rpy_old(0)) > r_limit_ || fabs(rpy(1) - rpy_old(1)) > p_limit_ || fabs(rpy(2) - rpy_old(2)) > y_limit_ ||
00144 transform.getOrigin().distance(transform_old_.getOrigin()) > distance_limit_)
00145 {
00146 if(triggerKeyFrame()) {
00147 transform_old_ = transform;
00148 first_ = false;
00149 }
00150 }
00151 }
00152 catch (tf::TransformException ex)
00153 {
00154 ROS_ERROR("[keyframe_detector] : %s",ex.what());
00155 }
00156 }
00157
00158 bool triggerKeyFrame() {
00159 cob_srvs::Trigger::Request req;
00160 cob_srvs::Trigger::Response res;
00161 if(keyframe_trigger_client_.call(req,res))
00162 {
00163 ROS_DEBUG("KeyFrame service called [OK].");
00164 }
00165 else
00166 {
00167 ROS_WARN("KeyFrame service called [FAILED].", res.success.data);
00168 return false;
00169 }
00170 return res.success.data;
00171 }
00172
00173
00174 protected:
00175 ros::NodeHandle n_;
00176 ros::Time stamp_;
00177 ros::Subscriber camera_info_sub_, transform_sub_;
00178 TransformListener tf_listener_;
00179 ros::ServiceClient keyframe_trigger_client_;
00180 dynamic_reconfigure::Server<cob_keyframe_detector::keyframe_detectorConfig> config_server_;
00181
00182 bool first_;
00183 bool trigger_always_;
00184
00185 StampedTransform transform_old_;
00186
00187 std::string frame_id_;
00188
00189 double y_limit_;
00190 double distance_limit_;
00191 double r_limit_;
00192 double p_limit_;
00193
00194 boost::mutex m_mutex_pointCloudSubCallback;
00195
00196 };
00197
00198
00199 int main (int argc, char** argv)
00200 {
00201 ros::init (argc, argv, "keyframe_detector");
00202
00203 KeyframeDetector kd;
00204
00205 ros::Rate loop_rate(30);
00206 while (ros::ok())
00207 {
00208 ros::spinOnce ();
00209 loop_rate.sleep();
00210 }
00211 }