utils.cpp
Go to the documentation of this file.
1 
29 #include <Eigen/Eigenvalues>
31 
35 
36 namespace tesseract_kinematics
37 {
38 void numericalJacobian(Eigen::Ref<Eigen::MatrixXd> jacobian,
39  const Eigen::Isometry3d& change_base,
41  const Eigen::Ref<const Eigen::VectorXd>& joint_values,
42  const std::string& link_name,
43  const Eigen::Ref<const Eigen::Vector3d>& link_point)
44 {
45  Eigen::VectorXd njvals;
46  double delta = 1e-8;
47  tesseract_common::TransformMap poses = kin.calcFwdKin(joint_values);
48  Eigen::Isometry3d pose{ change_base * poses[link_name] };
49 
50  for (int i = 0; i < static_cast<int>(joint_values.size()); ++i)
51  {
52  njvals = joint_values;
53  njvals[i] += delta;
54  Eigen::Isometry3d updated_pose = kin.calcFwdKin(njvals)[link_name];
55  updated_pose = change_base * updated_pose;
56 
57  Eigen::Vector3d temp{ pose * link_point };
58  Eigen::Vector3d temp2{ updated_pose * link_point };
59  jacobian(0, i) = (temp2.x() - temp.x()) / delta;
60  jacobian(1, i) = (temp2.y() - temp.y()) / delta;
61  jacobian(2, i) = (temp2.z() - temp.z()) / delta;
62 
63  Eigen::Vector3d omega = (pose.rotation() * tesseract_common::calcRotationalError(pose.rotation().transpose() *
64  updated_pose.rotation())) /
65  delta;
66  jacobian(3, i) = omega(0);
67  jacobian(4, i) = omega(1);
68  jacobian(5, i) = omega(2);
69  }
70 }
71 
72 void numericalJacobian(Eigen::Ref<Eigen::MatrixXd> jacobian,
73  const Eigen::Isometry3d& change_base,
74  const JointGroup& joint_group,
75  const Eigen::Ref<const Eigen::VectorXd>& joint_values,
76  const std::string& link_name,
77  const Eigen::Ref<const Eigen::Vector3d>& link_point)
78 {
79  Eigen::VectorXd njvals;
80  constexpr double delta = 1e-8;
81  tesseract_common::TransformMap poses = joint_group.calcFwdKin(joint_values);
82  Eigen::Isometry3d pose = change_base * poses[link_name];
83 
84  for (int i = 0; i < static_cast<int>(joint_values.size()); ++i)
85  {
86  njvals = joint_values;
87  njvals(i) += delta; // NOLINT
88  tesseract_common::TransformMap updated_poses = joint_group.calcFwdKin(njvals);
89  Eigen::Isometry3d updated_pose = change_base * updated_poses[link_name];
90 
91  Eigen::Vector3d temp = pose * link_point;
92  Eigen::Vector3d temp2 = updated_pose * link_point;
93  jacobian(0, i) = (temp2.x() - temp.x()) / delta;
94  jacobian(1, i) = (temp2.y() - temp.y()) / delta;
95  jacobian(2, i) = (temp2.z() - temp.z()) / delta;
96 
97  Eigen::VectorXd omega = (pose.rotation() * tesseract_common::calcRotationalError(pose.rotation().transpose() *
98  updated_pose.rotation())) /
99  delta;
100  jacobian(3, i) = omega(0);
101  jacobian(4, i) = omega(1);
102  jacobian(5, i) = omega(2);
103  }
104 }
105 
106 bool solvePInv(const Eigen::Ref<const Eigen::MatrixXd>& A,
107  const Eigen::Ref<const Eigen::VectorXd>& b,
108  Eigen::Ref<Eigen::VectorXd> x)
109 {
110  const double eps = 0.00001; // TODO: Turn into class member var
111  const double lambda = 0.01; // TODO: Turn into class member var
112 
113  if ((A.rows() == 0) || (A.cols() == 0))
114  {
115  CONSOLE_BRIDGE_logError("Empty matrices not supported in solvePinv()");
116  return false;
117  }
118 
119  if (A.rows() != b.size())
120  {
121  CONSOLE_BRIDGE_logError("Matrix size mismatch: A(%d, %d), b(%d)", A.rows(), A.cols(), b.size());
122  return false;
123  }
124 
125  // Calculate A+ (pseudoinverse of A) = V S+ U*, where U* is Hermition of U (just transpose if all values of U are
126  // real)
127  // in order to solve Ax=b -> x*=A+ b
128  Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
129  const Eigen::MatrixXd& U = svd.matrixU();
130  const Eigen::VectorXd& Sv = svd.singularValues();
131  const Eigen::MatrixXd& V = svd.matrixV();
132 
133  // calculate the reciprocal of Singular-Values
134  // damp inverse with lambda so that inverse doesn't oscillate near solution
135  long int nSv = Sv.size();
136  Eigen::VectorXd inv_Sv(nSv);
137  for (long int i = 0; i < nSv; ++i)
138  {
139  if (fabs(Sv(i)) > eps)
140  inv_Sv(i) = 1 / Sv(i);
141  else
142  inv_Sv(i) = Sv(i) / (Sv(i) * Sv(i) + lambda * lambda);
143  }
144  x = V * inv_Sv.asDiagonal() * U.transpose() * b;
145  return true;
146 }
147 
148 bool dampedPInv(const Eigen::Ref<const Eigen::MatrixXd>& A, Eigen::Ref<Eigen::MatrixXd> P, double eps, double lambda)
149 {
150  if ((A.rows() == 0) || (A.cols() == 0))
151  {
152  CONSOLE_BRIDGE_logError("Empty matrices not supported in dampedPInv()");
153  return false;
154  }
155 
156  // Calculate A+ (pseudoinverse of A) = V S+ U*, where U* is Hermition of U (just transpose if all values of U are
157  // real)
158  // in order to solve Ax=b -> x*=A+ b
159  Eigen::JacobiSVD<Eigen::MatrixXd> svd(A, Eigen::ComputeThinU | Eigen::ComputeThinV);
160  const Eigen::MatrixXd& U = svd.matrixU();
161  const Eigen::VectorXd& Sv = svd.singularValues();
162  const Eigen::MatrixXd& V = svd.matrixV();
163 
164  // calculate the reciprocal of Singular-Values
165  // damp inverse with lambda so that inverse doesn't oscillate near solution
166  long int nSv = Sv.size();
167  Eigen::VectorXd inv_Sv(nSv);
168  for (long int i = 0; i < nSv; ++i)
169  {
170  if (fabs(Sv(i)) > eps)
171  inv_Sv(i) = 1 / Sv(i);
172  else
173  {
174  inv_Sv(i) = Sv(i) / (Sv(i) * Sv(i) + lambda * lambda);
175  }
176  }
177  P = V * inv_Sv.asDiagonal() * U.transpose();
178  return true;
179 }
180 
181 bool isNearSingularity(const Eigen::Ref<const Eigen::MatrixXd>& jacobian, double threshold)
182 {
183  Eigen::JacobiSVD<Eigen::MatrixXd> svd(jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
184  const Eigen::VectorXd& sv = svd.singularValues();
185  return (sv.tail(1).value() < threshold);
186 }
187 
188 Manipulability calcManipulability(const Eigen::Ref<const Eigen::MatrixXd>& jacobian)
189 {
190  Manipulability manip;
191  Eigen::MatrixXd jacob_linear = jacobian.topRows(3);
192  Eigen::MatrixXd jacob_angular = jacobian.bottomRows(3);
193 
194  auto fn = [](const Eigen::MatrixXd& m) {
196  Eigen::SelfAdjointEigenSolver<Eigen::MatrixXd> sm(m, Eigen::DecompositionOptions::EigenvaluesOnly);
197  data.eigen_values = sm.eigenvalues().real();
198 
199  // Set eigenvalues near zero to zero. This also implies zero volume
200  for (Eigen::Index i = 0; i < data.eigen_values.size(); ++i) // NOLINT(modernize-loop-convert)
201  {
203  data.eigen_values[i] = +0;
204  }
205 
206  // If the minimum eigen value is approximately zero set measure and condition to max double
208  {
209  data.measure = std::numeric_limits<double>::max();
210  data.condition = std::numeric_limits<double>::max();
211  }
212  else
213  {
214  data.condition = data.eigen_values.maxCoeff() / data.eigen_values.minCoeff();
215  data.measure = std::sqrt(data.condition);
216  }
217 
218  data.volume = std::sqrt(data.eigen_values.prod());
219 
220  return data;
221  };
222 
223  Eigen::MatrixXd a = jacobian * jacobian.transpose();
224  Eigen::MatrixXd a_linear = jacob_linear * jacob_linear.transpose();
225  Eigen::MatrixXd a_angular = jacob_angular * jacob_angular.transpose();
226  manip.m = fn(a);
227  manip.m_linear = fn(a_linear);
228  manip.m_angular = fn(a_angular);
229 
230  // NOLINTNEXTLINE
231  Eigen::MatrixXd a_inv = a.inverse();
232  Eigen::MatrixXd a_linear_inv = a_linear.inverse();
233  Eigen::MatrixXd a_angular_inv = a_angular.inverse();
234  manip.f = fn(a_inv);
235  manip.f_linear = fn(a_linear_inv);
236  manip.f_angular = fn(a_angular_inv);
237 
238  return manip;
239 }
240 } // namespace tesseract_kinematics
tesseract_kinematics::ForwardKinematics
Forward kinematics functions.
Definition: forward_kinematics.h:43
tesseract_kinematics::isNearSingularity
bool isNearSingularity(const Eigen::Ref< const Eigen::MatrixXd > &jacobian, double threshold=0.01)
Check if the provided jacobian is near a singularity.
Definition: utils.cpp:181
tesseract_kinematics::numericalJacobian
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.cpp:38
tesseract_kinematics::Manipulability::m_linear
ManipulabilityEllipsoid m_linear
Linear velocity manipulability ellipsoid.
Definition: utils.h:154
tesseract_kinematics::calcManipulability
Manipulability calcManipulability(const Eigen::Ref< const Eigen::MatrixXd > &jacobian)
Calculate manipulability data about the provided jacobian.
Definition: utils.cpp:188
tesseract_kinematics::Manipulability::f_linear
ManipulabilityEllipsoid f_linear
Linear force manipulability ellipsoid.
Definition: utils.h:163
tesseract_common::TransformMap
AlignedMap< std::string, Eigen::Isometry3d > TransformMap
tesseract_common::almostEqualRelativeAndAbs
bool almostEqualRelativeAndAbs(const Eigen::Ref< const Eigen::VectorXd > &v1, const Eigen::Ref< const Eigen::VectorXd > &v2, const Eigen::Ref< const Eigen::VectorXd > &max_diff, const Eigen::Ref< const Eigen::VectorXd > &max_rel_diff)
tesseract_kinematics::JointGroup
A Joint Group is defined by a list of joint_names.
Definition: joint_group.h:44
TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
#define TESSERACT_COMMON_IGNORE_WARNINGS_PUSH
joint_group.h
A joint group with forward kinematics, Jacobian, limits methods.
tesseract_common::calcRotationalError
Eigen::Vector3d calcRotationalError(const Eigen::Ref< const Eigen::Matrix3d > &R)
utils.h
Kinematics utility functions.
tesseract_kinematics::ManipulabilityEllipsoid::measure
double measure
The ratio of longest and shortes axes of the manipulability ellipsoid.
Definition: utils.h:130
tesseract_kinematics::ManipulabilityEllipsoid::volume
double volume
This is propotial to the volume.
Definition: utils.h:140
tesseract_kinematics::ManipulabilityEllipsoid::condition
double condition
The condition number of A.
Definition: utils.h:137
tesseract_kinematics::Manipulability::m_angular
ManipulabilityEllipsoid m_angular
Angular velocity manipulability ellipsoid.
Definition: utils.h:157
tesseract_kinematics::Manipulability
Contains both manipulability ellipsoid and force ellipsoid data.
Definition: utils.h:144
tesseract_kinematics::ManipulabilityEllipsoid::eigen_values
EIGEN_MAKE_ALIGNED_OPERATOR_NEW Eigen::VectorXd eigen_values
The manipulability ellipsoid eigen values.
Definition: utils.h:121
tesseract_kinematics::ForwardKinematics::calcFwdKin
virtual tesseract_common::TransformMap calcFwdKin(const Eigen::Ref< const Eigen::VectorXd > &joint_angles) const =0
Calculates the transform for each tip link in the kinematic group.
tesseract_kinematics::Manipulability::m
EIGEN_MAKE_ALIGNED_OPERATOR_NEW ManipulabilityEllipsoid m
Full Manipulability Ellipsoid.
Definition: utils.h:151
forward_kinematics.h
Forward kinematics functions.
tesseract_kinematics::dampedPInv
bool dampedPInv(const Eigen::Ref< const Eigen::MatrixXd > &A, Eigen::Ref< Eigen::MatrixXd > P, double eps=0.011, double lambda=0.01)
Calculate Damped Pseudoinverse Use this SVD to compute A+ (pseudoinverse of A). Weighting still TBD.
Definition: utils.cpp:148
TESSERACT_COMMON_IGNORE_WARNINGS_POP
#define TESSERACT_COMMON_IGNORE_WARNINGS_POP
tesseract_kinematics::Manipulability::f_angular
ManipulabilityEllipsoid f_angular
Angular momentum manipulability ellipsoid.
Definition: utils.h:166
tesseract_kinematics::ManipulabilityEllipsoid
Used to store Manipulability and Force Ellipsoid data.
Definition: utils.h:114
tesseract_kinematics
Definition: forward_kinematics.h:40
tesseract_kinematics::JointGroup::calcFwdKin
tesseract_common::TransformMap calcFwdKin(const Eigen::Ref< const Eigen::VectorXd > &joint_angles) const
Calculates tool pose of robot chain.
Definition: joint_group.cpp:126
macros.h
tesseract_kinematics::Manipulability::f
ManipulabilityEllipsoid f
Full Force Ellipsoid.
Definition: utils.h:160
tesseract_kinematics::solvePInv
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.cpp:106


tesseract_kinematics
Author(s): Levi Armstrong
autogenerated on Sun May 18 2025 03:02:14