avoid_obstacles.cpp
Go to the documentation of this file.
00001 
00030 #include "constrained_ik/constraints/avoid_obstacles.h"
00031 #include <utility>
00032 #include <ros/ros.h>
00033 #include <pluginlib/class_list_macros.h>
00034 PLUGINLIB_EXPORT_CLASS(constrained_ik::constraints::AvoidObstacles, constrained_ik::Constraint)
00035 
00036 const double DEFAULT_WEIGHT = 1.0; 
00037 const double DEFAULT_MIN_DISTANCE = 0.1; 
00038 const double DEFAULT_AVOIDANCE_DISTANCE = 0.3; 
00039 const double DEFAULT_AMPLITUDE = 0.3; 
00040 const double DEFAULT_SHIFT = 5.0; 
00041 const double DEFAULT_ZERO_POINT = 10; 
00042 const double DYNAMIC_WEIGHT_FUNCTION_CONSTANT = -13.86; 
00044 namespace constrained_ik
00045 {
00046 namespace constraints
00047 {
00048 
00049 using namespace Eigen;
00050 using namespace collision_detection;
00051 using Eigen::VectorXd;
00052 using Eigen::MatrixXd;
00053 using std::string;
00054 using std::vector;
00055 
00056 AvoidObstacles::LinkAvoidance::LinkAvoidance(): weight_(DEFAULT_WEIGHT), min_distance_(DEFAULT_MIN_DISTANCE), avoidance_distance_(DEFAULT_AVOIDANCE_DISTANCE), amplitude_(DEFAULT_AMPLITUDE), jac_solver_(NULL) {}
00057 AvoidObstacles::LinkAvoidance::LinkAvoidance(std::string link_name): LinkAvoidance() {link_name_ = link_name;}
00058 
00059 void AvoidObstacles::init(const Constrained_IK * ik)
00060 {
00061   Constraint::init(ik);
00062 
00063   if (link_names_.size() == 0)
00064   {
00065     ik_->getLinkNames(link_names_);
00066     ROS_WARN("Avoid Obstacles: No links were specified therefore using all links in kinematic chain.");
00067   }
00068   
00069   for (std::map<std::string, LinkAvoidance>::iterator it = links_.begin(); it != links_.end(); ++it)
00070   {
00071     it->second.num_robot_joints_ = ik_->getKin().numJoints();
00072     if (!ik_->getKin().getSubChain(it->second.link_name_, it->second.avoid_chain_))
00073     {
00074       ROS_ERROR_STREAM("Failed to initialize Avoid Obstalces constraint because"
00075                        "it failed to create a KDL chain between URDF links: '" <<
00076                        ik_->getKin().getRobotBaseLinkName() << "' and '" << it->second.link_name_ <<"'");
00077       initialized_ = false;
00078       return;
00079     }
00080     it->second.num_inboard_joints_ = it->second.avoid_chain_.getNrOfJoints();
00081     it->second.jac_solver_ = new  KDL::ChainJntToJacSolver(it->second.avoid_chain_);
00082   }
00083 
00084   std::vector<const robot_model::LinkModel*> tmp = ik_->getKin().getJointModelGroup()->getLinkModels();
00085   for (std::vector<const robot_model::LinkModel*>::const_iterator it = tmp.begin(); it < tmp.end(); ++it)
00086   {
00087     std::vector<std::string>::iterator name_it = std::find(link_names_.begin(), link_names_.end(), (*it)->getName());
00088     if (name_it != link_names_.end())
00089       link_models_.insert(*it);
00090   }
00091 }
00092 
00093 void AvoidObstacles::loadParameters(const XmlRpc::XmlRpcValue &constraint_xml)
00094 {
00095   XmlRpc::XmlRpcValue local_xml = constraint_xml;
00096   std::vector<std::string> link_names;
00097   if (getParam(local_xml, "link_names", link_names))
00098   {    
00099     std::vector<double> amplitude, minimum_distance, avoidance_distance, weight;
00100     if (getParam(local_xml, "amplitude", amplitude))
00101     {
00102       if (link_names.size()!=amplitude.size())
00103       {
00104         ROS_WARN("Abstacle Avoidance: amplitude memebr must be same size array as link_names member, default parameters will be used.");
00105         amplitude.clear();
00106       }
00107     }
00108     else
00109     {
00110       ROS_WARN("Abstacle Avoidance: Unable to retrieve amplitude member, default parameter will be used.");
00111     }
00112 
00113     if (getParam(local_xml, "minimum_distance", minimum_distance))
00114     {
00115       if (link_names.size()!=minimum_distance.size())
00116       {
00117         ROS_WARN("Abstacle Avoidance: minimum_distance memebr must be same size array as link_names member, default parameters will be used.");
00118         minimum_distance.clear();
00119       }
00120     }
00121     else
00122     {
00123       ROS_WARN("Abstacle Avoidance: Unable to retrieve minimum_distance member, default parameter will be used.");
00124     }
00125 
00126     if (getParam(local_xml, "avoidance_distance", avoidance_distance))
00127     {
00128       if (link_names.size()!=avoidance_distance.size())
00129       {
00130         ROS_WARN("Abstacle Avoidance: avoidance_distance memebr must be same size array as link_names member, default parameters will be used.");
00131         avoidance_distance.clear();
00132       }
00133     }
00134     else
00135     {
00136       ROS_WARN("Abstacle Avoidance: Unable to retrieve avoidance_distance member, default parameter will be used.");
00137     }
00138 
00139     if (getParam(local_xml, "weights", weight))
00140     {
00141       if (link_names.size()!=weight.size())
00142       {
00143         ROS_WARN("Abstacle Avoidance: weights member must be same size array as link_names member, default parameters will be used.");
00144         weight.clear();
00145       }
00146     }
00147     else
00148     {
00149       ROS_WARN("Abstacle Avoidance: Unable to retrieve weight member, default parameter will be used.");
00150     }
00151 
00152 
00153     for (int i=0; i<link_names.size(); ++i)
00154     {
00155       addAvoidanceLink(link_names[i]);
00156       if (!amplitude.empty())
00157       {
00158         setAmplitude(link_names[i], amplitude[i]);
00159       }
00160       if (!minimum_distance.empty())
00161       {
00162         setMinDistance(link_names[i], minimum_distance[i]);
00163       }
00164       if (!avoidance_distance.empty())
00165       {
00166         setAvoidanceDistance(link_names[i], avoidance_distance[i]);
00167       }
00168       if (!weight.empty())
00169       {
00170         setWeight(link_names[i], weight[i]);
00171       }
00172     }
00173   }
00174   else
00175   {
00176     ROS_WARN("Abstacle Avoidance: Unable to retrieve link_names member, default parameter will be used.");
00177   }
00178 }
00179 
00180 ConstraintResults AvoidObstacles::evalConstraint(const SolverState &state) const
00181 {
00182   ConstraintResults output;
00183   AvoidObstaclesData cdata(state, this);
00184   double dynamic_weight;
00185   for (std::map<std::string, LinkAvoidance>::const_iterator it = links_.begin(); it != links_.end(); ++it)
00186   {
00187     DistanceInfoMap::const_iterator dit = cdata.distance_info_map_.find(it->second.link_name_);
00188     if (dit != cdata.distance_info_map_.end() && dit->second.distance > 0)
00189     {
00190       dynamic_weight = std::exp(DYNAMIC_WEIGHT_FUNCTION_CONSTANT * (std::abs(dit->second.distance-cdata.distance_res_.minimum_distance.min_distance)/distance_threshold_));
00191       constrained_ik::ConstraintResults tmp;
00192       tmp.error = calcError(cdata, it->second) * it->second.weight_ * dynamic_weight;
00193       tmp.jacobian = calcJacobian(cdata, it->second)  * it->second.weight_ * dynamic_weight;
00194       tmp.status = checkStatus(cdata, it->second);
00195       output.append(tmp);
00196     }
00197   }
00198 
00199   return output;
00200 }
00201 
00202 VectorXd AvoidObstacles::calcError(const AvoidObstacles::AvoidObstaclesData &cdata, const LinkAvoidance &link) const
00203 {
00204   Eigen::VectorXd dist_err;
00205   DistanceInfoMap::const_iterator it;
00206 
00207   dist_err.resize(1,1);
00208   it = cdata.distance_info_map_.find(link.link_name_);
00209   if (it != cdata.distance_info_map_.end() && it->second.distance > 0)
00210   {
00211     double dist = it->second.distance;
00212     double scale_x = link.avoidance_distance_/(DEFAULT_ZERO_POINT + DEFAULT_SHIFT);
00213     double scale_y = link.amplitude_;
00214     dist_err(0, 0) = scale_y/(1.0 + std::exp((dist/scale_x) - DEFAULT_SHIFT));
00215   }
00216   else
00217   {
00218     ROS_DEBUG("Unable to retrieve distance info, couldn't find link with that name %s", link.link_name_.c_str());
00219   }
00220   return  dist_err;
00221 }
00222 
00223 MatrixXd AvoidObstacles::calcJacobian(const AvoidObstacles::AvoidObstaclesData &cdata, const LinkAvoidance &link) const
00224 {
00225   KDL::Jacobian link_jacobian(link.num_inboard_joints_); // 6xn Jacobian to link, then dist_info.link_point
00226   MatrixXd jacobian;
00227 
00228   // use distance info to find reference point on link which is closest to a collision,
00229   // change the reference point of the link jacobian to that point
00230   DistanceInfoMap::const_iterator it;
00231   jacobian.setZero(1, link.num_robot_joints_);
00232   it = cdata.distance_info_map_.find(link.link_name_);
00233   if (it != cdata.distance_info_map_.end() && it->second.distance > 0)
00234   {
00235     KDL::JntArray joint_array(link.num_inboard_joints_);
00236     for(int i=0; i<link.num_inboard_joints_; i++)   joint_array(i) = cdata.state_.joints(i);
00237     link.jac_solver_->JntToJac(joint_array, link_jacobian);// this computes a 6xn jacobian, we only need 3xn
00238 
00239     // change the referece point to the point on the link closest to a collision
00240     KDL::Vector link_point(it->second.link_point.x(), it->second.link_point.y(), it->second.link_point.z());
00241     link_jacobian.changeRefPoint(link_point);
00242     
00243     MatrixXd j_tmp;
00244     basic_kin::BasicKin::KDLToEigen(link_jacobian,j_tmp);
00245     
00246     // The jacobian to improve distance only requires 1 redundant degree of freedom
00247     // so we project the jacobian onto the avoidance vector.
00248     jacobian.block(0, 0, 1, j_tmp.cols()) = it->second.avoidance_vector.transpose() * j_tmp.topRows(3);
00249   }
00250   else
00251   {
00252     ROS_DEBUG("Unable to retrieve distance info, couldn't find link with that name %s", link.link_name_.c_str());
00253   }
00254 
00255   return jacobian;
00256 }
00257 
00258 bool AvoidObstacles::checkStatus(const AvoidObstacles::AvoidObstaclesData &cdata, const LinkAvoidance &link) const
00259 {                               // returns true if its ok to stop with current ik conditions
00260   DistanceInfoMap::const_iterator it;
00261 
00262   it = cdata.distance_info_map_.find(link.link_name_);
00263   if (it != cdata.distance_info_map_.end())
00264   {
00265     if(it->second.distance<link.min_distance_) return false;
00266   }
00267   else
00268   {
00269     ROS_DEBUG("couldn't find link with that name %s", link.link_name_.c_str());
00270   }
00271 
00272   return true;
00273 }
00274 
00275 AvoidObstacles::AvoidObstaclesData::AvoidObstaclesData(const SolverState &state, const AvoidObstacles *parent): ConstraintData(state), parent_(parent)
00276 {
00277   DistanceRequest distance_req(true, false, parent_->link_models_, state_.planning_scene->getAllowedCollisionMatrix(), parent_->distance_threshold_);
00278   distance_req.group_name = state.group_name;
00279   distance_res_.clear();
00280   
00281   collision_detection::CollisionRequest collision_req;
00282   collision_detection::CollisionResult collision_res;
00283 
00284   state.collision_robot->distanceSelf(distance_req, distance_res_, *state_.robot_state);
00285   state.collision_world->distanceRobot(distance_req, distance_res_, *state_.collision_robot, *state_.robot_state);
00286   if (distance_res_.collision)
00287   {
00288     collision_req.distance = false;
00289     collision_req.contacts = true;
00290     collision_req.max_contacts = parent_->link_models_.size() * 2.0;
00291     state.collision_robot->checkSelfCollision(collision_req, collision_res, *state_.robot_state, state_.planning_scene->getAllowedCollisionMatrix());
00292     state.collision_world->checkRobotCollision(collision_req, collision_res, *state.collision_robot, *state_.robot_state, state_.planning_scene->getAllowedCollisionMatrix());
00293   }
00294   Eigen::Affine3d tf = state_.robot_state->getGlobalLinkTransform(parent_->ik_->getKin().getRobotBaseLinkName()).inverse();
00295   getDistanceInfo(distance_res_.distance, distance_info_map_, tf);
00296 }
00297 
00298 } // end namespace constraints
00299 } // end namespace constrained_ik


constrained_ik
Author(s): Chris Lewis , Jeremy Zoss , Dan Solomon
autogenerated on Sat Jun 8 2019 19:23:45