Blender V4.3
IK_QSegment.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_QSegment.h"
10
11// IK_QSegment
12
13IK_QSegment::IK_QSegment(int num_DoF, bool translational)
14 : m_parent(NULL),
15 m_child(NULL),
16 m_sibling(NULL),
17 m_composite(NULL),
18 m_num_DoF(num_DoF),
19 m_translational(translational)
20{
21 m_locked[0] = m_locked[1] = m_locked[2] = false;
22 m_weight[0] = m_weight[1] = m_weight[2] = 1.0;
23
24 m_max_extension = 0.0;
25
26 m_start = Vector3d(0, 0, 0);
27 m_rest_basis.setIdentity();
28 m_basis.setIdentity();
29 m_translation = Vector3d(0, 0, 0);
30
33}
34
36{
37 m_locked[0] = m_locked[1] = m_locked[2] = false;
38
42
43 for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) {
44 seg->Reset();
45 }
46}
47
48void IK_QSegment::SetTransform(const Vector3d &start,
49 const Matrix3d &rest_basis,
50 const Matrix3d &basis,
51 const double length)
52{
53 m_max_extension = start.norm() + length;
54
55 m_start = start;
56 m_rest_basis = rest_basis;
57
58 m_orig_basis = basis;
59 SetBasis(basis);
60
61 m_translation = Vector3d(0, length, 0);
63}
64
66{
67 return m_orig_basis.transpose() * m_basis;
68}
69
74
76{
77 if (m_parent) {
78 m_parent->RemoveChild(this);
79 }
80
81 for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) {
82 seg->m_parent = NULL;
83 }
84}
85
87{
88 if (m_parent == parent) {
89 return;
90 }
91
92 if (m_parent) {
93 m_parent->RemoveChild(this);
94 }
95
96 if (parent) {
97 m_sibling = parent->m_child;
98 parent->m_child = this;
99 }
100
101 m_parent = parent;
102}
103
105{
106 m_composite = seg;
107}
108
110{
111 if (m_child == NULL) {
112 return;
113 }
114 else if (m_child == child) {
116 }
117 else {
118 IK_QSegment *seg = m_child;
119
120 while (seg->m_sibling != child) {
121 seg = seg->m_sibling;
122 }
123
124 if (child == seg->m_sibling) {
125 seg->m_sibling = child->m_sibling;
126 }
127 }
128}
129
130void IK_QSegment::UpdateTransform(const Affine3d &global)
131{
132 // compute the global transform at the end of the segment
133 m_global_start = global.translation() + global.linear() * m_start;
134
135 m_global_transform.translation() = m_global_start;
136 m_global_transform.linear() = global.linear() * m_rest_basis * m_basis;
138
139 // update child transforms
140 for (IK_QSegment *seg = m_child; seg; seg = seg->m_sibling) {
141 seg->UpdateTransform(m_global_transform);
142 }
143}
144
145void IK_QSegment::PrependBasis(const Matrix3d &mat)
146{
147 m_basis = m_rest_basis.inverse() * mat * m_rest_basis * m_basis;
148}
149
150void IK_QSegment::Scale(double scale)
151{
152 m_start *= scale;
153 m_translation *= scale;
154 m_orig_translation *= scale;
155 m_global_start *= scale;
156 m_global_transform.translation() *= scale;
157 m_max_extension *= scale;
158}
159
160// IK_QSphericalSegment
161
163 : IK_QSegment(3, false), m_limit_x(false), m_limit_y(false), m_limit_z(false)
164{
165}
166
167Vector3d IK_QSphericalSegment::Axis(int dof) const
168{
169 return m_global_transform.linear().col(dof);
170}
171
172void IK_QSphericalSegment::SetLimit(int axis, double lmin, double lmax)
173{
174 if (lmin > lmax) {
175 return;
176 }
177
178 if (axis == 1) {
179 lmin = Clamp(lmin, -M_PI, M_PI);
180 lmax = Clamp(lmax, -M_PI, M_PI);
181
182 m_min_y = lmin;
183 m_max_y = lmax;
184
185 m_limit_y = true;
186 }
187 else {
188 // clamp and convert to axis angle parameters
189 lmin = Clamp(lmin, -M_PI, M_PI);
190 lmax = Clamp(lmax, -M_PI, M_PI);
191
192 lmin = sin(lmin * 0.5);
193 lmax = sin(lmax * 0.5);
194
195 if (axis == 0) {
196 m_min[0] = -lmax;
197 m_max[0] = -lmin;
198 m_limit_x = true;
199 }
200 else if (axis == 2) {
201 m_min[1] = -lmax;
202 m_max[1] = -lmin;
203 m_limit_z = true;
204 }
205 }
206}
207
208void IK_QSphericalSegment::SetWeight(int axis, double weight)
209{
210 m_weight[axis] = weight;
211}
212
213bool IK_QSphericalSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
214{
215 if (m_locked[0] && m_locked[1] && m_locked[2]) {
216 return false;
217 }
218
219 Vector3d dq;
220 dq.x() = jacobian.AngleUpdate(m_DoF_id);
221 dq.y() = jacobian.AngleUpdate(m_DoF_id + 1);
222 dq.z() = jacobian.AngleUpdate(m_DoF_id + 2);
223
224 // Directly update the rotation matrix, with Rodrigues' rotation formula,
225 // to avoid singularities and allow smooth integration.
226
227 double theta = dq.norm();
228
229 if (!FuzzyZero(theta)) {
230 Vector3d w = dq * (1.0 / theta);
231
232 double sine = sin(theta);
233 double cosine = cos(theta);
234 double cosineInv = 1 - cosine;
235
236 double xsine = w.x() * sine;
237 double ysine = w.y() * sine;
238 double zsine = w.z() * sine;
239
240 double xxcosine = w.x() * w.x() * cosineInv;
241 double xycosine = w.x() * w.y() * cosineInv;
242 double xzcosine = w.x() * w.z() * cosineInv;
243 double yycosine = w.y() * w.y() * cosineInv;
244 double yzcosine = w.y() * w.z() * cosineInv;
245 double zzcosine = w.z() * w.z() * cosineInv;
246
247 Matrix3d M = CreateMatrix(cosine + xxcosine,
248 -zsine + xycosine,
249 ysine + xzcosine,
250 zsine + xycosine,
251 cosine + yycosine,
252 -xsine + yzcosine,
253 -ysine + xzcosine,
254 xsine + yzcosine,
255 cosine + zzcosine);
256
257 m_new_basis = m_basis * M;
258 }
259 else {
260 m_new_basis = m_basis;
261 }
262
263 if (m_limit_y == false && m_limit_x == false && m_limit_z == false) {
264 return false;
265 }
266
267 Vector3d a = SphericalRangeParameters(m_new_basis);
268
269 if (m_locked[0]) {
270 a.x() = m_locked_ax;
271 }
272 if (m_locked[1]) {
273 a.y() = m_locked_ay;
274 }
275 if (m_locked[2]) {
276 a.z() = m_locked_az;
277 }
278
279 double ax = a.x(), ay = a.y(), az = a.z();
280
281 clamp[0] = clamp[1] = clamp[2] = false;
282
283 if (m_limit_y) {
284 if (a.y() > m_max_y) {
285 ay = m_max_y;
286 clamp[1] = true;
287 }
288 else if (a.y() < m_min_y) {
289 ay = m_min_y;
290 clamp[1] = true;
291 }
292 }
293
294 if (m_limit_x && m_limit_z) {
295 if (EllipseClamp(ax, az, m_min, m_max)) {
296 clamp[0] = clamp[2] = true;
297 }
298 }
299 else if (m_limit_x) {
300 if (ax < m_min[0]) {
301 ax = m_min[0];
302 clamp[0] = true;
303 }
304 else if (ax > m_max[0]) {
305 ax = m_max[0];
306 clamp[0] = true;
307 }
308 }
309 else if (m_limit_z) {
310 if (az < m_min[1]) {
311 az = m_min[1];
312 clamp[2] = true;
313 }
314 else if (az > m_max[1]) {
315 az = m_max[1];
316 clamp[2] = true;
317 }
318 }
319
320 if (clamp[0] == false && clamp[1] == false && clamp[2] == false) {
321 if (m_locked[0] || m_locked[1] || m_locked[2]) {
322 m_new_basis = ComputeSwingMatrix(ax, az) * ComputeTwistMatrix(ay);
323 }
324 return false;
325 }
326
327 m_new_basis = ComputeSwingMatrix(ax, az) * ComputeTwistMatrix(ay);
328
329 delta = MatrixToAxisAngle(m_basis.transpose() * m_new_basis);
330
331 if (!(m_locked[0] || m_locked[2]) && (clamp[0] || clamp[2])) {
332 m_locked_ax = ax;
333 m_locked_az = az;
334 }
335
336 if (!m_locked[1] && clamp[1]) {
337 m_locked_ay = ay;
338 }
339
340 return true;
341}
342
343void IK_QSphericalSegment::Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
344{
345 if (dof == 1) {
346 m_locked[1] = true;
347 jacobian.Lock(m_DoF_id + 1, delta[1]);
348 }
349 else {
350 m_locked[0] = m_locked[2] = true;
351 jacobian.Lock(m_DoF_id, delta[0]);
352 jacobian.Lock(m_DoF_id + 2, delta[2]);
353 }
354}
355
357{
358 m_basis = m_new_basis;
359}
360
361// IK_QNullSegment
362
364
365// IK_QRevoluteSegment
366
368 : IK_QSegment(1, false), m_axis(axis), m_angle(0.0), m_limit(false)
369{
370}
371
372void IK_QRevoluteSegment::SetBasis(const Matrix3d &basis)
373{
374 if (m_axis == 1) {
375 m_angle = ComputeTwist(basis);
376 m_basis = ComputeTwistMatrix(m_angle);
377 }
378 else {
379 m_angle = EulerAngleFromMatrix(basis, m_axis);
380 m_basis = RotationMatrix(m_angle, m_axis);
381 }
382}
383
384Vector3d IK_QRevoluteSegment::Axis(int) const
385{
386 return m_global_transform.linear().col(m_axis);
387}
388
389bool IK_QRevoluteSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
390{
391 if (m_locked[0]) {
392 return false;
393 }
394
395 m_new_angle = m_angle + jacobian.AngleUpdate(m_DoF_id);
396
397 clamp[0] = false;
398
399 if (m_limit == false) {
400 return false;
401 }
402
403 if (m_new_angle > m_max) {
404 delta[0] = m_max - m_angle;
405 }
406 else if (m_new_angle < m_min) {
407 delta[0] = m_min - m_angle;
408 }
409 else {
410 return false;
411 }
412
413 clamp[0] = true;
414 m_new_angle = m_angle + delta[0];
415
416 return true;
417}
418
419void IK_QRevoluteSegment::Lock(int, IK_QJacobian &jacobian, Vector3d &delta)
420{
421 m_locked[0] = true;
422 jacobian.Lock(m_DoF_id, delta[0]);
423}
424
426{
427 m_angle = m_new_angle;
428 m_basis = RotationMatrix(m_angle, m_axis);
429}
430
431void IK_QRevoluteSegment::SetLimit(int axis, double lmin, double lmax)
432{
433 if (lmin > lmax || m_axis != axis) {
434 return;
435 }
436
437 // clamp and convert to axis angle parameters
438 lmin = Clamp(lmin, -M_PI, M_PI);
439 lmax = Clamp(lmax, -M_PI, M_PI);
440
441 m_min = lmin;
442 m_max = lmax;
443
444 m_limit = true;
445}
446
447void IK_QRevoluteSegment::SetWeight(int axis, double weight)
448{
449 if (axis == m_axis) {
450 m_weight[0] = weight;
451 }
452}
453
454// IK_QSwingSegment
455
457
458void IK_QSwingSegment::SetBasis(const Matrix3d &basis)
459{
460 m_basis = basis;
462}
463
464Vector3d IK_QSwingSegment::Axis(int dof) const
465{
466 return m_global_transform.linear().col((dof == 0) ? 0 : 2);
467}
468
469bool IK_QSwingSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
470{
471 if (m_locked[0] && m_locked[1]) {
472 return false;
473 }
474
475 Vector3d dq;
476 dq.x() = jacobian.AngleUpdate(m_DoF_id);
477 dq.y() = 0.0;
478 dq.z() = jacobian.AngleUpdate(m_DoF_id + 1);
479
480 // Directly update the rotation matrix, with Rodrigues' rotation formula,
481 // to avoid singularities and allow smooth integration.
482
483 double theta = dq.norm();
484
485 if (!FuzzyZero(theta)) {
486 Vector3d w = dq * (1.0 / theta);
487
488 double sine = sin(theta);
489 double cosine = cos(theta);
490 double cosineInv = 1 - cosine;
491
492 double xsine = w.x() * sine;
493 double zsine = w.z() * sine;
494
495 double xxcosine = w.x() * w.x() * cosineInv;
496 double xzcosine = w.x() * w.z() * cosineInv;
497 double zzcosine = w.z() * w.z() * cosineInv;
498
499 Matrix3d M = CreateMatrix(cosine + xxcosine,
500 -zsine,
501 xzcosine,
502 zsine,
503 cosine,
504 -xsine,
505 xzcosine,
506 xsine,
507 cosine + zzcosine);
508
509 m_new_basis = m_basis * M;
510
511 RemoveTwist(m_new_basis);
512 }
513 else {
514 m_new_basis = m_basis;
515 }
516
517 if (m_limit_x == false && m_limit_z == false) {
518 return false;
519 }
520
521 Vector3d a = SphericalRangeParameters(m_new_basis);
522 double ax = 0, az = 0;
523
524 clamp[0] = clamp[1] = false;
525
526 if (m_limit_x && m_limit_z) {
527 ax = a.x();
528 az = a.z();
529
530 if (EllipseClamp(ax, az, m_min, m_max)) {
531 clamp[0] = clamp[1] = true;
532 }
533 }
534 else if (m_limit_x) {
535 if (ax < m_min[0]) {
536 ax = m_min[0];
537 clamp[0] = true;
538 }
539 else if (ax > m_max[0]) {
540 ax = m_max[0];
541 clamp[0] = true;
542 }
543 }
544 else if (m_limit_z) {
545 if (az < m_min[1]) {
546 az = m_min[1];
547 clamp[1] = true;
548 }
549 else if (az > m_max[1]) {
550 az = m_max[1];
551 clamp[1] = true;
552 }
553 }
554
555 if (clamp[0] == false && clamp[1] == false) {
556 return false;
557 }
558
559 m_new_basis = ComputeSwingMatrix(ax, az);
560
561 delta = MatrixToAxisAngle(m_basis.transpose() * m_new_basis);
562 delta[1] = delta[2];
563 delta[2] = 0.0;
564
565 return true;
566}
567
568void IK_QSwingSegment::Lock(int, IK_QJacobian &jacobian, Vector3d &delta)
569{
570 m_locked[0] = m_locked[1] = true;
571 jacobian.Lock(m_DoF_id, delta[0]);
572 jacobian.Lock(m_DoF_id + 1, delta[1]);
573}
574
576{
577 m_basis = m_new_basis;
578}
579
580void IK_QSwingSegment::SetLimit(int axis, double lmin, double lmax)
581{
582 if (lmin > lmax) {
583 return;
584 }
585
586 // clamp and convert to axis angle parameters
587 lmin = Clamp(lmin, -M_PI, M_PI);
588 lmax = Clamp(lmax, -M_PI, M_PI);
589
590 lmin = sin(lmin * 0.5);
591 lmax = sin(lmax * 0.5);
592
593 // put center of ellispe in the middle between min and max
594 double offset = 0.5 * (lmin + lmax);
595 // lmax = lmax - offset;
596
597 if (axis == 0) {
598 m_min[0] = -lmax;
599 m_max[0] = -lmin;
600
601 m_limit_x = true;
602 m_offset_x = offset;
603 m_max_x = lmax;
604 }
605 else if (axis == 2) {
606 m_min[1] = -lmax;
607 m_max[1] = -lmin;
608
609 m_limit_z = true;
610 m_offset_z = offset;
611 m_max_z = lmax;
612 }
613}
614
615void IK_QSwingSegment::SetWeight(int axis, double weight)
616{
617 if (axis == 0) {
618 m_weight[0] = weight;
619 }
620 else if (axis == 2) {
621 m_weight[1] = weight;
622 }
623}
624
625// IK_QElbowSegment
626
628 : IK_QSegment(2, false),
629 m_axis(axis),
630 m_twist(0.0),
631 m_angle(0.0),
632 m_cos_twist(1.0),
633 m_sin_twist(0.0),
634 m_limit(false),
635 m_limit_twist(false)
636{
637}
638
639void IK_QElbowSegment::SetBasis(const Matrix3d &basis)
640{
641 m_basis = basis;
642
643 m_twist = ComputeTwist(m_basis);
645 m_angle = EulerAngleFromMatrix(basis, m_axis);
646
647 m_basis = RotationMatrix(m_angle, m_axis) * ComputeTwistMatrix(m_twist);
648}
649
650Vector3d IK_QElbowSegment::Axis(int dof) const
651{
652 if (dof == 0) {
653 Vector3d v;
654 if (m_axis == 0) {
655 v = Vector3d(m_cos_twist, 0, m_sin_twist);
656 }
657 else {
658 v = Vector3d(-m_sin_twist, 0, m_cos_twist);
659 }
660
661 return m_global_transform.linear() * v;
662 }
663 else {
664 return m_global_transform.linear().col(1);
665 }
666}
667
668bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
669{
670 if (m_locked[0] && m_locked[1]) {
671 return false;
672 }
673
674 clamp[0] = clamp[1] = false;
675
676 if (!m_locked[0]) {
677 m_new_angle = m_angle + jacobian.AngleUpdate(m_DoF_id);
678
679 if (m_limit) {
680 if (m_new_angle > m_max) {
681 delta[0] = m_max - m_angle;
682 m_new_angle = m_max;
683 clamp[0] = true;
684 }
685 else if (m_new_angle < m_min) {
686 delta[0] = m_min - m_angle;
687 m_new_angle = m_min;
688 clamp[0] = true;
689 }
690 }
691 }
692
693 if (!m_locked[1]) {
694 m_new_twist = m_twist + jacobian.AngleUpdate(m_DoF_id + 1);
695
696 if (m_limit_twist) {
697 if (m_new_twist > m_max_twist) {
698 delta[1] = m_max_twist - m_twist;
699 m_new_twist = m_max_twist;
700 clamp[1] = true;
701 }
702 else if (m_new_twist < m_min_twist) {
703 delta[1] = m_min_twist - m_twist;
704 m_new_twist = m_min_twist;
705 clamp[1] = true;
706 }
707 }
708 }
709
710 return (clamp[0] || clamp[1]);
711}
712
713void IK_QElbowSegment::Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
714{
715 if (dof == 0) {
716 m_locked[0] = true;
717 jacobian.Lock(m_DoF_id, delta[0]);
718 }
719 else {
720 m_locked[1] = true;
721 jacobian.Lock(m_DoF_id + 1, delta[1]);
722 }
723}
724
726{
727 m_angle = m_new_angle;
728 m_twist = m_new_twist;
729
730 m_sin_twist = sin(m_twist);
731 m_cos_twist = cos(m_twist);
732
733 Matrix3d A = RotationMatrix(m_angle, m_axis);
734 Matrix3d T = RotationMatrix(m_sin_twist, m_cos_twist, 1);
735
736 m_basis = A * T;
737}
738
739void IK_QElbowSegment::SetLimit(int axis, double lmin, double lmax)
740{
741 if (lmin > lmax) {
742 return;
743 }
744
745 // clamp and convert to axis angle parameters
746 lmin = Clamp(lmin, -M_PI, M_PI);
747 lmax = Clamp(lmax, -M_PI, M_PI);
748
749 if (axis == 1) {
750 m_min_twist = lmin;
751 m_max_twist = lmax;
752 m_limit_twist = true;
753 }
754 else if (axis == m_axis) {
755 m_min = lmin;
756 m_max = lmax;
757 m_limit = true;
758 }
759}
760
761void IK_QElbowSegment::SetWeight(int axis, double weight)
762{
763 if (axis == m_axis) {
764 m_weight[0] = weight;
765 }
766 else if (axis == 1) {
767 m_weight[1] = weight;
768 }
769}
770
771// IK_QTranslateSegment
772
774{
775 m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = false;
776 m_axis_enabled[axis1] = true;
777
778 m_axis[0] = axis1;
779
780 m_limit[0] = m_limit[1] = m_limit[2] = false;
781}
782
784{
785 m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = false;
786 m_axis_enabled[axis1] = true;
787 m_axis_enabled[axis2] = true;
788
789 m_axis[0] = axis1;
790 m_axis[1] = axis2;
791
792 m_limit[0] = m_limit[1] = m_limit[2] = false;
793}
794
796{
797 m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = true;
798
799 m_axis[0] = 0;
800 m_axis[1] = 1;
801 m_axis[2] = 2;
802
803 m_limit[0] = m_limit[1] = m_limit[2] = false;
804}
805
806Vector3d IK_QTranslateSegment::Axis(int dof) const
807{
808 return m_global_transform.linear().col(m_axis[dof]);
809}
810
811bool IK_QTranslateSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
812{
813 int dof_id = m_DoF_id, dof = 0, i, clamped = false;
814
815 Vector3d dx(0.0, 0.0, 0.0);
816
817 for (i = 0; i < 3; i++) {
818 if (!m_axis_enabled[i]) {
819 m_new_translation[i] = m_translation[i];
820 continue;
821 }
822
823 clamp[dof] = false;
824
825 if (!m_locked[dof]) {
826 m_new_translation[i] = m_translation[i] + jacobian.AngleUpdate(dof_id);
827
828 if (m_limit[i]) {
829 if (m_new_translation[i] > m_max[i]) {
830 delta[dof] = m_max[i] - m_translation[i];
831 m_new_translation[i] = m_max[i];
832 clamped = clamp[dof] = true;
833 }
834 else if (m_new_translation[i] < m_min[i]) {
835 delta[dof] = m_min[i] - m_translation[i];
836 m_new_translation[i] = m_min[i];
837 clamped = clamp[dof] = true;
838 }
839 }
840 }
841
842 dof_id++;
843 dof++;
844 }
845
846 return clamped;
847}
848
850{
851 m_translation = m_new_translation;
852}
853
854void IK_QTranslateSegment::Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
855{
856 m_locked[dof] = true;
857 jacobian.Lock(m_DoF_id + dof, delta[dof]);
858}
859
860void IK_QTranslateSegment::SetWeight(int axis, double weight)
861{
862 int i;
863
864 for (i = 0; i < m_num_DoF; i++) {
865 if (m_axis[i] == axis) {
866 m_weight[i] = weight;
867 }
868 }
869}
870
871void IK_QTranslateSegment::SetLimit(int axis, double lmin, double lmax)
872{
873 if (lmax < lmin) {
874 return;
875 }
876
877 m_min[axis] = lmin;
878 m_max[axis] = lmax;
879 m_limit[axis] = true;
880}
881
883{
884 int i;
885
886 IK_QSegment::Scale(scale);
887
888 for (i = 0; i < 3; i++) {
889 m_min[0] *= scale;
890 m_max[1] *= scale;
891 }
892
893 m_new_translation *= scale;
894}
#define M_PI
static void RemoveTwist(Eigen::Matrix3d &R)
Definition IK_Math.h:146
static bool EllipseClamp(double &ax, double &az, double *amin, double *amax)
Definition IK_Math.h:207
static Eigen::Matrix3d CreateMatrix(double xx, double xy, double xz, double yx, double yy, double yz, double zx, double zy, double zz)
Definition IK_Math.h:34
static Eigen::Vector3d MatrixToAxisAngle(const Eigen::Matrix3d &R)
Definition IK_Math.h:193
static Eigen::Matrix3d RotationMatrix(double sine, double cosine, int axis)
Definition IK_Math.h:57
static Eigen::Matrix3d ComputeTwistMatrix(double tau)
Definition IK_Math.h:141
static Eigen::Vector3d SphericalRangeParameters(const Eigen::Matrix3d &R)
Definition IK_Math.h:158
static Eigen::Matrix3d ComputeSwingMatrix(double ax, double az)
Definition IK_Math.h:181
static bool FuzzyZero(double x)
Definition IK_Math.h:24
Group Output data from inside of a node group A color picker Mix two input colors RGB to Convert a color s luminance to a grayscale value Generate a normal vector and a dot product Brightness Control the brightness and contrast of the input color Vector Map input vector components with curves Camera Retrieve information about the camera and how it relates to the current shading point s position Clamp
ATTR_WARN_UNUSED_RESULT const BMVert * v
btAngularLimit m_limit
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
Vector3d Axis(int dof) const
void SetLimit(int axis, double lmin, double lmax)
IK_QElbowSegment(int axis)
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
void SetWeight(int axis, double weight)
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
void SetBasis(const Matrix3d &basis)
void Lock(int dof_id, double delta)
double AngleUpdate(int dof_id) const
void SetWeight(int axis, double weight)
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
Vector3d Axis(int dof) const
IK_QRevoluteSegment(int axis)
void SetBasis(const Matrix3d &basis)
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
void SetLimit(int axis, double lmin, double lmax)
virtual void SetBasis(const Matrix3d &basis)
Vector3d m_start
virtual EIGEN_MAKE_ALIGNED_OPERATOR_NEW ~IK_QSegment()
Vector3d m_translation
Matrix3d m_basis
Vector3d m_orig_translation
Vector3d m_global_start
void UpdateTransform(const Affine3d &global)
IK_QSegment * m_sibling
bool m_locked[3]
Matrix3d m_orig_basis
Affine3d m_global_transform
double m_max_extension
virtual void Scale(double scale)
IK_QSegment * m_child
double m_weight[3]
Matrix3d m_rest_basis
IK_QSegment * m_parent
void SetComposite(IK_QSegment *seg)
Matrix3d BasisChange() const
IK_QSegment(int num_DoF, bool translational)
void PrependBasis(const Matrix3d &mat)
void SetParent(IK_QSegment *parent)
IK_QSegment * m_composite
void RemoveChild(IK_QSegment *child)
Vector3d TranslationChange() const
void SetTransform(const Vector3d &start, const Matrix3d &rest_basis, const Matrix3d &basis, const double length)
void SetWeight(int axis, double weight)
Vector3d Axis(int dof) const
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
void SetLimit(int axis, double lmin, double lmax)
void SetWeight(int axis, double weight)
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
Vector3d Axis(int dof) const
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
void SetLimit(int axis, double lmin, double lmax)
void SetBasis(const Matrix3d &basis)
void SetWeight(int axis, double weight)
void Lock(int, IK_QJacobian &, Vector3d &)
void Scale(double scale)
Vector3d Axis(int dof) const
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
void SetLimit(int axis, double lmin, double lmax)
#define NULL
static double ComputeTwist(const KDL::Rotation &R)
static double EulerAngleFromMatrix(const KDL::Rotation &R, int axis)
ccl_device_inline float3 cos(float3 v)
#define M
#define T