Blender V4.3
IK_QTask.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_QTask.h"
10
11// IK_QTask
12
13IK_QTask::IK_QTask(int size, bool primary, bool active, const IK_QSegment *segment)
14 : m_size(size), m_primary(primary), m_active(active), m_segment(segment), m_weight(1.0)
15{
16}
17
18// IK_QPositionTask
19
20IK_QPositionTask::IK_QPositionTask(bool primary, const IK_QSegment *segment, const Vector3d &goal)
21 : IK_QTask(3, primary, true, segment), m_goal(goal)
22{
23 // computing clamping length
24 int num;
25 const IK_QSegment *seg;
26
27 m_clamp_length = 0.0;
28 num = 0;
29
30 for (seg = m_segment; seg; seg = seg->Parent()) {
31 m_clamp_length += seg->MaxExtension();
32 num++;
33 }
34
35 m_clamp_length /= 2 * num;
36}
37
39{
40 // compute beta
41 const Vector3d &pos = m_segment->GlobalEnd();
42
43 Vector3d d_pos = m_goal - pos;
44 double length = d_pos.norm();
45
46 if (length > m_clamp_length) {
47 d_pos = (m_clamp_length / length) * d_pos;
48 }
49
50 jacobian.SetBetas(m_id, m_size, m_weight * d_pos);
51
52 // compute derivatives
53 int i;
54 const IK_QSegment *seg;
55
56 for (seg = m_segment; seg; seg = seg->Parent()) {
57 Vector3d p = seg->GlobalStart() - pos;
58
59 for (i = 0; i < seg->NumberOfDoF(); i++) {
60 Vector3d axis = seg->Axis(i) * m_weight;
61
62 if (seg->Translational()) {
63 jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e2);
64 }
65 else {
66 Vector3d pa = p.cross(axis);
67 jacobian.SetDerivatives(m_id, seg->DoFId() + i, pa, 1e0);
68 }
69 }
70 }
71}
72
74{
75 const Vector3d &pos = m_segment->GlobalEnd();
76 Vector3d d_pos = m_goal - pos;
77 return d_pos.norm();
78}
79
80// IK_QOrientationTask
81
83 const IK_QSegment *segment,
84 const Matrix3d &goal)
85 : IK_QTask(3, primary, true, segment), m_goal(goal), m_distance(0.0)
86{
87}
88
90{
91 // compute betas
92 const Matrix3d &rot = m_segment->GlobalTransform().linear();
93
94 Matrix3d d_rotm = (m_goal * rot.transpose()).transpose();
95
96 Vector3d d_rot;
97 d_rot = -0.5 * Vector3d(d_rotm(2, 1) - d_rotm(1, 2),
98 d_rotm(0, 2) - d_rotm(2, 0),
99 d_rotm(1, 0) - d_rotm(0, 1));
100
101 m_distance = d_rot.norm();
102
103 jacobian.SetBetas(m_id, m_size, m_weight * d_rot);
104
105 // compute derivatives
106 int i;
107 const IK_QSegment *seg;
108
109 for (seg = m_segment; seg; seg = seg->Parent()) {
110 for (i = 0; i < seg->NumberOfDoF(); i++) {
111
112 if (seg->Translational()) {
113 jacobian.SetDerivatives(m_id, seg->DoFId() + i, Vector3d(0, 0, 0), 1e2);
114 }
115 else {
116 Vector3d axis = seg->Axis(i) * m_weight;
117 jacobian.SetDerivatives(m_id, seg->DoFId() + i, axis, 1e0);
118 }
119 }
120 }
121}
122
123// IK_QCenterOfMassTask
124// NOTE: implementation not finished!
125
127 const IK_QSegment *segment,
128 const Vector3d &goal_center)
129 : IK_QTask(3, primary, true, segment), m_goal_center(goal_center)
130{
131 m_total_mass_inv = ComputeTotalMass(m_segment);
132 if (!FuzzyZero(m_total_mass_inv)) {
133 m_total_mass_inv = 1.0 / m_total_mass_inv;
134 }
135}
136
137double IK_QCenterOfMassTask::ComputeTotalMass(const IK_QSegment *segment)
138{
139 double mass = /*seg->Mass()*/ 1.0;
140
141 const IK_QSegment *seg;
142 for (seg = segment->Child(); seg; seg = seg->Sibling()) {
143 mass += ComputeTotalMass(seg);
144 }
145
146 return mass;
147}
148
149Vector3d IK_QCenterOfMassTask::ComputeCenter(const IK_QSegment *segment)
150{
151 Vector3d center = /*seg->Mass()**/ segment->GlobalStart();
152
153 const IK_QSegment *seg;
154 for (seg = segment->Child(); seg; seg = seg->Sibling()) {
155 center += ComputeCenter(seg);
156 }
157
158 return center;
159}
160
161void IK_QCenterOfMassTask::JacobianSegment(IK_QJacobian &jacobian,
162 Vector3d &center,
163 const IK_QSegment *segment)
164{
165 int i;
166 Vector3d p = center - segment->GlobalStart();
167
168 for (i = 0; i < segment->NumberOfDoF(); i++) {
169 Vector3d axis = segment->Axis(i) * m_weight;
170 axis *= /*segment->Mass()**/ m_total_mass_inv;
171
172 if (segment->Translational()) {
173 jacobian.SetDerivatives(m_id, segment->DoFId() + i, axis, 1e2);
174 }
175 else {
176 Vector3d pa = axis.cross(p);
177 jacobian.SetDerivatives(m_id, segment->DoFId() + i, pa, 1e0);
178 }
179 }
180
181 const IK_QSegment *seg;
182 for (seg = segment->Child(); seg; seg = seg->Sibling()) {
183 JacobianSegment(jacobian, center, seg);
184 }
185}
186
188{
189 Vector3d center = ComputeCenter(m_segment) * m_total_mass_inv;
190
191 // compute beta
192 Vector3d d_pos = m_goal_center - center;
193
194 m_distance = d_pos.norm();
195
196#if 0
197 if (m_distance > m_clamp_length)
198 d_pos = (m_clamp_length / m_distance) * d_pos;
199#endif
200
201 jacobian.SetBetas(m_id, m_size, m_weight * d_pos);
202
203 // compute derivatives
204 JacobianSegment(jacobian, center, m_segment);
205}
206
208{
209 return m_distance;
210}
static bool FuzzyZero(double x)
Definition IK_Math.h:24
btMatrix3x3 transpose() const
Return the transpose of the matrix.
SIMD_FORCE_INLINE btScalar length() const
Return the length of the vector.
Definition btVector3.h:257
void ComputeJacobian(IK_QJacobian &jacobian)
Definition IK_QTask.cpp:187
IK_QCenterOfMassTask(bool primary, const IK_QSegment *segment, const Vector3d &center)
Definition IK_QTask.cpp:126
double Distance() const
Definition IK_QTask.cpp:207
void SetDerivatives(int id, int dof_id, const Vector3d &v, double norm_weight)
void SetBetas(int id, int size, const Vector3d &v)
IK_QOrientationTask(bool primary, const IK_QSegment *segment, const Matrix3d &goal)
Definition IK_QTask.cpp:82
void ComputeJacobian(IK_QJacobian &jacobian)
Definition IK_QTask.cpp:89
void ComputeJacobian(IK_QJacobian &jacobian)
Definition IK_QTask.cpp:38
double Distance() const
Definition IK_QTask.cpp:73
IK_QPositionTask(bool primary, const IK_QSegment *segment, const Vector3d &goal)
Definition IK_QTask.cpp:20
int NumberOfDoF() const
Definition IK_QSegment.h:77
int DoFId() const
Definition IK_QSegment.h:83
const Vector3d GlobalStart() const
const Affine3d & GlobalTransform() const
const Vector3d GlobalEnd() const
bool Translational() const
IK_QSegment * Parent() const
Definition IK_QSegment.h:63
const double MaxExtension() const
Definition IK_QSegment.h:94
virtual Vector3d Axis(int dof) const =0
IK_QSegment * Sibling() const
Definition IK_QSegment.h:58
const IK_QSegment * m_segment
Definition IK_QTask.h:71
double m_weight
Definition IK_QTask.h:72
int m_size
Definition IK_QTask.h:68
int m_id
Definition IK_QTask.h:67
IK_QTask(int size, bool primary, bool active, const IK_QSegment *segment)
Definition IK_QTask.cpp:13
#define rot(x, k)