cartesian_planner.cpp
Go to the documentation of this file.
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     // construct the compact response from the detailed one
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     // Load solver if not already loaded
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     // if we have path constraints, we prefer interpolating in pose space
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     // Generate Interpolated Cartesian Poses
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     // Generate Cartesian Trajectory
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         //Do IK and report results
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     // Check if planner was terminated
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     // Check if traj is a collision free path
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     // Required position change
00248     Eigen::Vector3d delta_translation = (stop.translation() - start.translation());
00249     Eigen::Vector3d start_pos = start.translation();
00250     Eigen::Affine3d stop_prime = start.inverse()*stop; //This the stop pose represented in the start pose coordinate system
00251     Eigen::AngleAxisd delta_rotation(stop_prime.rotation());
00252     //delta_rotation.fromRotationMatrix(stop_prime.rotation())
00253 
00254 
00255     // Calculate number of steps
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     // Step size
00261     Eigen::Vector3d step = delta_translation / steps;
00262 
00263     // Orientation interpolation
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 } //namespace constrained_ik
00283 


constrained_ik
Author(s): Chris Lewis , Jeremy Zoss , Dan Solomon
autogenerated on Sat Jun 8 2019 19:23:45