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
00040 #include <std_srvs/Empty.h>
00041 #include <std_msgs/Header.h>
00042 #include <sensor_msgs/PointCloud2.h>
00043 #include <arm_navigation_msgs/CollisionMap.h>
00044 #include <tf/transform_listener.h>
00045 #include <tf/message_filter.h>
00046 #include <message_filters/subscriber.h>
00047 #include <message_filters/synchronizer.h>
00048 #include <message_filters/sync_policies/exact_time.h>
00049 #include <message_filters/sync_policies/approximate_time.h>
00050
00051 #include <pcl/point_types.h>
00052 #include <pcl/point_cloud.h>
00053 #include <pcl/ros/conversions.h>
00054
00055 #include <pcl_ros/transforms.h>
00056
00057 #include <boost/thread/mutex.hpp>
00058 #include <boost/bind.hpp>
00059 #include <visualization_msgs/MarkerArray.h>
00060 #include <visualization_msgs/Marker.h>
00061 #include <arm_navigation_msgs/AttachedCollisionObject.h>
00062 #include <arm_navigation_msgs/MakeStaticCollisionMapAction.h>
00063 #include <collider/OccupancyPointQuery.h>
00064 #include <collider/OccupancyBBXQuery.h>
00065 #include <collider/OccupancyBBXSizeQuery.h>
00066 #include <actionlib/server/simple_action_server.h>
00067 #include <image_transport/image_transport.h>
00068 #include <image_geometry/pinhole_camera_model.h>
00069 #include <robot_self_filter/self_mask.h>
00070 #include <planning_environment/models/collision_models.h>
00071
00072 #include <vector>
00073 #include <algorithm>
00074
00075 #include <octomap/OcTreeStamped.h>
00076 #include <octomap_ros/OctomapROS.h>
00077 #include <octomap_msgs/Octomap.h>
00078 #include <octomap_msgs/GetOctomap.h>
00079
00080
00081 class Collider {
00082
00083 public:
00084
00085 Collider();
00086 ~Collider();
00087
00088 public:
00089
00090 typedef octomap::OcTreeStamped OcTreeType;
00091
00093 struct CloudInfo
00094 {
00095 CloudInfo(): cloud_name_(""), raw_cloud_name_(""), frame_subsample_(1.0),
00096 point_subsample_(1.0), sensor_frame_(""), sensor_stereo_other_frame_(""), counter_(0),
00097 dynamic_buffer_size_(1), static_buffer_size_(1),
00098 dynamic_buffer_duration_(0), static_buffer_duration_(0),
00099 dynamic_publish_(true), static_publish_(true),
00100 dynamic_until_static_publish_(true)
00101
00102 {
00103 };
00104 std::string cloud_name_;
00105 std::string raw_cloud_name_;
00106 int frame_subsample_;
00107 int point_subsample_;
00108 std::string sensor_frame_;
00109 std::string sensor_stereo_other_frame_;
00110 unsigned int counter_;
00111
00112 unsigned int dynamic_buffer_size_, static_buffer_size_;
00113 ros::Duration dynamic_buffer_duration_, static_buffer_duration_;
00114
00115
00116
00117
00118
00119
00120
00121 bool dynamic_publish_, static_publish_, dynamic_until_static_publish_;
00122 };
00123
00124
00125 struct BoxInfo
00126 {
00127 double dimensionX, dimensionY, dimensionZ;
00128 double originX, originY, originZ;
00129 double real_minX, real_minY, real_minZ;
00130 double real_maxX, real_maxY, real_maxZ;
00131 };
00132
00133
00134 protected:
00135
00136
00137 void cloudCallback(const sensor_msgs::PointCloud2::ConstPtr &cloud, const std::string topic_name);
00138 void cloudCombinedCallback(const sensor_msgs::PointCloud2::ConstPtr &cloud,
00139 const sensor_msgs::PointCloud2::ConstPtr &cloud_raw, const std::string topic_name);
00140 void cameraInfoCallback(const sensor_msgs::CameraInfo::ConstPtr &cam_info);
00141
00142 void attachedObjectCallback(const arm_navigation_msgs::AttachedCollisionObjectConstPtr& attached_object);
00143 void objectCallback(const arm_navigation_msgs::CollisionObjectConstPtr& object);
00144
00145
00146 void degradeOutdatedRaycasting(const std_msgs::Header& sensor_header, const octomap::point3d& sensor_origin, octomap::OcTreeStamped& tree);
00147 void degradeOutdatedRaw(const std_msgs::Header& sensor_header, const tf::Point& sensor_origin,
00148 const std::string& other_stereo_frame,
00149 const pcl::PointCloud<pcl::PointXYZ>& pcl_cloud_raw);
00150 void degradeSingleSpeckles();
00151 void computeBBX(const std_msgs::Header& sensor_header, octomap::point3d& bbx_min, octomap::point3d& bbx_max);
00152 bool inSensorCone(const cv::Point2d& uv) const;
00153 bool isOccludedMap(const octomap::point3d& sensor_origin, const octomap::point3d& p) const;
00154 octomap::point3d getSensorOrigin(const std_msgs::Header& sensor_header);
00155 bool isOccludedRaw (const cv::Point2d& uv, double range, const pcl::PointCloud<pcl::PointXYZ>& pcl_cloud_raw);
00156
00157
00158
00159
00160 void publishCollisionMap(const std::vector<geometry_msgs::Point>& pointlist, const std_msgs::Header &header, ros::Publisher &pub);
00161 void publishPointCloud(const std::vector<geometry_msgs::Point>& pointlist, const std_msgs::Header &header, ros::Publisher &pub);
00162 void publishMarkerArray(const std::vector<geometry_msgs::Point>& pointlist, const std_msgs::Header &header, const std_msgs::ColorRGBA& color, ros::Publisher &pub);
00163
00164
00165 bool reset(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res);
00166 void makeStaticCollisionMap(const arm_navigation_msgs::MakeStaticCollisionMapGoalConstPtr& goal);
00167 bool dummyReset(std_srvs::Empty::Request &req, std_srvs::Empty::Response &res);
00168
00169 bool octomapSrv(octomap_msgs::GetOctomap::Request &req, octomap_msgs::GetOctomap::Response &res);
00170 bool occupancyPointSrv(collider::OccupancyPointQuery::Request &req, collider::OccupancyPointQuery::Response &res);
00171 bool occupancyBBXSrv(collider::OccupancyBBXQuery::Request &req, collider::OccupancyBBXQuery::Response &res);
00172 bool occupancyBBXSizeSrv(collider::OccupancyBBXSizeQuery::Request &req, collider::OccupancyBBXSizeQuery::Response &res);
00173
00174
00175
00176 protected:
00177
00178 tf::TransformListener tf_;
00179 std::vector<message_filters::Subscriber<sensor_msgs::PointCloud2>* > message_filter_subscribers_;
00180 std::vector<tf::MessageFilter<sensor_msgs::PointCloud2>* > message_filters_;
00181
00182 planning_environment::CollisionModels *cm_;
00183 message_filters::Subscriber<arm_navigation_msgs::AttachedCollisionObject> *attached_collision_object_subscriber_;
00184 message_filters::Subscriber<arm_navigation_msgs::CollisionObject> *collision_object_subscriber_;
00185
00186 ros::NodeHandle root_handle_;
00187
00188 ros::Publisher cmap_publisher_, static_map_publisher_, pointcloud_publisher_, marker_pub_,
00189 octomap_visualization_pub_, octomap_visualization_free_pub_;
00190
00191 ros::Publisher octomap_visualization_attached_pub_, octomap_visualization_attached_array_pub_;
00192 std_msgs::ColorRGBA attached_color_;
00193
00194 ros::ServiceServer reset_service_, dummy_reset_service_, transparent_service_,
00195 get_octomap_service_, occupancy_point_service_,
00196 occupancy_bbx_service_, occupancy_bbx_size_service_;
00197
00198 ros::Subscriber* camera_info_subscriber_;
00199
00200 OcTreeType* collision_octree_;
00201 std::map<std::string,CloudInfo> cloud_sources_;
00202 robot_self_filter::SelfMask* robot_mask_right_;
00203 robot_self_filter::SelfMask* robot_mask_left_;
00204
00205 image_geometry::PinholeCameraModel cam_model_;
00206 bool cam_model_initialized_;
00207
00208 bool publish_over_dynamic_map_;
00209
00210 std::string fixed_frame_;
00211 double resolution_, max_range_, self_filter_min_dist_;
00212 int pruning_period_, pruning_counter_;
00213 bool transparent_freespace_;
00214 int camera_stereo_offset_left_;
00215 int camera_stereo_offset_right_;
00216 std_msgs::ColorRGBA color_free_, color_occupied_;
00217 cv::Size cam_size_;
00218
00219 BoxInfo workspace_box_;
00220
00221 inline void getOccupiedPoints(std::vector<geometry_msgs::Point>& pointlist) const{
00222 pointlist.reserve(collision_octree_->size() / 2.0);
00223 for (OcTreeType::iterator it = collision_octree_->begin(),
00224 end = collision_octree_->end(); it != end; ++it){
00225 if (collision_octree_->isNodeOccupied(*it)){
00226 geometry_msgs::Point p;
00227 p.x = it.getX();
00228 p.y = it.getY();
00229 p.z = it.getZ();
00230 pointlist.push_back(p);
00231 }
00232 }
00233 }
00234
00235 inline void getFreePoints(std::vector<geometry_msgs::Point>& pointlist) const{
00236 pointlist.reserve(collision_octree_->size() / 2.0);
00237 for (OcTreeType::iterator it = collision_octree_->begin(),
00238 end = collision_octree_->end(); it != end; ++it){
00239 if (!collision_octree_->isNodeOccupied(*it)){
00240 geometry_msgs::Point p;
00241 p.x = it.getX();
00242 p.y = it.getY();
00243 p.z = it.getZ();
00244 pointlist.push_back(p);
00245 if (it.getSize() != collision_octree_->getResolution())
00246 ROS_WARN("%f", it.getSize());
00247
00248 }
00249 }
00250 }
00251
00252 boost::shared_ptr<actionlib::SimpleActionServer<arm_navigation_msgs::MakeStaticCollisionMapAction> > action_server_;
00253
00254
00255 std::vector<message_filters::Subscriber<sensor_msgs::PointCloud2>* > sub_filtered_clouds_;
00256 std::vector<message_filters::Subscriber<sensor_msgs::PointCloud2>* > sub_raw_clouds_;
00257
00258
00259
00260 std::vector<message_filters::Synchronizer<message_filters::sync_policies::ApproximateTime<sensor_msgs::PointCloud2, sensor_msgs::PointCloud2> >* > sync_vector_;
00261 };
00262