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
00041 #include <flirtlib_ros/conversions.h>
00042 #include <mongo_ros/message_collection.h>
00043 #include <tf/transform_listener.h>
00044 #include <visualization_msgs/Marker.h>
00045 #include <ros/ros.h>
00046
00047 namespace flirtlib_ros
00048 {
00049
00050 namespace sm=sensor_msgs;
00051 namespace gm=geometry_msgs;
00052 namespace mr=mongo_ros;
00053 namespace vm=visualization_msgs;
00054 using std::vector;
00055 using std::string;
00056
00057 typedef boost::mutex::scoped_lock Lock;
00058 typedef vector<InterestPoint*> InterestPointVec;
00059
00060 class Node
00061 {
00062 public:
00063
00064 Node();
00065 void scanCB (sm::LaserScan::ConstPtr scan);
00066
00067 private:
00068
00069 bool haveNearbyScan (const gm::Pose& pose) const;
00070 gm::Pose getPoseAt (const ros::Time& t) const;
00071 RefScanRos extractFeatures (sm::LaserScan::ConstPtr scan,
00072 const gm::Pose& pose);
00073
00074
00075 boost::mutex mutex_;
00076 ros::NodeHandle nh_;
00077
00078
00079 const double pos_inc_, theta_inc_;
00080
00081
00082 FlirtlibFeatures features_;
00083
00084
00085 tf::TransformListener tf_;
00086 ros::Subscriber scan_sub_;
00087 ros::Publisher marker_pub_;
00088 mr::MessageCollection<RefScanRos> scans_;
00089
00090 };
00091
00092
00093
00094
00095
00096 template <class T>
00097 T getPrivateParam (const string& name)
00098 {
00099 ros::NodeHandle nh("~");
00100 T val;
00101 const bool found = nh.getParam(name, val);
00102 ROS_ASSERT_MSG (found, "Could not find parameter %s", name.c_str());
00103 ROS_DEBUG_STREAM_NAMED ("init", "Initialized " << name << " to " << val);
00104 return val;
00105 }
00106
00107 Node::Node () :
00108 pos_inc_(getPrivateParam<double>("pos_inc")),
00109 theta_inc_(getPrivateParam<double>("theta_inc")),
00110 features_(ros::NodeHandle("~")),
00111 scan_sub_(nh_.subscribe("scan", 1, &Node::scanCB, this)),
00112 marker_pub_(nh_.advertise<vm::Marker>("visualization_marker", 10)),
00113 scans_(getPrivateParam<string>("scan_db"), "scans")
00114 {
00115 ROS_ASSERT_MSG(scans_.count()==0, "Scan collection was not empty");
00116 scans_.ensureIndex("x");
00117 ROS_INFO ("generate_scan_map initialized");
00118 }
00119
00120
00121
00122
00123
00124 inline
00125 double angleDist (double t1, double t2)
00126 {
00127 if (t2<t1)
00128 std::swap(t1,t2);
00129 const double d = t2-t1;
00130 return std::min(d, 6.2832-d);
00131 }
00132
00133 bool Node::haveNearbyScan (const gm::Pose& pose) const
00134 {
00135 using mongo::GT;
00136 using mongo::LT;
00137
00138 bool found = false;
00139 const double x = pose.position.x;
00140 const double y = pose.position.y;
00141 const double theta = tf::getYaw(pose.orientation);
00142
00143
00144 mongo::Query q = BSON("x" << GT << x-pos_inc_ << LT << x+pos_inc_ <<
00145 "y" << GT << y-pos_inc_ << LT << y+pos_inc_);
00146 BOOST_FOREACH (mr::MessageWithMetadata<RefScanRos>::ConstPtr scan,
00147 scans_.queryResults(q, true))
00148 {
00149
00150 if (angleDist(theta, scan->lookupDouble("theta")) < theta_inc_)
00151 found = true;
00152 }
00153 return found;
00154 }
00155
00156 gm::Pose Node::getPoseAt (const ros::Time& t) const
00157 {
00158 tf::StampedTransform trans;
00159 tf_.waitForTransform("/map", "base_laser_link", t, ros::Duration(0.5));
00160 tf_.lookupTransform("/map", "base_laser_link", t, trans);
00161 gm::Pose pose;
00162 tf::poseTFToMsg(trans, pose);
00163 return pose;
00164 }
00165
00166
00167
00168
00169
00170 RefScanRos Node::extractFeatures (sm::LaserScan::ConstPtr scan,
00171 const gm::Pose& pose)
00172 {
00173 boost::shared_ptr<LaserReading> reading = fromRos(*scan);
00174 InterestPointVec pts;
00175 features_.detector_->detect(*reading, pts);
00176 BOOST_FOREACH (InterestPoint* p, pts)
00177 p->setDescriptor(features_.descriptor_->describe(*p, *reading));
00178 marker_pub_.publish(interestPointMarkers(pts, pose));
00179 const RefScan ref(scan, pose, pts);
00180 return toRos(ref);
00181 }
00182
00183
00184 void Node::scanCB (sm::LaserScan::ConstPtr scan)
00185 {
00186 try
00187 {
00188 const gm::Pose pose = getPoseAt(scan->header.stamp);
00189 if (haveNearbyScan(pose))
00190 return;
00191
00192
00193 const double x = pose.position.x;
00194 const double y = pose.position.y;
00195 const double th = tf::getYaw(pose.orientation);
00196
00197 scans_.insert(extractFeatures(scan, pose),
00198 mr::Metadata("x", x, "y", y, "theta", th));
00199 ROS_DEBUG_NAMED ("save_scan", "Saved scan at %.2f, %.2f, %.2f", x, y, th);
00200 }
00201 catch (tf::TransformException& e)
00202 {
00203 ROS_INFO ("Skipping callback due to tf error: '%s'", e.what());
00204 }
00205
00206 }
00207
00208 }
00209
00210 int main (int argc, char** argv)
00211 {
00212 ros::init(argc, argv, "generate_scan_map");
00213 flirtlib_ros::Node node;
00214 ros::spin();
00215 return 0;
00216 }