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
00037 #include <visualization_msgs/Marker.h>
00038 #include <visualization_msgs/MarkerArray.h>
00039 #include <planning_environment/models/model_utils.h>
00040 #include <collision_proximity/collision_proximity_space.h>
00041 #include <tf/tf.h>
00042
00043 using collision_proximity::CollisionProximitySpace;
00044
00045
00046
00047
00048
00049
00050
00051
00052 static std::string makeStringFromUnsignedInt(unsigned int j)
00053 {
00054 std::stringstream ss;
00055 ss << j;
00056 return ss.str();
00057 }
00058
00059 static std::string makeAttachedObjectId(std::string link, std::string object)
00060 {
00061 return link+"_"+object;
00062 }
00063
00064 CollisionProximitySpace::CollisionProximitySpace(const std::string& robot_description_name,
00065 bool register_with_environment_server, bool use_signed_environment_field , bool use_signed_self_field) :
00066 priv_handle_("~")
00067 {
00068 collision_models_interface_ = new planning_environment::CollisionModelsInterface(robot_description_name,
00069 register_with_environment_server);
00070
00071 priv_handle_.param("size_x", size_x_, 3.0);
00072 priv_handle_.param("size_y", size_y_, 3.0);
00073 priv_handle_.param("size_z", size_z_, 4.0);
00074 priv_handle_.param("origin_x", origin_x_, -1.0);
00075 priv_handle_.param("origin_y", origin_y_, -1.5);
00076 priv_handle_.param("origin_z", origin_z_, -2.0);
00077 priv_handle_.param("resolution", resolution_, 0.02);
00078 priv_handle_.param("collision_tolerance", tolerance_, 0.00);
00079 priv_handle_.param("max_environment_distance", max_environment_distance_, 0.25);
00080 priv_handle_.param("max_self_distance", max_self_distance_, 0.1);
00081 priv_handle_.param("undefined_distance", undefined_distance_, 1.0);
00082
00083 vis_distance_field_marker_publisher_ = root_handle_.advertise<visualization_msgs::Marker>("visualization_marker", 128);
00084 vis_marker_publisher_ = root_handle_.advertise<visualization_msgs::Marker>("collision_proximity_body_spheres", 128);
00085 vis_marker_array_publisher_ = root_handle_.advertise<visualization_msgs::MarkerArray>("collision_proximity_body_spheres_array", 128);
00086
00087 if(use_signed_self_field)
00088 {
00089 self_distance_field_ = (distance_field::DistanceField<distance_field::PropDistanceFieldVoxel>*)(new distance_field::SignedPropagationDistanceField(size_x_, size_y_, size_z_, resolution_, origin_x_, origin_y_, origin_z_, max_self_distance_));
00090 }
00091 else
00092 {
00093 self_distance_field_ = new distance_field::PropagationDistanceField(size_x_, size_y_, size_z_, resolution_, origin_x_, origin_y_, origin_z_, max_self_distance_);
00094 }
00095 if(use_signed_environment_field)
00096 {
00097 environment_distance_field_ = (distance_field::DistanceField<distance_field::PropDistanceFieldVoxel>*)(new distance_field::SignedPropagationDistanceField(size_x_, size_y_, size_z_, resolution_, origin_x_, origin_y_, origin_z_, max_environment_distance_));
00098 }
00099 else
00100 {
00101 environment_distance_field_ = new distance_field::PropagationDistanceField(size_x_, size_y_, size_z_, resolution_, origin_x_, origin_y_, origin_z_, max_environment_distance_);
00102 }
00103
00104 collision_models_interface_->addSetPlanningSceneCallback(boost::bind(&CollisionProximitySpace::setPlanningSceneCallback, this, _1));
00105 collision_models_interface_->addRevertPlanningSceneCallback(boost::bind(&CollisionProximitySpace::revertPlanningSceneCallback, this));
00106
00107 loadRobotBodyDecompositions();
00108
00109 loadDefaultCollisionOperations();
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122 }
00123
00124 CollisionProximitySpace::~CollisionProximitySpace()
00125 {
00126 delete collision_models_interface_;
00127 delete self_distance_field_;
00128 delete environment_distance_field_;
00129 for(std::map<std::string, BodyDecomposition*>::iterator it = body_decomposition_map_.begin();
00130 it != body_decomposition_map_.end();
00131 it++) {
00132 delete it->second;
00133 }
00134 deleteAllStaticObjectDecompositions();
00135 deleteAllAttachedObjectDecompositions();
00136 }
00137
00138 void CollisionProximitySpace::deleteAllStaticObjectDecompositions()
00139 {
00140 for(std::map<std::string, BodyDecompositionVector*>::iterator it = static_object_map_.begin();
00141 it != static_object_map_.end();
00142 it++) {
00143 delete it->second;
00144 }
00145 static_object_map_.clear();
00146 }
00147
00148 void CollisionProximitySpace::deleteAllAttachedObjectDecompositions()
00149 {
00150 for(std::map<std::string, BodyDecompositionVector*>::iterator it = attached_object_map_.begin();
00151 it != attached_object_map_.end();
00152 it++) {
00153 delete it->second;
00154 }
00155 attached_object_map_.clear();
00156 current_attached_body_decompositions_.clear();
00157 current_attached_body_names_.clear();
00158 current_attached_body_indices_.clear();
00159 }
00160
00161 void CollisionProximitySpace::loadDefaultCollisionOperations()
00162 {
00163 std::map<std::string, bool> all_true_map;
00164 const planning_models::KinematicModel* kmodel = collision_models_interface_->getKinematicModel();
00165
00166 for(unsigned int i = 0; i < kmodel->getLinkModels().size(); i++) {
00167 all_true_map[kmodel->getLinkModels()[i]->getName()] = true;
00168 }
00169
00170 for(unsigned int i = 0; i < kmodel->getLinkModels().size(); i++) {
00171 intra_group_collision_links_[kmodel->getLinkModels()[i]->getName()] = all_true_map;
00172 }
00173
00174
00175 const std::map<std::string, planning_models::KinematicModel::JointModelGroup*>& jmgm =
00176 collision_models_interface_->getKinematicModel()->getJointModelGroupMap();
00177 for(std::map<std::string, planning_models::KinematicModel::JointModelGroup*>::const_iterator it = jmgm.begin();
00178 it != jmgm.end();
00179 it++) {
00180 enabled_self_collision_links_[it->first] = all_true_map;
00181 std::vector<std::string> link_names = it->second->getUpdatedLinkModelNames();
00182 for(unsigned int i = 0; i < link_names.size(); i++) {
00183 enabled_self_collision_links_[it->first][link_names[i]] = false;
00184 }
00185 }
00186
00187 XmlRpc::XmlRpcValue coll_ops;
00188 if(!root_handle_.hasParam("/robot_description_planning/distance_collision_operations")) {
00189 ROS_WARN("No distance collision operations specified");
00190 return;
00191 }
00192 root_handle_.getParam("/robot_description_planning/distance_collision_operations", coll_ops);
00193
00194 if(coll_ops.getType() != XmlRpc::XmlRpcValue::TypeArray) {
00195 ROS_WARN("distance_collision_operations is not an array");
00196 return;
00197 }
00198
00199 if(coll_ops.size() == 0) {
00200 ROS_WARN("No collision operations in distance collision operations");
00201 return;
00202 }
00203
00204 for(int i = 0; i < coll_ops.size(); i++) {
00205 if(!coll_ops[i].hasMember("object1") || !coll_ops[i].hasMember("object2") || !coll_ops[i].hasMember("operation")) {
00206 ROS_WARN("All collision operations must have two objects and an operation");
00207 continue;
00208 }
00209 std::string object1 = std::string(coll_ops[i]["object1"]);
00210 std::string object2 = std::string(coll_ops[i]["object2"]);
00211 std::string operation = std::string(coll_ops[i]["operation"]);
00212
00213 if(jmgm.find(object1) == jmgm.end()) {
00214 if(object1 == object2) {
00215
00216 self_excludes_[object1] = true;
00217 } else {
00218
00219 if(jmgm.find(object2) == jmgm.end()) {
00220 intra_group_collision_links_[object1][object2] = (operation == "enable");
00221 intra_group_collision_links_[object2][object1] = (operation == "enable");
00222 } else {
00223 std::vector<std::string> group_links = jmgm.find(object2)->second->getUpdatedLinkModelNames();
00224 for(unsigned int j = 0; j < group_links.size(); j++) {
00225 intra_group_collision_links_[object1][group_links[j]] = (operation == "enable");
00226 intra_group_collision_links_[group_links[j]][object1] = (operation == "enable");
00227 }
00228 }
00229 }
00230 } else if(jmgm.find(object2) == jmgm.end()) {
00231 std::vector<std::string> group_links = jmgm.find(object1)->second->getUpdatedLinkModelNames();
00232 for(unsigned int j = 0; j < group_links.size(); j++) {
00233 intra_group_collision_links_[object2][group_links[j]] = (operation == "enable");
00234 intra_group_collision_links_[group_links[j]][object2] = (operation == "enable");
00235 }
00236 } else {
00237 std::vector<std::string> group_links_1 = jmgm.find(object1)->second->getUpdatedLinkModelNames();
00238 std::vector<std::string> group_links_2 = jmgm.find(object2)->second->getUpdatedLinkModelNames();
00239 for(unsigned int j = 0; j < group_links_1.size(); j++) {
00240 for(unsigned int k = 0; k < group_links_2.size(); k++) {
00241 intra_group_collision_links_[group_links_1[j]][group_links_2[k]] = (operation == "enable");
00242 intra_group_collision_links_[group_links_2[k]][group_links_1[j]] = (operation == "enable");
00243 }
00244 }
00245 }
00246 }
00247 }
00248
00249 void CollisionProximitySpace::loadRobotBodyDecompositions()
00250 {
00251 const planning_models::KinematicModel* kmodel = collision_models_interface_->getKinematicModel();
00252
00253 for(unsigned int i = 0; i < kmodel->getLinkModels().size(); i++) {
00254 if(kmodel->getLinkModels()[i]->getLinkShape() != NULL) {
00255 double padding = collision_models_interface_->getDefaultPadding();
00256
00257 if(collision_models_interface_->getDefaultLinkPaddingMap().find(kmodel->getLinkModels()[i]->getName()) !=
00258 collision_models_interface_->getDefaultLinkPaddingMap().end())
00259 {
00260 padding = collision_models_interface_->getDefaultLinkPaddingMap().at(kmodel->getLinkModels()[i]->getName());
00261 }
00262
00263 body_decomposition_map_[kmodel->getLinkModels()[i]->getName()] = new BodyDecomposition(kmodel->getLinkModels()[i]->getName(),
00264 kmodel->getLinkModels()[i]->getLinkShape(),
00265 resolution_/2.0, padding);
00266 }
00267 }
00268 }
00269
00270 bool CollisionProximitySpace::setPlanningScene(const arm_navigation_msgs::PlanningScene& scene) {
00271 return(collision_models_interface_->setPlanningSceneWithCallbacks(scene));
00272 }
00273
00274 void CollisionProximitySpace::setPlanningSceneCallback(const arm_navigation_msgs::PlanningScene& scene)
00275 {
00276 ros::WallTime n1 = ros::WallTime::now();
00277 deleteAllStaticObjectDecompositions();
00278 deleteAllAttachedObjectDecompositions();
00279
00280 syncObjectsWithCollisionSpace(*collision_models_interface_->getPlanningSceneState());
00281
00282 prepareEnvironmentDistanceField(*collision_models_interface_->getPlanningSceneState());
00283 ros::WallTime n2 = ros::WallTime::now();
00284 ROS_DEBUG_STREAM("Setting environment took " << (n2-n1).toSec());
00285 }
00286
00287 void CollisionProximitySpace::setupForGroupQueries(const std::string& group_name,
00288 const arm_navigation_msgs::RobotState& rob_state,
00289 std::vector<std::string>& link_names,
00290 std::vector<std::string>& attached_body_names)
00291 {
00292 ros::WallTime n1 = ros::WallTime::now();
00293
00294 current_group_name_ = group_name;
00295
00296 collision_models_interface_->disableCollisionsForNonUpdatedLinks(group_name);
00297 planning_environment::setRobotStateAndComputeTransforms(rob_state,
00298 *collision_models_interface_->getPlanningSceneState());
00299 getGroupLinkAndAttachedBodyNames(current_group_name_,
00300 *collision_models_interface_->getPlanningSceneState(),
00301 current_link_names_,
00302 current_link_indices_,
00303 current_attached_body_names_,
00304 current_attached_body_indices_);
00305 link_names = current_link_names_;
00306 attached_body_names = current_attached_body_names_;
00307 setupGradientStructures(current_link_names_,
00308 current_attached_body_names_,
00309 current_gradients_);
00310
00311 current_link_body_decompositions_.clear();
00312 current_attached_body_decompositions_.clear();
00313 current_self_excludes_.clear();
00314 for(unsigned int i = 0; i < current_link_names_.size(); i++) {
00315 current_link_body_decompositions_.push_back(body_decomposition_map_[current_link_names_[i]]);
00316 if(self_excludes_.find(current_link_names_[i]) != self_excludes_.end()) {
00317 current_self_excludes_.push_back(false);
00318 } else {
00319 current_self_excludes_.push_back(true);
00320 }
00321 }
00322 for(unsigned int i = 0; i < current_attached_body_names_.size(); i++) {
00323 current_attached_body_decompositions_.push_back(attached_object_map_[current_attached_body_names_[i]]);
00324 }
00325 current_intra_group_collision_links_.clear();
00326 unsigned int num_links = current_link_names_.size();
00327 unsigned int num_attached = current_attached_body_names_.size();
00328 unsigned int tot = num_links+num_attached;
00329 current_intra_group_collision_links_.resize(tot);
00330 for(unsigned int i = 0; i < tot; i++) {
00331 current_intra_group_collision_links_[i].resize(tot);
00332 for(unsigned int j = 0; j < tot; j++) {
00333 if(i < num_links && j < num_links) {
00334 current_intra_group_collision_links_[i][j] = intra_group_collision_links_.find(current_link_names_[i])->second.find(current_link_names_[j])->second;
00335
00336 } else {
00337 std::string name1;
00338 std::string name2;
00339 bool attached1 = false;
00340 bool attached2 = false;
00341 if(i < num_links) {
00342 name1 = current_link_names_[i];
00343 } else {
00344 attached1 = true;
00345 name1 = current_attached_body_names_[i-num_links];
00346 }
00347 if(j < num_links) {
00348 name2 = current_link_names_[j];
00349 } else {
00350 attached2 = true;
00351 name2 = current_attached_body_names_[j-num_links];
00352 }
00353 current_intra_group_collision_links_[i][j] = true;
00354 if(attached1) {
00355 if(attached_object_collision_links_.find(name1)->second.find(name2) != attached_object_collision_links_.find(name1)->second.end() && !attached_object_collision_links_.find(name1)->second.find(name2)->second) {
00356 current_intra_group_collision_links_[i][j] = false;
00357 }
00358 }
00359 if(attached2) {
00360 if(attached_object_collision_links_.find(name2)->second.find(name1) != attached_object_collision_links_.find(name2)->second.end() && !attached_object_collision_links_.find(name2)->second.find(name1)->second) {
00361 current_intra_group_collision_links_[i][j] = false;
00362 }
00363 }
00364 }
00365 }
00366 }
00367 setBodyPosesGivenKinematicState(*collision_models_interface_->getPlanningSceneState());
00368 setDistanceFieldForGroupQueries(current_group_name_, *collision_models_interface_->getPlanningSceneState());
00369 ros::WallTime n2 = ros::WallTime::now();
00370 ROS_DEBUG_STREAM("Setting self for group " << current_group_name_ << " took " << (n2-n1).toSec());
00371
00372 }
00373
00374 void CollisionProximitySpace::revertPlanningSceneCallback() {
00375
00376 collision_models_interface_->bodiesLock();
00377 current_group_name_ = "";
00378
00379 deleteAllStaticObjectDecompositions();
00380 deleteAllAttachedObjectDecompositions();
00381 collision_models_interface_->bodiesUnlock();
00382 }
00383
00384 void CollisionProximitySpace::setCurrentGroupState(const planning_models::KinematicState& state)
00385 {
00386 ros::WallTime n1 = ros::WallTime::now();
00387 if(current_group_name_.empty()) {
00388 return;
00389 }
00390 tf::Transform inv = getInverseWorldTransform(state);
00391 for(unsigned int i = 0; i < current_link_indices_.size(); i++) {
00392 const planning_models::KinematicState::LinkState* ls = state.getLinkStateVector()[current_link_indices_[i]];
00393 current_link_body_decompositions_[i]->updateSpheresPose(inv*ls->getGlobalCollisionBodyTransform());
00394 }
00395 for(unsigned int i = 0; i < current_attached_body_indices_.size(); i++) {
00396 const planning_models::KinematicState::LinkState* ls = state.getLinkStateVector()[current_attached_body_indices_[i]];
00397 for(unsigned int j = 0; j < ls->getAttachedBodyStateVector().size(); j++) {
00398 const planning_models::KinematicState::AttachedBodyState* att_state = ls->getAttachedBodyStateVector()[j];
00399 for(unsigned int k = 0; k < att_state->getGlobalCollisionBodyTransforms().size(); k++) {
00400 tf::Transform test = inv*att_state->getGlobalCollisionBodyTransforms()[k];
00401 current_attached_body_decompositions_[i]->updateSpheresPose(k, inv*att_state->getGlobalCollisionBodyTransforms()[k]);
00402 }
00403 }
00404 }
00405 updateSphereLocations(current_link_names_, current_attached_body_names_, current_gradients_);
00406 ROS_DEBUG_STREAM("Group state update took " << (ros::WallTime::now()-n1).toSec());
00407 }
00408
00409 void CollisionProximitySpace::setBodyPosesGivenKinematicState(const planning_models::KinematicState& state)
00410 {
00411 tf::Transform inv = getInverseWorldTransform(state);
00412 for(unsigned int i = 0; i < state.getLinkStateVector().size(); i++) {
00413 const planning_models::KinematicState::LinkState* ls = state.getLinkStateVector()[i];
00414 if(body_decomposition_map_.find(ls->getName()) == body_decomposition_map_.end()) {
00415
00416 continue;
00417 }
00418 body_decomposition_map_[ls->getName()]->updatePose(inv*ls->getGlobalCollisionBodyTransform());
00419 for(unsigned int j = 0; j < ls->getAttachedBodyStateVector().size(); j++) {
00420 const planning_models::KinematicState::AttachedBodyState* att_state = ls->getAttachedBodyStateVector()[j];
00421 std::string id = makeAttachedObjectId(ls->getName(), att_state->getName());
00422 if(attached_object_map_.find(id) == attached_object_map_.end()) {
00423 ROS_WARN_STREAM("Updating pose but no attached object for id " << id);
00424 continue;
00425 }
00426 if(attached_object_map_[id]->getSize() != att_state->getGlobalCollisionBodyTransforms().size()) {
00427 ROS_WARN_STREAM("For attached object bodies number " << attached_object_map_[id]->getSize()
00428 << " not equal to state number " << att_state->getGlobalCollisionBodyTransforms().size() << ". Not updating");
00429 continue;
00430 }
00431 for(unsigned int k = 0; k < att_state->getGlobalCollisionBodyTransforms().size(); k++) {
00432 tf::Transform test = inv*att_state->getGlobalCollisionBodyTransforms()[k];
00433 attached_object_map_[id]->updateBodyPose(k, inv*att_state->getGlobalCollisionBodyTransforms()[k]);
00434 }
00435 }
00436 }
00437 }
00438
00439 tf::Transform CollisionProximitySpace::getInverseWorldTransform(const planning_models::KinematicState& state) const {
00440 const planning_models::KinematicState::JointState* world_state = state.getJointStateVector()[0];
00441 if(world_state == NULL) {
00442 ROS_WARN_STREAM("World state " << collision_models_interface_->getKinematicModel()->getRoot()->getName() << " not found");
00443 }
00444 const tf::Transform& world_trans = world_state->getVariableTransform();
00445 tf::Transform ret(world_trans);
00446 return ret.inverse();
00447 }
00448
00449 void CollisionProximitySpace::syncObjectsWithCollisionSpace(const planning_models::KinematicState& state)
00450 {
00451 tf::Transform inv = getInverseWorldTransform(state);
00452 const collision_space::EnvironmentObjects *eo = collision_models_interface_->getCollisionSpace()->getObjects();
00453 std::vector<std::string> ns = eo->getNamespaces();
00454 for(unsigned int i = 0; i < ns.size(); i++) {
00455 if(ns[i] == COLLISION_MAP_NAME) continue;
00456 const collision_space::EnvironmentObjects::NamespaceObjects &no = eo->getObjects(ns[i]);
00457 BodyDecompositionVector* bdv = new BodyDecompositionVector();
00458 for(unsigned int j = 0; j < no.shape.size(); j++) {
00459 BodyDecomposition* bd = new BodyDecomposition(ns[i]+"_"+makeStringFromUnsignedInt(j), no.shape[j], resolution_);
00460 bd->updatePose(inv*no.shape_pose[j]);
00461 tf::Transform trans = bd->getBody()->getPose();
00462 bdv->addToVector(bd);
00463 }
00464 static_object_map_[ns[i]] = bdv;
00465 }
00466
00467 const std::vector<planning_models::KinematicState::LinkState*> link_states = state.getLinkStateVector();
00468 for(unsigned int i = 0; i < link_states.size(); i++) {
00469 const planning_models::KinematicState::LinkState* ls = link_states[i];
00470 for(unsigned int j = 0; j < ls->getAttachedBodyStateVector().size(); j++) {
00471 BodyDecompositionVector* bdv = new BodyDecompositionVector();
00472 const planning_models::KinematicState::AttachedBodyState* abs = ls->getAttachedBodyStateVector()[j];
00473 std::string id = makeAttachedObjectId(ls->getName(),abs->getName());
00474 for(unsigned int k = 0; k < abs->getAttachedBodyModel()->getShapes().size(); k++) {
00475 BodyDecomposition* bd = new BodyDecomposition(id+makeStringFromUnsignedInt(j), abs->getAttachedBodyModel()->getShapes()[k], resolution_);
00476 bd->updatePose(inv*abs->getGlobalCollisionBodyTransforms()[k]);
00477 bdv->addToVector(bd);
00478 }
00479 attached_object_map_[id] = bdv;
00480 for(unsigned int k = 0; k < abs->getAttachedBodyModel()->getTouchLinks().size(); k++) {
00481 attached_object_collision_links_[id][abs->getAttachedBodyModel()->getTouchLinks()[k]] = false;
00482 }
00483 }
00484 }
00485 }
00486
00487 void CollisionProximitySpace::setDistanceFieldForGroupQueries(const std::string& group_name,
00488 const planning_models::KinematicState& state)
00489 {
00490 if(enabled_self_collision_links_.find(group_name) == enabled_self_collision_links_.end()) {
00491 ROS_WARN_STREAM("No group named " << group_name << " in planning groups");
00492 return;
00493 }
00494 std::vector<std::string> df_links;
00495 for(std::map<std::string,bool>::iterator it = enabled_self_collision_links_[group_name].begin();
00496 it != enabled_self_collision_links_[group_name].end();
00497 it++) {
00498 if(it->second) {
00499 df_links.push_back(it->first);
00500 }
00501 }
00502 prepareSelfDistanceField(df_links, state);
00503 }
00504
00505 void CollisionProximitySpace::prepareEnvironmentDistanceField(const planning_models::KinematicState& state)
00506 {
00507 environment_distance_field_->reset();
00508 tf::Transform inv = getInverseWorldTransform(state);
00509 std::vector<tf::Vector3> all_points;
00510 for(std::map<std::string, BodyDecompositionVector*>::iterator it = static_object_map_.begin();
00511 it != static_object_map_.end();
00512 it++) {
00513 for(unsigned int i = 0; i < it->second->getSize(); i++) {
00514 std::vector<tf::Vector3> obj_points = it->second->getBodyDecomposition(i)->getCollisionPoints();
00515 all_points.insert(all_points.end(),obj_points.begin(), obj_points.end());
00516 }
00517 }
00518 for(unsigned int i = 0; i < collision_models_interface_->getCollisionMapPoses().size(); i++) {
00519 all_points.push_back(inv*collision_models_interface_->getCollisionMapPoses()[i].getOrigin());
00520 }
00521 environment_distance_field_->addPointsToField(all_points);
00522 visualizeDistanceField(environment_distance_field_);
00523
00524 }
00525
00526 void CollisionProximitySpace::prepareSelfDistanceField(const std::vector<std::string>& link_names,
00527 const planning_models::KinematicState& state)
00528 {
00529 self_distance_field_->reset();
00530 tf::Transform inv = getInverseWorldTransform(state);
00531 std::vector<tf::Vector3> all_points;
00532 for(unsigned int i = 0; i < link_names.size(); i++) {
00533 if(body_decomposition_map_.find(link_names[i]) == body_decomposition_map_.end()) {
00534
00535 continue;
00536 }
00537
00538 const BodyDecomposition* bd = body_decomposition_map_.find(link_names[i])->second;
00539 all_points.insert(all_points.end(), bd->getCollisionPoints().begin(), bd->getCollisionPoints().end());
00540 const planning_models::KinematicState::LinkState* ls = state.getLinkState(link_names[i]);
00541 for(unsigned int j = 0; j < ls->getAttachedBodyStateVector().size(); j++) {
00542 std::string id = makeAttachedObjectId(ls->getName(),ls->getAttachedBodyStateVector()[j]->getName());
00543 if(attached_object_map_.find(id) == attached_object_map_.end()) {
00544 ROS_WARN_STREAM("Have no attached object body for attached object " << id);
00545 continue;
00546 }
00547 const BodyDecompositionVector* att = attached_object_map_.find(id)->second;
00548 const std::vector<tf::Vector3>& att_points = att->getCollisionPoints();
00549 all_points.insert(all_points.end(), att_points.begin(), att_points.end());
00550 }
00551 }
00552 self_distance_field_->addPointsToField(all_points);
00553 }
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607
00608
00609
00610
00611
00612
00613
00614
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653
00654
00655
00656
00657
00658
00659
00660 bool CollisionProximitySpace::getGroupLinkAndAttachedBodyNames(const std::string& group_name,
00661 const planning_models::KinematicState& state,
00662 std::vector<std::string>& link_names,
00663 std::vector<unsigned int>& link_indices,
00664 std::vector<std::string>& attached_body_names,
00665 std::vector<unsigned int>& attached_body_link_indices) const
00666 {
00667 ros::WallTime n1 = ros::WallTime::now();
00668 link_names = collision_models_interface_->getKinematicModel()->getModelGroup(group_name)->getUpdatedLinkModelNames();
00669 if(link_names.size() == 0) {
00670 return false;
00671 }
00672
00673
00674 std::vector<std::string>::iterator it = link_names.begin();
00675 while(it != link_names.end()) {
00676 if(body_decomposition_map_.find(*it) == body_decomposition_map_.end()) {
00677 it = link_names.erase(it);
00678 } else {
00679 it++;
00680 }
00681 }
00682
00683 attached_body_names.clear();
00684 link_indices.clear();
00685 attached_body_link_indices.clear();
00686
00687 const std::vector<planning_models::KinematicState::LinkState*>& lsv = state.getLinkStateVector();
00688 for(unsigned int i = 0; i < link_names.size(); i++) {
00689 bool found = false;
00690 for(unsigned int j = 0; j < lsv.size(); j++) {
00691 if(lsv[j]->getName() == link_names[i]) {
00692 link_indices.push_back(j);
00693 found = true;
00694 break;
00695 }
00696 }
00697 if(!found) {
00698 ROS_INFO_STREAM("No link state found for link " << link_names[i]);
00699 }
00700 if(collision_models_interface_->getLinkAttachedObjects().find(link_names[i]) != collision_models_interface_->getLinkAttachedObjects().end()) {
00701 unsigned int j = 0;
00702 for(std::map<std::string, bodies::BodyVector*>::const_iterator it = collision_models_interface_->getLinkAttachedObjects().find(link_names[i])->second.begin();
00703 it != collision_models_interface_->getLinkAttachedObjects().find(link_names[i])->second.end();
00704 it++, j++) {
00705 std::string id = makeAttachedObjectId(link_names[i],it->first);
00706 attached_body_names.push_back(id);
00707 attached_body_link_indices.push_back(link_indices[i]);
00708 }
00709 }
00710 }
00711 return true;
00712 }
00713
00714 bool CollisionProximitySpace::updateSphereLocations(const std::vector<std::string>& link_names,
00715 const std::vector<std::string>& attached_body_names,
00716 std::vector<GradientInfo>& gradients)
00717 {
00718 if(link_names.size()+attached_body_names.size() != gradients.size()) {
00719 ROS_WARN_STREAM("Updating sphere locations with improperly sized gradients");
00720 return false;
00721 }
00722 for(unsigned int i = 0; i < link_names.size(); i++) {
00723 const std::vector<CollisionSphere>& lcs1 = body_decomposition_map_.find(link_names[i])->second->getCollisionSpheres();
00724 gradients[i].sphere_locations.resize(lcs1.size());
00725 gradients[i].sphere_radii.resize(lcs1.size());
00726 for(unsigned int j = 0; j < lcs1.size(); j++) {
00727 gradients[i].sphere_locations[j] = lcs1[j].center_;
00728 gradients[i].sphere_radii[j] = lcs1[j].radius_;
00729 }
00730 }
00731 unsigned int att_index = link_names.size();
00732 unsigned int att_count = attached_body_names.size();
00733 for(unsigned int i = 0; i < att_count; i++) {
00734 if(attached_object_map_.find(attached_body_names[i]) == attached_object_map_.end()) {
00735 ROS_WARN_STREAM("No attached object " << attached_body_names[i]);
00736 return false;
00737 }
00738 const std::vector<CollisionSphere>& att_vec = attached_object_map_.find(attached_body_names[i])->second->getCollisionSpheres();
00739 gradients[att_index].sphere_locations.resize(att_vec.size());
00740 gradients[att_index].sphere_radii.resize(att_vec.size());
00741 for(unsigned int j = 0; j < att_vec.size(); j++) {
00742 gradients[att_index].sphere_locations[j] = att_vec[j].center_;
00743 gradients[att_index].sphere_radii[j] = att_vec[j].radius_;
00744 }
00745 }
00746 return true;
00747 }
00748
00749 bool CollisionProximitySpace::setupGradientStructures(const std::vector<std::string>& link_names,
00750 const std::vector<std::string>& attached_body_names,
00751 std::vector<GradientInfo>& gradients) const
00752 {
00753 if(link_names.size() == 0) {
00754 ROS_WARN_STREAM("No link names in setup gradient structure");
00755 return false;
00756 }
00757 gradients.clear();
00758 unsigned int att_count = attached_body_names.size();
00759
00760 gradients.resize(link_names.size()+att_count);
00761
00762 for(unsigned int i = 0; i < link_names.size(); i++) {
00763 const std::vector<CollisionSphere>& lcs1 = body_decomposition_map_.find(link_names[i])->second->getCollisionSpheres();
00764 gradients[i].sphere_locations.resize(lcs1.size());
00765 gradients[i].sphere_radii.resize(lcs1.size());
00766 gradients[i].joint_name = collision_models_interface_->getKinematicModel()->getLinkModel(link_names[i])->getParentJointModel()->getName();
00767 for(unsigned int j = 0; j < lcs1.size(); j++) {
00768 gradients[i].sphere_locations[j] = lcs1[j].center_;
00769 gradients[i].sphere_radii[j] = lcs1[j].radius_;
00770 }
00771 gradients[i].distances.resize(lcs1.size(), DBL_MAX);
00772 gradients[i].gradients.resize(lcs1.size());
00773 }
00774 unsigned int att_index = link_names.size();
00775 for(unsigned int i = 0; i < att_count; i++) {
00776 if(attached_object_map_.find(attached_body_names[i]) == attached_object_map_.end()) {
00777 ROS_WARN_STREAM("No attached object " << attached_body_names[i]);
00778 return false;
00779 }
00780 const std::vector<CollisionSphere>& att_vec = attached_object_map_.find(attached_body_names[i])->second->getCollisionSpheres();
00781 gradients[att_index].sphere_locations.resize(att_vec.size());
00782 gradients[att_index].sphere_radii.resize(att_vec.size());
00783 gradients[att_index].joint_name = collision_models_interface_->getKinematicModel()->getLinkModel(link_names[link_names.size() - 1])->getParentJointModel()->getName();
00784 for(unsigned int j = 0; j < att_vec.size(); j++) {
00785 gradients[att_index].sphere_locations[j] = att_vec[j].center_;
00786 gradients[att_index].sphere_radii[j] = att_vec[j].radius_;
00787 }
00788 gradients[att_index].distances.resize(att_vec.size(), DBL_MAX);
00789 gradients[att_index].gradients.resize(att_vec.size());
00790 att_index++;
00791 }
00792 return true;
00793 }
00794
00795 bool CollisionProximitySpace::isStateInCollision() const
00796 {
00797 if(isEnvironmentCollision()) return true;
00798 if(isSelfCollision()) return true;
00799 return isIntraGroupCollision();
00800 }
00801
00802 bool CollisionProximitySpace::getStateCollisions(bool& in_collision,
00803 std::vector<CollisionType>& collisions) const
00804 {
00805 collisions.clear();
00806 collisions.resize(current_link_names_.size()+current_attached_body_names_.size());
00807 std::vector<bool> env_collisions, intra_collisions, self_collisions;
00808 env_collisions.resize(collisions.size(), false);
00809 intra_collisions = self_collisions = env_collisions;
00810 bool env_collision = getEnvironmentCollisions(env_collisions, false);
00811 bool intra_group_collision = getIntraGroupCollisions(intra_collisions, false);
00812 bool self_collision = getSelfCollisions(intra_collisions, false);
00813 for(unsigned int i = 0; i < current_link_names_.size()+current_attached_body_names_.size(); i++) {
00814 collisions[i].environment = env_collisions[i];
00815 collisions[i].self = self_collisions[i];
00816 collisions[i].intra = intra_collisions[i];
00817 }
00818 if(env_collision || intra_group_collision || self_collision) {
00819 in_collision = true;
00820 } else {
00821 in_collision = false;
00822 }
00823 return in_collision;
00824 }
00825
00826 bool CollisionProximitySpace::getStateGradients(std::vector<GradientInfo>& gradients,
00827 bool subtract_radii) const
00828 {
00829 gradients = current_gradients_;
00830
00831 std::vector<GradientInfo> intra_gradients;
00832 std::vector<GradientInfo> self_gradients;
00833 std::vector<GradientInfo> env_gradients;
00834
00835 bool env_coll = getEnvironmentProximityGradients(env_gradients, subtract_radii);
00836 bool self_coll = getSelfProximityGradients(self_gradients, subtract_radii);
00837 bool intra_coll = getIntraGroupProximityGradients(intra_gradients, subtract_radii);
00838
00839 for(unsigned int i = 0; i < gradients.size(); i++) {
00840 if(i < current_link_names_.size()) {
00841 ROS_DEBUG_STREAM("Link " << current_link_names_[i]
00842 << " env " << env_gradients[i].closest_distance
00843 << " self " << self_gradients[i].closest_distance
00844 << " intra " << intra_gradients[i].closest_distance);
00845 }
00846 {
00847 bool env_at_max = env_gradients[i].closest_distance >= max_environment_distance_;
00848 bool self_at_max = self_gradients[i].closest_distance >= max_self_distance_;
00849 if(env_at_max) {
00850 if(self_at_max || intra_gradients[i].closest_distance < self_gradients[i].closest_distance) {
00851 if(intra_gradients[i].closest_distance == DBL_MAX) {
00852 gradients[i].closest_distance = undefined_distance_;
00853 } else {
00854 gradients[i].closest_distance = intra_gradients[i].closest_distance;
00855 }
00856 ROS_DEBUG_STREAM("Intra gradient is closest");
00857 } else {
00858 ROS_DEBUG_STREAM("Self gradient is closest");
00859 gradients[i].closest_distance = self_gradients[i].closest_distance;
00860 }
00861 } else if(self_at_max) {
00862
00863 if(intra_gradients[i].closest_distance < env_gradients[i].closest_distance) {
00864 gradients[i].closest_distance = intra_gradients[i].closest_distance;
00865 ROS_DEBUG_STREAM("Intra gradient is closest");
00866 } else {
00867 gradients[i].closest_distance = env_gradients[i].closest_distance;
00868 ROS_DEBUG_STREAM("Env gradient is closest");
00869 }
00870 } else if(self_gradients[i].closest_distance < env_gradients[i].closest_distance) {
00871 gradients[i].closest_distance = self_gradients[i].closest_distance;
00872 ROS_DEBUG_STREAM("Self gradient is closest");
00873 } else {
00874 gradients[i].closest_distance = env_gradients[i].closest_distance;
00875 ROS_DEBUG_STREAM("Env gradient is closest");
00876 }
00877 }
00878
00879 if(i < current_link_names_.size() && gradients[i].closest_distance < 0.0) {
00880 ROS_DEBUG_STREAM("Link " << current_link_names_[i]
00881 << " env " << env_gradients[i].closest_distance
00882 << " self " << self_gradients[i].closest_distance
00883 << " intra " << intra_gradients[i].closest_distance);
00884 }
00885
00886
00887 for(unsigned int j = 0; j < gradients[i].distances.size(); j++) {
00888 bool env_at_max = env_gradients[i].distances[j] >= max_environment_distance_;
00889 bool self_at_max = self_gradients[i].distances[j] >= max_self_distance_;
00890 if(env_at_max) {
00891 if(self_at_max || intra_gradients[i].distances[j] < self_gradients[i].distances[j]) {
00892 if(intra_gradients[i].distances[j] == DBL_MAX) {
00893 gradients[i].distances[j] = undefined_distance_;
00894 } else {
00895 gradients[i].distances[j] = intra_gradients[i].distances[j];
00896 }
00897 gradients[i].gradients[j] = intra_gradients[i].gradients[j];
00898 } else {
00899 gradients[i].distances[j] = self_gradients[i].distances[j];
00900 gradients[i].gradients[j] = self_gradients[i].gradients[j];
00901 }
00902 } else if(self_at_max) {
00903 if(intra_gradients[i].distances[j] < env_gradients[i].distances[j]) {
00904 gradients[i].distances[j] = intra_gradients[i].distances[j];
00905 gradients[i].gradients[j] = intra_gradients[i].gradients[j];
00906 } else {
00907 gradients[i].distances[j] = env_gradients[i].distances[j];
00908 gradients[i].gradients[j] = env_gradients[i].gradients[j];
00909 }
00910 } else if(self_gradients[i].distances[j] < env_gradients[i].distances[j]) {
00911 gradients[i].distances[j] = self_gradients[i].distances[j];
00912 gradients[i].gradients[j] = self_gradients[i].gradients[j];
00913 } else {
00914 gradients[i].distances[j] = env_gradients[i].distances[j];
00915 gradients[i].gradients[j] = env_gradients[i].gradients[j];
00916 }
00917 }
00918 }
00919 return (env_coll || intra_coll || self_coll);
00920 }
00921
00922 bool CollisionProximitySpace::isIntraGroupCollision() const
00923 {
00924 std::vector<bool> collisions;
00925 return(getIntraGroupCollisions(collisions, true));
00926 }
00927
00928 bool CollisionProximitySpace::getIntraGroupCollisions(std::vector<bool>& collisions, bool stop_at_first_collision) const {
00929 bool in_collision = false;
00930 unsigned int num_links = current_link_names_.size();
00931 unsigned int num_attached = current_attached_body_names_.size();
00932 unsigned int tot = num_links+num_attached;
00933 for(unsigned int i = 0; i < tot; i++) {
00934 for(unsigned int j = i; j < tot; j++) {
00935 if(i == j) continue;
00936 if(!current_intra_group_collision_links_[i][j]) continue;
00937 const std::vector<CollisionSphere>* lcs1;
00938 const std::vector<CollisionSphere>* lcs2;
00939 if(i < num_links) {
00940 lcs1 = &(current_link_body_decompositions_[i]->getCollisionSpheres());
00941 } else {
00942 lcs1 = &(current_attached_body_decompositions_[i-num_links]->getCollisionSpheres());
00943 }
00944 if(j < num_links) {
00945 lcs2 = &(current_link_body_decompositions_[j]->getCollisionSpheres());
00946 } else {
00947 lcs2 = &(current_attached_body_decompositions_[j-num_links]->getCollisionSpheres());
00948 }
00949 for(unsigned int k = 0; k < lcs1->size(); k++) {
00950 for(unsigned int l = 0; l < lcs2->size(); l++) {
00951 double dist = (*lcs1)[k].center_.distance((*lcs2)[l].center_);
00952 dist += -(*lcs1)[k].radius_-(*lcs2)[l].radius_;
00953 if(dist <= tolerance_) {
00954 if(stop_at_first_collision) {
00955 return true;
00956 }
00957 collisions[i] = true;
00958 collisions[j] = true;
00959 in_collision = true;
00960 }
00961 }
00962 }
00963 }
00964 }
00965 return in_collision;
00966 }
00967
00968 bool CollisionProximitySpace::getIntraGroupProximityGradients(std::vector<GradientInfo>& gradients,
00969 bool subtract_radii) const {
00970 gradients = current_gradients_;
00971 bool in_collision = false;
00972 unsigned int count = 0;
00973 unsigned int num_links = current_link_names_.size();
00974 unsigned int num_attached = current_attached_body_names_.size();
00975 unsigned int tot = num_links+num_attached;
00976 std::vector<std::string> all_names = current_link_names_;
00977 all_names.insert(all_names.end(), current_attached_body_names_.begin(), current_attached_body_names_.end());
00978 for(unsigned int i = 0; i < tot; i++) {
00979 for(unsigned int j = 0; j < tot; j++) {
00980 if(i == j) continue;
00981 if(!current_intra_group_collision_links_[i][j]) {
00982 continue;
00983 }
00984 const std::vector<CollisionSphere>* lcs1;
00985 const std::vector<CollisionSphere>* lcs2;
00986 if(i < num_links) {
00987 lcs1 = &(current_link_body_decompositions_[i]->getCollisionSpheres());
00988 } else {
00989 lcs1 = &(current_attached_body_decompositions_[i-num_links]->getCollisionSpheres());
00990 }
00991 if(j < num_links) {
00992 lcs2 = &(current_link_body_decompositions_[j]->getCollisionSpheres());
00993 } else {
00994 lcs2 = &(current_attached_body_decompositions_[j-num_links]->getCollisionSpheres());
00995 }
00996 for(unsigned int k = 0; k < lcs1->size(); k++) {
00997 for(unsigned int l = 0; l < lcs2->size(); l++) {
00998 double dist = (*lcs1)[k].center_.distance((*lcs2)[l].center_);
00999 if(subtract_radii) {
01000 dist += -(*lcs1)[k].radius_-(*lcs2)[l].radius_;
01001 if(dist <= tolerance_) {
01002 in_collision = true;
01003 }
01004 }
01005 count++;
01006 if(dist < gradients[i].distances[k]) {
01007 gradients[i].distances[k] = dist;
01008 gradients[i].gradients[k] = (*lcs1)[k].center_-(*lcs2)[l].center_;
01009 }
01010 if(dist < gradients[i].closest_distance) {
01011 gradients[i].closest_distance = dist;
01012 }
01013 if(dist < gradients[j].distances[l]) {
01014 gradients[j].distances[l] = dist;
01015 gradients[j].gradients[l] = (*lcs2)[l].center_-(*lcs1)[k].center_;
01016 }
01017 if(dist < gradients[j].closest_distance) {
01018 gradients[j].closest_distance = dist;
01019 }
01020 }
01021 }
01022 }
01023 }
01024 return in_collision;
01025 }
01026
01027 bool CollisionProximitySpace::isSelfCollision() const
01028 {
01029 std::vector<bool> collisions;
01030 return(getSelfCollisions(collisions, true));
01031 }
01032
01033 bool CollisionProximitySpace::getSelfCollisions(std::vector<bool>& collisions,
01034 bool stop_at_first_collision) const
01035 {
01036 bool in_collision = false;
01037 for(unsigned int i = 0; i < current_link_names_.size(); i++) {
01038 const std::vector<CollisionSphere>& body_spheres = current_link_body_decompositions_[i]->getCollisionSpheres();
01039 bool coll = getCollisionSphereCollision(self_distance_field_, body_spheres, tolerance_);
01040 if(coll) {
01041 if(stop_at_first_collision) {
01042 return true;
01043 }
01044 in_collision = true;
01045 collisions[i] = true;
01046 }
01047 }
01048 for(unsigned int i = 0; i < current_attached_body_names_.size(); i++) {
01049 const std::vector<CollisionSphere>& body_spheres = current_attached_body_decompositions_[i]->getCollisionSpheres();
01050 bool coll = getCollisionSphereCollision(self_distance_field_, body_spheres, tolerance_);
01051 if(coll) {
01052 if(stop_at_first_collision) {
01053 return true;
01054 }
01055 in_collision = true;
01056 collisions[i+current_link_names_.size()] = true;
01057 }
01058 }
01059 return in_collision;
01060 }
01061
01062 bool CollisionProximitySpace::getSelfProximityGradients(std::vector<GradientInfo>& gradients,
01063 bool subtract_radii) const {
01064 gradients = current_gradients_;
01065 bool in_collision = false;
01066 for(unsigned int i = 0; i < current_link_names_.size(); i++) {
01067 if(!current_self_excludes_[i]) continue;
01068 const std::vector<CollisionSphere>& body_spheres = current_link_body_decompositions_[i]->getCollisionSpheres();
01069 if(gradients[i].distances.size() != body_spheres.size()) {
01070 ROS_INFO_STREAM("Wrong size for closest distances for link " << current_link_names_[i]);
01071 }
01072 bool coll = getCollisionSphereGradients(self_distance_field_, body_spheres, gradients[i], tolerance_, subtract_radii, max_self_distance_, false);
01073 if(coll) {
01074 in_collision = true;
01075 }
01076 }
01077 for(unsigned int i = 0; i < current_attached_body_names_.size(); i++) {
01078 const std::vector<CollisionSphere>& body_spheres = current_attached_body_decompositions_[i]->getCollisionSpheres();
01079 bool coll = getCollisionSphereGradients(self_distance_field_, body_spheres, gradients[i+current_link_names_.size()],
01080 tolerance_, subtract_radii, max_self_distance_, false);
01081 if(coll) {
01082 in_collision = true;
01083 }
01084 }
01085 return in_collision;
01086 }
01087
01088 bool CollisionProximitySpace::isEnvironmentCollision() const
01089 {
01090 std::vector<bool> collisions;
01091 return(getEnvironmentCollisions(collisions, true));
01092 }
01093
01094 bool CollisionProximitySpace::getEnvironmentCollisions(std::vector<bool>& collisions,
01095 bool stop_at_first_collision) const
01096 {
01097 bool in_collision = false;
01098 for(unsigned int i = 0; i < current_link_names_.size(); i++) {
01099 const std::vector<CollisionSphere>& body_spheres = current_link_body_decompositions_[i]->getCollisionSpheres();
01100 bool coll = getCollisionSphereCollision(environment_distance_field_, body_spheres, tolerance_);
01101 if(coll) {
01102 if(stop_at_first_collision) {
01103 return true;
01104 }
01105 in_collision = true;
01106 collisions[i] = true;
01107 }
01108 }
01109 for(unsigned int i = 0; i < current_attached_body_names_.size(); i++) {
01110 const std::vector<CollisionSphere>& body_spheres = current_attached_body_decompositions_[i]->getCollisionSpheres();
01111 bool coll = getCollisionSphereCollision(environment_distance_field_, body_spheres, tolerance_);
01112 if(coll) {
01113 if(stop_at_first_collision) {
01114 return true;
01115 }
01116 in_collision = true;
01117 collisions[i+current_link_names_.size()] = true;
01118 }
01119 }
01120 return in_collision;
01121 }
01122
01123 bool CollisionProximitySpace::getEnvironmentProximityGradients(std::vector<GradientInfo>& gradients,
01124 bool subtract_radii) const {
01125 gradients = current_gradients_;
01126 bool in_collision = false;
01127 for(unsigned int i = 0; i < current_link_names_.size(); i++) {
01128 const std::vector<CollisionSphere>& body_spheres = current_link_body_decompositions_[i]->getCollisionSpheres();
01129 if(gradients[i].distances.size() != body_spheres.size()) {
01130 ROS_INFO_STREAM("Wrong size for closest distances for link " << current_link_names_[i]);
01131 }
01132 bool coll = getCollisionSphereGradients(environment_distance_field_, body_spheres, gradients[i], tolerance_, subtract_radii, max_environment_distance_, false);
01133 if(coll) {
01134 in_collision = true;
01135 }
01136 }
01137 for(unsigned int i = 0; i < current_attached_body_names_.size(); i++) {
01138 const std::vector<CollisionSphere>& body_spheres = current_attached_body_decompositions_[i]->getCollisionSpheres();
01139 bool coll = getCollisionSphereGradients(environment_distance_field_, body_spheres, gradients[i+current_link_names_.size()], tolerance_, subtract_radii, max_environment_distance_, false);
01140 if(coll) {
01141 in_collision = true;
01142 }
01143 }
01144 return in_collision;
01145 }
01146
01147 void CollisionProximitySpace::getProximityGradientMarkers(const std::vector<std::string>& link_names,
01148 const std::vector<std::string>& attached_body_names,
01149 const std::vector<GradientInfo>& gradients,
01150 const std::string& ns,
01151 visualization_msgs::MarkerArray& arr) const
01152 {
01153 for(unsigned int i = 0; i < gradients.size(); i++) {
01154
01155 const std::vector<CollisionSphere>* lcs;
01156 std::string name;
01157 if(i < link_names.size()) {
01158 name = link_names[i];
01159 lcs = &(body_decomposition_map_.find(name)->second->getCollisionSpheres());
01160 } else {
01161 name = attached_body_names[i-link_names.size()];
01162 lcs = &(attached_object_map_.find(name)->second->getCollisionSpheres());
01163 }
01164 for(unsigned int j = 0; j < gradients[i].distances.size(); j++) {
01165 visualization_msgs::Marker arrow_mark;
01166 arrow_mark.header.frame_id = collision_models_interface_->getRobotFrameId();
01167 arrow_mark.header.stamp = ros::Time::now();
01168 if(ns.empty()) {
01169 arrow_mark.ns = "self_coll_gradients";
01170 } else {
01171 arrow_mark.ns = ns;
01172 }
01173 arrow_mark.id = i*1000+j;
01174 double xscale = 0.0;
01175 double yscale = 0.0;
01176 double zscale = 0.0;
01177 if(gradients[i].distances[j] > 0.0) {
01178 if(gradients[i].gradients[j].length() > 0.0) {
01179 xscale = gradients[i].gradients[j].x()/gradients[i].gradients[j].length();
01180 yscale = gradients[i].gradients[j].y()/gradients[i].gradients[j].length();
01181 zscale = gradients[i].gradients[j].z()/gradients[i].gradients[j].length();
01182 } else {
01183 ROS_DEBUG_STREAM("Negative length for " << name << " " << arrow_mark.id << " " << gradients[i].gradients[j].length());
01184 }
01185 } else {
01186 ROS_DEBUG_STREAM("Negative dist for " << name << " " << arrow_mark.id);
01187 }
01188 arrow_mark.points.resize(2);
01189 arrow_mark.points[1].x = (*lcs)[j].center_.x();
01190 arrow_mark.points[1].y = (*lcs)[j].center_.y();
01191 arrow_mark.points[1].z = (*lcs)[j].center_.z();
01192 arrow_mark.points[0] = arrow_mark.points[1];
01193 arrow_mark.points[0].x -= xscale*gradients[i].distances[j];
01194 arrow_mark.points[0].y -= yscale*gradients[i].distances[j];
01195 arrow_mark.points[0].z -= zscale*gradients[i].distances[j];
01196 arrow_mark.scale.x = 0.01;
01197 arrow_mark.scale.y = 0.03;
01198 arrow_mark.color.r = 1.0;
01199 arrow_mark.color.g = 0.2;
01200 arrow_mark.color.b = .5;
01201 arrow_mark.color.a = 1.0;
01202 arr.markers.push_back(arrow_mark);
01203 }
01204 }
01205 }
01206
01207 CollisionProximitySpace::TrajectorySafety CollisionProximitySpace::isTrajectorySafe(const trajectory_msgs::JointTrajectory& trajectory,
01208 const arm_navigation_msgs::Constraints& goal_constraints,
01209 const arm_navigation_msgs::Constraints& path_constraints,
01210 const std::string& groupName)
01211 {
01212 ROS_DEBUG_NAMED("safety", "Calling isTrajectorySafe");
01213
01214 collision_models_interface_->resetToStartState(*collision_models_interface_->getPlanningSceneState());
01215
01216 if(!collision_models_interface_->getPlanningSceneState()->hasJointStateGroup(groupName))
01217 {
01218 ROS_ERROR("Group %s does not exist. Cannot evaluate trajectory safety.", groupName.c_str());
01219 return ErrorUnsafe;
01220 }
01221 planning_models::KinematicState::JointStateGroup* stateGroup = collision_models_interface_->getPlanningSceneState()->
01222 getJointStateGroup(groupName);
01223 arm_navigation_msgs::ArmNavigationErrorCodes error_code;
01224 std::vector<arm_navigation_msgs::ArmNavigationErrorCodes> error_codes;
01225 std::map<std::string, double> stateMap;
01226 collision_models_interface_->getPlanningSceneState()->getKinematicStateValues(stateMap);
01227
01228 std::vector<arm_navigation_msgs::ContactInformation> contacts;
01229 collision_models_interface_->getAllCollisionsForState(*collision_models_interface_->getPlanningSceneState(),
01230 contacts);
01231
01232
01233
01234
01235
01236
01237
01238
01239
01240
01241 if(collision_models_interface_->isJointTrajectoryValid(*(collision_models_interface_->getPlanningSceneState()),
01242 trajectory, goal_constraints, path_constraints, error_code, error_codes, false))
01243 {
01244 ROS_INFO_STREAM("Mesh to mesh valid");
01245 return MeshToMeshSafe;
01246 }
01247
01248
01249 else
01250 {
01251 ROS_DEBUG_STREAM("Mesh to mesh invalid with " << error_code.val);
01252
01253 std::vector<double> lastDistances;
01254 TrajectoryPointType type = None;
01255
01256
01257
01258
01259
01260
01261
01262
01263 for(size_t i = 0; i < trajectory.points.size(); i++)
01264 {
01265 std::vector<GradientInfo> gradients;
01266 std::vector<double> distances;
01267 const trajectory_msgs::JointTrajectoryPoint& trajectoryPoint = trajectory.points[i];
01268 stateGroup->setKinematicState(trajectoryPoint.positions);
01269 setCurrentGroupState(*(collision_models_interface_->getPlanningSceneState()));
01270
01271 getStateGradients(gradients, true);
01272 bool in_collision = false;
01273 for(size_t j = 0; j < gradients.size(); j++)
01274 {
01275 GradientInfo& gradient = gradients[j];
01276 in_collision = in_collision || gradient.collision;
01277
01278 for(size_t k = 0; k < gradient.distances.size(); k++)
01279 {
01280 distances.push_back(gradient.distances[k]);
01281 in_collision = in_collision || gradient.distances[k] < tolerance_;
01282
01283
01284
01285 }
01286 }
01287
01288
01289 if(type == None && in_collision && i == 0)
01290 {
01291 type = StartCollision;
01292 ROS_DEBUG_NAMED("safety","In starting collision phase at index 0");
01293 }
01294
01295 else if(type == None && in_collision && i != 0)
01296 {
01297 type = EndCollision;
01298 ROS_DEBUG_NAMED("safety","In ending collision phase at index %lu", (long unsigned int)i);
01299 }
01300
01301
01302 else if(type == None && !in_collision && i != 0)
01303 {
01304 type = Middle;
01305 ROS_DEBUG_NAMED("safety","In middle collision phase at index %lu", (long unsigned int)i);
01306 }
01307
01308 else if (type == StartCollision && !in_collision)
01309 {
01310 type = Middle;
01311 ROS_DEBUG_NAMED("safety","In middle collision phase at index %lu", (long unsigned int)i);
01312 }
01313
01314 else if(type == Middle && in_collision)
01315 {
01316 type = EndCollision;
01317 ROS_DEBUG_NAMED("safety","In end collision phase at index %lu", (long unsigned int)i);
01318 }
01319
01320
01321 else if(type == EndCollision && !in_collision)
01322 {
01323 ROS_DEBUG_NAMED("safety","Got point in the end collision phase that was not in collision : %lu", (long unsigned int) i);
01324 return EndUnsafe;
01325 }
01326
01327
01328 for(size_t j = 0; j < distances.size(); j++)
01329 {
01330 double dist = distances[j];
01331 double lastDist = -10000;
01332
01333 if(lastDistances.size() > j)
01334 {
01335 lastDist = lastDistances[j];
01336 }
01337 else
01338 {
01339 lastDistances.push_back(dist);
01340 }
01341
01342
01343
01344 if(dist > tolerance_)
01345 {
01346 continue;
01347 }
01348
01349
01350
01351 switch(type)
01352 {
01353 case StartCollision:
01354
01355 if(dist < lastDist)
01356 {
01357 ROS_DEBUG_NAMED("safety","Start phase was not monotonically increasing in distance. Reason: point %lu sphere %lu", (long unsigned int)i, (long unsigned int)j);
01358 return StartUnsafe;
01359 }
01360 break;
01361 case EndCollision:
01362
01363
01364 if(dist > lastDist)
01365 {
01366 ROS_DEBUG_NAMED("safety","End phase was not monotonically decreasing in distance. Reason: point %lu sphere %lu", (long unsigned int)i, (long unsigned int)j);
01367 return EndUnsafe;
01368 }
01369 break;
01370 case Middle:
01371
01372 if(in_collision)
01373 {
01374 ROS_DEBUG_NAMED("safety","Middle phase had a collision. Reason: point %lu sphere %lu", (long unsigned int)i, (long unsigned int)j);
01375 return MiddleUnsafe;
01376 }
01377 break;
01378 case None:
01379
01380 break;
01381 }
01382
01383 lastDistances[j] = dist;
01384 }
01385 }
01386
01387 ROS_DEBUG_NAMED("safety","Trajectory passed all safety tests.");
01388 return InCollisionSafe;
01389 }
01390
01391
01392 }
01393
01395
01397
01398 void CollisionProximitySpace::visualizeDistanceField(distance_field::DistanceField<distance_field::PropDistanceFieldVoxel>* distance_field) const
01399 {
01400 tf::Transform ident;
01401 ident.setIdentity();
01402 visualization_msgs::Marker marker;
01403 distance_field->getIsoSurfaceMarkers(0.0, 0.0, collision_models_interface_->getWorldFrameId(), ros::Time::now(), ident, marker);
01404 vis_distance_field_marker_publisher_.publish(marker);
01405 }
01406
01407 void CollisionProximitySpace::visualizeDistanceFieldPlane(distance_field::DistanceField<distance_field::PropDistanceFieldVoxel>* distance_field) const
01408 {
01409 double length = distance_field->getSize(distance_field::PropagationDistanceField::DIM_X);
01410 double width = distance_field->getSize(distance_field::PropagationDistanceField::DIM_Y);
01411 double height = distance_field->getSize(distance_field::PropagationDistanceField::DIM_Z);
01412 tf::Vector3 origin(distance_field->getOrigin(distance_field::PropagationDistanceField::DIM_X) + length / 2.0,
01413 distance_field->getOrigin(distance_field::PropagationDistanceField::DIM_Y) + width / 2.0,
01414 distance_field->getOrigin(distance_field::PropagationDistanceField::DIM_Z) + height / 2.0);
01415
01416 for(double z = distance_field->getOrigin(distance_field::PropagationDistanceField::DIM_Z);
01417 z < distance_field->getSize(distance_field::PropagationDistanceField::DIM_Z);
01418 z += distance_field->getResolution(distance_field::PropagationDistanceField::DIM_Z))
01419 {
01420 visualization_msgs::Marker marker;
01421 distance_field->getPlaneMarkers(distance_field::XYPlane, length, width,
01422 z, origin, collision_models_interface_->getWorldFrameId(), ros::Time::now(), marker);
01423 vis_distance_field_marker_publisher_.publish(marker);
01424 ros::Time::sleepUntil(ros::Time::now() + ros::Duration(0.02));
01425 ros::spinOnce();
01426 }
01427 }
01428
01429
01430
01431
01432
01433
01434
01435
01436
01437
01438
01439
01440
01441
01442
01443
01444
01445
01446
01447
01448
01449
01450
01451
01452
01453
01454
01455
01456
01457
01458
01459
01460
01461
01462
01463
01464
01465
01466
01467
01468
01469
01470
01471
01472
01473
01474
01475
01476
01477
01478
01479
01480
01481
01482
01483
01484
01485
01486
01487
01488
01489
01490
01491
01492
01493
01494
01495
01496
01497
01498
01499
01500
01501
01502
01503
01504
01505
01506
01507
01508
01509
01510
01511
01512
01513
01514
01515 void CollisionProximitySpace::visualizeCollisions(const std::vector<std::string>& link_names,
01516 const std::vector<std::string>& attached_body_names,
01517 const std::vector<CollisionType> collisions) const
01518 {
01519 visualization_msgs::MarkerArray arr;
01520
01521 for(unsigned int i = 0; i < link_names.size(); i++) {
01522 std::string name = link_names[i];
01523
01524 boost::shared_ptr<const urdf::Link> urdf_link = collision_models_interface_->getParsedDescription()->getLink(name);
01525 if(urdf_link == NULL) {
01526 ROS_INFO_STREAM("No entry in urdf for link " << name);
01527 continue;
01528 }
01529 if(!urdf_link->collision) {
01530 continue;
01531 }
01532 const urdf::Geometry *geom = urdf_link->collision->geometry.get();
01533 if(!geom) {
01534 ROS_DEBUG_STREAM("No collision geometry for link " << name);
01535 continue;
01536 }
01537 const urdf::Mesh *mesh = dynamic_cast<const urdf::Mesh*>(geom);
01538 if(mesh) {
01539 if (!mesh->filename.empty()) {
01540 visualization_msgs::Marker mark;
01541 mark.header.frame_id = collision_models_interface_->getRobotFrameId();
01542 mark.header.stamp = ros::Time::now();
01543 mark.ns = "proximity_collisions";
01544 mark.id = i;
01545 mark.type = mark.MESH_RESOURCE;
01546 mark.scale.x = 1.05;
01547 mark.scale.y = 1.05;
01548 mark.scale.z = 1.05;
01549 mark.color.a = .5;
01550 if(collisions[i].intra) {
01551 ROS_DEBUG_STREAM(name << " in intra_group");
01552 mark.color.r = 1.0;
01553 } else if(collisions[i].environment) {
01554 ROS_DEBUG_STREAM(name << " in environment");
01555 mark.color.r = 1.0;
01556 mark.color.g = 1.0;
01557 } else if(collisions[i].self) {
01558 ROS_DEBUG_STREAM(name << " in self");
01559 mark.color.b = 1.0;
01560 } else {
01561 mark.color.g = 1.0;
01562 }
01563
01564 mark.frame_locked = true;
01565 const tf::Transform& trans = body_decomposition_map_.find(name)->second->getBody()->getPose();
01566 tf::poseTFToMsg(trans, mark.pose);
01567 mark.mesh_resource = mesh->filename;
01568 arr.markers.push_back(mark);
01569 }
01570 }
01571
01572 }
01573 for(unsigned int i = 0; i < attached_body_names.size(); i++) {
01574 std::string name = attached_body_names[i];
01575 const BodyDecompositionVector* bdv = attached_object_map_.find(attached_body_names[i])->second;
01576 for(unsigned int j = 0; j < bdv->getSize(); j++) {
01577 const BodyDecomposition* bd = bdv->getBodyDecomposition(j);
01578 visualization_msgs::Marker mark;
01579 mark.header.frame_id = collision_models_interface_->getRobotFrameId();
01580 mark.header.stamp = ros::Time::now();
01581 mark.ns = "proximity_collisions";
01582 mark.id = i+link_names.size();
01583 mark.type = mark.CYLINDER;
01584 bodies::BoundingCylinder cyl;
01585 bd->getBody()->computeBoundingCylinder(cyl);
01586 mark.scale.x = cyl.radius*2.0;
01587 mark.scale.y = cyl.radius*2.0;
01588 mark.scale.z = cyl.length;
01589 mark.color.a = .5;
01590 if(collisions[i+link_names.size()].intra) {
01591 ROS_DEBUG_STREAM(name << " in intra_group");
01592 mark.color.r = 1.0;
01593 } else if(collisions[i+link_names.size()].environment) {
01594 ROS_DEBUG_STREAM(name << " in environment");
01595 mark.color.r = 1.0;
01596 mark.color.g = 1.0;
01597 } else if(collisions[i+link_names.size()].self) {
01598 ROS_DEBUG_STREAM(name << " in self");
01599 mark.color.b = 1.0;
01600 } else {
01601 mark.color.g = 1.0;
01602 }
01603
01604 const tf::Transform& trans = bd->getBody()->getPose();
01605 tf::poseTFToMsg(trans, mark.pose);
01606 arr.markers.push_back(mark);
01607 }
01608 }
01609 vis_marker_array_publisher_.publish(arr);
01610 }
01611
01612 void CollisionProximitySpace::visualizeObjectVoxels(const std::vector<std::string>& object_names) const
01613 {
01614 visualization_msgs::Marker cube_list;
01615 cube_list.header.frame_id = collision_models_interface_->getRobotFrameId();
01616 cube_list.header.stamp = ros::Time::now();
01617 cube_list.type = cube_list.CUBE_LIST;
01618 cube_list.ns = "body_voxels";
01619 cube_list.id = 1000;
01620 cube_list.scale.x = resolution_;
01621 cube_list.scale.y = resolution_;
01622 cube_list.scale.z = resolution_;
01623 cube_list.color.b = 1.0;
01624 cube_list.color.a = .5;
01625 for(unsigned int i = 0; i < object_names.size(); i++) {
01626 const std::vector<tf::Vector3>* coll_points;
01627 if(body_decomposition_map_.find(object_names[i]) != body_decomposition_map_.end()) {
01628 coll_points = &(body_decomposition_map_.find(object_names[i])->second)->getCollisionPoints();
01629 } else if(static_object_map_.find(object_names[i]) != static_object_map_.end()) {
01630 coll_points = &(static_object_map_.find(object_names[i])->second)->getCollisionPoints();
01631 } else if(attached_object_map_.find(object_names[i]) != attached_object_map_.end()) {
01632 coll_points = &(attached_object_map_.find(object_names[i])->second)->getCollisionPoints();
01633 } else {
01634 ROS_WARN_STREAM("Don't have object named " << object_names[i]);
01635 continue;
01636 }
01637 for(unsigned int i = 0; i < coll_points->size(); i++) {
01638 geometry_msgs::Point p;
01639 p.x = (*coll_points)[i].x();
01640 p.y = (*coll_points)[i].y();
01641 p.z = (*coll_points)[i].z();
01642 cube_list.points.push_back(p);
01643 }
01644 }
01645 vis_marker_publisher_.publish(cube_list);
01646 }
01647
01648 void CollisionProximitySpace::visualizeObjectSpheres(const std::vector<std::string>& object_names) const
01649 {
01650 visualization_msgs::MarkerArray arr;
01651 unsigned int count = 0;
01652 for(unsigned int i = 0; i < object_names.size(); i++) {
01653
01654
01655
01656
01657
01658
01659
01660
01661 const std::vector<CollisionSphere>* coll_spheres;
01662 if(body_decomposition_map_.find(object_names[i]) != body_decomposition_map_.end()) {
01663 coll_spheres = &(body_decomposition_map_.find(object_names[i])->second)->getCollisionSpheres();
01664 } else if(static_object_map_.find(object_names[i]) != static_object_map_.end()) {
01665 coll_spheres = &(static_object_map_.find(object_names[i])->second)->getCollisionSpheres();
01666 } else if(attached_object_map_.find(object_names[i]) != attached_object_map_.end()) {
01667 coll_spheres = &(attached_object_map_.find(object_names[i])->second)->getCollisionSpheres();
01668 } else {
01669 ROS_WARN_STREAM("Don't have object named " << object_names[i]);
01670 continue;
01671 }
01672
01673
01674
01675 for(unsigned int i = 0; i < coll_spheres->size(); i++) {
01676 visualization_msgs::Marker sphere;
01677 sphere.header.frame_id = collision_models_interface_->getRobotFrameId();
01678 sphere.header.stamp = ros::Time::now();
01679 sphere.type = sphere.SPHERE;
01680 sphere.ns = "body_spheres";
01681 sphere.id = count++;
01682 sphere.color.g = 1.0;
01683 sphere.color.a = .5;
01684 sphere.scale.x = (*coll_spheres)[i].radius_*2.0;
01685 sphere.scale.y = sphere.scale.x;
01686 sphere.scale.z = sphere.scale.x;
01687 geometry_msgs::Point p;
01688 sphere.pose.position.x = (*coll_spheres)[i].center_.x();
01689 sphere.pose.position.y = (*coll_spheres)[i].center_.y();
01690 sphere.pose.position.z = (*coll_spheres)[i].center_.z();
01691 sphere.points.push_back(p);
01692 arr.markers.push_back(sphere);
01693 }
01694 }
01695 vis_marker_array_publisher_.publish(arr);
01696 }
01697
01698 void CollisionProximitySpace::visualizeBoundingCylinders(const std::vector<std::string>& object_names) const
01699 {
01700 visualization_msgs::MarkerArray arr;
01701 for(unsigned int i = 0; i < object_names.size(); i++) {
01702 visualization_msgs::Marker mark;
01703 mark.header.frame_id = collision_models_interface_->getRobotFrameId();
01704 mark.header.stamp = ros::Time::now();
01705 mark.type = mark.CYLINDER;
01706 mark.ns = "body_cylinders";
01707 mark.id = i;
01708 mark.color.r = 1.0;
01709 mark.color.a = .5;
01710 const BodyDecomposition* bsd = NULL;
01711 if(body_decomposition_map_.find(object_names[i]) != body_decomposition_map_.end()) {
01712 bsd = body_decomposition_map_.find(object_names[i])->second;
01713 } else if(static_object_map_.find(object_names[i]) != static_object_map_.end()) {
01714 bsd = static_object_map_.find(object_names[i])->second->getBodyDecomposition(0);
01715 } else if(attached_object_map_.find(object_names[i]) != attached_object_map_.end()) {
01716 bsd = attached_object_map_.find(object_names[i])->second->getBodyDecomposition(0);
01717 } else {
01718 ROS_WARN_STREAM("Don't have object named " << object_names[i]);
01719 continue;
01720 }
01721 bodies::BoundingCylinder cyl;
01722 bsd->getBody()->computeBoundingCylinder(cyl);
01723 mark.scale.x = cyl.radius*2.0;
01724 mark.scale.y = cyl.radius*2.0;
01725 mark.scale.z = cyl.length;
01726 mark.pose.position.x = cyl.pose.getOrigin().x();
01727 mark.pose.position.y = cyl.pose.getOrigin().y();
01728 mark.pose.position.z = cyl.pose.getOrigin().z();
01729 mark.pose.orientation.x = cyl.pose.getRotation().x();
01730 mark.pose.orientation.y = cyl.pose.getRotation().y();
01731 mark.pose.orientation.z = cyl.pose.getRotation().z();
01732 mark.pose.orientation.w = cyl.pose.getRotation().w();
01733
01734 arr.markers.push_back(mark);
01735 }
01736 vis_marker_array_publisher_.publish(arr);
01737 }