00001
00032 #include <constrained_ik/moveit_interface/cartesian_planner.h>
00033 #include <ros/ros.h>
00034 #include <eigen3/Eigen/Core>
00035 #include <eigen_conversions/eigen_msg.h>
00036 #include <moveit/robot_state/conversions.h>
00037 #include <constrained_ik/basic_kin.h>
00038
00039 namespace constrained_ik
00040 {
00041 CartesianPlanner::CartesianPlanner(const std::string &name, const std::string &group) :
00042 constrained_ik::CLIKPlanningContext(name, group),
00043 terminate_(false),
00044 robot_description_("robot_description")
00045 {
00046 solver_.reset(new Constrained_IK());
00047 std::string constraint_param = "constrained_ik_solver/" + getGroupName() + "/constraints";
00048 solver_->addConstraintsFromParamServer(constraint_param);
00049 }
00050
00051 bool CartesianPlanner::initializeSolver()
00052 {
00053 basic_kin::BasicKin kin;
00054 if (!kin.init(robot_model_->getJointModelGroup(getGroupName())))
00055 {
00056 ROS_ERROR("Cartesian planner could not load solver for move_group %s", getGroupName().c_str());
00057 return false;
00058 }
00059
00060 solver_->init(kin);
00061 return true;
00062 }
00063
00064 void CartesianPlanner::setSolverConfiguration(const ConstrainedIKConfiguration &config)
00065 {
00066 solver_->setSolverConfiguration(config);
00067 }
00068
00069 void CartesianPlanner::resetSolverConfiguration()
00070 {
00071 solver_->loadDefaultSolverConfiguration();
00072 }
00073
00074 bool CartesianPlanner::solve(planning_interface::MotionPlanDetailedResponse &res)
00075 {
00076 planning_interface::MotionPlanResponse response;
00077 bool success = solve(response);
00078
00079
00080 res.trajectory_.push_back(response.trajectory_);
00081 res.processing_time_.push_back(response.planning_time_);
00082 res.description_.push_back("Cartesian Constrained IK Planner");
00083 res.error_code_ = response.error_code_;
00084
00085 return success;
00086 }
00087
00088 bool CartesianPlanner::solve(planning_interface::MotionPlanResponse &res)
00089 {
00090 ros::WallTime start_time = ros::WallTime::now();
00091 robot_state::RobotStatePtr mid_state;
00092 std::vector<std::string> joint_names, link_names;
00093 Eigen::Affine3d start_pose, goal_pose;
00094
00095 robot_model_ = planning_scene_->getRobotModel();
00096
00097
00098 if(!solver_->isInitialized())
00099 if (!initializeSolver())
00100 return false;
00101
00102 robot_state::RobotState start_state(robot_model_);
00103 robot_state::robotStateMsgToRobotState(request_.start_state, start_state);
00104 robot_state::RobotState goal_state = start_state;
00105 robot_trajectory::RobotTrajectoryPtr traj(new robot_trajectory::RobotTrajectory(robot_model_, request_.group_name));
00106 const robot_model::JointModelGroup *jmg = robot_model_->getJointModelGroup(request_.group_name);
00107
00108 joint_names = jmg->getActiveJointModelNames();
00109 link_names = jmg->getLinkModelNames();
00110 start_pose = start_state.getGlobalLinkTransform(link_names.back());
00111
00112 ROS_INFO_STREAM("Cartesian Planning for Group: " << request_.group_name);
00113
00114 if (!request_.goal_constraints[0].joint_constraints.empty())
00115 {
00116 std::map<std::string, double> goal_joint_map;
00117 for (size_t i=0; i<request_.goal_constraints[0].joint_constraints.size(); ++i)
00118 {
00119 goal_joint_map[request_.goal_constraints[0].joint_constraints[i].joint_name] =
00120 request_.goal_constraints[0].joint_constraints[i].position;
00121 }
00122 goal_state.setVariablePositions(goal_joint_map);
00123 goal_state.update();
00124 goal_pose = goal_state.getGlobalLinkTransform(link_names.back());
00125 }
00126 else
00127 {
00128 geometry_msgs::Pose pose;
00129 if (!request_.goal_constraints[0].position_constraints.empty() && !request_.goal_constraints[0].orientation_constraints.empty())
00130 {
00131 pose.position = request_.goal_constraints[0].position_constraints[0].constraint_region.primitive_poses[0].position;
00132 pose.orientation = request_.goal_constraints[0].orientation_constraints[0].orientation;
00133 }
00134 else if (!request_.goal_constraints[0].position_constraints.empty() && request_.goal_constraints[0].orientation_constraints.empty())
00135 {
00136 tf::poseEigenToMsg(start_state.getGlobalLinkTransform(link_names.back()), pose);
00137 pose.position = request_.goal_constraints[0].position_constraints[0].constraint_region.primitive_poses[0].position;
00138 }
00139 else if (request_.goal_constraints[0].position_constraints.empty() && !request_.goal_constraints[0].orientation_constraints.empty())
00140 {
00141 tf::poseEigenToMsg(start_state.getGlobalLinkTransform(link_names.back()), pose);
00142 pose.orientation = request_.goal_constraints[0].orientation_constraints[0].orientation;
00143 }
00144 else
00145 {
00146 ROS_ERROR("No constraint was passed with request!");
00147 return false;
00148 }
00149 tf::poseMsgToEigen(pose, goal_pose);
00150 }
00151
00152 ROS_DEBUG_NAMED("clik", "Setting Position x from %f to %f", start_pose.translation()(0),goal_pose.translation()(0));
00153 ROS_DEBUG_NAMED("clik", "Setting Position y from %f to %f", start_pose.translation()(1),goal_pose.translation()(1));
00154 ROS_DEBUG_NAMED("clik", "Setting Position z from %f to %f", start_pose.translation()(2),goal_pose.translation()(2));
00155 ROS_DEBUG_NAMED("clik", "Setting Position yaw from %f to %f", start_pose.rotation().eulerAngles(3,2,1)(0),goal_pose.rotation().eulerAngles(3,2,1)(0));
00156 ROS_DEBUG_NAMED("clik", "Setting Position pitch from %f to %f", start_pose.rotation().eulerAngles(3,2,1)(1),goal_pose.rotation().eulerAngles(3,2,1)(1));
00157 ROS_DEBUG_NAMED("clik", "Setting Position roll from %f to %f", start_pose.rotation().eulerAngles(3,2,1)(2),goal_pose.rotation().eulerAngles(3,2,1)(2));
00158
00159
00160 Eigen::Affine3d world_to_base = start_state.getGlobalLinkTransform(solver_->getKin().getRobotBaseLinkName()).inverse();
00161 std::vector<Eigen::Affine3d, Eigen::aligned_allocator<Eigen::Affine3d> > poses = interpolateCartesian(
00162 world_to_base*start_pose, world_to_base*goal_pose, config_.translational_discretization_step, config_.orientational_discretization_step);
00163
00164
00165 int steps = poses.size();
00166 Eigen::VectorXd start_joints, joint_angles;
00167 bool found_ik;
00168 mid_state = robot_model::RobotStatePtr(new robot_model::RobotState(start_state));
00169 for (int j=0; j<steps; j++)
00170 {
00171 if (j!=0)
00172 {
00173 mid_state->copyJointGroupPositions(request_.group_name, start_joints);
00174
00175
00176 try
00177 {
00178 found_ik = solver_->calcInvKin(poses[j], start_joints, planning_scene_, joint_angles);
00179 mid_state->setJointGroupPositions(request_.group_name, joint_angles);
00180 mid_state->update();
00181 }
00182 catch (std::exception &e)
00183 {
00184 found_ik = false;
00185 ROS_ERROR_STREAM("Caught exception from IK: " << e.what());
00186 }
00187
00188 if (!found_ik || planning_scene_->isStateColliding(*mid_state, request_.group_name))
00189 {
00190 if (!config_.debug_mode)
00191 {
00192 ROS_INFO("Cartesian planner was unable to find a valid solution. :(");
00193 res.error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN;
00194 return false;
00195 }
00196 else
00197 {
00198 break;
00199 }
00200 }
00201
00202
00203 }
00204 traj->addSuffixWayPoint(*mid_state, 0.0);
00205
00206 if (terminate_)
00207 break;
00208
00209 res.planning_time_ = (ros::WallTime::now() - start_time).toSec();
00210 if (res.planning_time_ > request_.allowed_planning_time)
00211 {
00212 ROS_INFO("Cartesian planner was unable to find solution in allowed time. :(");
00213 res.error_code_.val = moveit_msgs::MoveItErrorCodes::TIMED_OUT;
00214 return false;
00215 }
00216 }
00217
00218
00219 if (terminate_)
00220 {
00221 ROS_INFO("Cartesian Trajectory was terminated!");
00222 res.error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN;
00223 return false;
00224 }
00225
00226
00227 if (planning_scene_->isPathValid(*traj, request_.group_name))
00228 {
00229 ROS_INFO("Cartesian Trajectory is collision free! :)");
00230 res.trajectory_=traj;
00231 res.error_code_.val = moveit_msgs::MoveItErrorCodes::SUCCESS;
00232 return true;
00233 }
00234 else
00235 {
00236 ROS_INFO("Cartesian Trajectory is not collision free. :(");
00237 res.error_code_.val = moveit_msgs::MoveItErrorCodes::INVALID_MOTION_PLAN;
00238 return false;
00239 }
00240 }
00241
00242 std::vector<Eigen::Affine3d, Eigen::aligned_allocator<Eigen::Affine3d> >
00243 CartesianPlanner::interpolateCartesian(const Eigen::Affine3d& start,
00244 const Eigen::Affine3d& stop,
00245 double ds, double dt) const
00246 {
00247
00248 Eigen::Vector3d delta_translation = (stop.translation() - start.translation());
00249 Eigen::Vector3d start_pos = start.translation();
00250 Eigen::Affine3d stop_prime = start.inverse()*stop;
00251 Eigen::AngleAxisd delta_rotation(stop_prime.rotation());
00252
00253
00254
00255
00256 unsigned steps_translation = static_cast<unsigned>(delta_translation.norm() / ds) + 1;
00257 unsigned steps_rotation = static_cast<unsigned>(delta_rotation.angle() / dt) + 1;
00258 unsigned steps = std::max(steps_translation, steps_rotation);
00259
00260
00261 Eigen::Vector3d step = delta_translation / steps;
00262
00263
00264 Eigen::Quaterniond start_q (start.rotation());
00265 Eigen::Quaterniond stop_q (stop.rotation());
00266 double slerp_ratio = 1.0 / steps;
00267
00268 std::vector<Eigen::Affine3d, Eigen::aligned_allocator<Eigen::Affine3d> > result;
00269 Eigen::Vector3d trans;
00270 Eigen::Quaterniond q;
00271 Eigen::Affine3d pose;
00272 result.reserve(steps+1);
00273 for (unsigned i = 0; i <= steps; ++i)
00274 {
00275 trans = start_pos + step * i;
00276 q = start_q.slerp(slerp_ratio * i, stop_q);
00277 pose = (Eigen::Translation3d(trans) * q);
00278 result.push_back(pose);
00279 }
00280 return result;
00281 }
00282 }
00283