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 <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
00058 chomp_robot_model_.init(cps_->getCollisionModelsInterface());
00059
00060
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
00067
00068
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
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
00087
00088
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
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
00392
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
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 }