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
00034
00035
00036
00037
00038 #include <ros/ros.h>
00039 #include <tf/tf.h>
00040 #include <boost/foreach.hpp>
00041 #include <visualization_msgs/Marker.h>
00042 #include <pole_structure_mapper/PoleSectionStamped.h>
00043 #include <pole_structure_mapper/PoleStructure.h>
00044
00045 #include <tf/transform_listener.h>
00046 #include <tf/message_filter.h>
00047 #include <message_filters/subscriber.h>
00048
00049 class PoleMapper
00050 {
00051 public:
00052 PoleMapper();
00053 ~PoleMapper();
00054
00055 void displayStructure();
00056 void publishStructure();
00057
00058 private:
00059 void poleSectionCallback(const pole_structure_mapper::PoleSectionStamped::ConstPtr& msg);
00060
00061 bool polesAreTheSame(pole_structure_mapper::PoleSection * pole1, pole_structure_mapper::PoleSection * pole2);
00062 void getPointInAxis(pole_structure_mapper::PoleSection * pole, geometry_msgs::Point * p, geometry_msgs::Point * p_in_axis);
00063
00064
00065 ros::NodeHandle nh_;
00066 ros::NodeHandle pnh_;
00067
00068
00069 std::string global_frame_id_;
00070
00071
00072 double diameter_threshold_;
00073 double axis_threshold_;
00074 double distance_threshold_;
00075 double length_threshold_;
00076
00077
00078 message_filters::Subscriber<pole_structure_mapper::PoleSectionStamped> pole_sub_;
00079 tf::TransformListener tf_;
00080 tf::MessageFilter<pole_structure_mapper::PoleSectionStamped> * tf_filter_;
00081
00082 ros::Publisher pole_structure_pub_;
00083 ros::Publisher marker_pub_;
00084
00085 pole_structure_mapper::PoleStructure pole_structure_;
00086 };
00087
00088 PoleMapper::PoleMapper() : nh_(), pnh_("~")
00089 {
00090 pnh_.param<std::string>("global_frame_id", global_frame_id_, "/map");
00091 pnh_.param("diameter_threshold", diameter_threshold_, 0.03);
00092 pnh_.param("axis_threshold", axis_threshold_, 10.0);
00093 axis_threshold_ = axis_threshold_*M_PI/180.0;
00094 pnh_.param("distance_threshold", distance_threshold_, 0.10);
00095 pnh_.param("length_threshold", length_threshold_, 0.60);
00096
00097 pole_sub_.subscribe(nh_, "/pole", 1);
00098 tf_filter_ = new tf::MessageFilter<pole_structure_mapper::PoleSectionStamped>(pole_sub_, tf_, global_frame_id_, 10);
00099 tf_filter_->registerCallback( boost::bind(&PoleMapper::poleSectionCallback, this, _1) );
00100
00101 pole_structure_pub_ = nh_.advertise<pole_structure_mapper::PoleStructure>("pole_structure", 1);
00102 marker_pub_ = nh_.advertise<visualization_msgs::Marker>("pole_structure_visualizer", 1);
00103
00104 pole_structure_.header.frame_id = global_frame_id_;
00105 }
00106
00107 PoleMapper::~PoleMapper()
00108 {
00109
00110 }
00111
00112 void PoleMapper::poleSectionCallback(const pole_structure_mapper::PoleSectionStamped::ConstPtr& msg)
00113 {
00114 ROS_INFO("Pole Structure Mapper - %s - Got a pole section...", __FUNCTION__);
00115
00116 if(msg->pole.length < length_threshold_) return;
00117
00118
00119 geometry_msgs::PointStamped cylinder_point, map_point;
00120
00121 cylinder_point.header = msg->header;
00122 cylinder_point.point = msg->pole.base;
00123
00124 try { tf_.transformPoint(global_frame_id_, cylinder_point, map_point); }
00125 catch(tf::TransformException &ex)
00126 {
00127 ROS_ERROR("Pole Structure Mapper- %s - Error: %s", __FUNCTION__, ex.what());
00128 return;
00129 }
00130
00131 geometry_msgs::Vector3Stamped cylinder_axis, map_axis;
00132
00133 cylinder_axis.header = msg->header;
00134 cylinder_axis.vector = msg->pole.axis;
00135
00136 try { tf_.transformVector(global_frame_id_, cylinder_axis, map_axis); }
00137 catch(tf::TransformException &ex)
00138 {
00139 ROS_ERROR("Pole Structure Mapper- %s - Error: %s", __FUNCTION__, ex.what());
00140 return;
00141 }
00142
00143 pole_structure_mapper::PoleSection map_pole_section;
00144 map_pole_section.base = map_point.point;
00145 map_pole_section.axis = map_axis.vector;
00146 map_pole_section.length = msg->pole.length;
00147 map_pole_section.diameter = msg->pole.diameter;
00148
00149
00150 bool found_pole = false;
00151 for(int i=0 ; i<pole_structure_.pole.size() ; i++)
00152 {
00153
00154 if(polesAreTheSame(&pole_structure_.pole[i], &map_pole_section))
00155 {
00156 ROS_INFO("Poles are the same!!!");
00157
00158
00159 geometry_msgs::Point points[4];
00160
00161 points[0].x = pole_structure_.pole[i].base.x;
00162 points[0].y = pole_structure_.pole[i].base.y;
00163 points[0].z = pole_structure_.pole[i].base.z;
00164
00165 points[1].x = pole_structure_.pole[i].base.x + pole_structure_.pole[i].length * pole_structure_.pole[i].axis.x;
00166 points[1].y = pole_structure_.pole[i].base.y + pole_structure_.pole[i].length * pole_structure_.pole[i].axis.y;
00167 points[1].z = pole_structure_.pole[i].base.z + pole_structure_.pole[i].length * pole_structure_.pole[i].axis.z;
00168
00169 geometry_msgs::Point top2, base2;
00170 points[3].x = map_pole_section.base.x + map_pole_section.length * map_pole_section.axis.x;
00171 points[3].y = map_pole_section.base.y + map_pole_section.length * map_pole_section.axis.y;
00172 points[3].z = map_pole_section.base.z + map_pole_section.length * map_pole_section.axis.z;
00173 getPointInAxis(&pole_structure_.pole[i], &points[3], &points[3]);
00174 getPointInAxis(&pole_structure_.pole[i], &map_pole_section.base, &points[2]);
00175
00176 geometry_msgs::Point cylinder_top;
00177
00178 double lowest_t = 0.0;
00179 double highest_t = 0.0;
00180
00181 for(int j=1 ; j<4 ; j++)
00182 {
00183 double t = (points[j].x - pole_structure_.pole[i].base.x)/pole_structure_.pole[i].axis.x;
00184
00185 if(t<lowest_t)
00186 {
00187 pole_structure_.pole[i].base.x = points[j].x;
00188 pole_structure_.pole[i].base.y = points[j].y;
00189 pole_structure_.pole[i].base.z = points[j].z;
00190 lowest_t = t;
00191 }
00192
00193 if(t>highest_t)
00194 {
00195 cylinder_top.x = points[j].x;
00196 cylinder_top.y = points[j].y;
00197 cylinder_top.z = points[j].z;
00198 highest_t = t;
00199 }
00200 }
00201
00202
00203 pole_structure_.pole[i].length = sqrt(pow(cylinder_top.x - pole_structure_.pole[i].base.x, 2) + pow(cylinder_top.y - pole_structure_.pole[i].base.y, 2) + pow(cylinder_top.z - pole_structure_.pole[i].base.z, 2));
00204
00205
00206 pole_structure_.pole[i].diameter = (pole_structure_.pole[i].diameter + map_pole_section.diameter) / 2.0;
00207
00208
00209 tf::Vector3 pi(pole_structure_.pole[i].axis.x, pole_structure_.pole[i].axis.y, pole_structure_.pole[i].axis.z);
00210 tf::Vector3 p(map_pole_section.axis.x, map_pole_section.axis.y, map_pole_section.axis.z);
00211 pi = pi.lerp(p, 0);
00212 pole_structure_.pole[i].axis.x = pi.x();
00213 pole_structure_.pole[i].axis.y = pi.y();
00214 pole_structure_.pole[i].axis.z = pi.z();
00215
00216
00217
00218
00219 found_pole = true;
00220 break;
00221 }
00222 }
00223
00224
00225 if(!found_pole)
00226 {
00227 ROS_INFO("Poles are not the same!!!");
00228
00229 pole_structure_.pole.push_back(map_pole_section);
00230 }
00231
00232 pole_structure_.header.stamp = ros::Time::now();
00233 }
00234
00235 bool PoleMapper::polesAreTheSame(pole_structure_mapper::PoleSection * pole1, pole_structure_mapper::PoleSection * pole2)
00236 {
00237
00238 if(fabs(pole1->diameter - pole2->diameter) > diameter_threshold_)
00239 return false;
00240
00241 ROS_INFO("Passed diameter...");
00242
00243
00244 tf::Vector3 p1(pole1->axis.x, pole1->axis.y, pole1->axis.z);
00245 tf::Vector3 p2(pole2->axis.x, pole2->axis.y, pole2->axis.z);
00246 double alpha = fabs(acos(p1.dot(p2)));
00247 if(axis_threshold_ < alpha && alpha < M_PI-axis_threshold_)
00248 return false;
00249
00250 ROS_INFO("Passed axis...");
00251
00252
00253 geometry_msgs::Point p;
00254 getPointInAxis(pole1, &pole2->base, &p);
00255
00256 double distance = sqrt(pow(pole2->base.x - p.x, 2) + pow(pole2->base.y - p.y, 2) + pow(pole2->base.z - p.z,2));
00257
00258 if(distance > distance_threshold_) return false;
00259
00260 ROS_INFO("Passed position...");
00261
00262 return true;
00263 }
00264
00265 void PoleMapper::getPointInAxis(pole_structure_mapper::PoleSection * pole, geometry_msgs::Point * p, geometry_msgs::Point * p_in_axis)
00266 {
00267 double t = (pole->axis.x*(p->x-pole->base.x) + pole->axis.y*(p->y-pole->base.y) + pole->axis.z*(p->z-pole->base.z))/(pow(pole->axis.x,2) + pow(pole->axis.y,2) + pow(pole->axis.z,2));
00268
00269 p_in_axis->x = pole->base.x + pole->axis.x * t;
00270 p_in_axis->y = pole->base.y + pole->axis.y * t;
00271 p_in_axis->z = pole->base.z + pole->axis.z * t;
00272 }
00273
00274 void PoleMapper::publishStructure()
00275 {
00276 pole_structure_pub_.publish(pole_structure_);
00277 }
00278
00279 void PoleMapper::displayStructure()
00280 {
00281 for(int i=0 ; i<pole_structure_.pole.size() ; i++)
00282 {
00283 char tag[16];
00284 sprintf(tag, "pole_%d", i);
00285
00286
00287 visualization_msgs::Marker marker;
00288 marker.header.frame_id = global_frame_id_;
00289 marker.header.stamp = ros::Time::now();
00290
00291 marker.ns = tag;
00292 marker.id = 0;
00293
00294 marker.type = visualization_msgs::Marker::CYLINDER;
00295
00296 marker.action = visualization_msgs::Marker::ADD;
00297
00298
00299 marker.pose.position.x = pole_structure_.pole[i].base.x + pole_structure_.pole[i].length/2.0 * pole_structure_.pole[i].axis.x;
00300 marker.pose.position.y = pole_structure_.pole[i].base.y + pole_structure_.pole[i].length/2.0 * pole_structure_.pole[i].axis.y;
00301 marker.pose.position.z = pole_structure_.pole[i].base.z + pole_structure_.pole[i].length/2.0 * pole_structure_.pole[i].axis.z;
00302
00303 tf::Vector3 axis_vector(pole_structure_.pole[i].axis.x, pole_structure_.pole[i].axis.y, pole_structure_.pole[i].axis.z);
00304 tf::Vector3 up_vector(0.0, 0.0, 1.0);
00305 tf::Vector3 right_vector = axis_vector.cross(up_vector);
00306 right_vector.normalized();
00307 tf::Quaternion q(right_vector, -1.0*acos(axis_vector.dot(up_vector)));
00308 q.normalize();
00309 geometry_msgs::Quaternion cylinder_orientation;
00310 tf::quaternionTFToMsg(q, cylinder_orientation);
00311
00312 marker.pose.orientation = cylinder_orientation;
00313
00314 marker.scale.x = pole_structure_.pole[i].diameter;
00315 marker.scale.y = pole_structure_.pole[i].diameter;
00316 marker.scale.z = pole_structure_.pole[i].length;
00317
00318 marker.color.r = 1.0f;
00319 marker.color.g = 0.0f;
00320 marker.color.b = 0.0f;
00321 marker.color.a = 0.8;
00322
00323 marker.lifetime = ros::Duration();
00324
00325
00326 marker_pub_.publish(marker);
00327 }
00328 }
00329
00330
00331 int main(int argc, char** argv)
00332 {
00333 ros::init(argc, argv, "pole_structure_mapper_node");
00334
00335 ROS_INFO("Pole Structure Mapper for ROS v0.1");
00336
00337 PoleMapper pm;
00338
00339 ros::Rate r(1.0);
00340 while(ros::ok())
00341 {
00342 pm.publishStructure();
00343 pm.displayStructure();
00344
00345 ros::spinOnce();
00346 r.sleep();
00347 }
00348 }
00349
00350
00351