00001
00002
00003 #include <string>
00004 #include <exception>
00005 #include <math.h>
00006
00007 #include <ros/ros.h>
00008 #include <urdf/model.h>
00009 #include <tf/transform_listener.h>
00010 #include <tf_conversions/tf_kdl.h>
00011 #include <tf/transform_datatypes.h>
00012 #include <kdl_parser/kdl_parser.hpp>
00013 #include <kdl/jntarray.hpp>
00014 #include <kdl/chainiksolverpos_nr_jl.hpp>
00015 #include <kdl/chainiksolvervel_wdls.hpp>
00016 #include <kdl/chainfksolverpos_recursive.hpp>
00017 #include <kinematics_msgs/GetPositionFK.h>
00018 #include <kinematics_msgs/GetPositionIK.h>
00019 #include <kinematics_msgs/GetKinematicSolverInfo.h>
00020 #include <kinematics_msgs/KinematicSolverInfo.h>
00021 #include <kdl_arm_kinematics/GetWeightedIK.h>
00022
00023 using std::string;
00024
00025 class Kinematics
00026 {
00027 public:
00028 class InitFailed : public std::runtime_error
00029 {
00030 public:
00031 InitFailed(const string &what)
00032 : std::runtime_error(what) {}
00033 };
00034
00035 Kinematics();
00036
00037 private:
00038 ros::NodeHandle nh, nh_private;
00039 std::string root_name, tip_name;
00040 KDL::JntArray joint_min, joint_max;
00041 KDL::Chain chain;
00042 unsigned int num_joints;
00043 int max_iterations;
00044 double epsilon;
00045 Eigen::MatrixXd default_weight_ts;
00046 Eigen::MatrixXd default_weight_js;
00047 double default_lambda;
00048
00049 ros::ServiceServer ik_service,ik_solver_info_service;
00050 ros::ServiceServer fk_service,fk_solver_info_service;
00051 ros::ServiceServer weighted_ik_service;
00052
00053 tf::TransformListener tf_listener;
00054
00055 kinematics_msgs::KinematicSolverInfo info;
00056
00057 void parseWeightParams(ros::NodeHandle &nh);
00058 bool loadModel(const std::string xml);
00059 bool readJoints(urdf::Model &robot_model);
00060 int getJointIndex(const std::string &name);
00061 int getKDLSegmentIndex(const std::string &name);
00062 bool solveCartToJnt(const KDL::JntArray &q_init, const KDL::Frame &q_in, KDL::JntArray &q_out,
00063 const KDL::Frame &tool_frame = KDL::Frame::Identity());
00064 bool solveCartToJnt(const KDL::JntArray &q_init, const KDL::Frame &q_in, KDL::JntArray &q_out,
00065 const KDL::Frame &tool_frame, const Eigen::MatrixXd &weight_ts,
00066 const Eigen::MatrixXd &weight_js, const double lambda);
00067 double calculateEps(const KDL::Frame &f, const KDL::Frame &ref,
00068 const Eigen::MatrixXd &weight=Eigen::MatrixXd::Identity(6,6));
00069 void initializeWeights(const kdl_arm_kinematics::KDLWeights &msg,
00070 Eigen::MatrixXd &weight_ts, Eigen::MatrixXd &weight_js, double &lambda);
00071
00077 bool getPositionIK(kinematics_msgs::GetPositionIK::Request &request,
00078 kinematics_msgs::GetPositionIK::Response &response);
00079
00085 bool getIKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request &request,
00086 kinematics_msgs::GetKinematicSolverInfo::Response &response);
00087
00093 bool getFKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request &request,
00094 kinematics_msgs::GetKinematicSolverInfo::Response &response);
00095
00101 bool getPositionFK(kinematics_msgs::GetPositionFK::Request &request,
00102 kinematics_msgs::GetPositionFK::Response &response);
00103
00104 bool getWeightedIK(kdl_arm_kinematics::GetWeightedIK::Request &request,
00105 kdl_arm_kinematics::GetWeightedIK::Response &response);
00106 };
00107
00108
00109
00110 Kinematics::Kinematics()
00111 : nh(),
00112 nh_private ("~"),
00113 default_weight_ts(Eigen::MatrixXd::Identity(6,6)),
00114 default_lambda(0.1)
00115 {
00116
00117 std::string urdf_xml, full_urdf_xml;
00118 nh_private.param("robot_description_name",urdf_xml,std::string("robot_description"));
00119 nh.searchParam(urdf_xml,full_urdf_xml);
00120 ROS_DEBUG("Reading xml file from parameter server");
00121 std::string result;
00122 if (!nh.getParam(full_urdf_xml, result))
00123 throw Kinematics::InitFailed("Could not load the xml from parameter server: " + urdf_xml);
00124
00125
00126 if (!nh_private.getParam("root_name", root_name))
00127 throw Kinematics::InitFailed("GenericIK: No root name found on parameter server");
00128
00129 if (!nh_private.getParam("tip_name", tip_name))
00130 throw Kinematics::InitFailed("GenericIK: No tip name found on parameter server");
00131
00132
00133 if (!loadModel(result))
00134 throw Kinematics::InitFailed("Could not load models!");
00135
00136 default_weight_js = Eigen::MatrixXd::Identity(chain.getNrOfJoints(), chain.getNrOfJoints());
00137 parseWeightParams(nh_private);
00138
00139 nh_private.param("maxIterations", max_iterations, 100);
00140 nh_private.param("epsilon", epsilon, 1e-2);
00141
00142 ROS_INFO("Advertising services");
00143 fk_service = nh_private.advertiseService("get_fk", &Kinematics::getPositionFK,this);
00144 ik_service = nh_private.advertiseService("get_ik", &Kinematics::getPositionIK,this);
00145 ik_solver_info_service = nh_private.advertiseService("get_ik_solver_info", &Kinematics::getIKSolverInfo,this);
00146 fk_solver_info_service = nh_private.advertiseService("get_fk_solver_info", &Kinematics::getFKSolverInfo,this);
00147 weighted_ik_service = nh_private.advertiseService("get_weighted_ik", &Kinematics::getWeightedIK, this);
00148 }
00149
00150 void Kinematics::parseWeightParams(ros::NodeHandle &nh)
00151 {
00152 ros::NodeHandle weights_nh(nh, "weights");
00153
00154 if(weights_nh.hasParam("lambda"))
00155 {
00156 weights_nh.getParam("lambda", default_lambda);
00157 ROS_INFO("Setting lambda to %lf", default_lambda);
00158 }
00159
00160 if(weights_nh.hasParam("weight_ts"))
00161 {
00162 ros::NodeHandle weight_ts_nh(weights_nh, "weight_ts");
00163 double value;
00164
00165 if(weight_ts_nh.getParam("x", value))
00166 {
00167 ROS_INFO("Reading weight_ts/x: %lf", value);
00168 default_weight_ts(0,0) = value;
00169 }
00170
00171 if(weight_ts_nh.getParam("y", value))
00172 {
00173 ROS_INFO("Reading weight_ts/y: %lf", value);
00174 default_weight_ts(1,1) = value;
00175 }
00176
00177 if(weight_ts_nh.getParam("z", value))
00178 {
00179 ROS_INFO("Reading weight_ts/z: %lf", value);
00180 default_weight_ts(2,2) = value;
00181 }
00182
00183 if(weight_ts_nh.getParam("roll", value))
00184 {
00185 ROS_INFO("Reading weight_ts/roll: %lf", value);
00186 default_weight_ts(3,3) = value;
00187 }
00188
00189 if(weight_ts_nh.getParam("pitch", value))
00190 {
00191 ROS_INFO("Reading weight_ts/pitch: %lf", value);
00192 default_weight_ts(4,4) = value;
00193 }
00194
00195 if(weight_ts_nh.getParam("yaw", value))
00196 {
00197 ROS_INFO("Reading weight_ts/yaw: %lf", value);
00198 default_weight_ts(5,5) = value;
00199 }
00200 }
00201
00202 if(weights_nh.hasParam("weight_js"))
00203 {
00204 ros::NodeHandle weight_js_nh(weights_nh, "weight_js");
00205 double value;
00206
00207 for (unsigned int i=0; i < info.joint_names.size(); i++)
00208 {
00209 if(weight_js_nh.getParam(info.joint_names[i], value))
00210 {
00211 ROS_INFO("Setting weight for joint '%s' to %lf", info.joint_names[i].c_str(), value);
00212 default_weight_js(i, i) = value;
00213 }
00214 }
00215 }
00216 }
00217
00218 bool Kinematics::loadModel(const std::string xml) {
00219 urdf::Model robot_model;
00220 KDL::Tree tree;
00221
00222 if (!robot_model.initString(xml)) {
00223 ROS_FATAL("Could not initialize robot model");
00224 return -1;
00225 }
00226 if (!kdl_parser::treeFromString(xml, tree)) {
00227 ROS_ERROR("Could not initialize tree object");
00228 return false;
00229 }
00230 if (!tree.getChain(root_name, tip_name, chain)) {
00231 ROS_ERROR("Could not initialize chain object");
00232 return false;
00233 }
00234
00235 if (!readJoints(robot_model)) {
00236 ROS_FATAL("Could not read information about the joints");
00237 return false;
00238 }
00239
00240 return true;
00241 }
00242
00243 bool Kinematics::readJoints(urdf::Model &robot_model) {
00244 num_joints = 0;
00245
00246 boost::shared_ptr<const urdf::Link> link = robot_model.getLink(tip_name);
00247 boost::shared_ptr<const urdf::Joint> joint;
00248
00249 while (link && link->name != root_name) {
00250 joint = robot_model.getJoint(link->parent_joint->name);
00251 if (!joint) {
00252 ROS_ERROR("Could not find joint: %s",link->parent_joint->name.c_str());
00253 return false;
00254 }
00255 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00256 ROS_INFO( "adding joint: [%s]", joint->name.c_str() );
00257 num_joints++;
00258 }
00259 link = robot_model.getLink(link->getParent()->name);
00260 }
00261
00262 joint_min.resize(num_joints);
00263 joint_max.resize(num_joints);
00264 info.joint_names.resize(num_joints);
00265 info.link_names.clear();
00266 info.limits.resize(num_joints);
00267
00268 link = robot_model.getLink(tip_name);
00269 unsigned int i = 0;
00270 while (link && i < num_joints) {
00271 joint = robot_model.getJoint(link->parent_joint->name);
00272 info.link_names.push_back(link->name);
00273 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED) {
00274 ROS_INFO( "getting bounds for joint: [%s]", joint->name.c_str() );
00275
00276 float lower, upper;
00277 int hasLimits;
00278 if ( joint->type != urdf::Joint::CONTINUOUS ) {
00279 lower = joint->limits->lower;
00280 upper = joint->limits->upper;
00281 hasLimits = 1;
00282 } else {
00283 lower = -M_PI;
00284 upper = M_PI;
00285 hasLimits = 0;
00286 }
00287 int index = num_joints - i -1;
00288
00289 joint_min.data[index] = lower;
00290 joint_max.data[index] = upper;
00291 info.joint_names[index] = joint->name;
00292 info.limits[index].joint_name = joint->name;
00293 info.limits[index].has_position_limits = hasLimits;
00294 info.limits[index].min_position = lower;
00295 info.limits[index].max_position = upper;
00296 i++;
00297 }
00298 link = robot_model.getLink(link->getParent()->name);
00299 }
00300 return true;
00301 }
00302
00303
00304 int Kinematics::getJointIndex(const std::string &name) {
00305 for (unsigned int i=0; i < info.joint_names.size(); i++) {
00306 if (info.joint_names[i] == name)
00307 return i;
00308 }
00309 return -1;
00310 }
00311
00312 int Kinematics::getKDLSegmentIndex(const std::string &name) {
00313 int i=0;
00314 while (i < (int)chain.getNrOfSegments()) {
00315 if (chain.getSegment(i).getName() == name) {
00316 return i+1;
00317 }
00318 i++;
00319 }
00320 return -1;
00321 }
00322
00323 bool Kinematics::solveCartToJnt(const KDL::JntArray &q_init, const KDL::Frame &q_in, KDL::JntArray &q_out,
00324 const KDL::Frame &tool_frame)
00325 {
00326 return solveCartToJnt(q_init, q_in, q_out, tool_frame,
00327 default_weight_ts, default_weight_js, default_lambda);
00328 }
00329
00330 bool Kinematics::solveCartToJnt(const KDL::JntArray &q_init, const KDL::Frame &p_in, KDL::JntArray &q_out,
00331 const KDL::Frame &tool_frame, const Eigen::MatrixXd &weight_ts, const Eigen::MatrixXd &weight_js,
00332 const double lambda)
00333 {
00334 KDL::Frame f;
00335 KDL::JntArray delta_q;
00336 KDL::Twist delta_twist;
00337 int i;
00338 double err;
00339
00340 KDL::Chain chain_with_tool(chain);
00341 chain_with_tool.addSegment(KDL::Segment(KDL::Joint(KDL::Joint::None), tool_frame));
00342
00343 KDL::ChainFkSolverPos_recursive fk_solver(chain_with_tool);
00344 KDL::ChainIkSolverVel_wdls ik_solver(chain_with_tool);
00345
00346 ik_solver.setWeightTS(weight_ts);
00347 ik_solver.setWeightJS(weight_js);
00348 ik_solver.setLambda(lambda);
00349
00350 q_out = q_init;
00351
00352 for(i=0;i<max_iterations;i++)
00353 {
00354 fk_solver.JntToCart(q_out, f);
00355
00356 err = calculateEps(f, p_in, weight_ts);
00357
00358 if(isnan(err))
00359 {
00360 ROS_WARN("NaN in IK");
00361 return false;
00362 }
00363
00364 if( err < epsilon )
00365 break;
00366
00367 delta_twist = diff(f, p_in);
00368 ik_solver.CartToJnt(q_out, delta_twist, delta_q);
00369 KDL::Add(q_out, delta_q, q_out);
00370
00371 for(unsigned int j=0; j<joint_min.rows(); j++)
00372 {
00373 if(q_out(j) < joint_min(j))
00374 q_out(j) = joint_min(j);
00375 }
00376
00377 for(unsigned int j=0; j<joint_max.rows(); j++)
00378 {
00379 if(q_out(j) > joint_max(j))
00380 q_out(j) = joint_max(j);
00381 }
00382 }
00383
00384 ROS_INFO("IK terminating after %d iterations and error %lf", i, err);
00385
00386 if(i < max_iterations)
00387 return true;
00388 return false;
00389 }
00390
00391 double Kinematics::calculateEps(const KDL::Frame &f, const KDL::Frame &ref, const Eigen::MatrixXd &weight)
00392 {
00393 double f_roll, f_pitch, f_yaw;
00394 double ref_roll, ref_pitch, ref_yaw;
00395 f.M.GetRPY(f_roll, f_pitch, f_yaw);
00396 ref.M.GetRPY(ref_roll, ref_pitch, ref_yaw);
00397
00398 double x_diff = f.p.x() - ref.p.x();
00399 double y_diff = f.p.y() - ref.p.y();
00400 double z_diff = f.p.z() - ref.p.z();
00401 double roll_diff = f_roll - ref_roll;
00402 double pitch_diff = f_pitch - ref_pitch;
00403 double yaw_diff = f_yaw - ref_yaw;
00404
00405 return (x_diff * x_diff * weight(0, 0)) +
00406 (y_diff * y_diff * weight(1, 1)) +
00407 (z_diff * z_diff * weight(2, 2)) +
00408 (roll_diff * roll_diff * weight(3, 3)) +
00409 (pitch_diff * pitch_diff * weight(4, 4)) +
00410 (yaw_diff * yaw_diff * weight(5, 5));
00411 }
00412
00413 void Kinematics::initializeWeights(const kdl_arm_kinematics::KDLWeights &msg,
00414 Eigen::MatrixXd &weight_ts, Eigen::MatrixXd &weight_js, double &lambda)
00415 {
00416 if(msg.mode == kdl_arm_kinematics::KDLWeights::INVALID_MODE)
00417 {
00418 return;
00419 }
00420 if(msg.mode & kdl_arm_kinematics::KDLWeights::SET_TS)
00421 {
00422 for(int i=0, a=0; i<6; i++)
00423 {
00424 for(int j=0; j<6; j++, a++)
00425 weight_ts(i, j) = msg.weight_ts[a];
00426 }
00427 }
00428 if(msg.mode & kdl_arm_kinematics::KDLWeights::SET_JS)
00429 {
00430 int dim = sqrt(msg.weight_js.size());
00431 weight_js = Eigen::MatrixXd(dim, dim);
00432 for(int i=0, a=0; i<dim; i++)
00433 {
00434 for(int j=0; j<dim; j++, a++)
00435 weight_js(i, j) = msg.weight_js[a];
00436 }
00437 }
00438 if(msg.mode & kdl_arm_kinematics::KDLWeights::SET_LAMBDA)
00439 lambda = msg.lambda;
00440 }
00441
00442 bool Kinematics::getPositionIK(kinematics_msgs::GetPositionIK::Request &request,
00443 kinematics_msgs::GetPositionIK::Response &response) {
00444
00445 geometry_msgs::PoseStamped pose_msg_in = request.ik_request.pose_stamped;
00446 tf::Stamped<tf::Pose> transform;
00447 tf::Stamped<tf::Pose> transform_root;
00448 tf::poseStampedMsgToTF( pose_msg_in, transform );
00449
00450
00451 KDL::JntArray jnt_pos_in;
00452 KDL::JntArray jnt_pos_out;
00453 jnt_pos_in.resize(num_joints);
00454
00455 if(request.ik_request.ik_seed_state.joint_state.name.size() < num_joints ||
00456 request.ik_request.ik_seed_state.joint_state.position.size() < num_joints)
00457 {
00458 ROS_ERROR("Invalid seed state. It must contain states for all joints used by the IK solver.");
00459 return false;
00460 }
00461 for (unsigned int i=0; i < num_joints; i++) {
00462 int tmp_index = getJointIndex(request.ik_request.ik_seed_state.joint_state.name[i]);
00463 if (tmp_index >=0) {
00464 jnt_pos_in(tmp_index) = request.ik_request.ik_seed_state.joint_state.position[i];
00465 } else {
00466 ROS_ERROR("i: %d, No joint index for %s",i,request.ik_request.ik_seed_state.joint_state.name[i].c_str());
00467 return false;
00468 }
00469 }
00470
00471
00472 try {
00473 tf_listener.transformPose(root_name, transform, transform_root);
00474 } catch (...) {
00475 ROS_ERROR("Could not transform IK pose to frame: %s", root_name.c_str());
00476 response.error_code.val = response.error_code.FRAME_TRANSFORM_FAILURE;
00477 return false;
00478 }
00479
00480 KDL::Frame F_dest;
00481 tf::TransformTFToKDL(transform_root, F_dest);
00482
00483 if (solveCartToJnt(jnt_pos_in, F_dest, jnt_pos_out))
00484 {
00485 response.solution.joint_state.name = info.joint_names;
00486 response.solution.joint_state.position.resize(num_joints);
00487 for (unsigned int i=0; i < num_joints; i++)
00488 {
00489 response.solution.joint_state.position[i] = jnt_pos_out(i);
00490 ROS_INFO("IK Solution: %s %d: %f",response.solution.joint_state.name[i].c_str(),i,jnt_pos_out(i));
00491 }
00492 response.error_code.val = response.error_code.SUCCESS;
00493 return true;
00494 } else {
00495 ROS_INFO("An IK solution could not be found");
00496 response.error_code.val = response.error_code.NO_IK_SOLUTION;
00497 return true;
00498 }
00499 }
00500
00501 bool Kinematics::getIKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request &request,
00502 kinematics_msgs::GetKinematicSolverInfo::Response &response) {
00503 response.kinematic_solver_info = info;
00504 return true;
00505 }
00506
00507 bool Kinematics::getFKSolverInfo(kinematics_msgs::GetKinematicSolverInfo::Request &request,
00508 kinematics_msgs::GetKinematicSolverInfo::Response &response) {
00509 response.kinematic_solver_info = info;
00510 return true;
00511 }
00512
00513 bool Kinematics::getPositionFK(kinematics_msgs::GetPositionFK::Request &request,
00514 kinematics_msgs::GetPositionFK::Response &response) {
00515 KDL::Frame p_out;
00516 KDL::JntArray jnt_pos_in;
00517 geometry_msgs::PoseStamped pose;
00518 tf::Stamped<tf::Pose> tf_pose;
00519
00520 KDL::ChainFkSolverPos_recursive fk_solver(chain);
00521
00522 jnt_pos_in.resize(num_joints);
00523 for (unsigned int i=0; i < num_joints; i++) {
00524 int tmp_index = getJointIndex(request.robot_state.joint_state.name[i]);
00525 if (tmp_index >=0)
00526 jnt_pos_in(tmp_index) = request.robot_state.joint_state.position[i];
00527 }
00528
00529 response.pose_stamped.resize(request.fk_link_names.size());
00530 response.fk_link_names.resize(request.fk_link_names.size());
00531
00532 for (unsigned int i=0; i < request.fk_link_names.size(); i++) {
00533 int segmentIndex = getKDLSegmentIndex(request.fk_link_names[i]);
00534 ROS_DEBUG("End effector index: %d",segmentIndex);
00535 ROS_DEBUG("Chain indices: %d",chain.getNrOfSegments());
00536 if (fk_solver.JntToCart(jnt_pos_in,p_out,segmentIndex) >=0) {
00537 tf_pose.frame_id_ = root_name;
00538 tf_pose.stamp_ = ros::Time();
00539 tf::PoseKDLToTF(p_out,tf_pose);
00540 try {
00541 tf_listener.transformPose(request.header.frame_id,tf_pose,tf_pose);
00542 } catch (...) {
00543 ROS_ERROR("Could not transform FK pose to frame: %s",request.header.frame_id.c_str());
00544 response.error_code.val = arm_navigation_msgs::ArmNavigationErrorCodes::FRAME_TRANSFORM_FAILURE;
00545 return false;
00546 }
00547 tf::poseStampedTFToMsg(tf_pose,pose);
00548 response.pose_stamped[i] = pose;
00549 response.fk_link_names[i] = request.fk_link_names[i];
00550 response.error_code.val = response.error_code.SUCCESS;
00551 } else {
00552 ROS_ERROR("Could not compute FK for %s",request.fk_link_names[i].c_str());
00553 response.error_code.val = arm_navigation_msgs::ArmNavigationErrorCodes::NO_FK_SOLUTION;
00554 }
00555 }
00556 return true;
00557 }
00558
00559 bool Kinematics::getWeightedIK(kdl_arm_kinematics::GetWeightedIK::Request &request,
00560 kdl_arm_kinematics::GetWeightedIK::Response &response)
00561 {
00562 geometry_msgs::PoseStamped pose_msg_in = request.pose;
00563 tf::Stamped<tf::Pose> transform;
00564 tf::Stamped<tf::Pose> transform_root;
00565 tf::poseStampedMsgToTF( pose_msg_in, transform );
00566
00567
00568 KDL::JntArray jnt_pos_in;
00569 KDL::JntArray jnt_pos_out;
00570 jnt_pos_in.resize(num_joints);
00571
00572 if(request.ik_seed.name.size() < num_joints ||
00573 request.ik_seed.position.size() < num_joints)
00574 {
00575 ROS_ERROR("Invalid seed state. It must contain states for all joints used by the IK solver.");
00576 return false;
00577 }
00578 for (unsigned int i=0; i < num_joints; i++)
00579 {
00580 int tmp_index = getJointIndex(request.ik_seed.name[i]);
00581 if (tmp_index >=0)
00582 jnt_pos_in(tmp_index) = request.ik_seed.position[i];
00583 else
00584 {
00585 ROS_ERROR("i: %d, No joint index for %s",i,request.ik_seed.name[i].c_str());
00586 return false;
00587 }
00588 }
00589
00590
00591 try
00592 {
00593 tf_listener.transformPose(root_name, transform, transform_root);
00594 }
00595 catch (...)
00596 {
00597 ROS_ERROR("Could not transform IK pose to frame: %s", root_name.c_str());
00598 response.error_code.val = response.error_code.FRAME_TRANSFORM_FAILURE;
00599 return false;
00600 }
00601
00602 KDL::Frame F_dest;
00603 tf::TransformTFToKDL(transform_root, F_dest);
00604
00605 KDL::Frame tool;
00606 tf::PoseMsgToKDL(request.tool_frame, tool);
00607
00609 Eigen::MatrixXd weight_ts(default_weight_ts);
00610 Eigen::MatrixXd weight_js(default_weight_js);
00611 double lambda = default_lambda;
00612
00613 initializeWeights(request.weights, weight_ts, weight_js, lambda);
00614
00615 if (solveCartToJnt(jnt_pos_in, F_dest, jnt_pos_out, tool, weight_ts, weight_js, lambda))
00616 {
00617 response.solution.name = info.joint_names;
00618 response.solution.position.resize(num_joints);
00619 for (unsigned int i=0; i < num_joints; i++)
00620 {
00621 response.solution.position[i] = jnt_pos_out(i);
00622 ROS_INFO("IK Solution: %s %d: %f",response.solution.name[i].c_str(),i,jnt_pos_out(i));
00623 }
00624 response.error_code.val = response.error_code.SUCCESS;
00625 return true;
00626 } else {
00627 ROS_INFO("An IK solution could not be found");
00628 response.error_code.val = response.error_code.NO_IK_SOLUTION;
00629 return true;
00630 }
00631 }
00632
00633 int main(int argc, char **argv) {
00634 ros::init(argc, argv, "arm_kinematics");
00635 try
00636 {
00637 Kinematics k;
00638 ros::spin();
00639 }
00640 catch(Kinematics::InitFailed &e)
00641 {
00642 ROS_ERROR("Could not initialize kinematics node: %s", e.what());
00643 return -1;
00644 }
00645
00646 return 0;
00647 }
00648