Blender V5.0
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
8
9#include "IK_QSegment.h"
10
11// IK_QSegment
12
13IK_QSegment::IK_QSegment(int num_DoF, bool translational)
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 = nullptr;
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 == nullptr) {
112 return;
113 }
114 if (m_child == child) {
115 m_child = m_child->m_sibling;
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 /*dof*/) 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 /*dof*/, 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 /*dof*/, 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 return m_global_transform.linear().col(1);
664}
665
666bool IK_QElbowSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
667{
668 if (m_locked[0] && m_locked[1]) {
669 return false;
670 }
671
672 clamp[0] = clamp[1] = false;
673
674 if (!m_locked[0]) {
675 m_new_angle = m_angle + jacobian.AngleUpdate(m_DoF_id);
676
677 if (m_limit) {
678 if (m_new_angle > m_max) {
679 delta[0] = m_max - m_angle;
680 m_new_angle = m_max;
681 clamp[0] = true;
682 }
683 else if (m_new_angle < m_min) {
684 delta[0] = m_min - m_angle;
685 m_new_angle = m_min;
686 clamp[0] = true;
687 }
688 }
689 }
690
691 if (!m_locked[1]) {
692 m_new_twist = m_twist + jacobian.AngleUpdate(m_DoF_id + 1);
693
694 if (m_limit_twist) {
695 if (m_new_twist > m_max_twist) {
696 delta[1] = m_max_twist - m_twist;
697 m_new_twist = m_max_twist;
698 clamp[1] = true;
699 }
700 else if (m_new_twist < m_min_twist) {
701 delta[1] = m_min_twist - m_twist;
702 m_new_twist = m_min_twist;
703 clamp[1] = true;
704 }
705 }
706 }
707
708 return (clamp[0] || clamp[1]);
709}
710
711void IK_QElbowSegment::Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
712{
713 if (dof == 0) {
714 m_locked[0] = true;
715 jacobian.Lock(m_DoF_id, delta[0]);
716 }
717 else {
718 m_locked[1] = true;
719 jacobian.Lock(m_DoF_id + 1, delta[1]);
720 }
721}
722
724{
725 m_angle = m_new_angle;
726 m_twist = m_new_twist;
727
728 m_sin_twist = sin(m_twist);
729 m_cos_twist = cos(m_twist);
730
731 Matrix3d A = RotationMatrix(m_angle, m_axis);
732 Matrix3d T = RotationMatrix(m_sin_twist, m_cos_twist, 1);
733
734 m_basis = A * T;
735}
736
737void IK_QElbowSegment::SetLimit(int axis, double lmin, double lmax)
738{
739 if (lmin > lmax) {
740 return;
741 }
742
743 // clamp and convert to axis angle parameters
744 lmin = Clamp(lmin, -M_PI, M_PI);
745 lmax = Clamp(lmax, -M_PI, M_PI);
746
747 if (axis == 1) {
748 m_min_twist = lmin;
749 m_max_twist = lmax;
750 m_limit_twist = true;
751 }
752 else if (axis == m_axis) {
753 m_min = lmin;
754 m_max = lmax;
755 m_limit = true;
756 }
757}
758
759void IK_QElbowSegment::SetWeight(int axis, double weight)
760{
761 if (axis == m_axis) {
762 m_weight[0] = weight;
763 }
764 else if (axis == 1) {
765 m_weight[1] = weight;
766 }
767}
768
769// IK_QTranslateSegment
770
772{
773 m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = false;
774 m_axis_enabled[axis1] = true;
775
776 m_axis[0] = axis1;
777
778 m_limit[0] = m_limit[1] = m_limit[2] = false;
779}
780
782{
783 m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = false;
784 m_axis_enabled[axis1] = true;
785 m_axis_enabled[axis2] = true;
786
787 m_axis[0] = axis1;
788 m_axis[1] = axis2;
789
790 m_limit[0] = m_limit[1] = m_limit[2] = false;
791}
792
794{
795 m_axis_enabled[0] = m_axis_enabled[1] = m_axis_enabled[2] = true;
796
797 m_axis[0] = 0;
798 m_axis[1] = 1;
799 m_axis[2] = 2;
800
801 m_limit[0] = m_limit[1] = m_limit[2] = false;
802}
803
804Vector3d IK_QTranslateSegment::Axis(int dof) const
805{
806 return m_global_transform.linear().col(m_axis[dof]);
807}
808
809bool IK_QTranslateSegment::UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp)
810{
811 int dof_id = m_DoF_id, dof = 0, i, clamped = false;
812
813 Vector3d dx(0.0, 0.0, 0.0);
814
815 for (i = 0; i < 3; i++) {
816 if (!m_axis_enabled[i]) {
817 m_new_translation[i] = m_translation[i];
818 continue;
819 }
820
821 clamp[dof] = false;
822
823 if (!m_locked[dof]) {
824 m_new_translation[i] = m_translation[i] + jacobian.AngleUpdate(dof_id);
825
826 if (m_limit[i]) {
827 if (m_new_translation[i] > m_max[i]) {
828 delta[dof] = m_max[i] - m_translation[i];
829 m_new_translation[i] = m_max[i];
830 clamped = clamp[dof] = true;
831 }
832 else if (m_new_translation[i] < m_min[i]) {
833 delta[dof] = m_min[i] - m_translation[i];
834 m_new_translation[i] = m_min[i];
835 clamped = clamp[dof] = true;
836 }
837 }
838 }
839
840 dof_id++;
841 dof++;
842 }
843
844 return clamped;
845}
846
848{
849 m_translation = m_new_translation;
850}
851
852void IK_QTranslateSegment::Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
853{
854 m_locked[dof] = true;
855 jacobian.Lock(m_DoF_id + dof, delta[dof]);
856}
857
858void IK_QTranslateSegment::SetWeight(int axis, double weight)
859{
860 int i;
861
862 for (i = 0; i < m_num_DoF; i++) {
863 if (m_axis[i] == axis) {
864 m_weight[i] = weight;
865 }
866 }
867}
868
869void IK_QTranslateSegment::SetLimit(int axis, double lmin, double lmax)
870{
871 if (lmax < lmin) {
872 return;
873 }
874
875 m_min[axis] = lmin;
876 m_max[axis] = lmax;
877 m_limit[axis] = true;
878}
879
881{
882 int i;
883
884 IK_QSegment::Scale(scale);
885
886 for (i = 0; i < 3; i++) {
887 m_min[0] *= scale;
888 m_max[1] *= scale;
889 }
890
891 m_new_translation *= scale;
892}
#define M_PI
static void RemoveTwist(Eigen::Matrix3d &R)
Definition IK_Math.h:138
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:35
static Eigen::Vector3d MatrixToAxisAngle(const Eigen::Matrix3d &R)
Definition IK_Math.h:185
static double Clamp(const double x, const double min, const double max)
Definition IK_Math.h:30
static Eigen::Matrix3d RotationMatrix(double sine, double cosine, int axis)
Definition IK_Math.h:58
static Eigen::Matrix3d ComputeTwistMatrix(double tau)
Definition IK_Math.h:133
static Eigen::Vector3d SphericalRangeParameters(const Eigen::Matrix3d &R)
Definition IK_Math.h:150
static Eigen::Matrix3d ComputeSwingMatrix(double ax, double az)
Definition IK_Math.h:173
static bool EllipseClamp(double &ax, double &az, const double *amin, const double *amax)
Definition IK_Math.h:199
static bool FuzzyZero(double x)
Definition IK_Math.h:25
return true
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
SIMD_FORCE_INLINE const btScalar & w() const
Return the w value.
Definition btQuadWord.h:119
IK_QElbowSegment(int axis)
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta) override
void SetLimit(int axis, double lmin, double lmax) override
void SetWeight(int axis, double weight) override
void UpdateAngleApply() override
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) override
Vector3d Axis(int dof) const override
void SetBasis(const Matrix3d &basis) override
void Lock(int dof_id, double delta)
double AngleUpdate(int dof_id) const
void UpdateAngleApply() override
IK_QRevoluteSegment(int axis)
Vector3d Axis(int dof) const override
void SetBasis(const Matrix3d &basis) override
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta) override
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) override
void SetWeight(int axis, double weight) override
void SetLimit(int axis, double lmin, double lmax) override
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
bool m_translational
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) override
Vector3d Axis(int dof) const override
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) override
void UpdateAngleApply() override
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta) override
void SetLimit(int axis, double lmin, double lmax) override
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) override
void UpdateAngleApply() override
void SetLimit(int axis, double lmin, double lmax) override
Vector3d Axis(int dof) const override
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta) override
void SetWeight(int axis, double weight) override
void SetBasis(const Matrix3d &basis) override
void SetWeight(int axis, double weight) override
void SetLimit(int axis, double lmin, double lmax) override
void UpdateAngleApply() override
void Scale(double scale) override
Vector3d Axis(int dof) const override
bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp) override
void Lock(int, IK_QJacobian &, Vector3d &) override
#define sin
#define cos
constexpr T clamp(T, U, U) RET
float length(VecOp< float, D >) RET
static double ComputeTwist(const KDL::Rotation &R)
static double EulerAngleFromMatrix(const KDL::Rotation &R, int axis)
#define M
#define T
i
Definition text_draw.cc:230