33 #include <boost/date_time.hpp> 34 #include <Eigen/Geometry> 43 TRAC_IK::TRAC_IK(
const std::string& base_link,
const std::string& tip_link,
const std::string& URDF_param,
double _maxtime,
double _eps,
SolveType _type) :
53 std::string xml_string;
55 std::string urdf_xml, full_urdf_xml;
56 node_handle.
param(
"urdf_xml", urdf_xml, URDF_param);
60 if (!node_handle.
getParam(full_urdf_xml, xml_string))
62 ROS_FATAL_NAMED(
"trac_ik",
"Could not load the xml from parameter server: %s", urdf_xml.c_str());
66 node_handle.
param(full_urdf_xml, xml_string, std::string());
74 ROS_FATAL(
"Failed to extract kdl tree from xml robot description");
76 if (!tree.
getChain(base_link, tip_link, chain))
77 ROS_FATAL(
"Couldn't find chain %s to %s", base_link.c_str(), tip_link.c_str());
79 std::vector<KDL::Segment> chain_segs = chain.segments;
81 urdf::JointConstSharedPtr joint;
83 std::vector<double> l_bounds, u_bounds;
85 lb.resize(chain.getNrOfJoints());
86 ub.resize(chain.getNrOfJoints());
89 for (
unsigned int i = 0; i < chain_segs.size(); ++i)
91 joint = robot_model.getJoint(chain_segs[i].getJoint().
getName());
92 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED)
97 if (joint->type != urdf::Joint::CONTINUOUS)
101 lower = std::max(joint->limits->lower, joint->safety->soft_lower_limit);
102 upper = std::min(joint->limits->upper, joint->safety->soft_upper_limit);
106 lower = joint->limits->lower;
107 upper = joint->limits->upper;
117 lb(joint_num - 1) = lower;
118 ub(joint_num - 1) = upper;
122 lb(joint_num - 1) = std::numeric_limits<float>::lowest();
123 ub(joint_num - 1) = std::numeric_limits<float>::max();
125 ROS_DEBUG_STREAM_NAMED(
"trac_ik",
"IK Using joint " << joint->name <<
" " << lb(joint_num - 1) <<
" " << ub(joint_num - 1));
145 void TRAC_IK::initialize()
148 assert(chain.getNrOfJoints() == lb.data.size());
149 assert(chain.getNrOfJoints() == ub.data.size());
155 for (uint i = 0; i < chain.segments.size(); i++)
157 std::string type = chain.segments[i].getJoint().getTypeName();
158 if (type.find(
"Rot") != std::string::npos)
160 if (ub(types.size()) >= std::numeric_limits<float>::max() &&
161 lb(types.size()) <= std::numeric_limits<float>::lowest())
166 else if (type.find(
"Trans") != std::string::npos)
170 assert(types.size() == lb.data.size());
178 for (uint i = 0; i < solutions.size(); i++)
179 if (myEqual(sol, solutions[i]))
190 double diffangle = fmod(val - max, 2 *
M_PI);
192 val = max + diffangle - 2 *
M_PI;
198 double diffangle = fmod(min - val, 2 *
M_PI);
200 val = min - diffangle + 2 *
M_PI;
206 double new_target = target +
M_PI;
207 if (val > new_target)
210 double diffangle = fmod(val - new_target, 2 * M_PI);
212 val = new_target + diffangle - 2 *
M_PI;
215 new_target = target -
M_PI;
216 if (val < new_target)
219 double diffangle = fmod(new_target - val, 2 * M_PI);
221 val = new_target - diffangle + 2 *
M_PI;
226 template<
typename T1,
typename T2>
227 bool TRAC_IK::runSolver(T1& solver, T2& other_solver,
233 double fulltime = maxtime;
236 boost::posix_time::time_duration timediff;
241 timediff = boost::posix_time::microsec_clock::local_time() - start_time;
242 time_left = fulltime - timediff.total_nanoseconds() / 1000000000.0;
247 solver.setMaxtime(time_left);
249 int RC = solver.CartToJnt(seed, p_in, q_out, bounds);
256 normalize_limits(q_init, q_out);
259 normalize_seed(q_init, q_out);
263 if (unique_solution(q_out))
265 solutions.push_back(q_out);
266 uint curr_size = solutions.size();
267 errors.resize(curr_size);
273 penalty = manipPenalty(q_out);
274 err = penalty * TRAC_IK::ManipValue1(q_out);
277 penalty = manipPenalty(q_out);
278 err = penalty * TRAC_IK::ManipValue2(q_out);
281 err = TRAC_IK::JointErr(q_init, q_out);
285 errors[curr_size - 1] = std::make_pair(err, curr_size - 1);
290 if (!solutions.empty() && solvetype ==
Speed)
293 for (
unsigned int j = 0; j < seed.
data.size(); j++)
295 seed(j) = fRand(q_init(j) - 2 *
M_PI, q_init(j) + 2 *
M_PI);
297 seed(j) = fRand(lb(j), ub(j));
299 other_solver.abort();
301 solver.setMaxtime(fulltime);
312 bool improved =
false;
314 for (uint i = 0; i < lb.data.size(); i++)
320 double target = seed(i);
321 double val = solution(i);
342 bool improved =
false;
344 for (uint i = 0; i < lb.data.size(); i++)
350 double target = seed(i);
353 target = (ub(i) + lb(i)) / 2.0;
355 double val = solution(i);
375 double penalty = 1.0;
376 for (uint i = 0; i < arr.
data.size(); i++)
380 double range = ub(i) - lb(i);
381 penalty *= ((arr(i) - lb(i)) * (ub(i) - arr(i)) / (range * range));
383 return std::max(0.0, 1.0 -
exp(-1 * penalty));
391 jacsolver->JntToJac(arr, jac);
393 Eigen::JacobiSVD<Eigen::MatrixXd> svdsolver(jac.data);
394 Eigen::MatrixXd singular_values = svdsolver.singularValues();
397 for (
unsigned int i = 0; i < singular_values.rows(); ++i)
398 error *= singular_values(i, 0);
406 jacsolver->JntToJac(arr, jac);
408 Eigen::JacobiSVD<Eigen::MatrixXd> svdsolver(jac.data);
409 Eigen::MatrixXd singular_values = svdsolver.singularValues();
411 return singular_values.minCoeff() / singular_values.maxCoeff();
420 ROS_ERROR(
"TRAC-IK was not properly initialized with a valid chain or limits. IK cannot proceed");
425 start_time = boost::posix_time::microsec_clock::local_time();
435 task1 = std::thread(&TRAC_IK::runKDL,
this, q_init, p_in);
436 task2 = std::thread(&TRAC_IK::runNLOPT,
this, q_init, p_in);
441 if (solutions.empty())
451 std::sort(errors.rbegin(), errors.rend());
454 std::sort(errors.begin(), errors.end());
458 q_out = solutions[errors[0].second];
460 return solutions.size();
466 if (task1.joinable())
468 if (task2.joinable())
#define ROS_DEBUG_STREAM_NAMED(name, args)
URDF_EXPORT bool initString(const std::string &xmlstring)
KDL_PARSER_PUBLIC bool treeFromUrdfModel(const urdf::ModelInterface &robot_model, KDL::Tree &tree)
ROSCONSOLE_DECL void initialize()
std::string getName(void *handle)
#define ROS_DEBUG_NAMED(name,...)
bool searchParam(const std::string &key, std::string &result) const
bool param(const std::string ¶m_name, T ¶m_val, const T &default_val) const
bool getChain(const std::string &chain_root, const std::string &chain_tip, Chain &chain) const
bool getParam(const std::string &key, std::string &s) const
#define ROS_FATAL_NAMED(name,...)
void normalizeAngle(double &val, const double &min, const double &max)
dual_quaternion exp(dual_quaternion a)