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 #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
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
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