Blender V5.0
IK_QJacobian.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2001-2002 NaN Holding BV. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include "IK_QJacobian.h"
10
11#include <algorithm>
12
13IK_QJacobian::IK_QJacobian() : m_sdls(true), m_min_damp(1.0) {}
14
16
17void IK_QJacobian::ArmMatrices(int dof, int task_size)
18{
19 m_dof = dof;
20 m_task_size = task_size;
21
22 m_jacobian.resize(task_size, dof);
23 m_jacobian.setZero();
24
25 m_alpha.resize(dof);
26 m_alpha.setZero();
27
28 m_nullspace.resize(dof, dof);
29
30 m_d_theta.resize(dof);
31 m_d_theta_tmp.resize(dof);
32 m_d_norm_weight.resize(dof);
33
34 m_norm.resize(dof);
35 m_norm.setZero();
36
37 m_beta.resize(task_size);
38
39 m_weight.resize(dof);
40 m_weight_sqrt.resize(dof);
41 m_weight.setOnes();
42 m_weight_sqrt.setOnes();
43
44 if (task_size >= dof) {
45 m_transpose = false;
46
47 m_jacobian_tmp.resize(task_size, dof);
48
49 m_svd_u.resize(task_size, dof);
50 m_svd_v.resize(dof, dof);
51 m_svd_w.resize(dof);
52
53 m_svd_u_beta.resize(dof);
54 }
55 else {
56 // use the SVD of the transpose jacobian, it works just as well
57 // as the original, and often allows using smaller matrices.
58 m_transpose = true;
59
60 m_jacobian_tmp.resize(dof, task_size);
61
62 m_svd_u.resize(task_size, task_size);
63 m_svd_v.resize(dof, task_size);
64 m_svd_w.resize(task_size);
65
66 m_svd_u_beta.resize(task_size);
67 }
68}
69
70void IK_QJacobian::SetBetas(int id, int /*size*/, const Vector3d &v)
71{
72 m_beta[id + 0] = v.x();
73 m_beta[id + 1] = v.y();
74 m_beta[id + 2] = v.z();
75}
76
77void IK_QJacobian::SetDerivatives(int id, int dof_id, const Vector3d &v, double norm_weight)
78{
79 m_jacobian(id + 0, dof_id) = v.x() * m_weight_sqrt[dof_id];
80 m_jacobian(id + 1, dof_id) = v.y() * m_weight_sqrt[dof_id];
81 m_jacobian(id + 2, dof_id) = v.z() * m_weight_sqrt[dof_id];
82
83 m_d_norm_weight[dof_id] = norm_weight;
84}
85
87{
88 if (m_transpose) {
89 // SVD will decompose Jt into V*W*Ut with U,V orthogonal and W diagonal,
90 // so J = U*W*Vt and Jinv = V*Winv*Ut
91 Eigen::JacobiSVD<MatrixXd> svd(m_jacobian.transpose(),
92 Eigen::ComputeThinU | Eigen::ComputeThinV);
93 m_svd_u = svd.matrixV();
94 m_svd_w = svd.singularValues();
95 m_svd_v = svd.matrixU();
96 }
97 else {
98 // SVD will decompose J into U*W*Vt with U,V orthogonal and W diagonal,
99 // so Jinv = V*Winv*Ut
100 Eigen::JacobiSVD<MatrixXd> svd(m_jacobian, Eigen::ComputeThinU | Eigen::ComputeThinV);
101 m_svd_u = svd.matrixU();
102 m_svd_w = svd.singularValues();
103 m_svd_v = svd.matrixV();
104 }
105
106 if (m_sdls) {
107 InvertSDLS();
108 }
109 else {
110 InvertDLS();
111 }
112}
113
115{
116 double epsilon = 1e-10;
117
118 // compute null space projection based on V
119 int i, j, rank = 0;
120 for (i = 0; i < m_svd_w.size(); i++) {
121 if (m_svd_w[i] > epsilon) {
122 rank++;
123 }
124 }
125
126 if (rank < m_task_size) {
127 return false;
128 }
129
130 MatrixXd basis(m_svd_v.rows(), rank);
131 int b = 0;
132
133 for (i = 0; i < m_svd_w.size(); i++) {
134 if (m_svd_w[i] > epsilon) {
135 for (j = 0; j < m_svd_v.rows(); j++) {
136 basis(j, b) = m_svd_v(j, i);
137 }
138 b++;
139 }
140 }
141
142 m_nullspace = basis * basis.transpose();
143
144 for (i = 0; i < m_nullspace.rows(); i++) {
145 for (j = 0; j < m_nullspace.cols(); j++) {
146 if (i == j) {
147 m_nullspace(i, j) = 1.0 - m_nullspace(i, j);
148 }
149 else {
150 m_nullspace(i, j) = -m_nullspace(i, j);
151 }
152 }
153 }
154
155 return true;
156}
157
159{
160 if (!ComputeNullProjection()) {
161 return;
162 }
163
164 // restrict lower priority jacobian
165 jacobian.Restrict(m_d_theta, m_nullspace);
166
167 // add angle update from lower priority
168 jacobian.Invert();
169
170 // note: now damps secondary angles with minimum damping value from
171 // SDLS, to avoid shaking when the primary task is near singularities,
172 // doesn't work well at all
173 int i;
174 for (i = 0; i < m_d_theta.size(); i++) {
175 m_d_theta[i] = m_d_theta[i] + /*m_min_damp * */ jacobian.AngleUpdate(i);
176 }
177}
178
179void IK_QJacobian::Restrict(VectorXd &d_theta, MatrixXd &nullspace)
180{
181 // subtract part already moved by higher task from beta
182 m_beta = m_beta - m_jacobian * d_theta;
183
184 // note: should we be using the norm of the unrestricted jacobian for SDLS?
185
186 // project jacobian on to null space of higher priority task
187 m_jacobian = m_jacobian * nullspace;
188}
189
190void IK_QJacobian::InvertSDLS()
191{
192 // Compute the dampeds least squeares pseudo inverse of J.
193 //
194 // Since J is usually not invertible (most of the times it's not even
195 // square), the pseudo inverse is used. This gives us a least squares
196 // solution.
197 //
198 // This is fine when the J*Jt is of full rank. When J*Jt is near to
199 // singular the least squares inverse tries to minimize |J(dtheta) - dX)|
200 // and doesn't try to minimize dTheta. This results in erratic changes in
201 // angle. The damped least squares minimizes |dtheta| to try and reduce this
202 // erratic behavior.
203 //
204 // The selectively damped least squares (SDLS) is used here instead of the
205 // DLS. The SDLS damps individual singular values, instead of using a single
206 // damping term.
207
208 double max_angle_change = M_PI_4;
209 double epsilon = 1e-10;
210 int i, j;
211
212 m_d_theta.setZero();
213 m_min_damp = 1.0;
214
215 for (i = 0; i < m_dof; i++) {
216 m_norm[i] = 0.0;
217 for (j = 0; j < m_task_size; j += 3) {
218 double n = 0.0;
219 n += m_jacobian(j, i) * m_jacobian(j, i);
220 n += m_jacobian(j + 1, i) * m_jacobian(j + 1, i);
221 n += m_jacobian(j + 2, i) * m_jacobian(j + 2, i);
222 m_norm[i] += sqrt(n);
223 }
224 }
225
226 for (i = 0; i < m_svd_w.size(); i++) {
227 if (m_svd_w[i] <= epsilon) {
228 continue;
229 }
230
231 double wInv = 1.0 / m_svd_w[i];
232 double alpha = 0.0;
233 double N = 0.0;
234
235 // compute alpha and N
236 for (j = 0; j < m_svd_u.rows(); j += 3) {
237 alpha += m_svd_u(j, i) * m_beta[j];
238 alpha += m_svd_u(j + 1, i) * m_beta[j + 1];
239 alpha += m_svd_u(j + 2, i) * m_beta[j + 2];
240
241 // note: for 1 end effector, N will always be 1, since U is
242 // orthogonal, .. so could be optimized
243 double tmp;
244 tmp = m_svd_u(j, i) * m_svd_u(j, i);
245 tmp += m_svd_u(j + 1, i) * m_svd_u(j + 1, i);
246 tmp += m_svd_u(j + 2, i) * m_svd_u(j + 2, i);
247 N += sqrt(tmp);
248 }
249 alpha *= wInv;
250
251 // compute M, dTheta and max_dtheta
252 double M = 0.0;
253 double max_dtheta = 0.0, abs_dtheta;
254
255 for (j = 0; j < m_d_theta.size(); j++) {
256 double v = m_svd_v(j, i);
257 M += fabs(v) * m_norm[j];
258
259 // compute tmporary dTheta's
260 m_d_theta_tmp[j] = v * alpha;
261
262 // find largest absolute dTheta
263 // multiply with weight to prevent unnecessary damping
264 abs_dtheta = fabs(m_d_theta_tmp[j]) * m_weight_sqrt[j];
265 max_dtheta = std::max(abs_dtheta, max_dtheta);
266 }
267
268 M *= wInv;
269
270 // compute damping term and damp the dTheta's
271 double gamma = max_angle_change;
272 if (N < M) {
273 gamma *= N / M;
274 }
275
276 double damp = (gamma < max_dtheta) ? gamma / max_dtheta : 1.0;
277
278 for (j = 0; j < m_d_theta.size(); j++) {
279 // slight hack: we do 0.80*, so that if there is some oscillation,
280 // the system can still converge (for joint limits). also, it's
281 // better to go a little to slow than to far
282
283 double dofdamp = damp / m_weight[j];
284 dofdamp = std::min(dofdamp, 1.0);
285
286 m_d_theta[j] += 0.80 * dofdamp * m_d_theta_tmp[j];
287 }
288
289 m_min_damp = std::min(damp, m_min_damp);
290 }
291
292 // weight + prevent from doing angle updates with angles > max_angle_change
293 double max_angle = 0.0, abs_angle;
294
295 for (j = 0; j < m_dof; j++) {
296 m_d_theta[j] *= m_weight[j];
297
298 abs_angle = fabs(m_d_theta[j]);
299
300 max_angle = std::max(abs_angle, max_angle);
301 }
302
303 if (max_angle > max_angle_change) {
304 double damp = (max_angle_change) / (max_angle_change + max_angle);
305
306 for (j = 0; j < m_dof; j++) {
307 m_d_theta[j] *= damp;
308 }
309 }
310}
311
312void IK_QJacobian::InvertDLS()
313{
314 // Compute damped least squares inverse of pseudo inverse
315 // Compute damping term lambda
316
317 // Note when lambda is zero this is equivalent to the
318 // least squares solution. This is fine when the m_jjt is
319 // of full rank. When m_jjt is near to singular the least squares
320 // inverse tries to minimize |J(dtheta) - dX)| and doesn't
321 // try to minimize dTheta. This results in erratic changes in angle.
322 // Damped least squares minimizes |dtheta| to try and reduce this
323 // erratic behavior.
324
325 // We don't want to use the damped solution everywhere so we
326 // only increase lamda from zero as we approach a singularity.
327
328 // find the smallest non-zero W value, anything below epsilon is
329 // treated as zero
330
331 double epsilon = 1e-10;
332 double max_angle_change = 0.1;
333 double x_length = sqrt(m_beta.dot(m_beta));
334
335 int i, j;
336 double w_min = std::numeric_limits<double>::max();
337
338 for (i = 0; i < m_svd_w.size(); i++) {
339 if (m_svd_w[i] > epsilon && m_svd_w[i] < w_min) {
340 w_min = m_svd_w[i];
341 }
342 }
343
344 // compute lambda damping term
345
346 double d = x_length / max_angle_change;
347 double lambda;
348
349 if (w_min <= d / 2) {
350 lambda = d / 2;
351 }
352 else if (w_min < d) {
353 lambda = sqrt(w_min * (d - w_min));
354 }
355 else {
356 lambda = 0.0;
357 }
358
359 lambda *= lambda;
360
361 lambda = std::min<double>(lambda, 10);
362
363 // immediately multiply with Beta, so we can do matrix*vector products
364 // rather than matrix*matrix products
365
366 // compute Ut*Beta
367 m_svd_u_beta = m_svd_u.transpose() * m_beta;
368
369 m_d_theta.setZero();
370
371 for (i = 0; i < m_svd_w.size(); i++) {
372 if (m_svd_w[i] > epsilon) {
373 double wInv = m_svd_w[i] / (m_svd_w[i] * m_svd_w[i] + lambda);
374
375 // compute V*Winv*Ut*Beta
376 m_svd_u_beta[i] *= wInv;
377
378 for (j = 0; j < m_d_theta.size(); j++) {
379 m_d_theta[j] += m_svd_v(j, i) * m_svd_u_beta[i];
380 }
381 }
382 }
383
384 for (j = 0; j < m_d_theta.size(); j++) {
385 m_d_theta[j] *= m_weight[j];
386 }
387}
388
389void IK_QJacobian::Lock(int dof_id, double delta)
390{
391 int i;
392
393 for (i = 0; i < m_task_size; i++) {
394 m_beta[i] -= m_jacobian(i, dof_id) * delta;
395 m_jacobian(i, dof_id) = 0.0;
396 }
397
398 m_norm[dof_id] = 0.0; // unneeded
399 m_d_theta[dof_id] = 0.0;
400}
401
402double IK_QJacobian::AngleUpdate(int dof_id) const
403{
404 return m_d_theta[dof_id];
405}
406
408{
409 int i;
410 double mx = 0.0, dtheta_abs;
411
412 for (i = 0; i < m_d_theta.size(); i++) {
413 dtheta_abs = fabs(m_d_theta[i] * m_d_norm_weight[i]);
414 mx = std::max(dtheta_abs, mx);
415 }
416
417 return mx;
418}
419
420void IK_QJacobian::SetDoFWeight(int dof, double weight)
421{
422 m_weight[dof] = weight;
423 m_weight_sqrt[dof] = sqrt(weight);
424}
#define M_PI_4
return true
ATTR_WARN_UNUSED_RESULT const BMVert const BMEdge * e
ATTR_WARN_UNUSED_RESULT const BMVert * v
void Lock(int dof_id, double delta)
void SetDerivatives(int id, int dof_id, const Vector3d &v, double norm_weight)
void SetDoFWeight(int dof, double weight)
void Restrict(VectorXd &d_theta, MatrixXd &nullspace)
void SubTask(IK_QJacobian &jacobian)
double AngleUpdateNorm() const
void SetBetas(int id, int size, const Vector3d &v)
double AngleUpdate(int dof_id) const
void ArmMatrices(int dof, int task_size)
bool ComputeNullProjection()
#define sqrt
ccl_device_inline float2 fabs(const float2 a)
#define M
#define N
double epsilon
default precision while comparing with Equal(..,..) functions. Initialized at 0.0000001.
Definition utility.cpp:22
i
Definition text_draw.cc:230