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 
21 /** \file
22  * \ingroup iksolver
23  */
24 
25 #pragma once
26 
27 #include "IK_Math.h"
28 #include "IK_QJacobian.h"
29 
30 #include <vector>
31 
32 /**
33  * An IK_Qsegment encodes information about a segments
34  * local coordinate system.
35  *
36  * These segments always point along the y-axis.
37  *
38  * Here we define the local coordinates of a joint as
39  * local_transform =
40  * translate(tr1) * rotation(A) * rotation(q) * translate(0,length,0)
41  * You can read this as:
42  * - first translate by (0,length,0)
43  * - multiply by the rotation matrix derived from the current
44  * angle parameterization q.
45  * - multiply by the user defined matrix representing the rest
46  * position of the bone.
47  * - translate by the used defined translation (tr1)
48  * The ordering of these transformations is vital, you must
49  * use exactly the same transformations when displaying the segments
50  */
51 
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 
Child()70   IK_QSegment *Child() const
71   {
72     return m_child;
73   }
74 
Sibling()75   IK_QSegment *Sibling() const
76   {
77     return m_sibling;
78   }
79 
Parent()80   IK_QSegment *Parent() const
81   {
82     return m_parent;
83   }
84 
85   // for combining two joints into one from the interface
86   void SetComposite(IK_QSegment *seg);
87 
Composite()88   IK_QSegment *Composite() const
89   {
90     return m_composite;
91   }
92 
93   // number of degrees of freedom
NumberOfDoF()94   int NumberOfDoF() const
95   {
96     return m_num_DoF;
97   }
98 
99   // unique id for this segment, for identification in the jacobian
DoFId()100   int DoFId() const
101   {
102     return m_DoF_id;
103   }
104 
SetDoFId(int dof_id)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.
MaxExtension()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
GlobalStart()121   const Vector3d GlobalStart() const
122   {
123     return m_global_start;
124   }
125 
GlobalEnd()126   const Vector3d GlobalEnd() const
127   {
128     return m_global_transform.translation();
129   }
130 
131   // the global transformation at the end of the segment
GlobalTransform()132   const Affine3d &GlobalTransform() const
133   {
134     return m_global_transform;
135   }
136 
137   // is a translational segment?
Translational()138   bool Translational() const
139   {
140     return m_translational;
141   }
142 
143   // locking (during inner clamping loop)
Locked(int dof)144   bool Locked(int dof) const
145   {
146     return m_locked[dof];
147   }
148 
UnLock()149   void UnLock()
150   {
151     m_locked[0] = m_locked[1] = m_locked[2] = false;
152   }
153 
154   // per dof joint weighting
Weight(int dof)155   double Weight(int dof) const
156   {
157     return m_weight[dof];
158   }
159 
ScaleWeight(int dof,double scale)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;
Lock(int,IK_QJacobian &,Vector3d &)174   virtual void Lock(int, IK_QJacobian &, Vector3d &)
175   {
176   }
177   virtual void UpdateAngleApply() = 0;
178 
179   // set joint limits
SetLimit(int,double,double)180   virtual void SetLimit(int, double, double)
181   {
182   }
183 
184   // set joint weights (per axis)
SetWeight(int,double)185   virtual void SetWeight(int, double)
186   {
187   }
188 
SetBasis(const Matrix3d & basis)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
209   IK_QSegment *m_parent;
210   IK_QSegment *m_child;
211   IK_QSegment *m_sibling;
212   IK_QSegment *m_composite;
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;
223   Vector3d m_orig_translation;
224 
225   // maximum extension of this segment
226   double m_max_extension;
227 
228   // accumulated transformations starting from root
229   Vector3d m_global_start;
230   Affine3d m_global_transform;
231 
232   // number degrees of freedom, (first) id of this segments DOF's
233   int m_num_DoF, m_DoF_id;
234 
235   bool m_locked[3];
236   bool m_translational;
237   double m_weight[3];
238 };
239 
240 class IK_QSphericalSegment : public IK_QSegment {
241  public:
242   IK_QSphericalSegment();
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 
UpdateAngle(const IK_QJacobian &,Vector3d &,bool *)267   bool UpdateAngle(const IK_QJacobian &, Vector3d &, bool *)
268   {
269     return false;
270   }
UpdateAngleApply()271   void UpdateAngleApply()
272   {
273   }
274 
Axis(int)275   Vector3d Axis(int) const
276   {
277     return Vector3d(0, 0, 0);
278   }
SetBasis(const Matrix3d &)279   void SetBasis(const Matrix3d &)
280   {
281     m_basis.setIdentity();
282   }
283 };
284 
285 class IK_QRevoluteSegment : public IK_QSegment {
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 
307 class IK_QSwingSegment : public IK_QSegment {
308  public:
309   // XZ DOF, uses one direct rotation
310   IK_QSwingSegment();
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 
329 class IK_QElbowSegment : public IK_QSegment {
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 
355 class IK_QTranslateSegment : public IK_QSegment {
356  public:
357   // 1DOF, 2DOF or 3DOF translational segments
358   IK_QTranslateSegment(int axis1);
359   IK_QTranslateSegment(int axis1, int axis2);
360   IK_QTranslateSegment();
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 };
379