arm_kinematics_solver_constraint_aware.cpp
Go to the documentation of this file.
00001 //Software License Agreement (BSD License)
00002 
00003 //Copyright (c) 2011, Willow Garage, Inc.
00004 //All rights reserved.
00005 
00006 //Redistribution and use in source and binary forms, with or without
00007 //modification, are permitted provided that the following conditions
00008 //are met:
00009 
00010 // * Redistributions of source code must retain the above copyright
00011 //   notice, this list of conditions and the following disclaimer.
00012 // * Redistributions in binary form must reproduce the above
00013 //   copyright notice, this list of conditions and the following
00014 //   disclaimer in the documentation and/or other materials provided
00015 //   with the distribution.
00016 // * Neither the name of Willow Garage, Inc. nor the names of its
00017 //   contributors may be used to endorse or promote products derived
00018 //   from this software without specific prior written permission.
00019 
00020 //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021 //"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022 //LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023 //FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024 //COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025 //INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026 //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027 //LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028 //CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029 //LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030 //ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031 //POSSIBILITY OF SUCH DAMAGE.
00032 
00033 #include <arm_kinematics_constraint_aware/arm_kinematics_solver_constraint_aware.h>
00034 #include <arm_kinematics_constraint_aware/arm_kinematics_constraint_aware_utils.h>
00035 #include <planning_environment/models/model_utils.h>
00036 
00037 namespace arm_kinematics_constraint_aware 
00038 {
00039 
00040 ArmKinematicsSolverConstraintAware::ArmKinematicsSolverConstraintAware(kinematics::KinematicsBase* solver,
00041                                                                        planning_environment::CollisionModels* cm,
00042                                                                        const std::string& group_name) :
00043   cm_(cm),
00044   active_(false),
00045   kinematics_solver_(solver),
00046   group_name_(group_name)
00047 {
00048   if(group_name.empty()) {
00049     ROS_INFO_STREAM("Must have non-empty group");
00050     return;
00051   }
00052   
00053   const planning_models::KinematicModel::JointModelGroup* joint_model_group = cm_->getKinematicModel()->getModelGroup(group_name_);
00054   if(joint_model_group == NULL) {
00055     ROS_WARN_STREAM("No joint group " << group_name_);
00056     return;
00057   }
00058   const planning_models::KinematicModel::GroupConfig& config =
00059     cm->getKinematicModel()->getJointModelGroupConfigMap().at(group_name_);
00060   if(config.base_link_.empty() || config.tip_link_.empty()) {
00061     ROS_WARN_STREAM("Group does not have base/tip config definition, can't solve ik");
00062     return;
00063   }
00064 
00065   base_name_ = config.base_link_;
00066   tip_name_ = config.tip_link_;
00067 
00068   const planning_models::KinematicModel::LinkModel* end_effector_link = cm->getKinematicModel()->getLinkModel(tip_name_);
00069   end_effector_collision_links_ = cm->getKinematicModel()->getChildLinkModelNames(end_effector_link);
00070 
00071   if(kinematics_solver_->initialize(group_name_,
00072                                     base_name_,
00073                                     tip_name_,
00074                                     .025)) {
00075   } else {
00076     ROS_INFO_STREAM("Initialize is failing for " << group_name);
00077     return;
00078   }
00079 
00080   active_ = true;
00081 }
00082 
00083 bool ArmKinematicsSolverConstraintAware::getPositionFK(const planning_models::KinematicState* robot_state,
00084                                                        const std::vector<std::string>& link_names,
00085                                                        std::vector<geometry_msgs::Pose> &poses)
00086 {
00087   poses.resize(link_names.size());
00088 
00089   for(unsigned int i = 0; i < link_names.size(); i++) {
00090     const planning_models::KinematicState::LinkState* ls = robot_state->getLinkState(link_names[i]);
00091     if(ls == NULL) return false;
00092     tf::poseTFToMsg(ls->getGlobalLinkTransform(), poses[i]);
00093   }
00094   return true;
00095 }
00096 bool ArmKinematicsSolverConstraintAware::getPositionIK(const geometry_msgs::Pose &pose,
00097                                                        const planning_models::KinematicState* robot_state,
00098                                                        sensor_msgs::JointState& solution,
00099                                                        arm_navigation_msgs::ArmNavigationErrorCodes& error_code)
00100 {
00101   std::map<std::string, double> seed_state_map;
00102   robot_state->getKinematicStateValues(seed_state_map);
00103   std::vector<double> seed_state_vector(kinematics_solver_->getJointNames().size());
00104   for(unsigned int i = 0; i < kinematics_solver_->getJointNames().size(); i++) {
00105     seed_state_vector[i] = seed_state_map[kinematics_solver_->getJointNames()[i]];
00106   } 
00107 
00108   std::vector<double> sol;
00109   int kinematics_error_code;
00110   bool ik_valid = kinematics_solver_->getPositionIK(pose,
00111                                                     seed_state_vector,
00112                                                     sol,
00113                                                     kinematics_error_code);
00114   if(ik_valid) {
00115     solution.name = kinematics_solver_->getJointNames();
00116     solution.position = sol;
00117     error_code.val = error_code.SUCCESS;
00118   } else {
00119     solution.name.clear();
00120     solution.position.clear();
00121     error_code = kinematicsErrorCodeToMotionPlanningErrorCode(kinematics_error_code);
00122   }
00123   return ik_valid;
00124 }
00125 
00126 bool ArmKinematicsSolverConstraintAware::findConstraintAwareSolution(const geometry_msgs::Pose& pose,
00127                                                                      const arm_navigation_msgs::Constraints& constraints,
00128                                                                      planning_models::KinematicState* robot_state,
00129                                                                      sensor_msgs::JointState& solution,
00130                                                                      arm_navigation_msgs::ArmNavigationErrorCodes& error_code, 
00131                                                                      const bool& do_initial_pose_check)
00132 {
00133   do_initial_pose_check_ = do_initial_pose_check;
00134   constraints_ = constraints;
00135   state_ = robot_state;
00136   
00137   std::map<std::string, double> seed_state_map;
00138   robot_state->getKinematicStateValues(seed_state_map);
00139   
00140   std::vector<double> seed_state_vector(kinematics_solver_->getJointNames().size());
00141   for(unsigned int i = 0; i < kinematics_solver_->getJointNames().size(); i++) {
00142     seed_state_vector[i] = seed_state_map[kinematics_solver_->getJointNames()[i]];
00143   } 
00144   
00145   std::vector<double> sol;
00146   int kinematics_error_code;
00147   bool ik_valid = kinematics_solver_->searchPositionIK(pose,
00148                                                       seed_state_vector,
00149                                                       1.0,
00150                                                       sol,
00151                                                       boost::bind(&ArmKinematicsSolverConstraintAware::initialPoseCheck, this, _1, _2, _3),
00152                                                       boost::bind(&ArmKinematicsSolverConstraintAware::collisionCheck, this, _1, _2, _3),
00153                                                       kinematics_error_code);
00154   if(ik_valid) {
00155     solution.name = kinematics_solver_->getJointNames();
00156     solution.position = sol;
00157     error_code.val = error_code.SUCCESS;
00158   } else {
00159     solution.name.clear();
00160     solution.position.clear();
00161     error_code = kinematicsErrorCodeToMotionPlanningErrorCode(kinematics_error_code);
00162   }
00163   return ik_valid;
00164 }
00165 
00166 bool ArmKinematicsSolverConstraintAware::findConsistentConstraintAwareSolution(const geometry_msgs::Pose& pose,
00167                                                                                const arm_navigation_msgs::Constraints& constraints,
00168                                                                                planning_models::KinematicState* robot_state,
00169                                                                                sensor_msgs::JointState& solution,
00170                                                                                arm_navigation_msgs::ArmNavigationErrorCodes& error_code, 
00171                                                                                const unsigned int& redundancy,
00172                                                                                const double& max_consistency,
00173                                                                                const bool& do_initial_pose_check)
00174 {
00175   do_initial_pose_check_ = do_initial_pose_check;
00176   constraints_ = constraints;
00177   state_ = robot_state;
00178   
00179   std::map<std::string, double> seed_state_map;
00180   robot_state->getKinematicStateValues(seed_state_map);
00181   
00182   std::vector<double> seed_state_vector(kinematics_solver_->getJointNames().size());
00183   for(unsigned int i = 0; i < kinematics_solver_->getJointNames().size(); i++) {
00184     seed_state_vector[i] = seed_state_map[kinematics_solver_->getJointNames()[i]];
00185   } 
00186   
00187   std::vector<double> sol;
00188   int kinematics_error_code;
00189   bool ik_valid = kinematics_solver_->searchPositionIK(pose,
00190                                                        seed_state_vector,
00191                                                        1.0,
00192                                                        redundancy,
00193                                                        max_consistency,
00194                                                        sol,
00195                                                        boost::bind(&ArmKinematicsSolverConstraintAware::initialPoseCheck, this, _1, _2, _3),
00196                                                        boost::bind(&ArmKinematicsSolverConstraintAware::collisionCheck, this, _1, _2, _3),
00197                                                        kinematics_error_code);
00198   if(ik_valid) {
00199     solution.name = kinematics_solver_->getJointNames();
00200     solution.position = sol;
00201     error_code.val = error_code.SUCCESS;
00202   } else {
00203     solution.name.clear();
00204     solution.position.clear();
00205     error_code = kinematicsErrorCodeToMotionPlanningErrorCode(kinematics_error_code);
00206   }
00207   return ik_valid;
00208 }
00209 
00210 
00211 void ArmKinematicsSolverConstraintAware::collisionCheck(const geometry_msgs::Pose &ik_pose,
00212                                                         const std::vector<double> &ik_solution,
00213                                                         int &error_code)
00214 {
00215   std::map<std::string, double> joint_values;
00216   for(unsigned int i=0; i < kinematics_solver_->getJointNames().size(); i++) {
00217     joint_values[kinematics_solver_->getJointNames()[i]] = ik_solution[i];
00218   }
00219   
00220   state_->setKinematicState(joint_values);
00221   error_code = kinematics::SUCCESS;
00222   if(cm_->isKinematicStateInCollision(*state_)) {
00223     error_code = kinematics::STATE_IN_COLLISION;
00224   } else if(!planning_environment::doesKinematicStateObeyConstraints(*state_, 
00225                                                                      constraints_)) {
00226     error_code = kinematics::GOAL_CONSTRAINTS_VIOLATED;
00227   }
00228 }
00229 
00230 void ArmKinematicsSolverConstraintAware::initialPoseCheck(const geometry_msgs::Pose &ik_pose,
00231                                                           const std::vector<double> &ik_solution,
00232                                                           int &error_code)
00233 {
00234   if(!do_initial_pose_check_) {
00235     error_code = kinematics::SUCCESS;
00236     return;
00237   }
00238   std::string kinematic_frame_id = kinematics_solver_->getBaseName();
00239   std::string planning_frame_id = cm_->getWorldFrameId();
00240   geometry_msgs::PoseStamped pose_stamped;
00241   pose_stamped.pose = ik_pose;
00242   pose_stamped.header.stamp = ros::Time::now();
00243   pose_stamped.header.frame_id = kinematic_frame_id;
00244   if(!cm_->convertPoseGivenWorldTransform(*state_,
00245                                           planning_frame_id,
00246                                           pose_stamped.header,
00247                                           pose_stamped.pose,
00248                                           pose_stamped)) {
00249     ROS_ERROR_STREAM("Cannot transform from " << pose_stamped.header.frame_id << " to " << planning_frame_id);
00250   }
00251   //disabling all collision for arm links
00252   collision_space::EnvironmentModel::AllowedCollisionMatrix save_acm = cm_->getCurrentAllowedCollisionMatrix();
00253   collision_space::EnvironmentModel::AllowedCollisionMatrix acm = save_acm;
00254   for(unsigned int i = 0; i < kinematics_solver_->getLinkNames().size(); i++) {
00255     acm.changeEntry(kinematics_solver_->getLinkNames()[i], true);
00256   }
00257   cm_->setAlteredAllowedCollisionMatrix(acm);
00258   
00259   tf::Transform transform;
00260   tf::poseMsgToTF(pose_stamped.pose,transform);
00261   if(!state_->hasLinkState(tip_name_)) {
00262     error_code = kinematics::INVALID_LINK_NAME;
00263     return;
00264   }
00265   state_->updateKinematicStateWithLinkAt(tip_name_, transform);
00266   if(cm_->isKinematicStateInCollision(*state_)) {
00267     error_code = kinematics::IK_LINK_IN_COLLISION;
00268     ROS_DEBUG_STREAM("Initial pose check failing");
00269   } else {
00270     error_code = kinematics::SUCCESS;
00271   }
00272   cm_->setAlteredAllowedCollisionMatrix(save_acm);
00273 }
00274 
00275 bool ArmKinematicsSolverConstraintAware::interpolateIKDirectional(const geometry_msgs::Pose& start_pose,
00276                                                                   const tf::Vector3& direction,
00277                                                                   const double& distance,
00278                                                                   const arm_navigation_msgs::Constraints& constraints,
00279                                                                   planning_models::KinematicState* robot_state,
00280                                                                   arm_navigation_msgs::ArmNavigationErrorCodes& error_code, 
00281                                                                   trajectory_msgs::JointTrajectory& traj,
00282                                                                   const unsigned int& redundancy,
00283                                                                   const double& max_consistency,
00284                                                                   const bool& reverse, 
00285                                                                   const bool& premultiply,
00286                                                                   const unsigned int& num_points,
00287                                                                   const ros::Duration& total_dur,
00288                                                                   const bool& do_initial_pose_check)
00289 {
00290   trajectory_msgs::JointTrajectory ret_traj;
00291   ret_traj.joint_names = kinematics_solver_->getJointNames();
00292   ret_traj.points.resize(num_points+1);
00293     
00294   tf::Transform first_pose;
00295   tf::poseMsgToTF(start_pose, first_pose);
00296 
00297   unsigned int index;
00298   unsigned int val;
00299   if(reverse) {
00300     val = 0;
00301     index = num_points;
00302   } else {
00303     val = 0;
00304     index = 0;
00305   }
00306 
00307   while(1) {
00308     //assumes that the axis is aligned
00309     tf::Transform trans(tf::Quaternion(0,0,0,1.0), direction*(int)val*fabs(distance/(num_points*1.0)));
00310     tf::Transform mult_trans;
00311     if(premultiply) {
00312       mult_trans = trans*first_pose;
00313     } else {
00314       mult_trans = first_pose*trans;
00315     }
00316     geometry_msgs::Pose trans_pose;
00317     tf::poseTFToMsg(mult_trans, trans_pose);
00318 
00319     ROS_DEBUG_STREAM("Pose is " << trans_pose.position.x << " "
00320                      << trans_pose.position.y << " "
00321                      << trans_pose.position.z << " "
00322                      << trans_pose.orientation.x << " "
00323                      << trans_pose.orientation.y << " "
00324                      << trans_pose.orientation.z << " "
00325                      << trans_pose.orientation.w);
00326 
00327     sensor_msgs::JointState solution;
00328     arm_navigation_msgs::ArmNavigationErrorCodes temp_error_code;
00329     if(findConsistentConstraintAwareSolution(trans_pose,
00330                                              constraints,
00331                                              robot_state,
00332                                              solution,
00333                                              temp_error_code,
00334                                              redundancy,
00335                                              max_consistency,
00336                                              do_initial_pose_check)) {
00337       ret_traj.points[index].positions = solution.position;
00338       ROS_DEBUG_STREAM("Setting point " << index << " to " <<
00339                        solution.position[0] << " " <<
00340                        solution.position[1] << " " <<
00341                        solution.position[2] << " " <<
00342                        solution.position[3] << " " <<
00343                        solution.position[4] << " " <<
00344                        solution.position[5] << " " <<
00345                        solution.position[6]); 
00346       ret_traj.points[index].time_from_start = ros::Duration((index*1.0)*total_dur.toSec()/(num_points*1.0));
00347     } else {
00348       return false;
00349     }
00350     if(reverse) {
00351       val++;
00352       if(index == 0) {
00353         break;
00354       }
00355       index--;
00356     } else {
00357       val++;
00358       index++;
00359       if(index > num_points) {
00360         break;
00361       }
00362     }
00363   }
00364   checkForWraparound(ret_traj);
00365   traj = ret_traj;
00366   return true;
00367 }
00368 
00369 void ArmKinematicsSolverConstraintAware::checkForWraparound(const trajectory_msgs::JointTrajectory& joint_trajectory) {
00370 
00371   std::vector<unsigned int> checks;
00372   for(unsigned int i = 0; i < joint_trajectory.joint_names.size(); i++) {
00373     const planning_models::KinematicModel::RevoluteJointModel* rev 
00374       = dynamic_cast<const planning_models::KinematicModel::RevoluteJointModel*>(cm_->getKinematicModel()->getJointModel(joint_trajectory.joint_names[i]));
00375     if(rev != NULL && rev->continuous_) {
00376       checks.push_back(i);
00377     }
00378   }
00379   for(unsigned int i = 1; i < joint_trajectory.points.size(); i++) {
00380     for(unsigned int j = 0; j < checks.size(); j++) {
00381       double last_val = joint_trajectory.points[i-1].positions[checks[j]];
00382       double cur_val = joint_trajectory.points[i].positions[checks[j]];
00383       if((last_val < (-2.0*M_PI+.04) && cur_val > (2*M_PI-.04)) ||
00384          (last_val > (2.0*M_PI-.04) && cur_val < (-2*M_PI+.04))) {
00385         ROS_ERROR_STREAM("Wrap around problem point " << i << " last val " << last_val << " cur val " << cur_val);
00386       }
00387     }
00388   }
00389 }
00390 
00391 }
00392 
00393 


arm_kinematics_constraint_aware
Author(s): Sachin Chitta
autogenerated on Mon Dec 2 2013 12:38:08