moveit2
The MoveIt Motion Planning Framework for ROS 2.
Loading...
Searching...
No Matches
path_circle_generator.cpp
Go to the documentation of this file.
1/*********************************************************************
2 * Software License Agreement (BSD License)
3 *
4 * Copyright (c) 2018 Pilz GmbH & Co. KG
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 Pilz GmbH & Co. KG 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
36
38{
39std::unique_ptr<KDL::Path> PathCircleGenerator::circleFromCenter(const KDL::Frame& start_pose,
40 const KDL::Frame& goal_pose,
41 const KDL::Vector& center_point, double eqradius)
42{
43 double a = (start_pose.p - center_point).Norm();
44 double b = (goal_pose.p - center_point).Norm();
45 double c = (start_pose.p - goal_pose.p).Norm();
46
47 if (fabs(a - b) > MAX_RADIUS_DIFF)
48 {
50 }
51
52 // compute the rotation angle
53 double alpha = cosines(a, b, c);
54
55 KDL::RotationalInterpolation* rot_interpo = new KDL::RotationalInterpolation_SingleAxis();
56 double old_kdl_epsilon = KDL::epsilon;
57 try
58 {
59 KDL::epsilon = MAX_COLINEAR_NORM;
60 auto circle = std::unique_ptr<KDL::Path>(
61 new KDL::Path_Circle(start_pose, center_point, goal_pose.p, goal_pose.M, alpha, rot_interpo, eqradius,
62 true /* take ownership of RotationalInterpolation */));
63 KDL::epsilon = old_kdl_epsilon;
64 return circle;
65 }
66 catch (KDL::Error_MotionPlanning&)
67 {
68 KDL::epsilon = old_kdl_epsilon;
69 throw; // and pass the exception on to the caller
70 }
71}
72
73std::unique_ptr<KDL::Path> PathCircleGenerator::circleFromInterim(const KDL::Frame& start_pose,
74 const KDL::Frame& goal_pose,
75 const KDL::Vector& interim_point, double eqradius)
76{
77 // compute the center point from interim point
78 // triangle edges
79 const KDL::Vector t = interim_point - start_pose.p;
80 const KDL::Vector u = goal_pose.p - start_pose.p;
81 const KDL::Vector v = goal_pose.p - interim_point;
82 // triangle normal
83 const KDL::Vector w = t * u; // cross product
84
85 // circle center
86 if (w.Norm() < MAX_COLINEAR_NORM)
87 {
88 throw KDL::Error_MotionPlanning_Circle_No_Plane();
89 }
90 const KDL::Vector center_point =
91 start_pose.p + (u * dot(t, t) * dot(u, v) - t * dot(u, u) * dot(t, v)) * 0.5 / pow(w.Norm(), 2);
92
93 // compute the rotation angle
94 // triangle edges
95 const KDL::Vector t_center = center_point - start_pose.p;
96 const KDL::Vector v_center = goal_pose.p - center_point;
97 double a = t_center.Norm();
98 double b = v_center.Norm();
99 double c = u.Norm();
100 double alpha = cosines(a, b, c);
101
102 KDL::Vector kdl_aux_point(interim_point);
103
104 // if the angle at the interim is an acute angle (<90deg), rotation angle is
105 // an obtuse angle (>90deg)
106 // in this case using the interim as auxiliary point for KDL::Path_Circle can
107 // lead to a path in the wrong direction
108 double interim_angle = cosines(t.Norm(), v.Norm(), u.Norm());
109 if (interim_angle < M_PI / 2)
110 {
111 alpha = 2 * M_PI - alpha;
112
113 // exclude that the goal is not colinear with start and center, then use the
114 // opposite of the goal as auxiliary point
115 if ((t_center * v_center).Norm() > MAX_COLINEAR_NORM)
116 {
117 kdl_aux_point = 2 * center_point - goal_pose.p;
118 }
119 }
120
121 KDL::RotationalInterpolation* rot_interpo = new KDL::RotationalInterpolation_SingleAxis();
122 return std::unique_ptr<KDL::Path>(
123 std::make_unique<KDL::Path_Circle>(start_pose, center_point, kdl_aux_point, goal_pose.M, alpha, rot_interpo,
124 eqradius, true /* take ownership of RotationalInterpolation */));
125}
126
127double PathCircleGenerator::cosines(const double a, const double b, const double c)
128{
129 return acos(std::max(std::min((pow(a, 2) + pow(b, 2) - pow(c, 2)) / (2.0 * a * b), 1.0), -1.0));
130}
131
132} // namespace pilz_industrial_motion_planner
static std::unique_ptr< KDL::Path > circleFromCenter(const KDL::Frame &start_pose, const KDL::Frame &goal_pose, const KDL::Vector &center_point, double eqradius)
set the path circle from start, goal and center point
static std::unique_ptr< KDL::Path > circleFromInterim(const KDL::Frame &start_pose, const KDL::Frame &goal_pose, const KDL::Vector &interim_point, double eqradius)
set circle from start, goal and interim point