Blender  V2.93
IK_QSegment.h
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  *
16  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
17  * All rights reserved.
18  * Original author: Laurence
19  */
20 
25 #pragma once
26 
27 #include "IK_Math.h"
28 #include "IK_QJacobian.h"
29 
30 #include <vector>
31 
52 class IK_QSegment {
53  public:
54  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
55  virtual ~IK_QSegment();
56 
57  // start: a user defined translation
58  // rest_basis: a user defined rotation
59  // basis: a user defined rotation
60  // length: length of this segment
61 
62  void SetTransform(const Vector3d &start,
63  const Matrix3d &rest_basis,
64  const Matrix3d &basis,
65  const double length);
66 
67  // tree structure access
68  void SetParent(IK_QSegment *parent);
69 
70  IK_QSegment *Child() const
71  {
72  return m_child;
73  }
74 
76  {
77  return m_sibling;
78  }
79 
81  {
82  return m_parent;
83  }
84 
85  // for combining two joints into one from the interface
86  void SetComposite(IK_QSegment *seg);
87 
89  {
90  return m_composite;
91  }
92 
93  // number of degrees of freedom
94  int NumberOfDoF() const
95  {
96  return m_num_DoF;
97  }
98 
99  // unique id for this segment, for identification in the jacobian
100  int DoFId() const
101  {
102  return m_DoF_id;
103  }
104 
105  void SetDoFId(int dof_id)
106  {
107  m_DoF_id = dof_id;
108  }
109 
110  // the max distance of the end of this bone from the local origin.
111  const double MaxExtension() const
112  {
113  return m_max_extension;
114  }
115 
116  // the change in rotation and translation w.r.t. the rest pose
117  Matrix3d BasisChange() const;
118  Vector3d TranslationChange() const;
119 
120  // the start and end of the segment
121  const Vector3d GlobalStart() const
122  {
123  return m_global_start;
124  }
125 
126  const Vector3d GlobalEnd() const
127  {
128  return m_global_transform.translation();
129  }
130 
131  // the global transformation at the end of the segment
132  const Affine3d &GlobalTransform() const
133  {
134  return m_global_transform;
135  }
136 
137  // is a translational segment?
138  bool Translational() const
139  {
140  return m_translational;
141  }
142 
143  // locking (during inner clamping loop)
144  bool Locked(int dof) const
145  {
146  return m_locked[dof];
147  }
148 
149  void UnLock()
150  {
151  m_locked[0] = m_locked[1] = m_locked[2] = false;
152  }
153 
154  // per dof joint weighting
155  double Weight(int dof) const
156  {
157  return m_weight[dof];
158  }
159 
160  void ScaleWeight(int dof, double scale)
161  {
162  m_weight[dof] *= scale;
163  }
164 
165  // recursively update the global coordinates of this segment, 'global'
166  // is the global transformation from the parent segment
167  void UpdateTransform(const Affine3d &global);
168 
169  // get axis from rotation matrix for derivative computation
170  virtual Vector3d Axis(int dof) const = 0;
171 
172  // update the angles using the dTheta's computed using the jacobian matrix
173  virtual bool UpdateAngle(const IK_QJacobian &, Vector3d &, bool *) = 0;
174  virtual void Lock(int, IK_QJacobian &, Vector3d &)
175  {
176  }
177  virtual void UpdateAngleApply() = 0;
178 
179  // set joint limits
180  virtual void SetLimit(int, double, double)
181  {
182  }
183 
184  // set joint weights (per axis)
185  virtual void SetWeight(int, double)
186  {
187  }
188 
189  virtual void SetBasis(const Matrix3d &basis)
190  {
191  m_basis = basis;
192  }
193 
194  // functions needed for pole vector constraint
195  void PrependBasis(const Matrix3d &mat);
196  void Reset();
197 
198  // scale
199  virtual void Scale(double scale);
200 
201  protected:
202  // num_DoF: number of degrees of freedom
203  IK_QSegment(int num_DoF, bool translational);
204 
205  // remove child as a child of this segment
206  void RemoveChild(IK_QSegment *child);
207 
208  // tree structure variables
213 
214  // full transform =
215  // start * rest_basis * basis * translation
216  Vector3d m_start;
217  Matrix3d m_rest_basis;
218  Matrix3d m_basis;
219  Vector3d m_translation;
220 
221  // original basis
222  Matrix3d m_orig_basis;
224 
225  // maximum extension of this segment
227 
228  // accumulated transformations starting from root
229  Vector3d m_global_start;
231 
232  // number degrees of freedom, (first) id of this segments DOF's
234 
235  bool m_locked[3];
237  double m_weight[3];
238 };
239 
241  public:
243 
244  Vector3d Axis(int dof) const;
245 
246  bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp);
247  void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta);
248  void UpdateAngleApply();
249 
250  bool ComputeClampRotation(Vector3d &clamp);
251 
252  void SetLimit(int axis, double lmin, double lmax);
253  void SetWeight(int axis, double weight);
254 
255  private:
256  Matrix3d m_new_basis;
257  bool m_limit_x, m_limit_y, m_limit_z;
258  double m_min[2], m_max[2];
259  double m_min_y, m_max_y, m_max_x, m_max_z, m_offset_x, m_offset_z;
260  double m_locked_ax, m_locked_ay, m_locked_az;
261 };
262 
263 class IK_QNullSegment : public IK_QSegment {
264  public:
265  IK_QNullSegment();
266 
267  bool UpdateAngle(const IK_QJacobian &, Vector3d &, bool *)
268  {
269  return false;
270  }
272  {
273  }
274 
275  Vector3d Axis(int) const
276  {
277  return Vector3d(0, 0, 0);
278  }
279  void SetBasis(const Matrix3d &)
280  {
281  m_basis.setIdentity();
282  }
283 };
284 
286  public:
287  // axis: the axis of the DoF, in range 0..2
288  IK_QRevoluteSegment(int axis);
289 
290  Vector3d Axis(int dof) const;
291 
292  bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp);
293  void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta);
294  void UpdateAngleApply();
295 
296  void SetLimit(int axis, double lmin, double lmax);
297  void SetWeight(int axis, double weight);
298  void SetBasis(const Matrix3d &basis);
299 
300  private:
301  int m_axis;
302  double m_angle, m_new_angle;
303  bool m_limit;
304  double m_min, m_max;
305 };
306 
308  public:
309  // XZ DOF, uses one direct rotation
311 
312  Vector3d Axis(int dof) const;
313 
314  bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp);
315  void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta);
316  void UpdateAngleApply();
317 
318  void SetLimit(int axis, double lmin, double lmax);
319  void SetWeight(int axis, double weight);
320  void SetBasis(const Matrix3d &basis);
321 
322  private:
323  Matrix3d m_new_basis;
324  bool m_limit_x, m_limit_z;
325  double m_min[2], m_max[2];
326  double m_max_x, m_max_z, m_offset_x, m_offset_z;
327 };
328 
330  public:
331  // XY or ZY DOF, uses two sequential rotations: first rotate around
332  // X or Z, then rotate around Y (twist)
333  IK_QElbowSegment(int axis);
334 
335  Vector3d Axis(int dof) const;
336 
337  bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp);
338  void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta);
339  void UpdateAngleApply();
340 
341  void SetLimit(int axis, double lmin, double lmax);
342  void SetWeight(int axis, double weight);
343  void SetBasis(const Matrix3d &basis);
344 
345  private:
346  int m_axis;
347 
348  double m_twist, m_angle, m_new_twist, m_new_angle;
349  double m_cos_twist, m_sin_twist;
350 
351  bool m_limit, m_limit_twist;
352  double m_min, m_max, m_min_twist, m_max_twist;
353 };
354 
356  public:
357  // 1DOF, 2DOF or 3DOF translational segments
358  IK_QTranslateSegment(int axis1);
359  IK_QTranslateSegment(int axis1, int axis2);
361 
362  Vector3d Axis(int dof) const;
363 
364  bool UpdateAngle(const IK_QJacobian &jacobian, Vector3d &delta, bool *clamp);
365  void Lock(int, IK_QJacobian &, Vector3d &);
366  void UpdateAngleApply();
367 
368  void SetWeight(int axis, double weight);
369  void SetLimit(int axis, double lmin, double lmax);
370 
371  void Scale(double scale);
372 
373  private:
374  int m_axis[3];
375  bool m_axis_enabled[3], m_limit[3];
376  Vector3d m_new_translation;
377  double m_min[3], m_max[3];
378 };
SIMD_FORCE_INLINE btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:895
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)
Vector3d Axis(int) const
Definition: IK_QSegment.h:275
void UpdateAngleApply()
Definition: IK_QSegment.h:271
bool UpdateAngle(const IK_QJacobian &, Vector3d &, bool *)
Definition: IK_QSegment.h:267
void SetBasis(const Matrix3d &)
Definition: IK_QSegment.h:279
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)
int NumberOfDoF() const
Definition: IK_QSegment.h:94
virtual void SetBasis(const Matrix3d &basis)
Definition: IK_QSegment.h:189
int DoFId() const
Definition: IK_QSegment.h:100
Vector3d m_start
Definition: IK_QSegment.h:216
const Vector3d GlobalStart() const
Definition: IK_QSegment.h:121
void UnLock()
Definition: IK_QSegment.h:149
virtual EIGEN_MAKE_ALIGNED_OPERATOR_NEW ~IK_QSegment()
Definition: IK_QSegment.cpp:89
const Affine3d & GlobalTransform() const
Definition: IK_QSegment.h:132
const Vector3d GlobalEnd() const
Definition: IK_QSegment.h:126
Vector3d m_translation
Definition: IK_QSegment.h:219
Matrix3d m_basis
Definition: IK_QSegment.h:218
virtual void Lock(int, IK_QJacobian &, Vector3d &)
Definition: IK_QSegment.h:174
virtual void UpdateAngleApply()=0
virtual bool UpdateAngle(const IK_QJacobian &, Vector3d &, bool *)=0
Vector3d m_orig_translation
Definition: IK_QSegment.h:223
IK_QSegment * Composite() const
Definition: IK_QSegment.h:88
IK_QSegment * Child() const
Definition: IK_QSegment.h:70
IK_QSegment * Sibling() const
Definition: IK_QSegment.h:75
Vector3d m_global_start
Definition: IK_QSegment.h:229
void ScaleWeight(int dof, double scale)
Definition: IK_QSegment.h:160
bool Translational() const
Definition: IK_QSegment.h:138
bool m_translational
Definition: IK_QSegment.h:236
bool Locked(int dof) const
Definition: IK_QSegment.h:144
void UpdateTransform(const Affine3d &global)
IK_QSegment * m_sibling
Definition: IK_QSegment.h:211
bool m_locked[3]
Definition: IK_QSegment.h:235
const double MaxExtension() const
Definition: IK_QSegment.h:111
Matrix3d m_orig_basis
Definition: IK_QSegment.h:222
virtual Vector3d Axis(int dof) const =0
Affine3d m_global_transform
Definition: IK_QSegment.h:230
double m_max_extension
Definition: IK_QSegment.h:226
virtual void Scale(double scale)
IK_QSegment * m_child
Definition: IK_QSegment.h:210
double m_weight[3]
Definition: IK_QSegment.h:237
Matrix3d m_rest_basis
Definition: IK_QSegment.h:217
virtual void SetWeight(int, double)
Definition: IK_QSegment.h:185
IK_QSegment * m_parent
Definition: IK_QSegment.h:209
void SetComposite(IK_QSegment *seg)
Matrix3d BasisChange() const
Definition: IK_QSegment.cpp:79
IK_QSegment(int num_DoF, bool translational)
Definition: IK_QSegment.cpp:28
double Weight(int dof) const
Definition: IK_QSegment.h:155
void PrependBasis(const Matrix3d &mat)
void SetParent(IK_QSegment *parent)
Definition: IK_QSegment.cpp:98
void SetDoFId(int dof_id)
Definition: IK_QSegment.h:105
IK_QSegment * m_composite
Definition: IK_QSegment.h:212
void RemoveChild(IK_QSegment *child)
virtual void SetLimit(int, double, double)
Definition: IK_QSegment.h:180
IK_QSegment * Parent() const
Definition: IK_QSegment.h:80
Vector3d TranslationChange() const
Definition: IK_QSegment.cpp:84
void SetTransform(const Vector3d &start, const Matrix3d &rest_basis, const Matrix3d &basis, const double length)
Definition: IK_QSegment.cpp:62
void Reset()
Definition: IK_QSegment.cpp:50
void SetWeight(int axis, double weight)
Vector3d Axis(int dof) const
void Lock(int dof, IK_QJacobian &jacobian, Vector3d &delta)
bool ComputeClampRotation(Vector3d &clamp)
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)
ccl_device_inline int clamp(int a, int mn, int mx)
Definition: util_math.h:283