moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
pr2_arm_ik.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2011, Willow Garage, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
17 * * Neither the name of Willow Garage nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 * POSSIBILITY OF SUCH DAMAGE.
33 *********************************************************************/
34
35/* Author: Sachin Chitta, E. Gil Jones */
36
37#include <angles/angles.h>
39#include "pr2_arm_ik.h"
40
41/**** List of angles (for reference) *******
42 th1 = shoulder/turret pan
43 th2 = shoulder/turret lift/pitch
44 th3 = shoulder/turret roll
45 th4 = elbow pitch
46 th5 = elbow roll
47 th6 = wrist pitch
48 th7 = wrist roll
49*****/
50using namespace angles;
52{
53namespace
54{
55rclcpp::Logger getLogger()
56{
57 return moveit::getLogger("moveit.core.moveit_constaint_samplers.test.pr2_arm_ik");
58}
59} // namespace
60
64
65bool PR2ArmIK::init(const urdf::ModelInterface& robot_model, const std::string& root_name, const std::string& tip_name)
66{
67 std::vector<urdf::Pose> link_offset;
68 int num_joints = 0;
69 urdf::LinkConstSharedPtr link = robot_model.getLink(tip_name);
70 while (link && num_joints < 7)
71 {
72 urdf::JointConstSharedPtr joint;
73 if (link->parent_joint)
74 joint = robot_model.getJoint(link->parent_joint->name);
75 if (!joint)
76 {
77 if (link->parent_joint)
78 {
79 RCLCPP_ERROR(getLogger(), "Could not find joint: %s", link->parent_joint->name.c_str());
80 }
81 else
82 {
83 RCLCPP_ERROR(getLogger(), "Link %s has no parent joint", link->name.c_str());
84 }
85 return false;
86 }
87 if (joint->type != urdf::Joint::UNKNOWN && joint->type != urdf::Joint::FIXED)
88 {
89 link_offset.push_back(link->parent_joint->parent_to_joint_origin_transform);
90 angle_multipliers_.push_back(joint->axis.x * fabs(joint->axis.x) + joint->axis.y * fabs(joint->axis.y) +
91 joint->axis.z * fabs(joint->axis.z));
92 RCLCPP_DEBUG(getLogger(), "Joint axis: %d, %f, %f, %f", 6 - num_joints, joint->axis.x, joint->axis.y,
93 joint->axis.z);
94 if (joint->type != urdf::Joint::CONTINUOUS)
95 {
96 if (joint->safety)
97 {
98 min_angles_.push_back(joint->safety->soft_lower_limit);
99 max_angles_.push_back(joint->safety->soft_upper_limit);
100 }
101 else
102 {
103 if (joint->limits)
104 {
105 min_angles_.push_back(joint->limits->lower);
106 max_angles_.push_back(joint->limits->upper);
107 }
108 else
109 {
110 min_angles_.push_back(0.0);
111 max_angles_.push_back(0.0);
112 RCLCPP_WARN(getLogger(), "No joint limits or joint '%s'", joint->name.c_str());
113 }
114 }
115 continuous_joint_.push_back(false);
116 }
117 else
118 {
119 min_angles_.push_back(-M_PI);
120 max_angles_.push_back(M_PI);
121 continuous_joint_.push_back(true);
122 }
123 addJointToChainInfo(link->parent_joint, solver_info_);
124 num_joints++;
125 }
126 link = robot_model.getLink(link->getParent()->name);
127 }
128
129 solver_info_.link_names.push_back(tip_name);
130
131 // solver_info_.link_names.push_back(tip_name);
132 // We expect order from root to tip, so reverse the order
133 std::reverse(angle_multipliers_.begin(), angle_multipliers_.end());
134 std::reverse(min_angles_.begin(), min_angles_.end());
135 std::reverse(max_angles_.begin(), max_angles_.end());
136 std::reverse(link_offset.begin(), link_offset.end());
137 std::reverse(solver_info_.limits.begin(), solver_info_.limits.end());
138 std::reverse(solver_info_.joint_names.begin(), solver_info_.joint_names.end());
139 std::reverse(solver_info_.link_names.begin(), solver_info_.link_names.end());
140 std::reverse(continuous_joint_.begin(), continuous_joint_.end());
141
142 if (num_joints != 7)
143 {
144 RCLCPP_ERROR(getLogger(), "PR2ArmIK:: Chain from %s to %s does not have 7 joints", root_name.c_str(),
145 tip_name.c_str());
146 return false;
147 }
148
149 torso_shoulder_offset_x_ = link_offset[0].position.x;
150 torso_shoulder_offset_y_ = link_offset[0].position.y;
151 torso_shoulder_offset_z_ = link_offset[0].position.z;
152 shoulder_upperarm_offset_ = distance(link_offset[1]);
153 upperarm_elbow_offset_ = distance(link_offset[3]);
154 elbow_wrist_offset_ = distance(link_offset[5]);
155 shoulder_elbow_offset_ = shoulder_upperarm_offset_ + upperarm_elbow_offset_;
156 shoulder_wrist_offset_ = shoulder_upperarm_offset_ + upperarm_elbow_offset_ + elbow_wrist_offset_;
157
158 Eigen::Isometry3f home = Eigen::Isometry3f::Identity();
159 home(0, 3) = shoulder_upperarm_offset_ + upperarm_elbow_offset_ + elbow_wrist_offset_;
160 home_inv_ = home.inverse();
161 grhs_ = home;
162 gf_ = home_inv_;
163 solution_.resize(NUM_JOINTS_ARM7DOF);
164 return true;
165}
166
167void PR2ArmIK::addJointToChainInfo(const urdf::JointConstSharedPtr& joint, moveit_msgs::msg::KinematicSolverInfo& info)
168{
169 moveit_msgs::msg::JointLimits limit;
170 info.joint_names.push_back(joint->name); // Joints are coming in reverse order
171
172 if (joint->type != urdf::Joint::CONTINUOUS)
173 {
174 if (joint->safety)
175 {
176 limit.min_position = joint->safety->soft_lower_limit;
177 limit.max_position = joint->safety->soft_upper_limit;
178 limit.has_position_limits = true;
179 }
180 else if (joint->limits)
181 {
182 limit.min_position = joint->limits->lower;
183 limit.max_position = joint->limits->upper;
184 limit.has_position_limits = true;
185 }
186 else
187 limit.has_position_limits = false;
188 }
189 else
190 {
191 limit.min_position = -M_PI;
192 limit.max_position = M_PI;
193 limit.has_position_limits = false;
194 }
195 if (joint->limits)
196 {
197 limit.max_velocity = joint->limits->velocity;
198 limit.has_velocity_limits = 1;
199 }
200 else
201 limit.has_velocity_limits = 0;
202 info.limits.push_back(limit);
203}
204
205void PR2ArmIK::getSolverInfo(moveit_msgs::msg::KinematicSolverInfo& info)
206{
207 info = solver_info_;
208}
209
210void PR2ArmIK::computeIKShoulderPan(const Eigen::Isometry3f& g_in, double t1_in,
211 std::vector<std::vector<double> >& solution) const
212{
213 // t1 = shoulder/turret pan is specified
214 // solution_ik_.resize(0);
215 std::vector<double> solution_ik(NUM_JOINTS_ARM7DOF, 0.0);
216 Eigen::Isometry3f g = g_in;
217 Eigen::Isometry3f gf_local = home_inv_;
218 Eigen::Isometry3f grhs_local = home_inv_;
219 // First bring everything into the arm frame
220 g(0, 3) = g_in(0, 3) - torso_shoulder_offset_x_;
221 g(1, 3) = g_in(1, 3) - torso_shoulder_offset_y_;
222 g(2, 3) = g_in(2, 3) - torso_shoulder_offset_z_;
223
224 double t1 = angles::normalize_angle(t1_in);
225 if (!checkJointLimits(t1, 0))
226 return;
227
228 double cost1, cost2, cost3, cost4;
229 double sint1, sint2, sint3, sint4;
230
231 gf_local = g * home_inv_;
232
233 cost1 = cos(t1);
234 sint1 = sin(t1);
235
236 double t2(0), t3(0), t4(0), t5(0), t6(0), t7(0);
237
238 double at(0), bt(0), ct(0);
239
240 double theta2[2], theta3[2], theta4[2], theta5[2], theta6[4], theta7[2];
241
242 double sopx = shoulder_upperarm_offset_ * cost1;
243 double sopy = shoulder_upperarm_offset_ * sint1;
244 double sopz = 0;
245
246 double x = g(0, 3);
247 double y = g(1, 3);
248 double z = g(2, 3);
249
250 double dx = x - sopx;
251 double dy = y - sopy;
252 double dz = z - sopz;
253
254 double dd = dx * dx + dy * dy + dz * dz;
255
256 double numerator =
257 dd - shoulder_upperarm_offset_ * shoulder_upperarm_offset_ +
258 2 * shoulder_upperarm_offset_ * shoulder_elbow_offset_ - 2 * shoulder_elbow_offset_ * shoulder_elbow_offset_ +
259 2 * shoulder_elbow_offset_ * shoulder_wrist_offset_ - shoulder_wrist_offset_ * shoulder_wrist_offset_;
260 double denominator =
261 2 * (shoulder_upperarm_offset_ - shoulder_elbow_offset_) * (shoulder_elbow_offset_ - shoulder_wrist_offset_);
262
263 double acos_term = numerator / denominator;
264
265 if (acos_term > 1.0 || acos_term < -1.0)
266 return;
267
268 double acos_angle = acos(acos_term);
269
270 theta4[0] = acos_angle;
271 theta4[1] = -acos_angle;
272
273#ifdef DEBUG
274 std::cout << "ComputeIK::theta3:" << numerator << ',' << denominator << ",\n" << theta4[0] << '\n';
275#endif
276
277 for (double theta : theta4)
278 {
279 t4 = theta;
280 cost4 = cos(t4);
281 sint4 = sin(t4);
282
283#ifdef DEBUG
284 std::cout << "t4 " << t4 << '\n';
285#endif
286 if (std::isnan(t4))
287 continue;
288
289 if (!checkJointLimits(t4, 3))
290 continue;
291
292 at = x * cost1 + y * sint1 - shoulder_upperarm_offset_;
293 bt = -z;
294 ct = -shoulder_upperarm_offset_ + shoulder_elbow_offset_ +
295 (shoulder_wrist_offset_ - shoulder_elbow_offset_) * cos(t4);
296
297 if (!solveCosineEqn(at, bt, ct, theta2[0], theta2[1]))
298 continue;
299
300 for (double theta : theta2)
301 {
302 t2 = theta;
303 if (!checkJointLimits(t2, 1))
304 continue;
305
306#ifdef DEBUG
307 std::cout << "t2 " << t2 << '\n';
308#endif
309 sint2 = sin(t2);
310 cost2 = cos(t2);
311
312 at = sint1 * (shoulder_elbow_offset_ - shoulder_wrist_offset_) * sint2 * sint4;
313 bt = (-shoulder_elbow_offset_ + shoulder_wrist_offset_) * cost1 * sint4;
314 ct = y - (shoulder_upperarm_offset_ + cost2 * (-shoulder_upperarm_offset_ + shoulder_elbow_offset_ +
315 (-shoulder_elbow_offset_ + shoulder_wrist_offset_) * cos(t4))) *
316 sint1;
317 if (!solveCosineEqn(at, bt, ct, theta3[0], theta3[1]))
318 continue;
319
320 for (double theta : theta3)
321 {
322 t3 = theta;
323
324 if (!checkJointLimits(angles::normalize_angle(t3), 2))
325 continue;
326
327 sint3 = sin(t3);
328 cost3 = cos(t3);
329#ifdef DEBUG
330 std::cout << "t3 " << t3 << '\n';
331#endif
332 if (fabs((shoulder_upperarm_offset_ - shoulder_elbow_offset_ +
333 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost4) *
334 sint2 +
335 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost2 * cost3 * sint4 - z) > IK_EPS)
336 continue;
337
338 if (fabs((shoulder_elbow_offset_ - shoulder_wrist_offset_) * sint1 * sint3 * sint4 +
339 cost1 * (shoulder_upperarm_offset_ +
340 cost2 * (-shoulder_upperarm_offset_ + shoulder_elbow_offset_ +
341 (-shoulder_elbow_offset_ + shoulder_wrist_offset_) * cost4) +
342 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost3 * sint2 * sint4) -
343 x) > IK_EPS)
344 continue;
345
346 grhs_local(0, 0) =
347 cost4 * (gf_local(0, 0) * cost1 * cost2 + gf_local(1, 0) * cost2 * sint1 - gf_local(2, 0) * sint2) -
348 (gf_local(2, 0) * cost2 * cost3 + cost3 * (gf_local(0, 0) * cost1 + gf_local(1, 0) * sint1) * sint2 +
349 (-(gf_local(1, 0) * cost1) + gf_local(0, 0) * sint1) * sint3) *
350 sint4;
351
352 grhs_local(0, 1) =
353 cost4 * (gf_local(0, 1) * cost1 * cost2 + gf_local(1, 1) * cost2 * sint1 - gf_local(2, 1) * sint2) -
354 (gf_local(2, 1) * cost2 * cost3 + cost3 * (gf_local(0, 1) * cost1 + gf_local(1, 1) * sint1) * sint2 +
355 (-(gf_local(1, 1) * cost1) + gf_local(0, 1) * sint1) * sint3) *
356 sint4;
357
358 grhs_local(0, 2) =
359 cost4 * (gf_local(0, 2) * cost1 * cost2 + gf_local(1, 2) * cost2 * sint1 - gf_local(2, 2) * sint2) -
360 (gf_local(2, 2) * cost2 * cost3 + cost3 * (gf_local(0, 2) * cost1 + gf_local(1, 2) * sint1) * sint2 +
361 (-(gf_local(1, 2) * cost1) + gf_local(0, 2) * sint1) * sint3) *
362 sint4;
363
364 grhs_local(1, 0) = cost3 * (gf_local(1, 0) * cost1 - gf_local(0, 0) * sint1) + gf_local(2, 0) * cost2 * sint3 +
365 (gf_local(0, 0) * cost1 + gf_local(1, 0) * sint1) * sint2 * sint3;
366
367 grhs_local(1, 1) = cost3 * (gf_local(1, 1) * cost1 - gf_local(0, 1) * sint1) + gf_local(2, 1) * cost2 * sint3 +
368 (gf_local(0, 1) * cost1 + gf_local(1, 1) * sint1) * sint2 * sint3;
369
370 grhs_local(1, 2) = cost3 * (gf_local(1, 2) * cost1 - gf_local(0, 2) * sint1) + gf_local(2, 2) * cost2 * sint3 +
371 (gf_local(0, 2) * cost1 + gf_local(1, 2) * sint1) * sint2 * sint3;
372
373 grhs_local(2, 0) =
374 cost4 *
375 (gf_local(2, 0) * cost2 * cost3 + cost3 * (gf_local(0, 0) * cost1 + gf_local(1, 0) * sint1) * sint2 +
376 (-(gf_local(1, 0) * cost1) + gf_local(0, 0) * sint1) * sint3) +
377 (gf_local(0, 0) * cost1 * cost2 + gf_local(1, 0) * cost2 * sint1 - gf_local(2, 0) * sint2) * sint4;
378
379 grhs_local(2, 1) =
380 cost4 *
381 (gf_local(2, 1) * cost2 * cost3 + cost3 * (gf_local(0, 1) * cost1 + gf_local(1, 1) * sint1) * sint2 +
382 (-(gf_local(1, 1) * cost1) + gf_local(0, 1) * sint1) * sint3) +
383 (gf_local(0, 1) * cost1 * cost2 + gf_local(1, 1) * cost2 * sint1 - gf_local(2, 1) * sint2) * sint4;
384
385 grhs_local(2, 2) =
386 cost4 *
387 (gf_local(2, 2) * cost2 * cost3 + cost3 * (gf_local(0, 2) * cost1 + gf_local(1, 2) * sint1) * sint2 +
388 (-(gf_local(1, 2) * cost1) + gf_local(0, 2) * sint1) * sint3) +
389 (gf_local(0, 2) * cost1 * cost2 + gf_local(1, 2) * cost2 * sint1 - gf_local(2, 2) * sint2) * sint4;
390
391 double val1 = sqrt(grhs_local(0, 1) * grhs_local(0, 1) + grhs_local(0, 2) * grhs_local(0, 2));
392 double val2 = grhs_local(0, 0);
393
394 theta6[0] = atan2(val1, val2);
395 theta6[1] = atan2(-val1, val2);
396
397 // theta6[3] = M_PI + theta6[0];
398 // theta6[4] = M_PI + theta6[1];
399
400 for (int mm = 0; mm < 2; ++mm)
401 {
402 t6 = theta6[mm];
403 if (!checkJointLimits(angles::normalize_angle(t6), 5))
404 continue;
405
406#ifdef DEBUG
407 std::cout << "t6 " << t6 << '\n';
408#endif
409 if (fabs(cos(t6) - grhs_local(0, 0)) > IK_EPS)
410 continue;
411
412 if (fabs(sin(t6)) < IK_EPS)
413 {
414 // std::cout << "Singularity" << '\n';
415 theta5[0] = acos(grhs_local(1, 1)) / 2.0;
416 theta7[0] = theta7[0];
417 theta7[1] = M_PI + theta7[0];
418 theta5[1] = theta7[1];
419 }
420 else
421 {
422 theta7[0] = atan2(grhs_local(0, 1), grhs_local(0, 2));
423 theta5[0] = atan2(grhs_local(1, 0), -grhs_local(2, 0));
424 theta7[1] = M_PI + theta7[0];
425 theta5[1] = M_PI + theta5[0];
426 }
427#ifdef DEBUG
428 std::cout << "theta1: " << t1 << '\n';
429 std::cout << "theta2: " << t2 << '\n';
430 std::cout << "theta3: " << t3 << '\n';
431 std::cout << "theta4: " << t4 << '\n';
432 std::cout << "theta5: " << t5 << '\n';
433 std::cout << "theta6: " << t6 << '\n';
434 std::cout << "theta7: " << t7 << '\n' << '\n' << '\n';
435#endif
436 for (int lll = 0; lll < 2; ++lll)
437 {
438 t5 = theta5[lll];
439 t7 = theta7[lll];
440 if (!checkJointLimits(t5, 4))
441 continue;
442 if (!checkJointLimits(t7, 6))
443 continue;
444
445#ifdef DEBUG
446 std::cout << "t5" << t5 << '\n';
447 std::cout << "t7" << t7 << '\n';
448#endif
449 if (fabs(sin(t6) * sin(t7) - grhs_local(0, 1)) > IK_EPS ||
450 fabs(cos(t7) * sin(t6) - grhs_local(0, 2)) > IK_EPS)
451 continue;
452
453 solution_ik[0] = normalize_angle(t1) * angle_multipliers_[0];
454 solution_ik[1] = normalize_angle(t2) * angle_multipliers_[1];
455 solution_ik[2] = normalize_angle(t3) * angle_multipliers_[2];
456 solution_ik[3] = normalize_angle(t4) * angle_multipliers_[3];
457 solution_ik[4] = normalize_angle(t5) * angle_multipliers_[4];
458 solution_ik[5] = normalize_angle(t6) * angle_multipliers_[5];
459 solution_ik[6] = normalize_angle(t7) * angle_multipliers_[6];
460 solution.push_back(solution_ik);
461
462#ifdef DEBUG
463 std::cout << "SOLN " << solution_ik[0] << ' ' << solution_ik[1] << ' ' << solution_ik[2] << ' '
464 << solution_ik[3] << ' ' << solution_ik[4] << ' ' << solution_ik[5] << ' ' << solution_ik[6]
465 << '\n'
466 << '\n';
467#endif
468 }
469 }
470 }
471 }
472 }
473}
474
475void PR2ArmIK::computeIKShoulderRoll(const Eigen::Isometry3f& g_in, const double t3,
476 std::vector<std::vector<double> >& solution) const
477{
478 std::vector<double> solution_ik(NUM_JOINTS_ARM7DOF, 0.0);
479 // ROS_INFO(" ");
480 // solution_ik_.clear();
481 // ROS_INFO("Solution IK size: %d",solution_ik_.size());
482 // for(unsigned int i=0; i < solution_ik_.size(); ++i)
483 // {
484 // solution_ik_[i].clear();
485 // }
486 // if(!solution_ik_.empty())
487 // solution_ik_.resize(0);
488 // t3 = shoulder/turret roll is specified
489 Eigen::Isometry3f g = g_in;
490 Eigen::Isometry3f gf_local = home_inv_;
491 Eigen::Isometry3f grhs_local = home_inv_;
492 // First bring everything into the arm frame
493 g(0, 3) = g_in(0, 3) - torso_shoulder_offset_x_;
494 g(1, 3) = g_in(1, 3) - torso_shoulder_offset_y_;
495 g(2, 3) = g_in(2, 3) - torso_shoulder_offset_z_;
496
497 if (!checkJointLimits(t3, 2))
498 {
499 return;
500 }
501 double x = g(0, 3);
502 double y = g(1, 3);
503 double z = g(2, 3);
504 double cost1, cost2, cost3, cost4;
505 double sint1, sint2, sint3, sint4;
506
507 gf_local = g * home_inv_;
508
509 cost3 = cos(t3);
510 sint3 = sin(t3);
511
512 double t1(0), t2(0), t4(0), t5(0), t6(0), t7(0);
513
514 double at(0), bt(0), ct(0);
515
516 double theta1[2], theta2[2], theta4[4], theta5[2], theta6[4], theta7[2];
517
518 double c0 = -sin(-t3) * elbow_wrist_offset_;
519 double c1 = -cos(-t3) * elbow_wrist_offset_;
520
521 double d0 = 4 * shoulder_upperarm_offset_ * shoulder_upperarm_offset_ *
522 (upperarm_elbow_offset_ * upperarm_elbow_offset_ + c1 * c1 - z * z);
523 double d1 = 8 * shoulder_upperarm_offset_ * shoulder_upperarm_offset_ * upperarm_elbow_offset_ * elbow_wrist_offset_;
524 double d2 =
525 4 * shoulder_upperarm_offset_ * shoulder_upperarm_offset_ * (elbow_wrist_offset_ * elbow_wrist_offset_ - c1 * c1);
526
527 double b0 = x * x + y * y + z * z - shoulder_upperarm_offset_ * shoulder_upperarm_offset_ -
528 upperarm_elbow_offset_ * upperarm_elbow_offset_ - c0 * c0 - c1 * c1;
529 double b1 = -2 * upperarm_elbow_offset_ * elbow_wrist_offset_;
530
531 if (!solveQuadratic(b1 * b1 - d2, 2 * b0 * b1 - d1, b0 * b0 - d0, &theta4[0], &theta4[1]))
532 {
533#ifdef DEBUG
534 printf("No solution to quadratic eqn\n");
535#endif
536 return;
537 }
538 theta4[0] = acos(theta4[0]);
539 theta4[2] = acos(theta4[1]);
540 theta4[1] = -theta4[0];
541 theta4[3] = -theta4[2];
542
543 for (double theta : theta4)
544 {
545 t4 = theta;
546
547 if (!checkJointLimits(t4, 3))
548 {
549 continue;
550 }
551 cost4 = cos(t4);
552 sint4 = sin(t4);
553#ifdef DEBUG
554 std::cout << "t4 " << t4 << '\n';
555#endif
556 if (std::isnan(t4))
557 continue;
558 at = cos(t3) * sin(t4) * (shoulder_elbow_offset_ - shoulder_wrist_offset_);
559 bt = (shoulder_upperarm_offset_ - shoulder_elbow_offset_ +
560 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cos(t4));
561 ct = z;
562
563 if (!solveCosineEqn(at, bt, ct, theta2[0], theta2[1]))
564 continue;
565
566 for (double theta : theta2)
567 {
568 t2 = theta;
569#ifdef DEBUG
570 std::cout << "t2 " << t2 << '\n';
571#endif
572 if (!checkJointLimits(t2, 1))
573 {
574 continue;
575 }
576
577 sint2 = sin(t2);
578 cost2 = cos(t2);
579
580 at = -y;
581 bt = x;
582 ct = (shoulder_elbow_offset_ - shoulder_wrist_offset_) * sin(t3) * sin(t4);
583 if (!solveCosineEqn(at, bt, ct, theta1[0], theta1[1]))
584 {
585#ifdef DEBUG
586 std::cout << "could not solve cosine equation for t1" << '\n';
587#endif
588 continue;
589 }
590
591 for (double theta : theta1)
592 {
593 t1 = theta;
594#ifdef DEBUG
595 std::cout << "t1 " << t1 << '\n';
596#endif
597 if (!checkJointLimits(t1, 0))
598 {
599 continue;
600 }
601 sint1 = sin(t1);
602 cost1 = cos(t1);
603 if (fabs((shoulder_upperarm_offset_ - shoulder_elbow_offset_ +
604 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost4) *
605 sint2 +
606 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost2 * cost3 * sint4 - z) > IK_EPS)
607 {
608#ifdef DEBUG
609 printf("z value not matched %f\n",
610 fabs((shoulder_upperarm_offset_ - shoulder_elbow_offset_ +
611 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost4) *
612 sint2 +
613 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost2 * cost3 * sint4 - z));
614#endif
615 continue;
616 }
617 if (fabs((shoulder_elbow_offset_ - shoulder_wrist_offset_) * sint1 * sint3 * sint4 +
618 cost1 * (shoulder_upperarm_offset_ +
619 cost2 * (-shoulder_upperarm_offset_ + shoulder_elbow_offset_ +
620 (-shoulder_elbow_offset_ + shoulder_wrist_offset_) * cost4) +
621 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost3 * sint2 * sint4) -
622 x) > IK_EPS)
623 {
624#ifdef DEBUG
625 printf("x value not matched by %f\n",
626 fabs((shoulder_elbow_offset_ - shoulder_wrist_offset_) * sint1 * sint3 * sint4 +
627 cost1 * (shoulder_upperarm_offset_ +
628 cost2 * (-shoulder_upperarm_offset_ + shoulder_elbow_offset_ +
629 (-shoulder_elbow_offset_ + shoulder_wrist_offset_) * cost4) +
630 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost3 * sint2 * sint4) -
631 x));
632#endif
633 continue;
634 }
635 if (fabs(-(shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost1 * sint3 * sint4 +
636 sint1 * (shoulder_upperarm_offset_ +
637 cost2 * (-shoulder_upperarm_offset_ + shoulder_elbow_offset_ +
638 (-shoulder_elbow_offset_ + shoulder_wrist_offset_) * cost4) +
639 (shoulder_elbow_offset_ - shoulder_wrist_offset_) * cost3 * sint2 * sint4) -
640 y) > IK_EPS)
641 {
642#ifdef DEBUG
643 printf("y value not matched\n");
644#endif
645 continue;
646 }
647 grhs_local(0, 0) =
648 cost4 * (gf_local(0, 0) * cost1 * cost2 + gf_local(1, 0) * cost2 * sint1 - gf_local(2, 0) * sint2) -
649 (gf_local(2, 0) * cost2 * cost3 + cost3 * (gf_local(0, 0) * cost1 + gf_local(1, 0) * sint1) * sint2 +
650 (-(gf_local(1, 0) * cost1) + gf_local(0, 0) * sint1) * sint3) *
651 sint4;
652
653 grhs_local(0, 1) =
654 cost4 * (gf_local(0, 1) * cost1 * cost2 + gf_local(1, 1) * cost2 * sint1 - gf_local(2, 1) * sint2) -
655 (gf_local(2, 1) * cost2 * cost3 + cost3 * (gf_local(0, 1) * cost1 + gf_local(1, 1) * sint1) * sint2 +
656 (-(gf_local(1, 1) * cost1) + gf_local(0, 1) * sint1) * sint3) *
657 sint4;
658
659 grhs_local(0, 2) =
660 cost4 * (gf_local(0, 2) * cost1 * cost2 + gf_local(1, 2) * cost2 * sint1 - gf_local(2, 2) * sint2) -
661 (gf_local(2, 2) * cost2 * cost3 + cost3 * (gf_local(0, 2) * cost1 + gf_local(1, 2) * sint1) * sint2 +
662 (-(gf_local(1, 2) * cost1) + gf_local(0, 2) * sint1) * sint3) *
663 sint4;
664
665 grhs_local(1, 0) = cost3 * (gf_local(1, 0) * cost1 - gf_local(0, 0) * sint1) + gf_local(2, 0) * cost2 * sint3 +
666 (gf_local(0, 0) * cost1 + gf_local(1, 0) * sint1) * sint2 * sint3;
667
668 grhs_local(1, 1) = cost3 * (gf_local(1, 1) * cost1 - gf_local(0, 1) * sint1) + gf_local(2, 1) * cost2 * sint3 +
669 (gf_local(0, 1) * cost1 + gf_local(1, 1) * sint1) * sint2 * sint3;
670
671 grhs_local(1, 2) = cost3 * (gf_local(1, 2) * cost1 - gf_local(0, 2) * sint1) + gf_local(2, 2) * cost2 * sint3 +
672 (gf_local(0, 2) * cost1 + gf_local(1, 2) * sint1) * sint2 * sint3;
673
674 grhs_local(2, 0) =
675 cost4 *
676 (gf_local(2, 0) * cost2 * cost3 + cost3 * (gf_local(0, 0) * cost1 + gf_local(1, 0) * sint1) * sint2 +
677 (-(gf_local(1, 0) * cost1) + gf_local(0, 0) * sint1) * sint3) +
678 (gf_local(0, 0) * cost1 * cost2 + gf_local(1, 0) * cost2 * sint1 - gf_local(2, 0) * sint2) * sint4;
679
680 grhs_local(2, 1) =
681 cost4 *
682 (gf_local(2, 1) * cost2 * cost3 + cost3 * (gf_local(0, 1) * cost1 + gf_local(1, 1) * sint1) * sint2 +
683 (-(gf_local(1, 1) * cost1) + gf_local(0, 1) * sint1) * sint3) +
684 (gf_local(0, 1) * cost1 * cost2 + gf_local(1, 1) * cost2 * sint1 - gf_local(2, 1) * sint2) * sint4;
685
686 grhs_local(2, 2) =
687 cost4 *
688 (gf_local(2, 2) * cost2 * cost3 + cost3 * (gf_local(0, 2) * cost1 + gf_local(1, 2) * sint1) * sint2 +
689 (-(gf_local(1, 2) * cost1) + gf_local(0, 2) * sint1) * sint3) +
690 (gf_local(0, 2) * cost1 * cost2 + gf_local(1, 2) * cost2 * sint1 - gf_local(2, 2) * sint2) * sint4;
691
692 double val1 = sqrt(grhs_local(0, 1) * grhs_local(0, 1) + grhs_local(0, 2) * grhs_local(0, 2));
693 double val2 = grhs_local(0, 0);
694
695 theta6[0] = atan2(val1, val2);
696 theta6[1] = atan2(-val1, val2);
697
698 for (int mm = 0; mm < 2; ++mm)
699 {
700 t6 = theta6[mm];
701#ifdef DEBUG
702 std::cout << "t6 " << t6 << '\n';
703#endif
704 if (!checkJointLimits(t6, 5))
705 {
706 continue;
707 }
708
709 if (fabs(cos(t6) - grhs_local(0, 0)) > IK_EPS)
710 continue;
711
712 if (fabs(sin(t6)) < IK_EPS)
713 {
714 // std::cout << "Singularity" << '\n';
715 theta5[0] = acos(grhs_local(1, 1)) / 2.0;
716 theta7[0] = theta5[0];
717 // theta7[1] = M_PI+theta7[0];
718 // theta5[1] = theta7[1];
719 }
720 else
721 {
722 theta7[0] = atan2(grhs_local(0, 1) / sin(t6), grhs_local(0, 2) / sin(t6));
723 theta5[0] = atan2(grhs_local(1, 0) / sin(t6), -grhs_local(2, 0) / sin(t6));
724 // theta7[1] = M_PI+theta7[0];
725 // theta5[1] = M_PI+theta5[0];
726 }
727 for (int lll = 0; lll < 1; ++lll)
728 {
729 t5 = theta5[lll];
730 t7 = theta7[lll];
731
732 if (!checkJointLimits(t5, 4))
733 {
734 continue;
735 }
736 if (!checkJointLimits(t7, 6))
737 {
738 continue;
739 }
740
741#ifdef DEBUG
742 std::cout << "t5 " << t5 << '\n';
743 std::cout << "t7 " << t7 << '\n';
744#endif
745 // if(fabs(sin(t6)*sin(t7)-grhs_local(0,1)) > IK_EPS || fabs(cos(t7)*sin(t6)-grhs_local(0,2)) > IK_EPS)
746 // continue;
747
748#ifdef DEBUG
749 std::cout << "theta1: " << t1 << '\n';
750 std::cout << "theta2: " << t2 << '\n';
751 std::cout << "theta3: " << t3 << '\n';
752 std::cout << "theta4: " << t4 << '\n';
753 std::cout << "theta5: " << t5 << '\n';
754 std::cout << "theta6: " << t6 << '\n';
755 std::cout << "theta7: " << t7 << '\n' << '\n' << '\n';
756#endif
757
758 solution_ik[0] = normalize_angle(t1 * angle_multipliers_[0]);
759 solution_ik[1] = normalize_angle(t2 * angle_multipliers_[1]);
760 solution_ik[2] = t3 * angle_multipliers_[2];
761 solution_ik[3] = normalize_angle(t4 * angle_multipliers_[3]);
762 solution_ik[4] = normalize_angle(t5 * angle_multipliers_[4]);
763 solution_ik[5] = normalize_angle(t6 * angle_multipliers_[5]);
764 solution_ik[6] = normalize_angle(t7 * angle_multipliers_[6]);
765 solution.push_back(solution_ik);
766#ifdef DEBUG
767 std::cout << "SOLN " << solution_ik[0] << ' ' << solution_ik[1] << ' ' << solution_ik[2] << ' '
768 << solution_ik[3] << ' ' << solution_ik[4] << ' ' << solution_ik[5] << ' ' << solution_ik[6]
769 << '\n'
770 << '\n';
771#endif
772 }
773 }
774 }
775 }
776 }
777}
778
779bool PR2ArmIK::checkJointLimits(const std::vector<double>& joint_values) const
780{
781 for (int i = 0; i < NUM_JOINTS_ARM7DOF; ++i)
782 {
783 if (!checkJointLimits(angles::normalize_angle(joint_values[i] * angle_multipliers_[i]), i))
784 {
785 return false;
786 }
787 }
788 return true;
789}
790
791bool PR2ArmIK::checkJointLimits(const double joint_value, const int joint_num) const
792{
793 double jv;
794 if (continuous_joint_[joint_num])
795 {
796 jv = angles::normalize_angle(joint_value * angle_multipliers_[joint_num]);
797 }
798 else if (joint_num == 2)
799 {
800 jv = joint_value * angle_multipliers_[joint_num];
801 }
802 else
803 {
804 jv = angles::normalize_angle(joint_value * angle_multipliers_[joint_num]);
805 }
806
807 return jv >= min_angles_[joint_num] && jv <= max_angles_[joint_num];
808}
809} // namespace pr2_arm_kinematics
void computeIKShoulderRoll(const Eigen::Isometry3f &g_in, double shoulder_roll_initial_guess, std::vector< std::vector< double > > &solution) const
compute IK based on an initial guess for the shoulder roll angle. h
bool init(const urdf::ModelInterface &robot_model, const std::string &root_name, const std::string &tip_name)
Initialize the solver by providing a urdf::Model and a root and tip name.
void computeIKShoulderPan(const Eigen::Isometry3f &g_in, double shoulder_pan_initial_guess, std::vector< std::vector< double > > &solution) const
compute IK based on an initial guess for the shoulder pan angle.
moveit_msgs::msg::KinematicSolverInfo solver_info_
get chain information about the arm.
Definition pr2_arm_ik.h:170
void getSolverInfo(moveit_msgs::msg::KinematicSolverInfo &info)
get chain information about the arm. This populates the IK query response, filling in joint level inf...
rclcpp::Logger getLogger(const std::string &name)
Creates a namespaced logger.
Definition logger.cpp:79
double distance(const urdf::Pose &transform)
Definition pr2_arm_ik.h:59
bool solveQuadratic(double a, double b, double c, double *x1, double *x2)
Definition pr2_arm_ik.h:65
bool solveCosineEqn(double a, double b, double c, double &soln1, double &soln2)
Definition pr2_arm_ik.h:95