- 3.0.2 rigid body dynamics module.
RigidBodyPose.h
Go to the documentation of this file.
1 /**********************************************************************************************************************
2 This file is part of the Control Toolbox (https://github.com/ethz-adrl/control-toolbox), copyright by ETH Zurich
3 Licensed under the BSD-2 license (see LICENSE file in main directory)
4 **********************************************************************************************************************/
5 
6 #pragma once
7 
8 #pragma GCC diagnostic push
9 #pragma GCC diagnostic ignored "-Wunused-parameter"
10 #pragma GCC diagnostic ignored "-Wunused-value"
11 #include <kindr/Core>
12 #pragma GCC diagnostic pop
13 
14 namespace ct {
15 namespace rbd {
16 namespace tpl {
17 
28 template <typename SCALAR = double>
30 {
31 public:
32  EIGEN_MAKE_ALIGNED_OPERATOR_NEW
33 
39  {
40  QUAT = 0,
41  EULER = 1
42  };
43 
44  using HomogeneousTransform = kindr::HomogeneousTransformationPosition3RotationQuaternion<SCALAR>;
45  using Matrix4Tpl = Eigen::Matrix<SCALAR, 4, 4>;
46  using Matrix3Tpl = Eigen::Matrix<SCALAR, 3, 3>;
47  using Position3Tpl = kindr::Position<SCALAR, 3>;
48  using Vector3Tpl = Eigen::Matrix<SCALAR, 3, 1>;
49 
52  : storage_(storage),
53  quat_(SCALAR(1.0), SCALAR(0.0), SCALAR(0.0), SCALAR(0.0)), // for CppAD cg compatibility
54  euler_(SCALAR(0.0), SCALAR(0.0), SCALAR(0.0))
55  {
56  }
57 
59  RigidBodyPose(const kindr::EulerAnglesXyz<SCALAR>& orientationEulerXyz,
60  const Position3Tpl& position,
61  STORAGE_TYPE storage = EULER)
62  : storage_(storage),
63  quat_(SCALAR(1.0), SCALAR(0.0), SCALAR(0.0), SCALAR(0.0)), // for CppAD cg compatibility
64  euler_(SCALAR(0.0), SCALAR(0.0), SCALAR(0.0)),
65  position_(position)
66  {
67  setFromEulerAnglesXyz(orientationEulerXyz);
68  }
69 
71  RigidBodyPose(const kindr::RotationQuaternion<SCALAR>& orientationQuat,
72  const Position3Tpl& position,
73  STORAGE_TYPE storage = EULER)
74  : storage_(storage),
75  quat_(SCALAR(1.0), SCALAR(0.0), SCALAR(0.0), SCALAR(0.0)), // for CppAD cg compatibility
76  euler_(SCALAR(0.0), SCALAR(0.0), SCALAR(0.0)),
77  position_(position)
78  {
79  setFromRotationQuaternion(orientationQuat);
80  }
81 
83  RigidBodyPose(const Eigen::Quaternion<SCALAR>& orientationQuat,
84  const Eigen::Matrix<SCALAR, 3, 1>& position,
85  STORAGE_TYPE storage = EULER)
86  : RigidBodyPose(kindr::RotationQuaternion<SCALAR>(orientationQuat), Position3Tpl(position))
87  {
88  }
89 
91  RigidBodyPose(const Matrix4Tpl& homTransform, STORAGE_TYPE storage = EULER)
92  : storage_(storage),
93  quat_(SCALAR(1.0), SCALAR(0.0), SCALAR(0.0), SCALAR(0.0)), // for CppAD cg compatibility
94  euler_(SCALAR(0.0), SCALAR(0.0), SCALAR(0.0)),
95  position_(homTransform.template topRightCorner<3, 1>())
96  {
97  kindr::RotationMatrix<SCALAR> rotMat(homTransform.template topLeftCorner<3, 3>());
98  setFromRotationMatrix(rotMat);
99  }
100 
103  : storage_(arg.storage_), quat_(arg.quat_), euler_(arg.euler_), position_(arg.position_)
104  {
105  }
106 
108  ~RigidBodyPose() = default;
109 
110  inline bool isNear(const RigidBodyPose& rhs, const double& tol = 1e-10) const
111  {
112  return getRotationQuaternion().isNear(rhs.getRotationQuaternion(), tol) &&
113  position().toImplementation().isApprox(rhs.position().toImplementation(), tol);
114  }
115 
119  kindr::EulerAnglesXyz<SCALAR> getEulerAnglesXyz() const
120  {
121  if (storedAsEuler())
122  {
123  return euler_;
124  }
125  else
126  {
127  return kindr::EulerAnglesXyz<SCALAR>(quat_);
128  }
129  }
130 
134  kindr::RotationQuaternion<SCALAR> getRotationQuaternion() const
135  {
136  if (storedAsEuler())
137  {
138  return kindr::RotationQuaternion<SCALAR>(euler_);
139  }
140  else
141  {
142  return quat_;
143  }
144  }
145 
150  kindr::RotationMatrix<SCALAR> getRotationMatrix() const
151  {
152  if (storedAsEuler())
153  {
154  Eigen::AngleAxis<SCALAR> rollAngle(euler_.toImplementation()(0), Eigen::Matrix<SCALAR, 3, 1>::UnitX());
155  Eigen::AngleAxis<SCALAR> pitchAngle(euler_.toImplementation()(1), Eigen::Matrix<SCALAR, 3, 1>::UnitY());
156  Eigen::AngleAxis<SCALAR> yawAngle(euler_.toImplementation()(2), Eigen::Matrix<SCALAR, 3, 1>::UnitZ());
157  Eigen::Quaternion<SCALAR> q = rollAngle * pitchAngle * yawAngle;
158  return kindr::RotationMatrix<SCALAR>(q.matrix());
159 
160  // return kindr::RotationMatrix<SCALAR>(euler_); // this is not JIT compatible as it uses a unit quat temporarily
161  }
162  else
163  {
164  return kindr::RotationMatrix<SCALAR>(quat_);
165  }
166  }
167 
171  void setFromEulerAnglesXyz(const kindr::EulerAnglesXyz<SCALAR>& eulerAngles)
172  {
173  if (storedAsEuler())
174  {
175  euler_.toImplementation() = eulerAngles.toImplementation();
176  }
177  else
178  {
179  quat_ = eulerAngles;
180  }
181  }
182 
186  void setFromEulerAnglesXyz(const Vector3Tpl& eulerAngles)
187  {
188  if (storedAsEuler())
189  {
190  euler_.toImplementation() = eulerAngles;
191  }
192  else
193  {
194  quat_ = kindr::EulerAnglesXyz<SCALAR>(eulerAngles);
195  }
196  }
197 
201  void setFromRotationQuaternion(const kindr::RotationQuaternion<SCALAR>& quat)
202  {
203  if (storedAsEuler())
204  {
205  euler_ = quat;
206  }
207  else
208  {
209  quat_ = quat;
210  }
211  }
212 
216  void setFromRotationQuaternion(const Eigen::Quaterniond& quat)
217  {
218  if (storedAsEuler())
219  {
220  euler_ = kindr::EulerAnglesXyz<SCALAR>(kindr::RotationQuaternion<SCALAR>(quat));
221  }
222  else
223  {
224  quat_ = kindr::RotationQuaternion<SCALAR>(quat);
225  }
226  }
227 
231  void setFromRotationMatrix(const kindr::RotationMatrix<SCALAR>& rotMat)
232  {
233  if (storedAsEuler())
234  {
235  euler_ = kindr::EulerAnglesXyz<SCALAR>(rotMat);
236  }
237  else
238  {
239  quat_ = kindr::RotationQuaternion<SCALAR>(rotMat);
240  }
241  }
242 
246  const Position3Tpl& position() const { return position_; }
247 
251  Position3Tpl& position() { return position_; }
252 
257  {
258  if (ref_frame.storedAsEuler() && storedAsEuler())
259  {
260  return RigidBodyPose<SCALAR>(ref_frame.getEulerAnglesXyz().inverted() * euler_,
261  ref_frame.getEulerAnglesXyz().inverseRotate(position() - ref_frame.position()));
262  }
263  else if (ref_frame.storedAsEuler() && !storedAsEuler())
264  {
265  return RigidBodyPose<SCALAR>(ref_frame.getEulerAnglesXyz().inverted() * quat_,
266  ref_frame.getEulerAnglesXyz().inverseRotate(position() - ref_frame.position()));
267  }
268  else if (!ref_frame.storedAsEuler() && storedAsEuler())
269  {
270  return RigidBodyPose<SCALAR>(ref_frame.getRotationQuaternion().inverted() * euler_,
271  ref_frame.getRotationQuaternion().inverseRotate(position() - ref_frame.position()));
272  }
273  else
274  {
275  return RigidBodyPose<SCALAR>(ref_frame.getRotationQuaternion().inverted() * quat_,
276  ref_frame.getRotationQuaternion().inverseRotate(position() - ref_frame.position()));
277  }
278  }
279 
283  template <class Vector3s>
284  Vector3s rotateBaseToInertia(const Vector3s& vector) const
285  {
286  Vector3s out;
287 
288  if (storedAsEuler())
289  {
290  kindr::RotationMatrix<SCALAR> rotationMatrix = getRotationMatrix();
291 
292  // incredibly ugly hack to get along with different types
293  Eigen::Matrix<SCALAR, 3, 1> vec_temp;
294  vec_temp << vector(0), vector(1), vector(2);
295 
296  Eigen::Matrix<SCALAR, 3, 1> result = rotationMatrix.toImplementation() * vec_temp;
297  out = (Vector3s)result;
298 
299  // return euler_.rotate(vector); // temporarily replaced -- the kindr rotate() method is not auto-diffable
300  }
301  else
302  {
303  out = quat_.rotate(vector);
304  }
305 
306  return out;
307  }
308 
309 
314  {
315  kindr::RotationMatrix<SCALAR> rotMat = getRotationMatrix();
316  return rotMat.toImplementation() * mat;
317  }
318 
319 
323  kindr::RotationQuaternion<SCALAR> rotateBaseToInertiaQuaternion(const kindr::RotationQuaternion<SCALAR>& q) const
324  {
325  kindr::RotationQuaternion<SCALAR> result;
326 
327  if (storedAsEuler())
328  result = kindr::RotationQuaternion<SCALAR>(euler_) * q;
329  else
330  result = quat_ * q;
331 
332  return result;
333  }
334 
338  template <class Vector3s>
339  Vector3s rotateInertiaToBase(const Vector3s& vector) const
340  {
341  // more efficient than inverseRotate and (more importantly) compatible with auto-diff
342  // https://github.com/ethz-asl/kindr/issues/84
343  // return Vector3d::Zero();
344  // return kindr::RotationMatrix<SCALAR>(euler_).transposed().rotate(vector);
345  if (storedAsEuler())
346  {
347  return kindr::RotationMatrix<SCALAR>(euler_).transposed().rotate(vector);
348  }
349  else
350  {
351  return quat_.inverseRotate(vector);
352  }
353  }
354 
359  {
360  throw std::runtime_error("get homogeneous transform not implemented");
361  return HomogeneousTransform();
362  }
363 
368  static Vector3Tpl gravity3DW(SCALAR g = SCALAR(-9.81)) { return Vector3Tpl(SCALAR(0.0), SCALAR(0.0), g); }
372  Vector3Tpl computeGravityB(const Vector3Tpl& gravityW = gravity3DW()) const
373  {
374  return rotateInertiaToBase(gravityW);
375  }
376 
380  Eigen::Matrix<SCALAR, 6, 1> computeGravityB6D(const Vector3Tpl& gravityW = gravity3DW()) const
381  {
382  Eigen::Matrix<SCALAR, 6, 1> gravityWout(Eigen::Matrix<SCALAR, 6, 1>::Zero());
383  gravityWout.template tail<3>() = rotateInertiaToBase(gravityW);
384  return gravityWout;
385  }
386 
390  void setIdentity()
391  {
392  euler_.setIdentity();
393  quat_.setIdentity();
394  position().setZero();
395  }
396 
397  void setRandom()
398  {
399  euler_.setRandom();
400  quat_ = euler_;
401  position().toImplementation().setRandom();
402  }
403 
404  STORAGE_TYPE getStorageType() const { return storage_; }
405 
406 private:
407  bool storedAsEuler() const
408  {
409  if (storage_ == EULER)
410  return true;
411  else
412  return false;
413  }
414 
415  STORAGE_TYPE storage_;
416 
417  kindr::RotationQuaternion<SCALAR> quat_;
418  kindr::EulerAnglesXyz<SCALAR> euler_;
419 
420  Position3Tpl position_;
421 };
422 
423 } // namespace tpl
424 
425 // convenience typedef (required)
427 
428 } // namespace rbd
429 } // namespace ct
RigidBodyPose< SCALAR > inReferenceFrame(const RigidBodyPose< SCALAR > &ref_frame) const
This method returns the Base frame in a custom Frame specified in the Inertia Frame.
Definition: RigidBodyPose.h:256
Eigen::Matrix< double, 3, 3 > Matrix3Tpl
Definition: RigidBodyPose.h:46
RigidBodyPose(const RigidBodyPose< SCALAR > &arg)
copy-constructor for a RigidBodyPose
Definition: RigidBodyPose.h:102
STORAGE_TYPE
the orientation can either be stored as EulerAngles or as quaternion.
Definition: RigidBodyPose.h:38
Eigen::Matrix< SCALAR, 6, 1 > computeGravityB6D(const Vector3Tpl &gravityW=gravity3DW()) const
This methods returns the 6D gravity vector expressed in the Base frame.
Definition: RigidBodyPose.h:380
RigidBodyPose(const Matrix4Tpl &homTransform, STORAGE_TYPE storage=EULER)
construct a RigidBodyPose from a homogeneous transformation matrix
Definition: RigidBodyPose.h:91
Pose of a single rigid body.
Definition: RigidBodyPose.h:29
Vector3Tpl computeGravityB(const Vector3Tpl &gravityW=gravity3DW()) const
This methods returns the 3D gravity vector expressed in the Base frame.
Definition: RigidBodyPose.h:372
const Position3Tpl & position() const
This method returns the position of the Base frame in the inertia frame.
Definition: RigidBodyPose.h:246
void setFromRotationQuaternion(const kindr::RotationQuaternion< SCALAR > &quat)
This method sets the quaternion angles rotation (X,Y,Z / roll,pitch,yaw) from a kindr quaternion type...
Definition: RigidBodyPose.h:201
void setRandom()
Definition: RigidBodyPose.h:397
HomogeneousTransform getHomogeneousTransform() const
This methods returns the Homogeneous transform from the Base frame to the inertia frame...
Definition: RigidBodyPose.h:358
RigidBodyPose(const kindr::RotationQuaternion< SCALAR > &orientationQuat, const Position3Tpl &position, STORAGE_TYPE storage=EULER)
construct a RigidBodyPose from a rotation quaternion and a position vector
Definition: RigidBodyPose.h:71
Vector3s rotateInertiaToBase(const Vector3s &vector) const
This methods rotates a 3D vector expressed in Inertia frame to Base Frame.
Definition: RigidBodyPose.h:339
kindr::RotationQuaternion< SCALAR > rotateBaseToInertiaQuaternion(const kindr::RotationQuaternion< SCALAR > &q) const
This methods rotates a quaternion expressed in Base frame to Inertia Frame.
Definition: RigidBodyPose.h:323
kindr::EulerAnglesXyz< SCALAR > getEulerAnglesXyz() const
This method returns the Euler angles rotation (X,Y,Z / roll,pitch,yaw).
Definition: RigidBodyPose.h:119
CppAD::AD< CppAD::cg::CG< double > > SCALAR
kindr::HomogeneousTransformationPosition3RotationQuaternion< double > HomogeneousTransform
Definition: RigidBodyPose.h:44
STORAGE_TYPE getStorageType() const
Definition: RigidBodyPose.h:404
void setFromRotationQuaternion(const Eigen::Quaterniond &quat)
This method sets the quaternion angles rotation (X,Y,Z / roll,pitch,yaw) from an Eigen quaternion...
Definition: RigidBodyPose.h:216
Eigen::Matrix< double, 3, 1 > Vector3Tpl
Definition: RigidBodyPose.h:48
~RigidBodyPose()=default
destructor for a rigid body pose
void setIdentity()
Sets orientation to identity and position to (0, 0, 0)
Definition: RigidBodyPose.h:390
bool isNear(const RigidBodyPose &rhs, const double &tol=1e-10) const
Definition: RigidBodyPose.h:110
kindr::RotationQuaternion< SCALAR > getRotationQuaternion() const
This method returns the quaternion rotation.
Definition: RigidBodyPose.h:134
Eigen::Matrix< double, 4, 4 > Matrix4Tpl
Definition: RigidBodyPose.h:45
RigidBodyPose(const Eigen::Quaternion< SCALAR > &orientationQuat, const Eigen::Matrix< SCALAR, 3, 1 > &position, STORAGE_TYPE storage=EULER)
construct a RigidBodyPose from a rotation quaternion and a position vector
Definition: RigidBodyPose.h:83
Definition: RigidBodyPose.h:41
Position3Tpl & position()
This method returns the position of the Base frame in the inertia frame.
Definition: RigidBodyPose.h:251
kindr::RotationMatrix< SCALAR > getRotationMatrix() const
This method returns the rotation matrix from base to inertia frame. This method returns which is the...
Definition: RigidBodyPose.h:150
kindr::Position< double, 3 > Position3Tpl
Definition: RigidBodyPose.h:47
static Vector3Tpl gravity3DW(SCALAR g=SCALAR(-9.81))
Definition: RigidBodyPose.h:368
RigidBodyPose(STORAGE_TYPE storage=EULER)
default construct a RigidBodyPose
Definition: RigidBodyPose.h:51
Matrix3Tpl rotateBaseToInertiaMat(const Matrix3Tpl &mat) const
This methods rotates a 3D matrix expressed in Base frame to Inertia Frame.
Definition: RigidBodyPose.h:313
RigidBodyPose(const kindr::EulerAnglesXyz< SCALAR > &orientationEulerXyz, const Position3Tpl &position, STORAGE_TYPE storage=EULER)
construct a RigidBodyPose from Euler Angles and a position vector
Definition: RigidBodyPose.h:59
Definition: RigidBodyPose.h:40
Vector3s rotateBaseToInertia(const Vector3s &vector) const
This methods rotates a 3D vector expressed in Base frame to Inertia Frame.
Definition: RigidBodyPose.h:284
void setFromEulerAnglesXyz(const Vector3Tpl &eulerAngles)
This method sets the Euler angles rotation (X,Y,Z / roll,pitch,yaw) from a kindr type.
Definition: RigidBodyPose.h:186
void setFromRotationMatrix(const kindr::RotationMatrix< SCALAR > &rotMat)
This method sets the quaternion angles rotation from a kindr rotation matrix.
Definition: RigidBodyPose.h:231
void setFromEulerAnglesXyz(const kindr::EulerAnglesXyz< SCALAR > &eulerAngles)
This method sets the Euler angles rotation (X,Y,Z / roll,pitch,yaw) from a kindr type.
Definition: RigidBodyPose.h:171