00001
00026 #include "constrained_ik/moveit_interface/constrained_ik_plugin.h"
00027
00028 #include <ros/ros.h>
00029 #include <kdl_parser/kdl_parser.hpp>
00030 #include <tf_conversions/tf_kdl.h>
00031 #include <eigen_conversions/eigen_kdl.h>
00032 #include <pluginlib/class_list_macros.h>
00033 PLUGINLIB_EXPORT_CLASS(constrained_ik::ConstrainedIKPlugin, kinematics::KinematicsBase)
00034
00035 using namespace KDL;
00036 using namespace tf;
00037 using namespace std;
00038 using namespace ros;
00039
00040 namespace constrained_ik
00041 {
00042
00043 ConstrainedIKPlugin::ConstrainedIKPlugin():active_(false), dimension_(0)
00044 {
00045 }
00046
00047 bool ConstrainedIKPlugin::isActive() const
00048 {
00049 if(active_)
00050 return true;
00051 ROS_ERROR("kinematics not active");
00052 return false;
00053 }
00054
00055 bool ConstrainedIKPlugin::initialize(const std::string& robot_description,
00056 const std::string& group_name,
00057 const std::string& base_name,
00058 const std::string& tip_name,
00059 double search_discretization)
00060 {
00061 setValues(robot_description, group_name, base_name, tip_name, search_discretization);
00062
00063
00064 rdf_loader::RDFLoader rdf_loader(robot_description_);
00065 const boost::shared_ptr<srdf::Model> &srdf = rdf_loader.getSRDF();
00066 const boost::shared_ptr<urdf::ModelInterface>& urdf_model = rdf_loader.getURDF();
00067
00068 if (!urdf_model || !srdf)
00069 {
00070 ROS_ERROR_STREAM("URDF and SRDF must be loaded for Constrained Ik solver to work.");
00071 return false;
00072 }
00073
00074
00075 robot_model_ptr_.reset(new robot_model::RobotModel(urdf_model,srdf));
00076 if(!robot_model_ptr_)
00077 {
00078 ROS_ERROR_STREAM("Could not load URDF model from " << robot_description);
00079 active_ = false;
00080 return false;
00081 }
00082
00083 const robot_model::JointModelGroup* joint_model_group = robot_model_ptr_->getJointModelGroup(group_name);
00084 if (!joint_model_group)
00085 return false;
00086
00087 if (!joint_model_group->isChain())
00088 {
00089 ROS_ERROR_NAMED("clik", "Group '%s' is not a chain.", group_name.c_str());
00090 return false;
00091 }
00092
00093 robot_state_.reset(new moveit::core::RobotState(robot_model_ptr_));
00094
00095
00096 planning_scene_.reset(new planning_scene::PlanningScene(robot_model_ptr_));
00097
00098
00099 if (!kin_.init(joint_model_group))
00100 {
00101 ROS_ERROR("Could not initialize BasicIK");
00102 active_ = false;
00103 }
00104 else
00105 {
00106 dimension_ = kin_.numJoints();
00107 kin_.getJointNames(joint_names_);
00108 kin_.getLinkNames(link_names_);
00109 active_ = true;
00110 }
00111
00112 try
00113 {
00114 solver_.reset(new Constrained_IK());
00115 std::string constraint_param = "constrained_ik_solver/" + group_name + "/constraints";
00116 solver_->addConstraintsFromParamServer(constraint_param);
00117 solver_->init(kin_);
00118 }
00119 catch (exception &e)
00120 {
00121 ROS_ERROR_STREAM("Caught exception from solver_: " << e.what());
00122 return false;
00123 }
00124
00125 return active_;
00126 }
00127
00128 bool ConstrainedIKPlugin::getPositionIK(const geometry_msgs::Pose &ik_pose,
00129 const std::vector<double> &ik_seed_state,
00130 std::vector<double> &solution,
00131 moveit_msgs::MoveItErrorCodes &error_code,
00132 const kinematics::KinematicsQueryOptions &options) const
00133 {
00134
00135 if(!active_)
00136 {
00137 ROS_ERROR("kinematics not active");
00138 error_code.val = error_code.NO_IK_SOLUTION;
00139 return false;
00140 }
00141 if(ik_seed_state.size() != dimension_)
00142 {
00143 ROS_ERROR("ik_seed_state does not have same dimension as solver");
00144 error_code.val = error_code.NO_IK_SOLUTION;
00145 return false;
00146 }
00147
00148
00149 KDL::Frame pose_desired;
00150 tf::poseMsgToKDL(ik_pose, pose_desired);
00151 Eigen::Affine3d goal;
00152 tf::transformKDLToEigen(pose_desired, goal);
00153
00154 Eigen::VectorXd seed(dimension_), joint_angles(dimension_);
00155 for(size_t ii=0; ii < dimension_; ++ii)
00156 {
00157 seed(ii) = ik_seed_state[ii];
00158 }
00159
00160
00161 try
00162 {
00163 if(!solver_->calcInvKin(goal, seed, planning_scene_, joint_angles))
00164 {
00165 ROS_ERROR_STREAM("Unable to find IK solution.");
00166 error_code.val = error_code.NO_IK_SOLUTION;
00167 return false;
00168 }
00169 }
00170 catch (exception &e)
00171 {
00172 ROS_ERROR_STREAM("Caught exception from IK: " << e.what());
00173 error_code.val = error_code.NO_IK_SOLUTION;
00174 return false;
00175 }
00176 solution.resize(dimension_);
00177 for(size_t ii=0; ii < dimension_; ++ii)
00178 {
00179 solution[ii] = joint_angles(ii);
00180 }
00181
00182 return true;
00183
00184 }
00185
00186 bool ConstrainedIKPlugin::searchPositionIK( const geometry_msgs::Pose &ik_pose,
00187 const std::vector<double> &ik_seed_state,
00188 double timeout,
00189 std::vector<double> &solution,
00190 moveit_msgs::MoveItErrorCodes &error_code,
00191 const kinematics::KinematicsQueryOptions &options) const
00192 {
00193 static IKCallbackFn solution_callback = 0;
00194 static std::vector<double> consistency_limits;
00195 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code);
00196 }
00197
00198 bool ConstrainedIKPlugin::searchPositionIK( const geometry_msgs::Pose &ik_pose,
00199 const std::vector<double> &ik_seed_state,
00200 double timeout,
00201 const std::vector<double> &consistency_limits,
00202 std::vector<double> &solution,
00203 moveit_msgs::MoveItErrorCodes &error_code,
00204 const kinematics::KinematicsQueryOptions &options) const
00205 {
00206 static IKCallbackFn solution_callback = 0;
00207 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code);
00208 }
00209
00210 bool ConstrainedIKPlugin::searchPositionIK( const geometry_msgs::Pose &ik_pose,
00211 const std::vector<double> &ik_seed_state,
00212 double timeout,
00213 std::vector<double> &solution,
00214 const IKCallbackFn &solution_callback,
00215 moveit_msgs::MoveItErrorCodes &error_code,
00216 const kinematics::KinematicsQueryOptions &options) const
00217 {
00218 static std::vector<double> consistency_limits;
00219 return searchPositionIK(ik_pose, ik_seed_state, timeout, consistency_limits, solution, solution_callback, error_code);
00220 }
00221
00222 bool ConstrainedIKPlugin::searchPositionIK( const geometry_msgs::Pose &ik_pose,
00223 const std::vector<double> &ik_seed_state,
00224 double timeout,
00225 const std::vector<double> &consistency_limits,
00226 std::vector<double> &solution,
00227 const IKCallbackFn &solution_callback,
00228 moveit_msgs::MoveItErrorCodes &error_code,
00229 const kinematics::KinematicsQueryOptions &options) const
00230 {
00231
00232 if(!active_)
00233 {
00234 ROS_ERROR("kinematics not active");
00235 error_code.val = error_code.FAILURE;
00236 return false;
00237 }
00238
00239 KDL::Frame pose_desired;
00240 tf::poseMsgToKDL(ik_pose, pose_desired);
00241 Eigen::Affine3d goal;
00242 tf::transformKDLToEigen(pose_desired, goal);
00243
00244 if(dimension_ != ik_seed_state.size()){
00245 ROS_ERROR("dimension_ and ik_seed_state are of different sizes");
00246 return(false);
00247 }
00248 Eigen::VectorXd seed(dimension_), joint_angles;
00249 for(size_t ii=0; ii < dimension_; ii++)
00250 {
00251 seed(ii) = ik_seed_state[ii];
00252 }
00253
00254
00255 bool success(true);
00256 try
00257 {
00258 if(!solver_->calcInvKin(goal, seed, planning_scene_, joint_angles))
00259 {
00260 ROS_ERROR_STREAM("Unable to find IK solution.");
00261 error_code.val = error_code.NO_IK_SOLUTION;
00262 success &= false;
00263 }
00264 }
00265 catch (exception &e)
00266 {
00267 ROS_ERROR_STREAM("Caught exception from IK: " << e.what());
00268 error_code.val = error_code.NO_IK_SOLUTION;
00269 success &= false;
00270 }
00271
00272 solution.resize(dimension_);
00273 for(size_t ii=0; ii < dimension_; ++ii)
00274 {
00275 solution[ii] = joint_angles(ii);
00276 }
00277
00278
00279 if (solution_callback)
00280 {
00281 solution_callback(ik_pose, solution, error_code);
00282 if(error_code.val != error_code.SUCCESS)
00283 success &= false;
00284 }
00285
00286 if (success)
00287 error_code.val = error_code.SUCCESS;
00288
00289 return success;
00290
00291 }
00292
00293 bool ConstrainedIKPlugin::getPositionFK(const std::vector<std::string> &link_names,
00294 const std::vector<double> &joint_angles,
00295 std::vector<geometry_msgs::Pose> &poses) const
00296 {
00297 if(!active_)
00298 {
00299 ROS_ERROR("kinematics not active");
00300 return false;
00301 }
00302
00303 Eigen::VectorXd jnt_pos_in;
00304 geometry_msgs::PoseStamped pose;
00305 tf::Stamped<tf::Pose> tf_pose;
00306
00307 jnt_pos_in.resize(dimension_);
00308 for(int i=0; i < dimension_; i++)
00309 {
00310 jnt_pos_in(i) = joint_angles[i];
00311 }
00312
00313 poses.resize(link_names.size());
00314
00315 std::vector<KDL::Frame> kdl_poses;
00316 bool valid = kin_.linkTransforms(jnt_pos_in, kdl_poses, link_names);
00317 for(size_t ii=0; ii < kdl_poses.size(); ++ii)
00318 {
00319 tf::poseKDLToMsg(kdl_poses[ii],poses[ii]);
00320 }
00321
00322 ROS_INFO_STREAM("poses: ");
00323 for (size_t ii=0; ii<poses.size(); ++ii)
00324 {
00325 ROS_INFO_STREAM(poses[ii]);
00326 }
00327 return valid;
00328 }
00329
00330 const std::vector<std::string>& ConstrainedIKPlugin::getJointNames() const
00331 {
00332 isActive();
00333 return joint_names_;
00334 }
00335
00336 const std::vector<std::string>& ConstrainedIKPlugin::getLinkNames() const
00337 {
00338 isActive();
00339 return link_names_;
00340 }
00341
00342 }