26#ifndef TESSERACT_KINEMATICS_UTILS_H
27#define TESSERACT_KINEMATICS_UTILS_H
33#include <Eigen/Geometry>
34#include <Eigen/Eigenvalues>
35#include <console_bridge/console.h>
44template <
typename FloatType>
45using VectorX = Eigen::Matrix<FloatType, Eigen::Dynamic, 1>;
56 const Eigen::Isometry3d& change_base,
58 const Eigen::Ref<const Eigen::VectorXd>& joint_values,
59 const std::string& link_name,
60 const Eigen::Ref<const Eigen::Vector3d>& link_point)
62 Eigen::VectorXd njvals;
65 Eigen::Isometry3d
pose{ change_base * poses[link_name] };
67 for (
int i = 0; i < static_cast<int>(joint_values.size()); ++i)
69 njvals = joint_values;
71 Eigen::Isometry3d updated_pose =
kin.calcFwdKin(njvals)[link_name];
72 updated_pose = change_base * updated_pose;
74 Eigen::Vector3d temp{
pose * link_point };
75 Eigen::Vector3d temp2{ updated_pose * link_point };
76 jacobian(0, i) = (temp2.x() - temp.x()) / delta;
77 jacobian(1, i) = (temp2.y() - temp.y()) / delta;
78 jacobian(2, i) = (temp2.z() - temp.z()) / delta;
81 updated_pose.rotation())) /
99 const Eigen::Ref<const Eigen::VectorXd>& joint_values,
100 const std::string& link_name,
101 const Eigen::Ref<const Eigen::Vector3d>& link_point)
103 Eigen::VectorXd njvals;
106 Eigen::Isometry3d
pose = poses[link_name];
108 for (
int i = 0; i < static_cast<int>(joint_values.size()); ++i)
110 njvals = joint_values;
113 Eigen::Isometry3d updated_pose = updated_poses[link_name];
115 Eigen::Vector3d temp =
pose * link_point;
116 Eigen::Vector3d temp2 = updated_pose * link_point;
117 jacobian(0, i) = (temp2.x() - temp.x()) / delta;
118 jacobian(1, i) = (temp2.y() - temp.y()) / delta;
119 jacobian(2, i) = (temp2.z() - temp.z()) / delta;
122 updated_pose.rotation())) /
138inline static bool solvePInv(
const Eigen::Ref<const Eigen::MatrixXd>& A,
139 const Eigen::Ref<const Eigen::VectorXd>& b,
140 Eigen::Ref<Eigen::VectorXd> x)
142 const double eps = 0.00001;
143 const double lambda = 0.01;
145 if ((A.rows() == 0) || (A.cols() == 0))
147 CONSOLE_BRIDGE_logError(
"Empty matrices not supported in solvePinv()");
151 if (A.rows() != b.size())
153 CONSOLE_BRIDGE_logError(
"Matrix size mismatch: A(%d, %d), b(%d)", A.rows(), A.cols(), b.size());
160 Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
161 const Eigen::MatrixXd& U = svd.matrixU();
162 const Eigen::VectorXd& Sv = svd.singularValues();
163 const Eigen::MatrixXd& V = svd.matrixV();
167 long int nSv = Sv.size();
168 Eigen::VectorXd inv_Sv(nSv);
169 for (
long int i = 0; i < nSv; ++i)
171 if (fabs(Sv(i)) > eps)
172 inv_Sv(i) = 1 / Sv(i);
174 inv_Sv(i) = Sv(i) / (Sv(i) * Sv(i) + lambda * lambda);
176 x = V * inv_Sv.asDiagonal() * U.transpose() * b;
189inline static bool dampedPInv(
const Eigen::Ref<const Eigen::MatrixXd>& A,
190 Eigen::Ref<Eigen::MatrixXd> P,
191 const double eps = 0.011,
192 const double lambda = 0.01)
194 if ((A.rows() == 0) || (A.cols() == 0))
196 CONSOLE_BRIDGE_logError(
"Empty matrices not supported in dampedPInv()");
203 Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
204 const Eigen::MatrixXd& U = svd.matrixU();
205 const Eigen::VectorXd& Sv = svd.singularValues();
206 const Eigen::MatrixXd& V = svd.matrixV();
210 long int nSv = Sv.size();
211 Eigen::VectorXd inv_Sv(nSv);
212 for (
long int i = 0; i < nSv; ++i)
214 if (fabs(Sv(i)) > eps)
215 inv_Sv(i) = 1 / Sv(i);
218 inv_Sv(i) = Sv(i) / (Sv(i) * Sv(i) + lambda * lambda);
221 P = V * inv_Sv.asDiagonal() * U.transpose();
235 Eigen::JacobiSVD<Eigen::MatrixXd> svd(
jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
236 const Eigen::VectorXd& sv = svd.singularValues();
237 return (sv.tail(1).value() < threshold);
244 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
274 EIGEN_MAKE_ALIGNED_OPERATOR_NEW
304 Eigen::MatrixXd jacob_linear =
jacobian.topRows(3);
305 Eigen::MatrixXd jacob_angular =
jacobian.bottomRows(3);
307 auto fn = [](
const Eigen::MatrixXd&
m) {
309 Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> sm(
m, Eigen::DecompositionOptions::EigenvaluesOnly);
310 data.eigen_values = sm.eigenvalues().real();
313 for (Eigen::Index i = 0; i <
data.eigen_values.size(); ++i)
316 data.eigen_values[i] = +0;
322 data.measure = std::numeric_limits<double>::max();
323 data.condition = std::numeric_limits<double>::max();
327 data.condition =
data.eigen_values.maxCoeff() /
data.eigen_values.minCoeff();
328 data.measure = std::sqrt(
data.condition);
331 data.volume = std::sqrt(
data.eigen_values.prod());
337 Eigen::MatrixXd a_linear = jacob_linear * jacob_linear.transpose();
338 Eigen::MatrixXd a_angular = jacob_angular * jacob_angular.transpose();
343 Eigen::MatrixXd a_inv = a.inverse();
344 Eigen::MatrixXd a_linear_inv = a_linear.inverse();
345 Eigen::MatrixXd a_angular_inv = a_angular.inverse();
357template <
typename FloatType>
359 const Eigen::Ref<const Eigen::VectorXd>& sol,
360 const Eigen::MatrixX2d&
limits,
361 std::vector<Eigen::Index>::const_iterator current_index,
362 std::vector<Eigen::Index>::const_iterator end_index)
365 for (; current_index != end_index; ++current_index)
367 if (std::isinf(
limits(*current_index, 0)))
369 std::stringstream ss;
370 ss <<
"Lower limit of joint " << *current_index <<
" is infinite; no redundant solutions will be generated"
372 CONSOLE_BRIDGE_logWarn(ss.str().c_str());
376 val = sol[*current_index];
377 while ((val -= (2.0 * M_PI)) >
limits(*current_index, 0) ||
381 if (val <
limits(*current_index, 1) ||
384 Eigen::VectorXd new_sol = sol;
385 new_sol[*current_index] = val;
390 redundant_sols.push_back(new_sol.template cast<FloatType>());
393 getRedundantSolutionsHelper<FloatType>(redundant_sols, new_sol,
limits, current_index + 1, end_index);
398 if (std::isinf(
limits(*current_index, 1)))
400 std::stringstream ss;
401 ss <<
"Upper limit of joint " << *current_index <<
" is infinite; no redundant solutions will be generated"
403 CONSOLE_BRIDGE_logWarn(ss.str().c_str());
407 val = sol[*current_index];
408 while ((val += (2.0 * M_PI)) <
limits(*current_index, 1) ||
412 if (val >
limits(*current_index, 0) ||
415 Eigen::VectorXd new_sol = sol;
416 new_sol[*current_index] = val;
421 redundant_sols.push_back(new_sol.template cast<FloatType>());
424 getRedundantSolutionsHelper<FloatType>(redundant_sols, new_sol,
limits, current_index + 1, end_index);
438template <
typename FloatType>
440 const Eigen::MatrixX2d&
limits,
441 const std::vector<Eigen::Index>& redundancy_capable_joints)
443 if (redundancy_capable_joints.empty())
446 for (
const Eigen::Index& idx : redundancy_capable_joints)
448 if (idx >= sol.size())
450 std::stringstream ss;
451 ss <<
"Redundant joint index " << idx <<
" is greater than or equal to the joint state size (" << sol.size()
453 throw std::runtime_error(ss.str());
457 std::vector<VectorX<FloatType>> redundant_sols;
458 getRedundantSolutionsHelper<FloatType>(redundant_sols,
459 sol.template cast<double>(),
461 redundancy_capable_joints.begin(),
462 redundancy_capable_joints.end());
463 return redundant_sols;
475template <
typename FloatType>
476inline bool isValid(
const std::array<FloatType, 6>& qs)
478 for (
const auto&
q : qs)
479 if (!std::isfinite(
q))
490template <
typename FloatType>
492 const std::vector<Eigen::Index>& redundancy_capable_joints)
494 const static auto pi = FloatType(M_PI);
495 const static auto two_pi = FloatType(2.0 * M_PI);
497 for (
const auto& i : redundancy_capable_joints)
499 FloatType diff = std::fmod(qs[i] +
pi, two_pi);
500 qs[i] = (diff < 0) ? (diff +
pi) : (diff -
pi);
Forward kinematics functions.
Definition: forward_kinematics.h:47
A Joint Group is defined by a list of joint_names.
Definition: joint_group.h:43
tesseract_common::TransformMap calcFwdKin(const Eigen::Ref< const Eigen::VectorXd > &joint_angles) const
Calculates tool pose of robot chain.
Definition: joint_group.cpp:115
CollisionMarginData data(default_margin)
Definition: collision_margin_data_unit.cpp:34
Forward kinematics functions.
A basic scene graph using boost.
A kinematic group with forward and inverse kinematics methods.
tesseract_kinematics::Manipulability m
Definition: kinematics_core_unit.cpp:179
q[0]
Definition: kinematics_core_unit.cpp:15
Eigen::MatrixXd jacobian
Definition: kinematics_core_unit.cpp:153
auto kin
Definition: kinematics_factory_unit.cpp:1165
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
Definition: macros.h:71
Definition: create_convex_hull.cpp:36
template void enforcePositionLimits< double >(Eigen::Ref< Eigen::Matrix< double, Eigen::Dynamic, 1 > > joint_positions, const Eigen::Ref< const Eigen::Matrix< double, Eigen::Dynamic, 2 > > &position_limits)
template bool satisfiesPositionLimits< double >(const Eigen::Ref< const Eigen::Matrix< double, Eigen::Dynamic, 1 > > &joint_positions, const Eigen::Ref< const Eigen::Matrix< double, Eigen::Dynamic, 2 > > &position_limits, double max_diff, double max_rel_diff)
AlignedMap< std::string, Eigen::Isometry3d > TransformMap
Definition: types.h:66
Eigen::Vector3d calcRotationalError(const Eigen::Ref< const Eigen::Matrix3d > &R)
Calculate the rotation error vector given a rotation error matrix where the angle is between [-pi,...
Definition: utils.cpp:124
bool almostEqualRelativeAndAbs(double a, double b, double max_diff=1e-6, double max_rel_diff=std::numeric_limits< double >::epsilon())
Check if two double are relatively equal.
Definition: utils.cpp:393
Definition: forward_kinematics.h:44
void getRedundantSolutionsHelper(std::vector< VectorX< FloatType > > &redundant_sols, const Eigen::Ref< const Eigen::VectorXd > &sol, const Eigen::MatrixX2d &limits, std::vector< Eigen::Index >::const_iterator current_index, std::vector< Eigen::Index >::const_iterator end_index)
This a recursive function for calculating all permutations of the redundant solutions.
Definition: utils.h:358
static bool dampedPInv(const Eigen::Ref< const Eigen::MatrixXd > &A, Eigen::Ref< Eigen::MatrixXd > P, const double eps=0.011, const double lambda=0.01)
Calculate Damped Pseudoinverse Use this SVD to compute A+ (pseudoinverse of A). Weighting still TBD.
Definition: utils.h:189
bool isValid(const std::array< FloatType, 6 > &qs)
Given a vector of floats, this check if they are finite.
Definition: utils.h:476
std::vector< VectorX< FloatType > > getRedundantSolutions(const Eigen::Ref< const VectorX< FloatType > > &sol, const Eigen::MatrixX2d &limits, const std::vector< Eigen::Index > &redundancy_capable_joints)
Kinematics only return solution between PI and -PI. Provided the limits it will append redundant solu...
Definition: utils.h:439
static void numericalJacobian(Eigen::Ref< Eigen::MatrixXd > jacobian, const Eigen::Isometry3d &change_base, const tesseract_kinematics::ForwardKinematics &kin, const Eigen::Ref< const Eigen::VectorXd > &joint_values, const std::string &link_name, const Eigen::Ref< const Eigen::Vector3d > &link_point)
Numerically calculate a jacobian. This is mainly used for testing.
Definition: utils.h:55
void harmonizeTowardZero(Eigen::Ref< VectorX< FloatType > > qs, const std::vector< Eigen::Index > &redundancy_capable_joints)
This take an array of floats and modifies them in place to be between [-PI, PI].
Definition: utils.h:491
Eigen::Matrix< FloatType, Eigen::Dynamic, 1 > VectorX
Definition: utils.h:45
static bool solvePInv(const Eigen::Ref< const Eigen::MatrixXd > &A, const Eigen::Ref< const Eigen::VectorXd > &b, Eigen::Ref< Eigen::VectorXd > x)
Solve equation Ax=b for x Use this SVD to compute A+ (pseudoinverse of A). Weighting still TBD.
Definition: utils.h:138
Manipulability calcManipulability(const Eigen::Ref< const Eigen::MatrixXd > &jacobian)
Calculate manipulability data about the provided jacobian.
Definition: utils.h:301
bool isNearSingularity(const Eigen::Ref< const Eigen::MatrixXd > &jacobian, double threshold=0.01)
Check if the provided jacobian is near a singularity.
Definition: utils.h:233
Used to store Manipulability and Force Ellipsoid data.
Definition: utils.h:242
double volume
This is propotial to the volume.
Definition: utils.h:267
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Eigen::VectorXd eigen_values
The manipulability ellipsoid eigen values.
Definition: utils.h:248
double condition
The condition number of A.
Definition: utils.h:264
double measure
The ratio of longest and shortes axes of the manipulability ellipsoid.
Definition: utils.h:257
Contains both manipulability ellipsoid and force ellipsoid data.
Definition: utils.h:272
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ManipulabilityEllipsoid m
Full Manipulability Ellipsoid.
Definition: utils.h:278
ManipulabilityEllipsoid f
Full Force Ellipsoid.
Definition: utils.h:287
ManipulabilityEllipsoid f_linear
Linear force manipulability ellipsoid.
Definition: utils.h:290
ManipulabilityEllipsoid f_angular
Angular momentum manipulability ellipsoid.
Definition: utils.h:293
ManipulabilityEllipsoid m_angular
Angular velocity manipulability ellipsoid.
Definition: utils.h:284
ManipulabilityEllipsoid m_linear
Linear velocity manipulability ellipsoid.
Definition: utils.h:281
auto pose
Definition: tesseract_environment_collision.cpp:118
joint_1 limits
Definition: tesseract_scene_graph_joint_unit.cpp:153
JointGroup joint_group
Definition: tesseract_srdf_unit.cpp:1805