Go to the documentation of this file.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 #define BOOST_PARAMETER_MAX_ARITY 7
00037 #include "jsk_pcl_ros/collision_detector.h"
00038 #include <cmath>
00039 
00040 namespace jsk_pcl_ros
00041 {
00042   void CollisionDetector::onInit()
00043   {
00044     DiagnosticNodelet::onInit();
00045     initSelfMask();
00046     pnh_->param<std::string>("world_frame_id", world_frame_id_, "map");
00047     sub_ = pnh_->subscribe("input", 1, &CollisionDetector::pointcloudCallback, this);
00048     service_ = pnh_->advertiseService("check_collision", &CollisionDetector::serviceCallback, this);
00049     onInitPostProcess();
00050  }
00051 
00052   void CollisionDetector::subscribe()
00053   {
00054   }
00055 
00056   void CollisionDetector::unsubscribe()
00057   {
00058   }
00059 
00060   void CollisionDetector::initSelfMask()
00061   {
00062     
00063     std::string content;
00064     urdf::Model urdf_model;
00065     if (nh_->getParam("robot_description", content)) {
00066       if (!urdf_model.initString(content)) {
00067         NODELET_ERROR("Unable to parse URDF description!");
00068       }
00069     }
00070 
00071     std::string root_link_id;
00072     std::string world_frame_id;
00073     pnh_->param<std::string>("root_link_id", root_link_id, "BODY");
00074     pnh_->param<std::string>("world_frame_id", world_frame_id, "map");
00075 
00076     double default_padding, default_scale;
00077     pnh_->param("self_see_default_padding", default_padding, 0.01);
00078     pnh_->param("self_see_default_scale", default_scale, 1.0);
00079     std::vector<robot_self_filter::LinkInfo> links;
00080     std::string link_names;
00081 
00082     if (!pnh_->hasParam("self_see_links")) {
00083       NODELET_WARN("No links specified for self filtering.");
00084     } else {
00085       XmlRpc::XmlRpcValue ssl_vals;;
00086       pnh_->getParam("self_see_links", ssl_vals);
00087       if (ssl_vals.getType() != XmlRpc::XmlRpcValue::TypeArray) {
00088         NODELET_WARN("Self see links need to be an array");
00089       } else {
00090         if (ssl_vals.size() == 0) {
00091           NODELET_WARN("No values in self see links array");
00092         } else {
00093           for (int i = 0; i < ssl_vals.size(); i++) {
00094             robot_self_filter::LinkInfo li;
00095             if (ssl_vals[i].getType() != XmlRpc::XmlRpcValue::TypeStruct) {
00096               NODELET_WARN("Self see links entry %d is not a structure.  Stopping processing of self see links",i);
00097               break;
00098             }
00099             if (!ssl_vals[i].hasMember("name")) {
00100               NODELET_WARN("Self see links entry %d has no name.  Stopping processing of self see links",i);
00101               break;
00102             }
00103             li.name = std::string(ssl_vals[i]["name"]);
00104             if (!ssl_vals[i].hasMember("padding")) {
00105               NODELET_DEBUG("Self see links entry %d has no padding.  Assuming default padding of %g",i,default_padding);
00106               li.padding = default_padding;
00107             } else {
00108               li.padding = ssl_vals[i]["padding"];
00109             }
00110             if (!ssl_vals[i].hasMember("scale")) {
00111               NODELET_DEBUG("Self see links entry %d has no scale.  Assuming default scale of %g",i,default_scale);
00112               li.scale = default_scale;
00113             } else {
00114               li.scale = ssl_vals[i]["scale"];
00115             }
00116             links.push_back(li);
00117           }
00118         }
00119       }
00120     }
00121     self_mask_ = boost::shared_ptr<robot_self_filter::SelfMaskUrdfRobot>(new robot_self_filter::SelfMaskUrdfRobot(tf_listener_, tf_broadcaster_, links, urdf_model, root_link_id, world_frame_id));
00122   }
00123 
00124   void CollisionDetector::pointcloudCallback(const sensor_msgs::PointCloud2::ConstPtr& msg)
00125   {
00126     boost::mutex::scoped_lock lock(mutex_);
00127     NODELET_DEBUG("update pointcloud.");
00128 
00129     pcl::fromROSMsg(*msg, cloud_);
00130     cloud_frame_id_ = msg->header.frame_id;
00131     cloud_stamp_ = msg->header.stamp;
00132   }
00133 
00134   bool CollisionDetector::serviceCallback(jsk_recognition_msgs::CheckCollision::Request &req,
00135                                           jsk_recognition_msgs::CheckCollision::Response &res)
00136   {
00137     sensor_msgs::JointState joint = req.joint;
00138     geometry_msgs::PoseStamped pose = req.pose;
00139     res.result = checkCollision(joint, pose);
00140     return true;
00141   }
00142 
00143   bool CollisionDetector::checkCollision(const sensor_msgs::JointState& joint,
00144                                          const geometry_msgs::PoseStamped& pose)
00145   {
00146     boost::mutex::scoped_lock lock(mutex_);
00147     NODELET_DEBUG("checkCollision is called.");
00148 
00149     
00150     tf::StampedTransform sensor_to_world_tf;
00151     try {
00152       tf_listener_.lookupTransform(world_frame_id_, cloud_frame_id_, cloud_stamp_, sensor_to_world_tf);
00153     } catch (tf::TransformException& ex) {
00154       NODELET_ERROR_STREAM( "Transform error of sensor data: " << ex.what() << ", quitting callback");
00155       return false;
00156     }
00157 
00158     
00159     Eigen::Matrix4f sensor_to_world;
00160     pcl_ros::transformAsMatrix(sensor_to_world_tf, sensor_to_world);
00161     pcl::transformPointCloud(cloud_, cloud_, sensor_to_world);
00162 
00163     self_mask_->assumeFrameFromJointAngle(joint, pose);
00164 
00165     
00166     bool contain_flag = false;
00167     pcl::PointXYZ p;
00168     for (size_t i = 0; i < cloud_.size(); i++) {
00169       p = cloud_.at(i);
00170       if (finite(p.x) && finite(p.y) && finite(p.z) &&
00171          self_mask_->getMaskContainment(p.x, p.y, p.z) == robot_self_filter::INSIDE) {
00172         contain_flag = true;
00173         break;
00174       }
00175     }
00176 
00177     if (contain_flag) {
00178       NODELET_INFO("collision!");
00179     } else {
00180       NODELET_INFO("no collision!");
00181     }
00182     return contain_flag;
00183   }
00184 }
00185 
00186 #include <pluginlib/class_list_macros.h>
00187 PLUGINLIB_EXPORT_CLASS (jsk_pcl_ros::CollisionDetector, nodelet::Nodelet);