ur_inv_kin.cpp
Go to the documentation of this file.
1 /*********************************************************************
2  *
3  * Provides forward and inverse kinematics for Univeral robot designs
4  * Author: Kelsey Hawkins (kphawkins@gatech.edu)
5  *
6  * Software License Agreement (BSD License)
7  *
8  * Copyright (c) 2013, Georgia Institute of Technology
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  *
15  * * Redistributions of source code must retain the above copyright
16  * notice, this list of conditions and the following disclaimer.
17  * * Redistributions in binary form must reproduce the above
18  * copyright notice, this list of conditions and the following
19  * disclaimer in the documentation and/or other materials provided
20  * with the distribution.
21  * * Neither the name of the Georgia Institute of Technology nor the names of
22  * its contributors may be used to endorse or promote products derived
23  * from this software without specific prior written permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
26  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
27  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
28  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
29  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
30  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
31  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
32  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
33  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36  * POSSIBILITY OF SUCH DAMAGE.
37  *********************************************************************/
40 
41 static const std::vector<Eigen::Index> REDUNDANT_CAPABLE_JOINTS{ 0, 1, 2, 3, 4, 5 };
42 
43 namespace tesseract_kinematics
44 {
45 // LCOV_EXCL_START
46 namespace
47 {
48 const double ZERO_THRESH = 0.00000001;
49 int SIGN(double x) { return (x > 0) - (x < 0); } // NOLINT
50 const double PI = M_PI;
51 } // namespace
52 
53 int inverse(const Eigen::Isometry3d& T, const URParameters& params, double* q_sols, double q6_des)
54 {
55  int num_sols = 0;
56  double T02 = T(0, 2);
57  double T00 = T(0, 0);
58  double T01 = T(0, 1);
59  double T03 = T(0, 3);
60  double T12 = T(1, 2);
61  double T10 = T(1, 0);
62  double T11 = T(1, 1);
63  double T13 = T(1, 3);
64  double T22 = T(2, 2);
65  double T20 = T(2, 0);
66  double T21 = T(2, 1);
67  double T23 = T(2, 3);
68 
70  double q1[2]; // NOLINT
71  {
72  double A = params.d6 * T12 - T13;
73  double B = params.d6 * T02 - T03;
74  double R = A * A + B * B;
75  if (fabs(A) < ZERO_THRESH)
76  {
77  double div{ 0 };
78  if (fabs(fabs(params.d4) - fabs(B)) < ZERO_THRESH)
79  div = -SIGN(params.d4) * SIGN(B);
80  else
81  div = -params.d4 / B;
82  double arcsin = asin(div);
83  if (fabs(arcsin) < ZERO_THRESH)
84  arcsin = 0.0;
85  if (arcsin < 0.0)
86  q1[0] = arcsin + 2.0 * PI;
87  else
88  q1[0] = arcsin;
89  q1[1] = PI - arcsin;
90  }
91  else if (fabs(B) < ZERO_THRESH)
92  {
93  double div{ 0 };
94  if (fabs(fabs(params.d4) - fabs(A)) < ZERO_THRESH)
95  div = SIGN(params.d4) * SIGN(A);
96  else
97  div = params.d4 / A;
98  double arccos = acos(div);
99  q1[0] = arccos;
100  q1[1] = 2.0 * PI - arccos;
101  }
102  else if (params.d4 * params.d4 > R)
103  {
104  return num_sols;
105  }
106  else
107  {
108  double arccos = acos(params.d4 / sqrt(R));
109  double arctan = atan2(-B, A);
110  double pos = arccos + arctan;
111  double neg = -arccos + arctan;
112  if (fabs(pos) < ZERO_THRESH)
113  pos = 0.0;
114  if (fabs(neg) < ZERO_THRESH)
115  neg = 0.0;
116  if (pos >= 0.0)
117  q1[0] = pos;
118  else
119  q1[0] = 2.0 * PI + pos;
120  if (neg >= 0.0)
121  q1[1] = neg;
122  else
123  q1[1] = 2.0 * PI + neg;
124  }
125  }
127 
129  double q5[2][2]; // NOLINT
130  {
131  for (int i = 0; i < 2; i++)
132  {
133  double numer = (T03 * sin(q1[i]) - T13 * cos(q1[i]) - params.d4);
134  double div{ 0 };
135  if (fabs(fabs(numer) - fabs(params.d6)) < ZERO_THRESH)
136  div = SIGN(numer) * SIGN(params.d6);
137  else
138  div = numer / params.d6;
139  double arccos = acos(div);
140  q5[i][0] = arccos;
141  q5[i][1] = 2.0 * PI - arccos;
142  }
143  }
145 
146  {
147  for (int i = 0; i < 2; i++)
148  {
149  for (int j = 0; j < 2; j++)
150  {
151  double c1 = cos(q1[i]), s1 = sin(q1[i]);
152  double c5 = cos(q5[i][j]), s5 = sin(q5[i][j]);
153  double q6{ 0 };
155  if (fabs(s5) < ZERO_THRESH)
156  q6 = q6_des;
157  else
158  {
159  q6 = atan2(SIGN(s5) * -(T01 * s1 - T11 * c1), SIGN(s5) * (T00 * s1 - T10 * c1));
160  if (fabs(q6) < ZERO_THRESH)
161  q6 = 0.0;
162  if (q6 < 0.0)
163  q6 += 2.0 * PI;
164  }
166 
167  double q2[2], q3[2], q4[2]; // NOLINT
169  double c6 = cos(q6), s6 = sin(q6);
170  double x04x = -s5 * (T02 * c1 + T12 * s1) - c5 * (s6 * (T01 * c1 + T11 * s1) - c6 * (T00 * c1 + T10 * s1));
171  double x04y = c5 * (T20 * c6 - T21 * s6) - T22 * s5;
172  double p13x = params.d5 * (s6 * (T00 * c1 + T10 * s1) + c6 * (T01 * c1 + T11 * s1)) -
173  params.d6 * (T02 * c1 + T12 * s1) + T03 * c1 + T13 * s1;
174  double p13y = T23 - params.d1 - params.d6 * T22 + params.d5 * (T21 * c6 + T20 * s6);
175 
176  double c3 =
177  (p13x * p13x + p13y * p13y - params.a2 * params.a2 - params.a3 * params.a3) / (2.0 * params.a2 * params.a3);
178  if (fabs(fabs(c3) - 1.0) < ZERO_THRESH)
179  c3 = SIGN(c3);
180  else if (fabs(c3) > 1.0)
181  {
182  // TODO NO SOLUTION
183  continue;
184  }
185  double arccos = acos(c3);
186  q3[0] = arccos;
187  q3[1] = 2.0 * PI - arccos;
188  double denom = params.a2 * params.a2 + params.a3 * params.a3 + 2 * params.a2 * params.a3 * c3;
189  double s3 = sin(arccos);
190  double A = (params.a2 + params.a3 * c3), B = params.a3 * s3;
191  q2[0] = atan2((A * p13y - B * p13x) / denom, (A * p13x + B * p13y) / denom);
192  q2[1] = atan2((A * p13y + B * p13x) / denom, (A * p13x - B * p13y) / denom);
193  double c23_0 = cos(q2[0] + q3[0]);
194  double s23_0 = sin(q2[0] + q3[0]);
195  double c23_1 = cos(q2[1] + q3[1]);
196  double s23_1 = sin(q2[1] + q3[1]);
197  q4[0] = atan2(c23_0 * x04y - s23_0 * x04x, x04x * c23_0 + x04y * s23_0);
198  q4[1] = atan2(c23_1 * x04y - s23_1 * x04x, x04x * c23_1 + x04y * s23_1);
200  for (int k = 0; k < 2; k++)
201  {
202  if (fabs(q2[k]) < ZERO_THRESH)
203  q2[k] = 0.0;
204  else if (q2[k] < 0.0)
205  q2[k] += 2.0 * PI;
206  if (fabs(q4[k]) < ZERO_THRESH)
207  q4[k] = 0.0;
208  else if (q4[k] < 0.0)
209  q4[k] += 2.0 * PI;
210  q_sols[num_sols * 6 + 0] = q1[i];
211  q_sols[num_sols * 6 + 1] = q2[k];
212  q_sols[num_sols * 6 + 2] = q3[k];
213  q_sols[num_sols * 6 + 3] = q4[k];
214  q_sols[num_sols * 6 + 4] = q5[i][j];
215  q_sols[num_sols * 6 + 5] = q6;
216  num_sols++;
217  }
218  }
219  }
220  }
221  return num_sols;
222 }
223 // LCOV_EXCL_STOP
224 
226  std::string base_link_name,
227  std::string tip_link_name,
228  std::vector<std::string> joint_names,
229  std::string solver_name)
230  : params_(params)
231  , base_link_name_(std::move(base_link_name))
232  , tip_link_name_(std::move(tip_link_name))
233  , joint_names_(std::move(joint_names))
234  , solver_name_(std::move(solver_name))
235 {
236  if (joint_names_.size() != 6)
237  throw std::runtime_error("OPWInvKin, only support six joints!");
238 }
239 
240 InverseKinematics::UPtr URInvKin::clone() const { return std::make_unique<URInvKin>(*this); }
241 
242 URInvKin::URInvKin(const URInvKin& other) { *this = other; }
243 
245 {
248  joint_names_ = other.joint_names_;
249  params_ = other.params_;
250  solver_name_ = other.solver_name_;
251 
252  return *this;
253 }
254 
256  const Eigen::Ref<const Eigen::VectorXd>& /*seed*/) const
257 {
258  assert(tip_link_poses.size() == 1);
259  assert(tip_link_poses.find(tip_link_name_) != tip_link_poses.end());
260  assert(std::abs(1.0 - tip_link_poses.at(tip_link_name_).matrix().determinant()) < 1e-6); // NOLINT
261 
262  Eigen::Isometry3d base_offset = Eigen::Isometry3d::Identity() * Eigen::AngleAxisd(M_PI, Eigen::Vector3d::UnitZ());
263  Eigen::Isometry3d corrected_pose = base_offset.inverse() * tip_link_poses.at(tip_link_name_);
264 
265  // Do the analytic IK
266  // NOLINTNEXTLINE
267  std::array<std::array<double, 6>, 8> sols; // maximum of 8 IK solutions
268  auto num_sols = static_cast<std::size_t>(inverse(corrected_pose, params_, sols[0].data(), 0));
269 
270  // Check the output
271  IKSolutions solution_set;
272  solution_set.reserve(num_sols);
273  for (std::size_t i = 0; i < num_sols; ++i)
274  {
275  Eigen::Map<Eigen::VectorXd> eigen_sol(sols[i].data(), static_cast<Eigen::Index>(sols[i].size()));
276 
277  // Harmonize between [-PI, PI]
278  harmonizeTowardZero<double>(eigen_sol, REDUNDANT_CAPABLE_JOINTS); // Modifies 'sol' in place
279 
280  // Add solution
281  solution_set.emplace_back(eigen_sol);
282  }
283 
284  return solution_set;
285 }
286 
287 Eigen::Index URInvKin::numJoints() const { return 6; }
288 std::vector<std::string> URInvKin::getJointNames() const { return joint_names_; }
289 std::string URInvKin::getBaseLinkName() const { return base_link_name_; }
290 std::string URInvKin::getWorkingFrame() const { return base_link_name_; }
291 std::vector<std::string> URInvKin::getTipLinkNames() const { return { tip_link_name_ }; }
292 std::string URInvKin::getSolverName() const { return solver_name_; }
293 
294 } // namespace tesseract_kinematics
tesseract_kinematics::URInvKin::getJointNames
std::vector< std::string > getJointNames() const override final
Get list of joint names for kinematic object.
Definition: ur_inv_kin.cpp:288
tesseract_kinematics::URInvKin::URInvKin
URInvKin(const URInvKin &other)
Definition: ur_inv_kin.cpp:242
tesseract_common::TransformMap
AlignedMap< std::string, Eigen::Isometry3d > TransformMap
tesseract_kinematics::URParameters::d5
double d5
Definition: types.h:53
ur_inv_kin.h
tesseract_kinematics::URInvKin::getSolverName
std::string getSolverName() const override final
Get the name of the solver. Recommend using the name of the class.
Definition: ur_inv_kin.cpp:292
tesseract_kinematics::URInvKin::operator=
URInvKin & operator=(const URInvKin &other)
Definition: ur_inv_kin.cpp:244
tesseract_kinematics::URInvKin::getBaseLinkName
std::string getBaseLinkName() const override final
Get the robot base link name.
Definition: ur_inv_kin.cpp:289
tesseract_kinematics::URInvKin::joint_names_
std::vector< std::string > joint_names_
Joint names for the kinematic object.
Definition: ur_inv_kin.h:132
tesseract_kinematics::URParameters::d6
double d6
Definition: types.h:54
tesseract_kinematics::InverseKinematics::UPtr
std::unique_ptr< InverseKinematics > UPtr
Definition: inverse_kinematics.h:52
utils.h
Kinematics utility functions.
tesseract_kinematics::URParameters::d4
double d4
Definition: types.h:52
tesseract_kinematics::URParameters
The Universal Robot kinematic parameters.
Definition: types.h:41
tesseract_kinematics::URParameters::a2
double a2
Definition: types.h:50
tesseract_kinematics::URInvKin::solver_name_
std::string solver_name_
Name of this solver.
Definition: ur_inv_kin.h:133
tesseract_kinematics::URInvKin::getWorkingFrame
std::string getWorkingFrame() const override final
Get the inverse kinematics working frame.
Definition: ur_inv_kin.cpp:290
tesseract_kinematics::URInvKin::clone
InverseKinematics::UPtr clone() const override final
Clone the forward kinematics object.
Definition: ur_inv_kin.cpp:240
tesseract_kinematics::URInvKin::numJoints
Eigen::Index numJoints() const override final
Number of joints in robot.
Definition: ur_inv_kin.cpp:287
tesseract_kinematics::URInvKin::getTipLinkNames
std::vector< std::string > getTipLinkNames() const override final
Get the names of the tip links of the kinematics group.
Definition: ur_inv_kin.cpp:291
tesseract_kinematics::URParameters::a3
double a3
Definition: types.h:51
tesseract_kinematics::URParameters::d1
double d1
Definition: types.h:49
REDUNDANT_CAPABLE_JOINTS
static const std::vector< Eigen::Index > REDUNDANT_CAPABLE_JOINTS
Definition: ur_inv_kin.cpp:41
tesseract_kinematics::URInvKin::base_link_name_
std::string base_link_name_
Link name of first link in the kinematic object.
Definition: ur_inv_kin.h:130
tesseract_kinematics
Definition: forward_kinematics.h:40
tesseract_kinematics::URInvKin::tip_link_name_
std::string tip_link_name_
Link name of last kink in the kinematic object.
Definition: ur_inv_kin.h:131
tesseract_kinematics::URInvKin::calcInvKin
tesseract_kinematics::IKSolutions calcInvKin(const tesseract_common::TransformMap &tip_link_poses, const Eigen::Ref< const Eigen::VectorXd > &seed) const override final
Calculates joint solutions given a pose for each tip link.
Definition: ur_inv_kin.cpp:255
tesseract_kinematics::IKSolutions
std::vector< Eigen::VectorXd > IKSolutions
The inverse kinematics solutions container.
Definition: types.h:38
tesseract_kinematics::inverse
int inverse(const Eigen::Isometry3d &T, const URParameters &params, double *q_sols, double q6_des)
Definition: ur_inv_kin.cpp:53
tesseract_kinematics::URInvKin
Universal Robot Inverse Kinematics Implementation.
Definition: ur_inv_kin.h:85
tesseract_kinematics::URInvKin::params_
URParameters params_
The UR Inverse kinematics parameters.
Definition: ur_inv_kin.h:129


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