collision_proximity_planner.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2009, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00037 #include <collision_proximity_planner/collision_proximity_planner.h>
00038 #include <collision_proximity_planner/collision_proximity_planner_utils.h>
00039 #include <planning_environment/models/model_utils.h>
00040 
00041 using namespace std;
00042 
00043 namespace collision_proximity_planner
00044 {
00045 
00046 CollisionProximityPlanner::CollisionProximityPlanner(const std::string& robot_description_name):private_handle_("~")
00047 {
00048   private_handle_.param("use_pseudo_inverse", use_pseudo_inverse_, false);
00049   private_handle_.param("group_cps", group_name_cps_, std::string(" "));
00050   private_handle_.param("max_iterations", max_iterations_, 100);
00051   private_handle_.param("max_joint_update", max_joint_update_, 0.02);
00052 
00053   cps_ = new collision_proximity::CollisionProximitySpace(robot_description_name);
00054 
00055   cps_->setCollisionTolerance(cps_->getCollisionModelsInterface()->getDefaultPadding());
00056  
00057   // build the robot model
00058   chomp_robot_model_.init(cps_->getCollisionModelsInterface());
00059 
00060   // initialize the visualization publisher:
00061   vis_marker_array_publisher_ = private_handle_.advertise<visualization_msgs::MarkerArray>( "visualization_marker_array", 0 );
00062   vis_marker_publisher_ = private_handle_.advertise<visualization_msgs::Marker>( "visualization_marker", 0 );
00063 
00064   planning_service_ = private_handle_.advertiseService("plan",&CollisionProximityPlanner::getFreePath,this);
00065 
00066   //  joint_axis_.resize(chomp_robot_model_.getKDLTree()->getNrOfJoints());
00067   //  joint_pos_.resize(chomp_robot_model_.getKDLTree()->getNrOfJoints());
00068   //  segment_frames_.resize(chomp_robot_model_.getKDLTree()->getNrOfSegments());
00069   ROS_INFO("Initalized collision proximity planner");
00070 }
00071 
00072 CollisionProximityPlanner::~CollisionProximityPlanner()
00073 {
00074 }
00075 
00076 bool CollisionProximityPlanner::initializeForGroup(const std::string& group_name) 
00077 {
00078   // get the planning group:
00079   planning_group_ = chomp_robot_model_.getPlanningGroup(group_name);
00080   if(planning_group_ == NULL) {
00081     ROS_ERROR_STREAM("No planning group for " << group_name);
00082     return false;
00083   }
00084   num_joints_ = planning_group_->chomp_joints_.size();
00085   ROS_INFO("Planning for %d joints", num_joints_);
00086   //  num_collision_points_ = planning_group_->collision_points_.size();
00087   
00088   // set up joint index:
00089   group_joint_to_kdl_joint_index_.clear();
00090   group_joint_to_kdl_joint_index_.resize(num_joints_);
00091   for (int i=0; i<num_joints_; ++i)
00092     group_joint_to_kdl_joint_index_[i] = planning_group_->chomp_joints_[i].kdl_joint_index_;
00093 
00094   robot_state_group_.joint_state.position.clear();
00095   robot_state_group_.joint_state.name.clear();
00096   robot_state_group_.joint_state.position.resize(num_joints_);
00097   robot_state_group_.joint_state.name.resize(num_joints_);
00098   for(int i=0; i < num_joints_; i++)
00099     robot_state_group_.joint_state.name[i] = planning_group_->chomp_joints_[i].joint_name_;
00100 
00101   collision_increments_ = Eigen::MatrixXd::Zero(1, num_joints_);
00102   jacobian_ = Eigen::MatrixXd::Zero(3, num_joints_);
00103   jacobian_pseudo_inverse_ = Eigen::MatrixXd::Zero(num_joints_, 3);
00104   jacobian_jacobian_tranpose_ = Eigen::MatrixXd::Zero(3, 3);
00105   return true;
00106 }
00107 
00108 bool CollisionProximityPlanner::getFreePath(arm_navigation_msgs::GetMotionPlan::Request &req,
00109                                             arm_navigation_msgs::GetMotionPlan::Response &res)
00110 {
00111   ROS_INFO("Computing free path");
00112   clear();
00113   if(!req.motion_plan_request.group_name.empty() && initializeForGroup(req.motion_plan_request.group_name)) {
00114     cps_->setupForGroupQueries(req.motion_plan_request.group_name,
00115                                req.motion_plan_request.start_state,
00116                                current_link_names_,
00117                                current_attached_body_names_);
00118   } else {
00119     return false;
00120   }
00121   for(unsigned int i=0; i < current_link_names_.size(); i++)
00122   {
00123     ROS_DEBUG("Finding active joints for %s",current_link_names_[i].c_str());
00124     std::vector<int> ac_j;
00125     int segment_number;
00126     chomp_robot_model_.getActiveJointInformation(current_link_names_[i],ac_j,segment_number);
00127     ROS_DEBUG("Found %zu active joints for %s",ac_j.size(),current_link_names_[i].c_str());
00128     active_joints_.push_back(ac_j);
00129   }
00130   bool result = findPathToFreeState(req.motion_plan_request.start_state,res.trajectory);
00131   if(result) {
00132     res.error_code.val = res.error_code.SUCCESS;
00133   } else {
00134     res.error_code.val = res.error_code.PLANNING_FAILED;
00135   }
00136   return result;
00137 }
00138 
00139 void CollisionProximityPlanner::clear()
00140 {
00141   active_joints_.clear();
00142   group_state_joint_array_group_mapping_.clear();
00143   joint_array_group_group_state_mapping_.clear();
00144 }
00145 
00146 void CollisionProximityPlanner::fillInGroupState(arm_navigation_msgs::RobotState &robot_state,
00147                                                  const arm_navigation_msgs::RobotState &group_state)
00148 {
00149   for(unsigned int i=0; i < group_state.joint_state.name.size(); i++)
00150   {
00151     for(unsigned int j=0; j < robot_state.joint_state.name.size(); j++)
00152     {
00153       if(group_state.joint_state.name[i] == robot_state.joint_state.name[j])
00154       {
00155         ROS_INFO("Filling in group state for %s",robot_state.joint_state.name[j].c_str());
00156         robot_state.joint_state.position[j] = group_state.joint_state.position[i];
00157       }
00158     }
00159   }
00160 }
00161 
00162 void CollisionProximityPlanner::getGroupArray(const KDL::JntArray &jnt_array,
00163                                               const std::vector<int> &group_joint_to_kdl_joint_index,
00164                                               KDL::JntArray &jnt_array_group)
00165 {
00166   for(int i=0; i < num_joints_; i++)
00167     jnt_array_group(i) = jnt_array(group_joint_to_kdl_joint_index[i]);
00168 }
00169 
00170 void CollisionProximityPlanner::fillInGroupArray(const KDL::JntArray &jnt_array_group,
00171                                                  const std::vector<int> &group_joint_to_kdl_joint_index,
00172                                                  KDL::JntArray &jnt_array)
00173 {
00174   for(int i=0; i < num_joints_; i++)
00175     jnt_array(group_joint_to_kdl_joint_index[i]) = jnt_array_group(i);
00176 }
00177 
00178 bool CollisionProximityPlanner::findPathToFreeState(const arm_navigation_msgs::RobotState &robot_state, 
00179                                                     arm_navigation_msgs::RobotTrajectory &robot_trajectory)
00180 {
00181   std::vector<KDL::JntArray> jnt_trajectory;
00182   Eigen::MatrixXd collision_increments;
00183   KDL::JntArray jnt_array;
00184   jnt_array.resize(robot_state.joint_state.name.size());
00185   chomp_robot_model_.jointStateToArray(robot_state.joint_state,jnt_array);
00186   performForwardKinematics(jnt_array,true);
00187   bool in_collision = true;
00188   double distance;
00189 
00190   KDL::JntArray jnt_array_group;
00191   jnt_array_group.resize(num_joints_);
00192   getGroupArray(jnt_array,group_joint_to_kdl_joint_index_,jnt_array_group);
00193 
00194   for(int i=0; i < max_iterations_; i++)
00195   {    
00196     ROS_DEBUG("Iteration: %d",max_iterations_);
00197     jnt_trajectory.push_back(jnt_array_group);
00198     fillInGroupArray(jnt_array_group,group_joint_to_kdl_joint_index_,jnt_array);
00199     performForwardKinematics(jnt_array,false);
00200     updateGroupRobotState(jnt_array_group);
00201     updateCollisionProximitySpace(robot_state_group_);
00202     in_collision = calculateCollisionIncrements(collision_increments,distance);
00203     if(!in_collision)
00204     {
00205       ROS_INFO("Found state not in collision in %d iterations",i+1);
00206       break;
00207     }
00208     updateJointState(jnt_array_group,collision_increments);
00209     for(int j=0; j < num_joints_; j++)
00210     {
00211       ROS_DEBUG("Joint update: %d %f %f",j,collision_increments(0,j),jnt_array_group(j));
00212     }
00213   }
00214   
00215   kdlJointTrajectoryToRobotTrajectory(jnt_trajectory,robot_trajectory);
00216   if(in_collision)
00217   {
00218     ROS_WARN("Final position is also in collision");
00219     return true;
00220   }
00221   return true;
00222 }
00223 
00224 bool CollisionProximityPlanner::setGroupState(const arm_navigation_msgs::RobotState &group_state)
00225 {
00226   int joints_found = 0;
00227   group_state_joint_array_group_mapping_.resize(num_joints_);
00228   for(unsigned int i=0; i < group_state.joint_state.name.size(); i++)
00229   {
00230     for(unsigned int j=0; j < robot_state_group_.joint_state.name.size(); j++)
00231     {
00232       if(group_state.joint_state.name[i] == robot_state_group_.joint_state.name[j])
00233       {
00234         joints_found++;
00235         group_state_joint_array_group_mapping_[i] = j;
00236         joint_array_group_group_state_mapping_[j] = i;
00237       }
00238     }
00239   }
00240   if(joints_found != num_joints_)
00241     return false;
00242   return true;
00243 }
00244 
00245 bool CollisionProximityPlanner::mapGroupState(const arm_navigation_msgs::RobotState &group_state,
00246                                               const std::vector<int>& mapping)
00247 {
00248   if((int) group_state.joint_state.name.size() < num_joints_ || (int) group_state.joint_state.position.size() < num_joints_)
00249   {
00250     ROS_ERROR("Group state needs to contain %zu joints", robot_state_group_.joint_state.name.size());
00251     return false;
00252   }
00253   for(int i=0; i < num_joints_; i++)
00254     jnt_array_group_(mapping[i]) = group_state.joint_state.position[i];
00255   return true;
00256 }
00257 
00258 bool CollisionProximityPlanner::getStateGradient(const arm_navigation_msgs::RobotState &group_state,
00259                                                  double &distance,
00260                                                  arm_navigation_msgs::RobotState &gradient)
00261 {
00262   Eigen::MatrixXd collision_increments;
00263   if(!mapGroupState(group_state,group_state_joint_array_group_mapping_))
00264     return false;
00265   fillInGroupArray(jnt_array_group_,group_joint_to_kdl_joint_index_,jnt_array_);
00266   performForwardKinematics(jnt_array_,false);
00267   updateGroupRobotState(jnt_array_group_);
00268   updateCollisionProximitySpace(robot_state_group_);
00269   calculateCollisionIncrements(collision_increments,distance);
00270   for(int i=0; i < num_joints_; i++)
00271     gradient.joint_state.position[joint_array_group_group_state_mapping_[i]] = collision_increments(0,i);
00272 
00273   return true;
00274 }
00275 
00276 bool CollisionProximityPlanner::refineState(const arm_navigation_msgs::RobotState &group_state,
00277                                             arm_navigation_msgs::RobotTrajectory &robot_trajectory)
00278 {
00279   std::vector<KDL::JntArray> jnt_trajectory;
00280   Eigen::MatrixXd collision_increments;
00281   bool in_collision = true;
00282   double distance;
00283   if(!mapGroupState(group_state,group_state_joint_array_group_mapping_))
00284     return false;
00285   for(int i=0; i < max_iterations_; i++)
00286   {    
00287     ROS_DEBUG("Iteration: %d",max_iterations_);
00288     jnt_trajectory.push_back(jnt_array_group_);
00289     fillInGroupArray(jnt_array_group_,group_joint_to_kdl_joint_index_,jnt_array_);
00290     performForwardKinematics(jnt_array_,false);
00291     updateGroupRobotState(jnt_array_group_);
00292     updateCollisionProximitySpace(robot_state_group_);
00293     in_collision = calculateCollisionIncrements(collision_increments,distance);
00294     if(!in_collision)
00295     {
00296       ROS_INFO("Found state not in collision in %d iterations",i+1);
00297       break;
00298     }
00299     updateJointState(jnt_array_group_,collision_increments);
00300     for(int j=0; j < num_joints_; j++)
00301     {
00302       ROS_DEBUG("Joint update: %d %f %f",j,collision_increments(0,j),jnt_array_group_(j));
00303     }
00304   }  
00305   kdlJointTrajectoryToRobotTrajectory(jnt_trajectory,robot_trajectory);
00306   if(in_collision)
00307   {
00308     ROS_WARN("Final position is also in collision");
00309     return false;
00310   }
00311   return true;
00312 };
00313 
00314 void CollisionProximityPlanner::kdlJointTrajectoryToRobotTrajectory(std::vector<KDL::JntArray> &jnt_trajectory,
00315                                                                     arm_navigation_msgs::RobotTrajectory &robot_trajectory)
00316 {
00317   robot_trajectory.joint_trajectory.header.frame_id = reference_frame_;
00318   robot_trajectory.joint_trajectory.header.stamp = ros::Time::now();
00319   robot_trajectory.joint_trajectory.joint_names.resize(num_joints_);
00320   robot_trajectory.joint_trajectory.points.resize(jnt_trajectory.size());
00321   for(unsigned int i=0; i < robot_trajectory.joint_trajectory.points.size(); i++)
00322   {
00323     robot_trajectory.joint_trajectory.points[i].positions.resize(num_joints_);
00324     for(int j=0; j < num_joints_; j++)
00325       robot_trajectory.joint_trajectory.points[i].positions[j] = jnt_trajectory[i](j);
00326   }
00327   robot_trajectory.joint_trajectory.joint_names = robot_state_group_.joint_state.name;
00328 }
00329 
00330 void CollisionProximityPlanner::updateGroupRobotState(const KDL::JntArray &jnt_array)
00331 {
00332   for(int i=0; i < num_joints_; i++)
00333     robot_state_group_.joint_state.position[i] = jnt_array(i);
00334 }
00335 void CollisionProximityPlanner::updateCollisionProximitySpace(const arm_navigation_msgs::RobotState &group_state)
00336 {
00337   planning_environment::setRobotStateAndComputeTransforms(group_state, *cps_->getCollisionModelsInterface()->getPlanningSceneState());
00338   cps_->setCurrentGroupState(*cps_->getCollisionModelsInterface()->getPlanningSceneState());
00339 }
00340 
00341 bool CollisionProximityPlanner::calculateCollisionIncrements(Eigen::MatrixXd &collision_increments,
00342                                                              double &min_distance)
00343 {
00344   collision_increments = Eigen::MatrixXd::Zero(1, num_joints_);
00345 
00346   std::vector<collision_proximity::GradientInfo> gradients;
00347 
00348   Eigen::Vector3d cartesian_gradient;
00349   bool in_collision =   cps_->getStateGradients(gradients, true);  
00350   bool state_in_collision = cps_->getCollisionModelsInterface()->isKinematicStateInCollision(*cps_->getCollisionModelsInterface()->getPlanningSceneState());
00351 
00352   min_distance = DBL_MAX;
00353   for(unsigned int i=0; i < current_link_names_.size(); i++)
00354   {
00355     ROS_DEBUG("Link: %s",current_link_names_[i].c_str());
00356     for(unsigned int j=0; j < gradients[i].sphere_locations.size(); j++)
00357     {      
00358       ROS_DEBUG("Contact: %d",j);
00359       Eigen::Vector3d collision_point_pos_eigen;
00360       collision_point_pos_eigen(0) = gradients[i].sphere_locations[j].x();
00361       collision_point_pos_eigen(1) = gradients[i].sphere_locations[j].y();
00362       collision_point_pos_eigen(2) = gradients[i].sphere_locations[j].z();
00363 
00364       cartesian_gradient(0) = -gradients[i].distances[j] * gradients[i].distances[j] * gradients[i].gradients[j].x();
00365       cartesian_gradient(1) = -gradients[i].distances[j] * gradients[i].distances[j] * gradients[i].gradients[j].y();
00366       cartesian_gradient(2) = -gradients[i].distances[j] * gradients[i].distances[j] * gradients[i].gradients[j].z();
00367 
00368       if(min_distance > gradients[i].distances[j])
00369         min_distance = gradients[i].distances[j];
00370 
00371       ROS_DEBUG("Point: %f %f %f",gradients[i].sphere_locations[j].x(),gradients[i].sphere_locations[j].y(),gradients[i].sphere_locations[j].z());
00372       ROS_DEBUG("Gradient: %f %f %f",gradients[i].gradients[j].x(),gradients[i].gradients[j].y(),gradients[i].gradients[j].z());
00373       ROS_DEBUG("Environment distance: %f",gradients[i].distances[j]);
00374       getJacobian((int)i,joint_pos_eigen_,joint_axis_eigen_,collision_point_pos_eigen,jacobian_,group_joint_to_kdl_joint_index_);
00375       if (use_pseudo_inverse_)
00376       {
00377         //        calculatePseudoInverse();
00378         collision_increments.row(0).transpose() -=
00379           jacobian_pseudo_inverse_ * cartesian_gradient;
00380       }
00381       else
00382       {
00383         ROS_DEBUG("Jacobian");
00384         for(int i=0; i < num_joints_; i++)
00385           ROS_DEBUG("%f %f %f",jacobian_.col(i)(0),jacobian_.col(i)(1),jacobian_.col(i)(2));
00386         collision_increments.row(0).transpose() -=
00387           jacobian_.transpose() * cartesian_gradient;
00388         ROS_DEBUG("Cartesian gradient: %f %f %f",cartesian_gradient(0),cartesian_gradient(1),cartesian_gradient(2));
00389         ROS_DEBUG("Collision increment: %f %f %f %f %f %f %f",collision_increments.row(0)(0),collision_increments.row(0)(1),collision_increments.row(0)(2),collision_increments.row(0)(3),collision_increments.row(0)(4),collision_increments.row(0)(5),collision_increments.row(0)(6));
00390       }
00391       //     if (point_is_in_collision_[i][j])
00392       //        break;
00393     }
00394   }
00395   return in_collision || state_in_collision;
00396 }
00397 
00398 void CollisionProximityPlanner::performForwardKinematics(KDL::JntArray &jnt_array, const bool& full)
00399 {
00400   if(full)
00401     planning_group_->fk_solver_->JntToCartFull(jnt_array, joint_pos_, joint_axis_, segment_frames_);    
00402   else
00403     planning_group_->fk_solver_->JntToCartPartial(jnt_array, joint_pos_, joint_axis_, segment_frames_);    
00404 
00405   kdlVecToEigenVec(joint_axis_, joint_axis_eigen_, 3, 1);
00406   kdlVecToEigenVec(joint_pos_, joint_pos_eigen_, 3, 1);
00407   kdlVecToEigenVec(collision_point_pos_, collision_point_pos_eigen_, 3, 1);
00408 }
00409 
00410 void CollisionProximityPlanner::updateJointState(KDL::JntArray &jnt_array,
00411                                                  Eigen::MatrixXd &collision_increments)
00412 {
00413   double diff = collision_increments.row(0).norm();
00414   double scale = diff/max_joint_update_;
00415   if(scale > 1.0)
00416     scale = 1.0/scale;
00417   for(int i=0; i < num_joints_; i++)
00418     jnt_array(i) += scale * collision_increments(0,i);
00419 }
00420 
00421 /*void ChompOptimizer::addIncrementsToTrajectory()
00422 {
00423 //  double scale = 1.0;
00424   for (int i=0; i<num_joints_; i++)
00425   {
00426     double scale = 1.0;
00427     double max = final_increments_.col(i).maxCoeff();
00428     double min = final_increments_.col(i).minCoeff();
00429     double max_scale = planning_group_->chomp_joints_[i].joint_update_limit_ / fabs(max);
00430     double min_scale = planning_group_->chomp_joints_[i].joint_update_limit_ / fabs(min);
00431     if (max_scale < scale)
00432       scale = max_scale;
00433     if (min_scale < scale)
00434       scale = min_scale;
00435     group_trajectory_.getFreeTrajectoryBlock().col(i) += scale * final_increments_.col(i);
00436   }
00437   //ROS_DEBUG("Scale: %f",scale);
00438   //group_trajectory_.getFreeTrajectoryBlock() += scale * final_increments_;
00439 }
00440 */
00441 
00442 
00443 }


collision_proximity_planner
Author(s): Sachin Chitta
autogenerated on Fri Dec 6 2013 21:13:39