Go to the documentation of this file.00001
00026 #include <industrial_collision_detection/collision_detection/collision_common.h>
00027 #include <moveit/collision_detection_fcl/collision_common.h>
00028 #include <ros/ros.h>
00029
00030 namespace collision_detection
00031 {
00032 bool getDistanceInfo(const DistanceMap &distance_detailed, DistanceInfoMap &distance_info_map)
00033 {
00034 Eigen::Affine3d tf;
00035 tf.setIdentity();
00036 return getDistanceInfo(distance_detailed, distance_info_map, tf);
00037 }
00038
00039 bool getDistanceInfo(const DistanceMap &distance_detailed, DistanceInfoMap &distance_info_map, const Eigen::Affine3d &tf)
00040 {
00041 bool status = true;
00042 for (DistanceMap::const_iterator it = distance_detailed.begin(); it != distance_detailed.end(); ++it)
00043 {
00044 DistanceInfo dist_info;
00045 DistanceResultsData dist = static_cast<const DistanceResultsData>(it->second);
00046 if (dist.link_name[0] == it->first)
00047 {
00048 dist_info.nearest_obsticle = dist.link_name[1];
00049 dist_info.link_point = tf * dist.nearest_points[0];
00050 dist_info.obsticle_point = tf * dist.nearest_points[1];
00051 dist_info.avoidance_vector = dist_info.link_point - dist_info.obsticle_point;
00052 dist_info.avoidance_vector.normalize();
00053 dist_info.distance = dist.min_distance;
00054 }
00055 else if (dist.link_name[1] == it->first)
00056 {
00057 dist_info.nearest_obsticle = dist.link_name[0];
00058 dist_info.link_point = tf * dist.nearest_points[1];
00059 dist_info.obsticle_point = tf * dist.nearest_points[0];
00060 dist_info.avoidance_vector = dist_info.link_point - dist_info.obsticle_point;
00061 dist_info.avoidance_vector.normalize();
00062 dist_info.distance = dist.min_distance;
00063 }
00064 else
00065 {
00066 ROS_ERROR("getDistanceInfo was unable to find link after match!");
00067 status &= false;
00068 }
00069
00070 distance_info_map.insert(std::make_pair(it->first, dist_info));
00071 }
00072
00073 return status;
00074 }
00075
00076 void DistanceRequest::enableGroup(const robot_model::RobotModelConstPtr &kmodel)
00077 {
00078 if (kmodel->hasJointModelGroup(group_name))
00079 active_components_only = &kmodel->getJointModelGroup(group_name)->getUpdatedLinkModelsWithGeometrySet();
00080 else
00081 active_components_only = NULL;
00082 }
00083
00084 bool distanceDetailedCallback(fcl::CollisionObject* o1, fcl::CollisionObject* o2, void* data, double& min_dist)
00085 {
00086 DistanceData* cdata = reinterpret_cast<DistanceData*>(data);
00087
00088 const CollisionGeometryData* cd1 = static_cast<const CollisionGeometryData*>(o1->collisionGeometry()->getUserData());
00089 const CollisionGeometryData* cd2 = static_cast<const CollisionGeometryData*>(o2->collisionGeometry()->getUserData());
00090 bool active1 = true, active2 = true;
00091
00092
00093 if (cd1->sameObject(*cd2))
00094 return false;
00095
00096
00097 if (cdata->req->active_components_only)
00098 {
00099 const robot_model::LinkModel *l1 = cd1->type == BodyTypes::ROBOT_LINK ? cd1->ptr.link : (cd1->type == BodyTypes::ROBOT_ATTACHED ? cd1->ptr.ab->getAttachedLink() : NULL);
00100 const robot_model::LinkModel *l2 = cd2->type == BodyTypes::ROBOT_LINK ? cd2->ptr.link : (cd2->type == BodyTypes::ROBOT_ATTACHED ? cd2->ptr.ab->getAttachedLink() : NULL);
00101
00102
00103 if ((!l1 || cdata->req->active_components_only->find(l1) == cdata->req->active_components_only->end()) &&
00104 (!l2 || cdata->req->active_components_only->find(l2) == cdata->req->active_components_only->end()))
00105 {
00106 return false;
00107 }
00108 else
00109 {
00110 if (!l1 || cdata->req->active_components_only->find(l1) == cdata->req->active_components_only->end())
00111 active1 = false;
00112
00113 if (!l2 || cdata->req->active_components_only->find(l2) == cdata->req->active_components_only->end())
00114 active2 = false;
00115 }
00116 }
00117
00118
00119 bool always_allow_collision = false;
00120 if (cdata->req->acm)
00121 {
00122 AllowedCollision::Type type;
00123
00124 bool found = cdata->req->acm->getAllowedCollision(cd1->getID(), cd2->getID(), type);
00125 if (found)
00126 {
00127
00128 if (type == AllowedCollision::ALWAYS)
00129 {
00130 always_allow_collision = true;
00131 if (!cdata->req->verbose)
00132 logDebug("Collision between '%s' and '%s' is always allowed. No contacts are computed.",
00133 cd1->getID().c_str(), cd2->getID().c_str());
00134 }
00135 }
00136 }
00137
00138
00139 if (cd1->type == BodyTypes::ROBOT_LINK && cd2->type == BodyTypes::ROBOT_ATTACHED)
00140 {
00141 const std::set<std::string> &tl = cd2->ptr.ab->getTouchLinks();
00142 if (tl.find(cd1->getID()) != tl.end())
00143 {
00144 always_allow_collision = true;
00145 if (!cdata->req->verbose)
00146 logDebug("Robot link '%s' is allowed to touch attached object '%s'. No contacts are computed.",
00147 cd1->getID().c_str(), cd2->getID().c_str());
00148 }
00149 }
00150 else
00151 {
00152 if (cd2->type == BodyTypes::ROBOT_LINK && cd1->type == BodyTypes::ROBOT_ATTACHED)
00153 {
00154 const std::set<std::string> &tl = cd1->ptr.ab->getTouchLinks();
00155 if (tl.find(cd2->getID()) != tl.end())
00156 {
00157 always_allow_collision = true;
00158 if (!cdata->req->verbose)
00159 logDebug("Robot link '%s' is allowed to touch attached object '%s'. No contacts are computed.",
00160 cd2->getID().c_str(), cd1->getID().c_str());
00161 }
00162 }
00163 }
00164
00165 if(always_allow_collision)
00166 {
00167 return false;
00168 }
00169
00170 if (!cdata->req->verbose)
00171 logDebug("Actually checking collisions between %s and %s", cd1->getID().c_str(), cd2->getID().c_str());
00172
00173
00174 fcl::DistanceResult fcl_result;
00175 DistanceResultsData dist_result;
00176 double dist_threshold = cdata->req->distance_threshold;
00177 std::map<std::string, DistanceResultsData>::iterator it1, it2;
00178
00179 if (!cdata->req->global)
00180 {
00181 it1 = cdata->res->distance.find(cd1->ptr.obj->id_);
00182 it2 = cdata->res->distance.find(cd2->ptr.obj->id_);
00183
00184 if (cdata->req->active_components_only)
00185 {
00186 if (active1 && active2)
00187 {
00188 if (it1 != cdata->res->distance.end() && it2 != cdata->res->distance.end())
00189 dist_threshold = std::max(it1->second.min_distance, it2->second.min_distance);
00190 }
00191 else if (active1 && !active2)
00192 {
00193 if (it1 != cdata->res->distance.end())
00194 dist_threshold = it1->second.min_distance;
00195 }
00196 else if (!active1 && active2)
00197 {
00198 if (it2 != cdata->res->distance.end())
00199 dist_threshold = it2->second.min_distance;
00200 }
00201 }
00202 else
00203 {
00204 if (it1 != cdata->res->distance.end() && it2 != cdata->res->distance.end())
00205 dist_threshold = std::max(it1->second.min_distance, it2->second.min_distance);
00206 }
00207 }
00208 else
00209 {
00210 dist_threshold = cdata->res->minimum_distance.min_distance;
00211 }
00212
00213 fcl_result.min_distance = dist_threshold;
00214 double d = fcl::distance(o1, o2, fcl::DistanceRequest(cdata->req->detailed), fcl_result);
00215
00216
00217
00218
00219 if (d < dist_threshold)
00220 {
00221 dist_result.min_distance = fcl_result.min_distance;
00222 dist_result.nearest_points[0] = Eigen::Vector3d(fcl_result.nearest_points[0].data.vs);
00223 dist_result.nearest_points[1] = Eigen::Vector3d(fcl_result.nearest_points[1].data.vs);
00224 dist_result.link_name[0] = cd1->ptr.obj->id_;
00225 dist_result.link_name[1] = cd2->ptr.obj->id_;
00226
00227 cdata->res->minimum_distance.update(dist_result);
00228
00229 if (!cdata->req->global)
00230 {
00231 if (d <= 0 && !cdata->res->collision)
00232 {
00233 cdata->res->collision = true;
00234 }
00235
00236 if (active1)
00237 {
00238 if (it1 == cdata->res->distance.end())
00239 {
00240 cdata->res->distance.insert(std::make_pair(cd1->ptr.obj->id_, dist_result));
00241 }
00242 else
00243 {
00244 it1->second.update(dist_result);
00245 }
00246 }
00247
00248 if (active2)
00249 {
00250 if (it2 == cdata->res->distance.end())
00251 {
00252 cdata->res->distance.insert(std::make_pair(cd2->ptr.obj->id_, dist_result));
00253 }
00254 else
00255 {
00256 it2->second.update(dist_result);
00257 }
00258 }
00259 }
00260 else
00261 {
00262 if (d <= 0)
00263 {
00264 cdata->res->collision = true;
00265 cdata->done = true;
00266 }
00267 }
00268 }
00269
00270 return cdata->done;
00271 }
00272 }