UnitTestUtils.hpp
Go to the documentation of this file.
1 //
2 // Created by jordan on 5/22/16.
3 //
4 
5 #ifndef __RDL_UNIT_TEST_UTILS_HP__
6 #define __RDL_UNIT_TEST_UTILS_HP__
7 
8 #include <math.h>
9 #include "rdl_dynamics/Model.h"
10 #include "rdl_dynamics/Dynamics.h"
13 #include "rdl_dynamics/Point3.hpp"
16 
17 using namespace RobotDynamics;
18 using namespace RobotDynamics::Math;
19 
20 namespace unit_test_utils
21 {
22 const double TEST_PREC = 1.0e-14;
23 
24 // Call this from test fixtures to make sure none of the methods called
25 // are modifying the zero vectors/matrices
26 // cppcheck-suppress unused-function
28 {
29  for (unsigned int i = 0; i < model.ndof0_vec.rows(); i++)
30  {
31  if (model.ndof0_vec[i] != 0.)
32  {
33  return false;
34  }
35  }
36 
37  for (unsigned int i = 0; i < model.q0_vec.rows(); i++)
38  {
39  if (model.q0_vec[i] != 0.)
40  {
41  return false;
42  }
43  }
44 
45  for (unsigned int i = 0; i < model.nbodies0_vec.rows(); i++)
46  {
47  if (model.nbodies0_vec[i] != 0.)
48  {
49  return false;
50  }
51  }
52 
53  for (unsigned int i = 0; i < model.ndof0_mat.rows(); i++)
54  {
55  for (unsigned int j = 0; j < model.ndof0_mat.cols(); j++)
56  {
57  if (model.ndof0_mat(i, j) != 0.)
58  {
59  return false;
60  }
61  }
62  }
63 
64  for (unsigned int i = 0; i < model.three_x_qd0.rows(); i++)
65  {
66  for (unsigned int j = 0; j < model.three_x_qd0.cols(); j++)
67  {
68  if (model.three_x_qd0(i, j) != 0.)
69  {
70  return false;
71  }
72  }
73  }
74 
75  for (unsigned int i = 0; i < model.mCustomJoints.size(); i++)
76  {
77  CustomJoint* custom_joint = model.mCustomJoints[i];
78 
79  for (unsigned int j = 0; j < custom_joint->mDoFCount; j++)
80  {
81  if (custom_joint->ndof0_vec[j] != 0.)
82  {
83  return false;
84  }
85  }
86  }
87 
88  return true;
89 }
90 
91 template <typename T>
92 static T getRandomNumber()
93 {
94  double val = (2000.0 * rand() / RAND_MAX - 1000.0);
95  return static_cast<T>(val);
96 }
97 
98 template <typename T>
99 static T getRandomNumber(T min, T max)
100 {
101  double val = (fabs((max - min)) * rand() / RAND_MAX + min);
102  return static_cast<T>(val);
103 }
104 
106 {
107  Point3d point;
108  point.x() = getRandomNumber<double>();
109  point.y() = getRandomNumber<double>();
110  point.z() = getRandomNumber<double>();
111 
112  return point;
113 }
114 
115 template <typename T>
116 static T getRandomAngle()
117 {
118  double angle = 2 * (M_PI - 0.01) * rand() / RAND_MAX - (M_PI - 0.01);
119  return static_cast<T>(angle);
120 }
121 
123 {
124  for (int i = 0; i < 6; i++)
125  {
126  for (int j = 0; j < 6; j++)
127  {
128  if (fabs(t1(i, j) - t2(i, j)) > epsilon)
129  {
130  return false;
131  }
132  }
133  }
134 
135  return true;
136 }
137 
138 static inline bool checkMatrix3dEpsilonClose(const RobotDynamics::Math::Matrix3d& t1, const RobotDynamics::Math::Matrix3d& t2, const double epsilon)
139 {
140  for (int i = 0; i < 3; i++)
141  {
142  for (int j = 0; j < 3; j++)
143  {
144  if (fabs(t1(i, j) - t2(i, j)) > epsilon)
145  {
146  return false;
147  }
148  }
149  }
150 
151  return true;
152 }
153 
154 static inline bool checkMatrixNdEpsilonClose(const RobotDynamics::Math::MatrixNd& t1, const RobotDynamics::Math::MatrixNd& t2, const double epsilon)
155 {
156  if (t1.rows() != t2.rows() || t1.cols() != t2.cols())
157  {
158  throw RobotDynamics::RdlException("Cannot compare MatrixNd's of different sizes!");
159  }
160 
161  for (int i = 0; i < t1.rows(); i++)
162  {
163  for (int j = 0; j < t1.cols(); j++)
164  {
165  if (fabs(t1(i, j) - t2(i, j)) > epsilon)
166  {
167  return false;
168  }
169  }
170  }
171 
172  return true;
173 }
174 
176 {
177  if (t1.rows() != t2.rows() || t1.cols() != t2.cols())
178  {
179  throw RobotDynamics::RdlException("Cannot compare MatrixNd's of different sizes!");
180  }
181 
182  for (int i = 0; i < t1.rows(); i++)
183  {
184  for (int j = 0; j < t1.cols(); j++)
185  {
186  if (t1(i, j) != t2(i, j))
187  {
188  return false;
189  }
190  }
191  }
192 
193  return true;
194 }
195 
197 {
198  for (int i = 0; i < 3; i++)
199  {
200  for (int j = 0; j < 3; j++)
201  {
202  if (t1(i, j) != t2(i, j))
203  {
204  return false;
205  }
206  }
207  }
208 
209  return true;
210 }
211 
213 {
214  for (int i = 0; i < 3; i++)
215  {
216  if (v1(i) != v2(i))
217  {
218  return false;
219  }
220  }
221 
222  return true;
223 }
224 
226 {
227  for (int i = 0; i < 4; i++)
228  {
229  if (v1(i) != v2(i))
230  {
231  return false;
232  }
233  }
234 
235  return true;
236 }
237 
239 {
240  if (v1.rows() != v2.rows())
241  {
242  throw RobotDynamics::RdlException("Cannot compare vectors because they are not the same length!");
243  }
244 
245  for (int i = 0; i < v1.rows(); i++)
246  {
247  if (v1(i) != v2(i))
248  {
249  return false;
250  }
251  }
252 
253  return true;
254 }
255 
256 static inline bool checkVector3dEpsilonClose(const RobotDynamics::Math::Vector3d& v1, const RobotDynamics::Math::Vector3d& v2, const double epsilon)
257 {
258  for (int i = 0; i < 3; i++)
259  {
260  if (fabs(v1(i) - v2(i)) > epsilon)
261  {
262  return false;
263  }
264  }
265 
266  return true;
267 }
268 
270 {
271  return (v1.linear().getReferenceFrame() == v2.linear().getReferenceFrame() && checkVector3dEpsilonClose(v1.linear(), v2.linear(), epsilon) &&
272  checkVector3dEpsilonClose(v1.angular(), v2.angular(), epsilon));
273 }
274 
275 static inline bool checkVector4dEpsilonClose(const RobotDynamics::Math::Vector4d& v1, const RobotDynamics::Math::Vector4d& v2, const double epsilon)
276 {
277  for (int i = 0; i < 4; i++)
278  {
279  if (fabs(v1(i) - v2(i)) > epsilon)
280  {
281  return false;
282  }
283  }
284 
285  return true;
286 }
287 
288 static inline bool checkVectorNdEpsilonClose(const RobotDynamics::Math::VectorNd& v1, const RobotDynamics::Math::VectorNd& v2, const double epsilon)
289 {
290  if (v1.rows() != v2.rows())
291  {
292  throw RobotDynamics::RdlException("Cannot compare vectors because they are not the same length!");
293  }
294 
295  for (int i = 0; i < v1.rows(); i++)
296  {
297  if (fabs(v1(i) - v2(i)) > epsilon)
298  {
299  return false;
300  }
301  }
302 
303  return true;
304 }
305 
307 {
308  for (int i = 0; i < 6; i++)
309  {
310  if (fabs(v1(i) - v2(i)) > epsilon)
311  {
312  return false;
313  }
314  }
315 
316  return true;
317 }
318 
320 {
321  for (int i = 0; i < 6; i++)
322  {
323  if (v1(i) != v2(i))
324  {
325  return false;
326  }
327  }
328 
329  return true;
330 }
331 
332 static inline void updateAllFrames(std::vector<ReferenceFramePtr> frames)
333 {
334  for (int i = 0; i < frames.size(); i++)
335  {
336  frames[i]->update();
337  }
338 }
339 
340 static inline ReferenceFramePtr getARandomFrame(std::vector<ReferenceFramePtr> frames)
341 {
342  int index = rand() % frames.size();
343 
344  return frames[index];
345 }
346 
348 {
352 
353  RobotDynamics::Math::SpatialTransform X = X_x * X_y * X_z;
354 
355  return X;
356 }
357 
359 {
360  if (frame->getParentFrame() == nullptr)
361  {
363  }
364 
366  ReferenceFramePtr parent = frame;
367  while (parent != nullptr)
368  {
369  transform = parent->getTransformToParent() * transform;
370  parent = parent->getParentFrame();
371  }
372 
373  return transform;
374 }
375 
376 static inline ReferenceFramePtr createRandomUnchangingFrame(const std::string& frameName, ReferenceFramePtr parentFrame, const unsigned int movableBodyId)
377 {
378  return ReferenceFramePtr(new ReferenceFrame(frameName, parentFrame, createRandomSpatialTransform(), false, movableBodyId));
379 }
380 
395 void integrateEuler(Model& model, const Math::VectorNd& Q, const Math::VectorNd& QDot, Math::VectorNd& x, const Math::VectorNd& tau, double h,
396  Math::SpatialForceV* f_ext = nullptr)
397 {
398  Math::VectorNd qddot = Math::VectorNd::Zero(model.qdot_size);
399 
400  Math::VectorNd q = Math::VectorNd::Zero(model.q_size);
401  Math::VectorNd qdot = Math::VectorNd::Zero(model.qdot_size);
402 
403  q = Q;
404  qdot = QDot;
405 
406  forwardDynamics(model, q, qdot, tau, qddot, f_ext);
407 
408  Math::VectorNd x_0 = Math::VectorNd::Zero(model.q_size + model.qdot_size);
409  Math::VectorNd dx = Math::VectorNd::Zero(2 * model.qdot_size);
410 
411  x_0.head(model.q_size) = Q;
412  x_0.tail(model.qdot_size) = QDot;
413 
414  dx.head(model.qdot_size) = qdot;
415  dx.tail(model.qdot_size) = qddot;
416 
417  for (unsigned int i = 0; i < model.mBodies.size(); i++)
418  {
419  if (model.mJoints[i].mJointType == JointTypeSpherical)
420  {
421  // See algorithm in section 4.2.2 of "Quaternion kinematics for the error-state Kalman filter" by Joan Sola
422  unsigned int q_index = model.mJoints[i].q_index;
423  RobotDynamics::Math::Quaternion w_q(QDot[q_index], QDot[q_index + 1], QDot[q_index + 2], 0.);
425  RobotDynamics::Math::Quaternion q_int, new_q;
426 
427  x[model.q_size + q_index] = x_0[model.q_size + q_index] + h * dx[model.dof_count + q_index];
428  x[model.q_size + q_index + 1] = x_0[model.q_size + q_index + 1] + h * dx[model.dof_count + q_index + 1];
429  x[model.q_size + q_index + 2] = x_0[model.q_size + q_index + 2] + h * dx[model.dof_count + q_index + 2];
430 
431  Vector3d w_np1(x[model.q_size + q_index], x[model.q_size + q_index + 1], x[model.q_size + q_index + 2]);
432  Vector3d w_n(QDot[q_index], QDot[q_index + 1], QDot[q_index + 2]);
433  Vector3d w_bar = (w_np1 + w_n) / 2.0;
434  Vector3d w_bar_axis = w_bar / w_bar.norm();
435  Vector3d first_order_term = (h / 24.0) * (w_n.cross(w_np1));
436  q_int = toQuaternion(w_bar_axis, w_bar.norm() * h);
437  q_int += RobotDynamics::Math::Quaternion(first_order_term[0], first_order_term[1], first_order_term[2], 0.0);
438  q_int.normalize();
439 
440  new_q = q * q_int;
441 
442  new_q.normalize();
443 
444  x[q_index] = new_q[0];
445  x[q_index + 1] = new_q[1];
446  x[q_index + 2] = new_q[2];
447  x[model.multdof3_w_index[i]] = new_q[3];
448  }
449  else
450  {
451  unsigned int idx = model.mJoints[i].q_index;
452  x[idx] = x_0[idx] + h * dx[idx];
453  x[model.q_size + idx] = x_0[model.q_size + idx] + h * dx[model.dof_count + idx];
454  }
455  }
456 }
457 
471 void integrateRk4(Model& model, const Math::VectorNd& Q, const Math::VectorNd& QDot, Math::VectorNd& x, const Math::VectorNd& tau, double h,
472  Math::SpatialForceV* f_ext = nullptr)
473 {
474  Math::VectorNd q_n = Q;
475  Math::VectorNd qdot_n = QDot;
476  Math::VectorNd qddot = Math::VectorNd::Zero(model.qdot_size);
477  Math::VectorNd k1 = Math::VectorNd::Zero(2 * model.qdot_size);
478  Math::VectorNd k2 = Math::VectorNd::Zero(2 * model.qdot_size);
479  Math::VectorNd k3 = Math::VectorNd::Zero(2 * model.qdot_size);
480  Math::VectorNd k4 = Math::VectorNd::Zero(2 * model.qdot_size);
481 
482  k1.setZero();
483  k2.setZero();
484  k3.setZero();
485  k4.setZero();
486 
487  Math::VectorNd q = Math::VectorNd::Zero(model.q_size);
488  Math::VectorNd qdot = Math::VectorNd::Zero(model.qdot_size);
489 
490  q = Q;
491  qdot = QDot;
492 
493  forwardDynamics(model, q, qdot, tau, qddot, f_ext);
494 
495  k1.head(model.qdot_size) = qdot;
496  k1.tail(model.qdot_size) = qddot;
497 
498  q = q_n + (h / 2.) * k1.head(model.q_size);
499  qdot = qdot_n + (h / 2.) * k1.tail(model.qdot_size);
500 
501  forwardDynamics(model, q, qdot, tau, qddot, f_ext);
502 
503  k2.head(model.qdot_size) = qdot;
504  k2.tail(model.qdot_size) = qddot;
505 
506  q = q_n + (h / 2.) * k2.head(model.q_size);
507  qdot = qdot_n + (h / 2.) * k2.tail(model.qdot_size);
508 
509  forwardDynamics(model, q, qdot, tau, qddot, f_ext);
510 
511  k3.head(model.qdot_size) = qdot;
512  k3.tail(model.qdot_size) = qddot;
513 
514  q = q_n + h * k3.head(model.q_size);
515  qdot = qdot_n + h * k3.tail(model.qdot_size);
516 
517  forwardDynamics(model, q, qdot, tau, qddot, f_ext);
518 
519  k4.head(model.qdot_size) = qdot;
520  k4.tail(model.qdot_size) = qddot;
521 
522  Math::VectorNd x_0 = Math::VectorNd::Zero(model.q_size + model.qdot_size);
523 
524  x_0.head(model.q_size) = Q;
525  x_0.tail(model.qdot_size) = QDot;
526 
527  x = x_0 + (h / 6.) * (k1 + 2. * k2 + 2. * k3 + k4);
528 }
529 } // namespace unit_test_utils
530 
531 #endif //__UNIT_TEST_UTILS__
EIGEN_STRONG_INLINE double & x()
Definition: Point3.hpp:234
unsigned int mDoFCount
Definition: Joint.h:688
static bool checkVectorNdEpsilonClose(const RobotDynamics::Math::VectorNd &v1, const RobotDynamics::Math::VectorNd &v2, const double epsilon)
std::vector< SpatialForce, Eigen::aligned_allocator< SpatialForce > > SpatialForceV
std::vector< Joint > mJoints
All joints.
Definition: Model.h:209
ReferenceFramePtr getReferenceFrame() const
Get a pointer to the reference frame this FrameObject is expressed in.
Definition: FrameObject.hpp:52
static ReferenceFramePtr createRandomUnchangingFrame(const std::string &frameName, ReferenceFramePtr parentFrame, const unsigned int movableBodyId)
Math::Quaternion GetQuaternion(unsigned int i, const Math::VectorNd &Q) const
Gets the quaternion for body i (only valid if body i is connected by a JointTypeSpherical joint) ...
Definition: Model.h:596
std::vector< unsigned int > multdof3_w_index
Definition: Model.h:240
Math::VectorNd ndof0_vec
Definition: Joint.h:696
CustomJoint is a struct used to create a joint with user defined parameters. This is accomplished by ...
Definition: Joint.h:662
SpatialTransform Xroty(const double &yrot)
Get transform with zero translation and pure rotation about y axis.
FrameVector linear() const
Get copy of linear component.
VectorNd QDot
const double TEST_PREC
Math::VectorNd ndof0_vec
Definition: Model.h:284
VectorNd Q
static ReferenceFramePtr getARandomFrame(std::vector< ReferenceFramePtr > frames)
bool checkModelZeroVectorsAndMatrices(RobotDynamics::Model &model)
FrameVector angular() const
Get copy of angular component.
static Quaternion toQuaternion(const Vector3d &axis, double angle_rad)
Get quaternion representation of axis and angle.
static bool checkVector4dEpsilonClose(const RobotDynamics::Math::Vector4d &v1, const RobotDynamics::Math::Vector4d &v2, const double epsilon)
Math::VectorNd nbodies0_vec
Definition: Model.h:285
static Point3d getRandomPoint3()
static bool checkMatrix3dEq(const RobotDynamics::Math::Matrix3d &t1, const RobotDynamics::Math::Matrix3d &t2)
SpatialTransform Xrotz(const double &zrot)
Get transform with zero translation and pure rotation about z axis.
std::shared_ptr< ReferenceFrame > ReferenceFramePtr
static bool checkVector3dEq(const RobotDynamics::Math::Vector3d &v1, const RobotDynamics::Math::Vector3d &v2)
unsigned int q_size
The size of the -vector. For models without spherical joints the value is the same as Model::dof_coun...
Definition: Model.h:178
Compact representation of spatial transformations.
Math::MatrixNd ndof0_mat
Definition: Model.h:281
std::vector< Body > mBodies
All bodies 0 ... N_B, including the base.
Definition: Model.h:321
static T getRandomNumber(T min, T max)
static RobotDynamics::Math::SpatialTransform getTransformToRootByClimbingTree(ReferenceFramePtr frame)
ReferenceFrame object used to tell what frame objects are expressed in. Every ReferenceFrame has a po...
Quaternion that are used for singularity free joints.
Definition: Quaternion.h:25
Math::VectorNd q0_vec
Definition: Model.h:283
SpatialTransform Xrotx(const double &xrot)
Get transform with zero translation and pure rotation about x axis.
Eigen::VectorXd VectorNd
Definition: rdl_eigenmath.h:25
static bool checkMatrixNdEpsilonClose(const RobotDynamics::Math::MatrixNd &t1, const RobotDynamics::Math::MatrixNd &t2, const double epsilon)
static T getRandomAngle()
void integrateRk4(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &x, const Math::VectorNd &tau, double h, Math::SpatialForceV *f_ext=nullptr)
Using a Runge-Kutta 4th order algorithm, integrate the system dynamics one step.
std::vector< CustomJoint * > mCustomJoints
Definition: Model.h:242
static bool checkSpatialMatrixEpsilonClose(const RobotDynamics::Math::SpatialMatrix &t1, const RobotDynamics::Math::SpatialMatrix &t2, const double epsilon)
Contains all information about the rigid body model.
Definition: Model.h:121
Math types such as vectors and matrices and utility functions.
Definition: ForceVector.hpp:21
static bool checkSpatialVectorsEpsilonClose(const RobotDynamics::Math::SpatialVector &v1, const RobotDynamics::Math::SpatialVector &v2, const double epsilon)
static bool checkVector4dEq(const RobotDynamics::Math::Vector4d &v1, const RobotDynamics::Math::Vector4d &v2)
Eigen::MatrixXd MatrixNd
Definition: rdl_eigenmath.h:26
EIGEN_STRONG_INLINE double & y()
Definition: Point3.hpp:244
void integrateEuler(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, Math::VectorNd &x, const Math::VectorNd &tau, double h, Math::SpatialForceV *f_ext=nullptr)
Using simple Euler integration, integrate the system dynamics one step.
static bool checkSpatialVectorsEq(const RobotDynamics::Math::SpatialVector &v1, const RobotDynamics::Math::SpatialVector &v2)
A custom exception.
A FrameVector is a pair of 3D vector with a ReferenceFrame.
static bool checkVector3dEpsilonClose(const RobotDynamics::Math::Vector3d &v1, const RobotDynamics::Math::Vector3d &v2, const double epsilon)
Math::MatrixNd three_x_qd0
Definition: Model.h:282
static bool checkMatrixNdEq(const RobotDynamics::Math::MatrixNd &t1, const RobotDynamics::Math::MatrixNd &t2)
static RobotDynamics::Math::SpatialTransform createRandomSpatialTransform()
3 DoF joint using Quaternions for joint positional variables and
Definition: Joint.h:195
void forwardDynamics(Model &model, const Math::VectorNd &Q, const Math::VectorNd &QDot, const Math::VectorNd &Tau, Math::VectorNd &QDDot, Math::SpatialForceV *f_ext=nullptr, bool update_kinematics=true)
Computes forward dynamics with the Articulated Body Algorithm.
Definition: Dynamics.cc:455
EIGEN_STRONG_INLINE double & z()
Definition: Point3.hpp:254
static bool checkVectorNdEq(const RobotDynamics::Math::VectorNd &v1, const RobotDynamics::Math::VectorNd &v2)
static void updateAllFrames(std::vector< ReferenceFramePtr > frames)
unsigned int dof_count
number of degrees of freedoms of the model
Definition: Model.h:169
static bool checkFrameVectorPairEpsilonClose(const RobotDynamics::Math::FrameVectorPair &v1, const RobotDynamics::Math::FrameVectorPair &v2, const double epsilon)
Namespace for all structures of the RobotDynamics library.
Definition: Body.h:21
static bool checkMatrix3dEpsilonClose(const RobotDynamics::Math::Matrix3d &t1, const RobotDynamics::Math::Matrix3d &t2, const double epsilon)
unsigned int qdot_size
The size of the.
Definition: Model.h:187


rdl_dynamics
Author(s):
autogenerated on Tue Apr 20 2021 02:25:28