$search
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 }