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