Rigid Body Dynamics Library
Joint.h
Go to the documentation of this file.
1/*
2 * RBDL - Rigid Body Dynamics Library
3 * Copyright (c) 2011-2018 Martin Felis <martin@fysx.org>
4 *
5 * Licensed under the zlib license. See LICENSE for more details.
6 */
7
8#ifndef RBDL_JOINT_H
9#define RBDL_JOINT_H
10
11#include "rbdl/rbdl_math.h"
12#include <assert.h>
13#include <iostream>
14#include "rbdl/Logging.h"
15#include "rbdl/rbdl_errors.h"
16
17namespace RigidBodyDynamics
18{
19
20struct Model;
21
183enum JointType {
184 JointTypeUndefined = 0,
185 JointTypeRevolute,
186 JointTypePrismatic,
187 JointTypeRevoluteX,
188 JointTypeRevoluteY,
189 JointTypeRevoluteZ,
190 JointTypeSpherical,
191 JointTypeEulerZYX,
192 JointTypeEulerXYZ,
193 JointTypeEulerYXZ,
194 JointTypeEulerZXY,
195 JointTypeTranslationXYZ,
196 JointTypeFloatingBase,
197 JointTypeFixed,
198 JointTypeHelical, //1 DoF joint with both rotational and translational motion
199 JointType1DoF,
200 JointType2DoF,
201 JointType3DoF,
202 JointType4DoF,
203 JointType5DoF,
204 JointType6DoF,
205 JointTypeCustom,
206};
207
208struct JointMapEntry{
209 JointType id;
210 const char* name;
211 const char* abbr;
212};
213
214static const JointMapEntry JointMap[] = {
215 { JointTypeUndefined , "Undefined" , "UNDEFINED"},
216 { JointTypeRevolute , "Revolute" , "" },
217 { JointTypePrismatic , "Prismatic" , "" },
218 { JointTypeRevoluteX , "RevoluteX" , "" },
219 { JointTypeRevoluteY , "RevoluteY" , "" },
220 { JointTypeRevoluteZ , "RevoluteZ" , "" },
221 { JointTypeSpherical , "Spherical" , "Sphere" },
222 { JointTypeEulerZYX , "EulerZYX" , "EaZYX" },
223 { JointTypeEulerXYZ , "EulerXYZ" , "EaXYZ" },
224 { JointTypeEulerYXZ , "EulerYXZ" , "EaYXZ" },
225 { JointTypeEulerZXY , "EulerZXY" , "EaZXY" },
226 { JointTypeTranslationXYZ , "TranslationXYZ" , "TrXYZ" },
227 { JointTypeFloatingBase , "FloatingBase" , "FloBas" },
228 { JointTypeFixed , "Fixed" , "Fixed" },
229 { JointTypeHelical , "Helical" , "Helic" },
230 { JointType1DoF , "1DoF" , "" },
231 { JointType2DoF , "2DoF" , "" },
232 { JointType3DoF , "3DoF" , "" },
233 { JointType4DoF , "4DoF" , "" },
234 { JointType5DoF , "5DoF" , "" },
235 { JointType6DoF , "6DoF" , "" },
236 { JointTypeCustom , "Custom" , "Cus" }
237};
238
239struct AxisMapEntry{
240 unsigned int id;
241 const char* name;
242};
243
244static const AxisMapEntry AxisMap[]={
245 {0, "Rx"},
246 {1, "Ry"},
247 {2, "Rz"},
248 {3, "Tx"},
249 {4, "Ty"},
250 {5, "Tz"}
251};
252
259struct RBDL_DLLAPI Joint {
260 Joint() :
261 mJointAxes (NULL),
262 mJointType (JointTypeUndefined),
263 mDoFCount (0),
264 q_index (0),
265 custom_joint_index(-1) {};
266 Joint (JointType type) :
267 mJointAxes (NULL),
268 mJointType (type),
269 mDoFCount (0),
270 q_index (0),
271 custom_joint_index(-1)
272 {
273 if (type == JointTypeRevoluteX) {
274 mDoFCount = 1;
275 mJointAxes = new Math::SpatialVector[mDoFCount];
276 mJointAxes[0] = Math::SpatialVector (1., 0., 0., 0., 0., 0.);
277 } else if (type == JointTypeRevoluteY) {
278 mDoFCount = 1;
279 mJointAxes = new Math::SpatialVector[mDoFCount];
280 mJointAxes[0] = Math::SpatialVector (0., 1., 0., 0., 0., 0.);
281 } else if (type == JointTypeRevoluteZ) {
282 mDoFCount = 1;
283 mJointAxes = new Math::SpatialVector[mDoFCount];
284 mJointAxes[0] = Math::SpatialVector (0., 0., 1., 0., 0., 0.);
285 } else if (type == JointTypeSpherical) {
286 mDoFCount = 3;
287
288 mJointAxes = new Math::SpatialVector[mDoFCount];
289
290 mJointAxes[0] = Math::SpatialVector (0., 0., 1., 0., 0., 0.);
291 mJointAxes[1] = Math::SpatialVector (0., 1., 0., 0., 0., 0.);
292 mJointAxes[2] = Math::SpatialVector (1., 0., 0., 0., 0., 0.);
293 } else if (type == JointTypeEulerZYX) {
294 mDoFCount = 3;
295
296 mJointAxes = new Math::SpatialVector[mDoFCount];
297
298 mJointAxes[0] = Math::SpatialVector (0., 0., 1., 0., 0., 0.);
299 mJointAxes[1] = Math::SpatialVector (0., 1., 0., 0., 0., 0.);
300 mJointAxes[2] = Math::SpatialVector (1., 0., 0., 0., 0., 0.);
301 } else if (type == JointTypeEulerXYZ) {
302 mDoFCount = 3;
303
304 mJointAxes = new Math::SpatialVector[mDoFCount];
305
306 mJointAxes[0] = Math::SpatialVector (1., 0., 0., 0., 0., 0.);
307 mJointAxes[1] = Math::SpatialVector (0., 1., 0., 0., 0., 0.);
308 mJointAxes[2] = Math::SpatialVector (0., 0., 1., 0., 0., 0.);
309 } else if (type == JointTypeEulerYXZ) {
310 mDoFCount = 3;
311
312 mJointAxes = new Math::SpatialVector[mDoFCount];
313
314 mJointAxes[0] = Math::SpatialVector (0., 1., 0., 0., 0., 0.);
315 mJointAxes[1] = Math::SpatialVector (1., 0., 0., 0., 0., 0.);
316 mJointAxes[2] = Math::SpatialVector (0., 0., 1., 0., 0., 0.);
317 } else if (type == JointTypeEulerZXY) {
318 mDoFCount = 3;
319
320 mJointAxes = new Math::SpatialVector[mDoFCount];
321
322 mJointAxes[0] = Math::SpatialVector (0., 0., 1., 0., 0., 0.);
323 mJointAxes[1] = Math::SpatialVector (1., 0., 0., 0., 0., 0.);
324 mJointAxes[2] = Math::SpatialVector (0., 1., 0., 0., 0., 0.);
325 } else if (type == JointTypeTranslationXYZ) {
326 mDoFCount = 3;
327
328 mJointAxes = new Math::SpatialVector[mDoFCount];
329
330 mJointAxes[0] = Math::SpatialVector (0., 0., 0., 1., 0., 0.);
331 mJointAxes[1] = Math::SpatialVector (0., 0., 0., 0., 1., 0.);
332 mJointAxes[2] = Math::SpatialVector (0., 0., 0., 0., 0., 1.);
333 } else if (type >= JointType1DoF && type <= JointType6DoF) {
334 // create a joint and allocate memory for it.
335 // Warning: the memory does not get initialized by this function!
336 mDoFCount = type - JointType1DoF + 1;
337 mJointAxes = new Math::SpatialVector[mDoFCount];
338 std::cerr << "Warning: uninitalized vector" << std::endl;
339 } else if (type == JointTypeCustom) {
340 //This constructor cannot be used for a JointTypeCustom because
341 //we have no idea what mDoFCount is.
342 std::ostringstream errormsg;
343 errormsg << "Error: Invalid use of Joint constructor Joint(JointType"
344 << " type). Only allowed when type != JointTypeCustom"
345 << std::endl;
346 throw Errors::RBDLError(errormsg.str());
347 } else if (type != JointTypeFixed && type != JointTypeFloatingBase) {
348 std::ostringstream errormsg;
349 errormsg <<
350 "Error: Invalid use of Joint constructor Joint(JointType type). Only allowed when type == JointTypeFixed or JointTypeSpherical."
351 << std::endl;
352 throw Errors::RBDLError(errormsg.str());
353 }
354 }
355 Joint (JointType type, int degreesOfFreedom) :
356 mJointAxes (NULL),
357 mJointType (type),
358 mDoFCount (0),
359 q_index (0),
360 custom_joint_index(-1)
361 {
362 if (type == JointTypeCustom) {
363 mDoFCount = degreesOfFreedom;
364 mJointAxes = new Math::SpatialVector[mDoFCount];
365 for(unsigned int i=0; i<mDoFCount; ++i) {
366 mJointAxes[i] = Math::SpatialVector (0., 0., 0., 0., 0., 0.);
367 }
368 } else {
369 std::ostringstream errormsg;
370 errormsg << "Error: Invalid use of Joint constructor Joint(JointType"
371 << " type, int degreesOfFreedom). Only allowed when "
372 << "type == JointTypeCustom."
373 << std::endl;
374 throw Errors::RBDLError(errormsg.str());
375 }
376 }
377 Joint (const Joint &joint) :
378 mJointType (joint.mJointType),
379 mDoFCount (joint.mDoFCount),
380 q_index (joint.q_index),
381 custom_joint_index(joint.custom_joint_index)
382 {
383 mJointAxes = new Math::SpatialVector[mDoFCount];
384
385 for (unsigned int i = 0; i < mDoFCount; i++) {
386 mJointAxes[i] = joint.mJointAxes[i];
387 }
388 };
389 Joint& operator= (const Joint &joint)
390 {
391 if (this != &joint) {
392 if (mDoFCount > 0) {
393 assert (mJointAxes);
394 delete[] mJointAxes;
395 }
396 mJointType = joint.mJointType;
397 mDoFCount = joint.mDoFCount;
398 custom_joint_index = joint.custom_joint_index;
399 mJointAxes = new Math::SpatialVector[mDoFCount];
400
401 for (unsigned int i = 0; i < mDoFCount; i++) {
402 mJointAxes[i] = joint.mJointAxes[i];
403 }
404
405 q_index = joint.q_index;
406 }
407 return *this;
408 }
409 ~Joint()
410 {
411 if (mJointAxes) {
412 assert (mJointAxes);
413 delete[] mJointAxes;
414 mJointAxes = NULL;
415 mDoFCount = 0;
416 custom_joint_index = -1;
417 }
418 }
419
428 Joint (
429 const JointType joint_type,
430 const Math::Vector3d &joint_axis
431 )
432 {
433 mDoFCount = 1;
434 mJointAxes = new Math::SpatialVector[mDoFCount];
435
436 // Some assertions, as we concentrate on simple cases
437
438 // Only rotation around the Z-axis
439 assert ( joint_type == JointTypeRevolute || joint_type == JointTypePrismatic );
440
441 mJointType = joint_type;
442
443 if (joint_type == JointTypeRevolute) {
444 // make sure we have a unit axis
445 mJointAxes[0].set (
446 joint_axis[0],
447 joint_axis[1],
448 joint_axis[2],
449 0., 0., 0.
450 );
451
452 } else if (joint_type == JointTypePrismatic) {
453 // make sure we have a unit axis
454#ifndef RBDL_USE_CASADI_MATH
455 assert (joint_axis.squaredNorm() == 1.);
456#endif
457
458 mJointAxes[0].set (
459 0., 0., 0.,
460 joint_axis[0],
461 joint_axis[1],
462 joint_axis[2]
463 );
464 }
465 }
466
474 Joint (
475 const Math::SpatialVector &axis_0
476 )
477 {
478 mDoFCount = 1;
479 mJointAxes = new Math::SpatialVector[mDoFCount];
480 mJointAxes[0] = Math::SpatialVector (axis_0);
481
482 // TODO this has to be properly determined AND test case. Try Matt's dot product idea
483#ifdef RBDL_USE_CASADI_MATH
484 if (!axis_0[0].is_zero()) {
485#else
486 if (axis_0 == Math::SpatialVector(1., 0., 0., 0., 0., 0.)) {
487#endif
488 mJointType = JointTypeRevoluteX;
489#ifdef RBDL_USE_CASADI_MATH
490 } else if (!axis_0[1].is_zero()) {
491#else
492 } else if (axis_0 == Math::SpatialVector(0., 1., 0., 0., 0., 0.)) {
493#endif
494 mJointType = JointTypeRevoluteY;
495#ifdef RBDL_USE_CASADI_MATH
496 } else if (!axis_0[2].is_zero()) {
497#else
498 } else if (axis_0 == Math::SpatialVector(0., 0., 1., 0., 0., 0.)) {
499#endif
500 mJointType = JointTypeRevoluteZ;
501#ifdef RBDL_USE_CASADI_MATH
502 } else if (axis_0[0].is_zero() && axis_0[1].is_zero() && axis_0[2].is_zero()) {
503#else
504 } else if (axis_0[0] == 0. && axis_0[1] == 0. && axis_0[2] == 0.) {
505#endif
506 mJointType = JointTypePrismatic;
507 } else {
508 mJointType = JointTypeHelical;
509 }
510 validate_spatial_axis (mJointAxes[0]);
511 }
512
523 Joint (
524 const Math::SpatialVector &axis_0,
525 const Math::SpatialVector &axis_1
526 )
527 {
528 mJointType = JointType2DoF;
529 mDoFCount = 2;
530
531 mJointAxes = new Math::SpatialVector[mDoFCount];
532 mJointAxes[0] = axis_0;
533 mJointAxes[1] = axis_1;
534
535 validate_spatial_axis (mJointAxes[0]);
536 validate_spatial_axis (mJointAxes[1]);
537 }
538
550 Joint (
551 const Math::SpatialVector &axis_0,
552 const Math::SpatialVector &axis_1,
553 const Math::SpatialVector &axis_2
554 )
555 {
556 mJointType = JointType3DoF;
557 mDoFCount = 3;
558
559 mJointAxes = new Math::SpatialVector[mDoFCount];
560
561 mJointAxes[0] = axis_0;
562 mJointAxes[1] = axis_1;
563 mJointAxes[2] = axis_2;
564
565 validate_spatial_axis (mJointAxes[0]);
566 validate_spatial_axis (mJointAxes[1]);
567 validate_spatial_axis (mJointAxes[2]);
568 }
569
582 Joint (
583 const Math::SpatialVector &axis_0,
584 const Math::SpatialVector &axis_1,
585 const Math::SpatialVector &axis_2,
586 const Math::SpatialVector &axis_3
587 )
588 {
589 mJointType = JointType4DoF;
590 mDoFCount = 4;
591
592 mJointAxes = new Math::SpatialVector[mDoFCount];
593
594 mJointAxes[0] = axis_0;
595 mJointAxes[1] = axis_1;
596 mJointAxes[2] = axis_2;
597 mJointAxes[3] = axis_3;
598
599 validate_spatial_axis (mJointAxes[0]);
600 validate_spatial_axis (mJointAxes[1]);
601 validate_spatial_axis (mJointAxes[2]);
602 validate_spatial_axis (mJointAxes[3]);
603 }
604
618 Joint (
619 const Math::SpatialVector &axis_0,
620 const Math::SpatialVector &axis_1,
621 const Math::SpatialVector &axis_2,
622 const Math::SpatialVector &axis_3,
623 const Math::SpatialVector &axis_4
624 )
625 {
626 mJointType = JointType5DoF;
627 mDoFCount = 5;
628
629 mJointAxes = new Math::SpatialVector[mDoFCount];
630
631 mJointAxes[0] = axis_0;
632 mJointAxes[1] = axis_1;
633 mJointAxes[2] = axis_2;
634 mJointAxes[3] = axis_3;
635 mJointAxes[4] = axis_4;
636
637 validate_spatial_axis (mJointAxes[0]);
638 validate_spatial_axis (mJointAxes[1]);
639 validate_spatial_axis (mJointAxes[2]);
640 validate_spatial_axis (mJointAxes[3]);
641 validate_spatial_axis (mJointAxes[4]);
642 }
643
658 Joint (
659 const Math::SpatialVector &axis_0,
660 const Math::SpatialVector &axis_1,
661 const Math::SpatialVector &axis_2,
662 const Math::SpatialVector &axis_3,
663 const Math::SpatialVector &axis_4,
664 const Math::SpatialVector &axis_5
665 )
666 {
667 mJointType = JointType6DoF;
668 mDoFCount = 6;
669
670 mJointAxes = new Math::SpatialVector[mDoFCount];
671
672 mJointAxes[0] = axis_0;
673 mJointAxes[1] = axis_1;
674 mJointAxes[2] = axis_2;
675 mJointAxes[3] = axis_3;
676 mJointAxes[4] = axis_4;
677 mJointAxes[5] = axis_5;
678
679 validate_spatial_axis (mJointAxes[0]);
680 validate_spatial_axis (mJointAxes[1]);
681 validate_spatial_axis (mJointAxes[2]);
682 validate_spatial_axis (mJointAxes[3]);
683 validate_spatial_axis (mJointAxes[4]);
684 validate_spatial_axis (mJointAxes[5]);
685 }
686
692 bool validate_spatial_axis (Math::SpatialVector &axis)
693 {
694#ifdef RBDL_USE_CASADI_MATH
695 // If using casadi, the axes won't be validated
696 return true;
697#else
698 bool axis_rotational = false;
699 bool axis_translational = false;
700
701 Math::Vector3d rotation (axis[0], axis[1], axis[2]);
702 Math::Vector3d translation (axis[3], axis[4], axis[5]);
703
704 if (fabs(rotation.norm()) > 1.0e-8) {
705 axis_rotational = true;
706 }
707
708 if (fabs(translation.norm()) > 1.0e-8) {
709 axis_translational = true;
710 }
711
712 if(axis_rotational && rotation.norm() - 1.0 > 1.0e-8) {
713 std::cerr << "Warning: joint rotation axis is not unit!" << std::endl;
714 }
715
716 if(axis_translational && translation.norm() - 1.0 > 1.0e-8) {
717 std::cerr << "Warning: joint translation axis is not unit!" << std::endl;
718 }
719
720 return axis_rotational != axis_translational;
721#endif
722 }
723
725 Math::SpatialVector* mJointAxes;
727 JointType mJointType;
729 // have here a value of 0 and their actual numbers of degrees of freedom
730 // can be obtained using the CustomJoint structure.
731 unsigned int mDoFCount;
732 unsigned int q_index;
733 unsigned int custom_joint_index;
734};
735
746RBDL_DLLAPI
747void jcalc (
748 Model &model,
749 unsigned int joint_id,
750 const Math::VectorNd &q,
751 const Math::VectorNd &qdot
752);
753
754RBDL_DLLAPI
755Math::SpatialTransform jcalc_XJ (
756 Model &model,
757 unsigned int joint_id,
758 const Math::VectorNd &q);
759
760RBDL_DLLAPI
761void jcalc_X_lambda_S (
762 Model &model,
763 unsigned int joint_id,
764 const Math::VectorNd &q
765);
766
767struct RBDL_DLLAPI CustomJoint {
768 CustomJoint()
769 { }
770 virtual ~CustomJoint() {};
771
772 virtual void jcalc (Model &model,
773 unsigned int joint_id,
774 const Math::VectorNd &q,
775 const Math::VectorNd &qdot
776 ) = 0;
777 virtual void jcalc_X_lambda_S (Model &model,
778 unsigned int joint_id,
779 const Math::VectorNd &q
780 ) = 0;
781
782 unsigned int mDoFCount;
783 Math::SpatialTransform XJ;
786 Math::MatrixNd Dinv;
788 Math::VectorNd d_u;
789};
790
791}
792
793/* RBDL_JOINT_H */
794#endif
SpatialVector_t SpatialVector
Definition: rbdl_math.h:61
RBDL_DLLAPI void jcalc(Model &model, unsigned int joint_id, const VectorNd &q, const VectorNd &qdot)
Definition: Joint.cc:49
RBDL_DLLAPI Math::SpatialTransform jcalc_XJ(Model &model, unsigned int joint_id, const Math::VectorNd &q)
Definition: Joint.cc:350
RBDL_DLLAPI void jcalc_X_lambda_S(Model &model, unsigned int joint_id, const VectorNd &q)
Definition: Joint.cc:403
MX_Xd_dynamic fabs(const MX_Xd_dynamic &m)
Definition: MX_Xd_utils.h:371