48 const double ZERO_THRESH = 0.00000001;
49 int SIGN(
double x) {
return (x > 0) - (x < 0); }
50 const double PI = M_PI;
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)
78 if (fabs(fabs(params.
d4) - fabs(B)) < ZERO_THRESH)
79 div = -SIGN(params.
d4) * SIGN(B);
82 double arcsin = asin(div);
83 if (fabs(arcsin) < ZERO_THRESH)
86 q1[0] = arcsin + 2.0 * PI;
91 else if (fabs(B) < ZERO_THRESH)
94 if (fabs(fabs(params.
d4) - fabs(A)) < ZERO_THRESH)
95 div = SIGN(params.
d4) * SIGN(A);
98 double arccos = acos(div);
100 q1[1] = 2.0 * PI - arccos;
102 else if (params.
d4 * params.
d4 > R)
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)
114 if (fabs(neg) < ZERO_THRESH)
119 q1[0] = 2.0 * PI + pos;
123 q1[1] = 2.0 * PI + neg;
131 for (
int i = 0; i < 2; i++)
133 double numer = (T03 * sin(q1[i]) - T13 * cos(q1[i]) - params.
d4);
135 if (fabs(fabs(numer) - fabs(params.
d6)) < ZERO_THRESH)
136 div = SIGN(numer) * SIGN(params.
d6);
138 div = numer / params.
d6;
139 double arccos = acos(div);
141 q5[i][1] = 2.0 * PI - arccos;
147 for (
int i = 0; i < 2; i++)
149 for (
int j = 0; j < 2; j++)
151 double c1 = cos(q1[i]), s1 = sin(q1[i]);
152 double c5 = cos(q5[i][j]), s5 = sin(q5[i][j]);
155 if (fabs(s5) < ZERO_THRESH)
159 q6 = atan2(SIGN(s5) * -(T01 * s1 - T11 * c1), SIGN(s5) * (T00 * s1 - T10 * c1));
160 if (fabs(q6) < ZERO_THRESH)
167 double q2[2], q3[2], q4[2];
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);
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)
180 else if (fabs(c3) > 1.0)
185 double arccos = acos(c3);
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++)
202 if (fabs(q2[k]) < ZERO_THRESH)
204 else if (q2[k] < 0.0)
206 if (fabs(q4[k]) < ZERO_THRESH)
208 else if (q4[k] < 0.0)
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;
226 std::string base_link_name,
227 std::string tip_link_name,
228 std::vector<std::string> joint_names,
229 std::string solver_name)
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))
237 throw std::runtime_error(
"OPWInvKin, only support six joints!");
256 const Eigen::Ref<const Eigen::VectorXd>& )
const
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);
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_);
267 std::array<std::array<double, 6>, 8> sols;
268 auto num_sols =
static_cast<std::size_t
>(
inverse(corrected_pose,
params_, sols[0].data(), 0));
272 solution_set.reserve(num_sols);
273 for (std::size_t i = 0; i < num_sols; ++i)
275 Eigen::Map<Eigen::VectorXd> eigen_sol(sols[i].data(),
static_cast<Eigen::Index
>(sols[i].size()));
281 solution_set.emplace_back(eigen_sol);