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