Newer
Older
#include <ur_kinematics/ur_moveit_plugin.h>
#include <geometry_msgs/PoseStamped.h>
#include <ros/ros.h>
#include <pluginlib/class_list_macros.h>
#include <ur_kinematics/ur_kin.h>
#include <limits>
//register URKinematicsPlugin as a KinematicsBase implementation
PLUGINLIB_EXPORT_CLASS(ur_kinematics::URKinematicsPlugin,kinematics::KinematicsBase);
URKinematicsPlugin::URKinematicsPlugin()
: kdl_kinematics_plugin::KDLKinematicsPlugin(), ik_weights_(6) {}
bool URKinematicsPlugin::searchPositionIK(const geometry_msgs::Pose &ik_pose,
const std::vector<double> &ik_seed_state,
double timeout,
std::vector<double> &solution,
const IKCallbackFn &solution_callback,
moveit_msgs::MoveItErrorCodes &error_code,
const std::vector<double> &consistency_limits,
const kinematics::KinematicsQueryOptions &options) const
KDL::Frame kdl_ik_pose;
tf::poseMsgToKDL(ik_pose, kdl_ik_pose);
double homo_ik_pose[4][4];
kdl_ik_pose.Make4x4((double*) homo_ik_pose);
for(int i=0; i<3; i++) homo_ik_pose[i][3] *= 1000;
double q_ik_sols[8][6]; // maximum of 8 IK solutions
uint16_t num_sols = inverse((double*) homo_ik_pose, (double*) q_ik_sols, ik_seed_state[5]);
if(num_sols <= 0) {
// NO SOLUTION
error_code.val = error_code.NO_IK_SOLUTION;
return false;
}
std::vector<int> tried_solutions;
while(true) {
// use weighted absolute deviations to determine the solution closest the seed state
double min_weighted_diff = std::numeric_limits<double>::infinity();
int min_diff_index = -1;
for(uint16_t i=0; i<num_sols; i++) {
if(std::find(tried_solutions.begin(), tried_solutions.end(), i) != tried_solutions.end())
continue;
double cur_weighted_diff = 0;
for(uint16_t j=0; j<6; j++) {
// solution violates the consistency_limits, throw it out
if(std::fabs(ik_seed_state[j] - q_ik_sols[i][j]) > consistency_limits[j]) {
cur_weighted_diff = std::numeric_limits<double>::infinity();
break;
}
cur_weighted_diff += ik_weights_[j] * std::fabs(q_ik_sols[i][j] - ik_seed_state[j]);
}
if(cur_weighted_diff != std::numeric_limits<double>::infinity() &&
cur_weighted_diff < min_weighted_diff) {
min_weighted_diff = cur_weighted_diff;
min_diff_index = i;
}
if(min_diff_index < 0) {
// NO SOLUTION, failed consistency_limits/solution_callback
error_code.val = error_code.NO_IK_SOLUTION;
return false;
// copy the best solution to the output
solution.resize(6);
std::copy(q_ik_sols[min_diff_index], q_ik_sols[min_diff_index+1], solution.begin());
if(!solution_callback.empty())
solution_callback(ik_pose, solution, error_code);
else
error_code.val = error_code.SUCCESS;
if(error_code.val == error_code.SUCCESS)
return true;
tried_solutions.push_back(min_diff_index);
}
/**
* @brief Initialization function for the kinematics
* @return True if initialization was successful, false otherwise
*/
bool URKinematicsPlugin::initialize(const std::string& robot_description,
const std::string& group_name,
const std::string& base_frame,
const std::string& tip_frame,
double search_discretization)
{
ros::NodeHandle private_handle("~");
if(private_handle.hasParam("ik_weights")) {
private_handle.getParam("ik_weights", ik_weights_);
} else {
ik_weights_[0] = 1.0;
ik_weights_[1] = 1.0;
ik_weights_[2] = 0.1;
ik_weights_[3] = 0.1;
ik_weights_[4] = 0.3;
ik_weights_[5] = 0.3;
}
return kdl_kinematics_plugin::KDLKinematicsPlugin::initialize(
robot_description, group_name, base_frame, tip_frame, search_discretization);
}