LCOV - code coverage report
Current view: top level - src/rdl/rdl_dynamics/include/rdl_dynamics - Joint.hpp (source / functions) Hit Total Coverage
Test: projectcoverage.info Lines: 185 185 100.0 %
Date: 2024-12-13 18:04:46 Functions: 16 17 94.1 %
Branches: 0 0 -

           Branch data     Line data    Source code
       1                 :            : // Copyright (c) 2017 Jordan Lack <jlack1987@gmail.com>
       2                 :            : // Copyright (c) 2011-2016 Martin Felis <martin.felis@iwr.uni-heidelberg.de>
       3                 :            : // RDL - Robot Dynamics Library
       4                 :            : // Licensed under the zlib license. See LICENSE for more details.
       5                 :            : 
       6                 :            : #ifndef __RDL_JOINT_H__
       7                 :            : #define __RDL_JOINT_H__
       8                 :            : 
       9                 :            : /**
      10                 :            :  * @file Joint.hpp
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <assert.h>
      14                 :            : #include <iostream>
      15                 :            : #include <rdl_dynamics/RdlExceptions.hpp>
      16                 :            : #include <rdl_dynamics/rdl_eigenmath.hpp>
      17                 :            : namespace RobotDynamics
      18                 :            : {
      19                 :            : struct Model;
      20                 :            : 
      21                 :            : /** \page joint_description Joint Modeling
      22                 :            :  *
      23                 :            :  * \section joint_overview Overview
      24                 :            :  *
      25                 :            :  * The Robot Dynamics Library supports a multitude of joints:
      26                 :            :  * revolute, planar, fixed, singularity-free spherical joints and joints
      27                 :            :  * with multiple degrees of freedom in any combinations.
      28                 :            :  *
      29                 :            :  * Fixed joints do not cause any overhead in RDL as the bodies that are
      30                 :            :  * rigidly connected are merged into a single body. For details see \ref joint_models_fixed.
      31                 :            :  *
      32                 :            :  * Joints with multiple degrees of freedom are emulated by default which
      33                 :            :  * means that they are split up into multiple single degree of freedom
      34                 :            :  * joints which results in equivalent models. This has the benefit that it
      35                 :            :  * simplifies the required algebra and also code branching in RDL. A
      36                 :            :  * special case are joints with three degrees of freedom for which specific
      37                 :            :  * joints are available that should be used for performance reasons
      38                 :            :  * whenever possible. See \ref joint_three_dof for details.
      39                 :            :  *
      40                 :            :  * Joints are defined by their motion subspace. For each degree of freedom
      41                 :            :  * a one dimensional motion subspace is specified as a Math::SpatialVector.
      42                 :            :  * This vector follows the following convention: \f[ (r_x, r_y, r_z, t_x, t_y, t_z) \f]
      43                 :            :  *
      44                 :            :  * To specify a planar joint with three degrees of freedom for which the
      45                 :            :  * first two are translations in \f$x\f$ and \f$y\f$ direction and the last
      46                 :            :  * is a rotation around \f$z\f$, the following joint definition can be
      47                 :            :  * used:
      48                 :            : 
      49                 :            :  * \code Joint planar_joint = Joint (
      50                 :            :  *     Math::SpatialVector (0., 0., 0., 1.,  0., 0.),
      51                 :            :  *     Math::SpatialVector (0., 0., 0., 0., 1., 0.),
      52                 :            :  *     Math::SpatialVector (0., 0., 1., 0., 0., 0.)
      53                 :            :  *     );
      54                 :            :  * \endcode
      55                 :            : 
      56                 :            :  * \note Please note that in the Robot Dynamics Library all angles
      57                 :            :  * are specified in radians.
      58                 :            :  *
      59                 :            :  * \section joint_models_fixed Fixed Joints
      60                 :            :  *
      61                 :            :  * Fixed joints do not add an additional degree of freedom to the model.
      62                 :            :  * When adding a body that via a fixed joint (i.e. when the type is
      63                 :            :  * JointTypeFixed) then the dynamical parameters mass and inertia are
      64                 :            :  * merged onto its moving parent. By doing so fixed bodies do not add
      65                 :            :  * computational costs when performing dynamics computations.
      66                 :            : 
      67                 :            :  * To ensure a consistent API for the Kinematics such fixed bodies have a
      68                 :            :  * different range of ids. Where as the ids start at 1 get incremented for
      69                 :            :  * each added body, fixed bodies start at Model::fixed_body_discriminator
      70                 :            :  * which has a default value of std::numeric_limits<unsigned int>::max() /
      71                 :            :  * 2. This means theoretical a maximum of each 2147483646 movable and fixed
      72                 :            :  * bodies are possible.
      73                 :            : 
      74                 :            :  * To check whether a body is connected by a fixed joint you can use the
      75                 :            :  * function Model::IsFixedBodyId().
      76                 :            : 
      77                 :            :  * \section joint_three_dof 3-DoF Joints
      78                 :            :  *
      79                 :            :  * RDL has highly efficient implementations for the following three degree
      80                 :            :  * of freedom joints:
      81                 :            :  * <ul>
      82                 :            :  *   <li>\ref JointTypeTranslationXYZ which first translates along X, then
      83                 :            :  *   Y, and finally Z.</li>
      84                 :            :  *   <li>\ref JointTypeEulerZYX which first rotates around Z, then Y, and
      85                 :            :  *   then X.</li>
      86                 :            :  *   <li>\ref JointTypeEulerXYZ which first rotates around X, then Y, and
      87                 :            :  *   then Z.</li>
      88                 :            :  *   <li>\ref JointTypeEulerYXZ which first rotates around Y, then X, and
      89                 :            :  *   then Z.</li>
      90                 :            :  *   <li>\ref JointTypeSpherical which is a singularity free joint that
      91                 :            :  *   uses a Quaternion and the bodies angular velocity (see \ref
      92                 :            :  *   joint_singularities for details).</li>
      93                 :            :  * </ul>
      94                 :            :  *
      95                 :            :  * These joints can be created by providing the joint type as an argument
      96                 :            :  * to the Joint constructor, e.g.:
      97                 :            :  *
      98                 :            :  * \code Joint joint_rot_zyx = Joint ( JointTypeEulerZYX ); \endcode
      99                 :            :  *
     100                 :            :  * Using 3-Dof joints is always favourable over using their emulated
     101                 :            :  * counterparts as they are considerably faster and describe the same
     102                 :            :  * kinematics and dynamics.
     103                 :            : 
     104                 :            :  * \section joint_floatingbase Floating-Base Joint (a.k.a. Freeflyer Joint)
     105                 :            :  *
     106                 :            :  * RDL has a special joint type for floating-base systems that uses the
     107                 :            :  * enum JointTypeFloatingBase. The first three DoF are translations along
     108                 :            :  * X,Y, and Z. For the rotational part it uses a JointTypeSpherical joint.
     109                 :            :  * It is internally modeled by a JointTypeTranslationXYZ and a
     110                 :            :  * JointTypeSpherical joint. It is recommended to only use this joint for
     111                 :            :  * the very first body added to the model.
     112                 :            :  *
     113                 :            :  * Positional variables are translations along X, Y, and Z, and for
     114                 :            :  * rotations it uses Quaternions. To set/get the orientation use
     115                 :            :  * Model::SetQuaternion () / Model::GetQuaternion() with the body id
     116                 :            :  * returned when adding the floating base (i.e. the call to
     117                 :            :  * Model::addBody() or Model::appendBody()).
     118                 :            : 
     119                 :            :  * \section joint_singularities Joint Singularities
     120                 :            : 
     121                 :            :  * Singularities in the models arise when a joint has three rotational
     122                 :            :  * degrees of freedom and the rotations are described by Euler- or
     123                 :            :  * Cardan-angles. The singularities present in these rotation
     124                 :            :  * parametrizations (e.g. for ZYX Euler-angles for rotations where a
     125                 :            :  * +/- 90 degrees rotation around the Y-axis) may cause problems in
     126                 :            :  * dynamics calculations, such as a rank-deficit joint-space inertia matrix
     127                 :            :  * or exploding accelerations in the forward dynamics calculations.
     128                 :            :  *
     129                 :            :  * For this case RDL has the special joint type
     130                 :            :  * RobotDynamics::JointTypeSpherical. When using this joint type the
     131                 :            :  * model does not suffer from singularities, however this also results in
     132                 :            :  * a change of interpretation for the values \f$\mathbf{q}, \mathbf{\dot{q}}, \mathbf{\ddot{q}}\f$, and \f$\mathbf{\tau}\f$:
     133                 :            :  *
     134                 :            :  * <ul>
     135                 :            :  * <li> The values in \f$\mathbf{q}\f$ for the joint parameterizes the orientation of a joint using a
     136                 :            :  * Quaternion \f$q_i\f$ </li>
     137                 :            :  * <li> The values in \f$\mathbf{\dot{q}}\f$ for the joint describe the angular
     138                 :            :  * velocity \f$\omega\f$ of the joint in body coordinates</li>
     139                 :            :  * <li> The values in \f$\mathbf{\ddot{q}}\f$ for the joint describe the angular
     140                 :            :  * acceleration \f$\dot{\omega}\f$ of the joint in body coordinates</li>
     141                 :            :  * <li> The values in \f$\mathbf{\tau}\f$ for the joint describe the three couples
     142                 :            :  * acting on the body in body coordinates that are actuated by the joint.</li>
     143                 :            :  * </ul>
     144                 :            : 
     145                 :            :  * As a result, the dimension of the vector \f$\mathbf{q}\f$ is higher than
     146                 :            :  * of the vector of the velocity variables. Additionally, the values in
     147                 :            :  * \f$\mathbf{\dot{q}}\f$ are \b not the derivative of \f$q\f$ and are therefore
     148                 :            :  * denoted by \f$\mathbf{\bar{q}}\f$ (and similarly for the joint
     149                 :            :  * accelerations).
     150                 :            : 
     151                 :            :  * RDL stores the Quaternions in \f$\mathbf{q}\f$ such that the 4th component of
     152                 :            :  * the joint is appended to \f$\mathbf{q}\f$. E.g. for a model with the joints:
     153                 :            :  * TX, Spherical, TY, Spherical, the values of \f$\mathbf{q},\mathbf{\bar{q}},\mathbf{\bar{\bar{q}}},\mathbf{\tau}\f$ are:
     154                 :            :  *
     155                 :            : 
     156                 :            :    \f{eqnarray*}
     157                 :            :         \mathbf{q} &=& ( q_{tx}, q_{q1,x}, q_{q1,y}, q_{q1,z}, q_{ty}, q_{q2,x}, q_{q2,y}, q_{q2,z}, q_{q1,w}, q_{q2,w})^T
     158                 :            :  *\\
     159                 :            :    \mathbf{\bar{q}} &=& ( \dot{q}_{tx}, \omega_{1,x}, \omega_{1,y}, \omega_{1,z}, \dot{q}_{ty}, \omega_{2,x}, \omega_{2,y},
     160                 :            :  *\\*\omega_{2,z} )^T \\
     161                 :            :    \mathbf{\bar{\bar{q}}} &=& ( \ddot{q}_{tx}, \dot{\omega}_{1,x}, \dot{\omega}_{1,y}, \dot{\omega}_{1,z}, \ddot{q}_{ty},
     162                 :            :  *\\*\dot{\omega}_{2,x}, \dot{\omega}_{2,y}, \dot{\omega}_{2,z} )^T \\
     163                 :            :    \mathbf{\tau} &=& ( \tau_{tx}, \tau_{1,x}, \tau_{1,y}, \tau_{1,z}, \tau_{ty}, \tau_{2,x}, \tau_{2,y}, \tau_{2,z} )^T
     164                 :            :    \f}
     165                 :            : 
     166                 :            :  * \subsection spherical_integration Numerical Integration of Quaternions
     167                 :            :  *
     168                 :            :  * An additional consequence of this is, that special treatment is required
     169                 :            :  * when numerically integrating the angular velocities. One possibility is
     170                 :            :  * to interpret the angular velocity as an axis-angle pair scaled by the
     171                 :            :  * timestep and use it create a quaternion that is applied to the previous
     172                 :            :  * Quaternion. Another is to compute the quaternion rates from the angular
     173                 :            :  * velocity. For details see James Diebel "Representing Attitude: Euler
     174                 :            :  * Angles, Unit Quaternions, and Rotation Vectors", 2006,
     175                 :            :  * http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.110.5134.
     176                 :            :  *
     177                 :            :  */
     178                 :            : 
     179                 :            : /** \brief General types of joints
     180                 :            :  */
     181                 :            : enum JointType
     182                 :            : {
     183                 :            :     JointTypeUndefined = 0,
     184                 :            :     JointTypeRevolute,
     185                 :            :     JointTypePrismatic,
     186                 :            :     JointTypeRevoluteX,
     187                 :            :     JointTypeRevoluteY,
     188                 :            :     JointTypeRevoluteZ,
     189                 :            :     JointTypeSpherical,  ///< 3 DoF joint using Quaternions for joint positional variables and
     190                 :            :                          // angular velocity for joint velocity variables.
     191                 :            :     JointTypeEulerZYX,   ///< 3 DoF joint that uses Euler ZYX convention (faster than emulated
     192                 :            :                          // multi DoF joints).
     193                 :            :     JointTypeEulerXYZ,   ///< 3 DoF joint that uses Euler XYZ convention (faster than emulated
     194                 :            :                          // multi DoF joints).
     195                 :            :     JointTypeEulerYXZ,   ///< 3 DoF joint that uses Euler YXZ convention (faster than emulated
     196                 :            :                          // multi DoF joints).
     197                 :            :     JointTypeTranslationXYZ,
     198                 :            :     JointTypeFloatingBase,  ///< A 6-DoF joint for floating-base (or freeflyer) systems.
     199                 :            :     JointTypeFixed,         ///< Fixed joint which causes the inertial properties to be merged with
     200                 :            :                             // the parent body.
     201                 :            :     JointType1DoF,
     202                 :            :     JointType2DoF,    ///< Emulated 2 DoF joint.
     203                 :            :     JointType3DoF,    ///< Emulated 3 DoF joint.
     204                 :            :     JointType4DoF,    ///< Emulated 4 DoF joint.
     205                 :            :     JointType5DoF,    ///< Emulated 5 DoF joint.
     206                 :            :     JointType6DoF,    ///< Emulated 6 DoF joint.
     207                 :            :     JointTypeCustom,  ///< User defined joints of varying size
     208                 :            : };
     209                 :            : 
     210                 :            : /**
     211                 :            :  * @struct Joint
     212                 :            :  * \brief Describes a joint relative to the predecessor body.
     213                 :            :  *
     214                 :            :  * @note The construction of a Joint is NOT a realtime safe procedure, so be sure you are not
     215                 :            :  * creating temporary joints at runtime. For maximum performance, you should create all joints
     216                 :            :  * at config time and just reference those.
     217                 :            :  *
     218                 :            :  * This class contains all information required for one single joint. This
     219                 :            :  * contains the joint type and the axis of the joint. See \ref joint_description for detailed description.
     220                 :            :  *
     221                 :            :  */
     222                 :            : struct Joint
     223                 :            : {
     224                 :       2194 :     Joint() : mJointAxes(nullptr), mJointType(JointTypeUndefined), mDoFCount(0), q_index(0), custom_joint_index(-1)
     225                 :            :     {
     226                 :       2194 :     }
     227                 :            : 
     228                 :        666 :     explicit Joint(JointType type) : mJointAxes(nullptr), mJointType(type), mDoFCount(0), q_index(0), custom_joint_index(-1)
     229                 :            :     {
     230                 :        666 :         if (type == JointTypeRevoluteX)
     231                 :            :         {
     232                 :        133 :             mDoFCount = 1;
     233                 :        266 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     234                 :        133 :             mJointAxes[0] = Math::SpatialVector(1., 0., 0., 0., 0., 0.);
     235                 :            :         }
     236                 :        533 :         else if (type == JointTypeRevoluteY)
     237                 :            :         {
     238                 :         35 :             mDoFCount = 1;
     239                 :         70 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     240                 :         35 :             mJointAxes[0] = Math::SpatialVector(0., 1., 0., 0., 0., 0.);
     241                 :            :         }
     242                 :        498 :         else if (type == JointTypeRevoluteZ)
     243                 :            :         {
     244                 :         19 :             mDoFCount = 1;
     245                 :         38 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     246                 :         19 :             mJointAxes[0] = Math::SpatialVector(0., 0., 1., 0., 0., 0.);
     247                 :            :         }
     248                 :        479 :         else if (type == JointTypeSpherical)
     249                 :            :         {
     250                 :         43 :             mDoFCount = 3;
     251                 :            : 
     252                 :        172 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     253                 :            : 
     254                 :         43 :             mJointAxes[0] = Math::SpatialVector(0., 0., 1., 0., 0., 0.);
     255                 :         43 :             mJointAxes[1] = Math::SpatialVector(0., 1., 0., 0., 0., 0.);
     256                 :         43 :             mJointAxes[2] = Math::SpatialVector(1., 0., 0., 0., 0., 0.);
     257                 :            :         }
     258                 :        436 :         else if (type == JointTypeEulerZYX)
     259                 :            :         {
     260                 :        120 :             mDoFCount = 3;
     261                 :            : 
     262                 :        480 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     263                 :            : 
     264                 :        120 :             mJointAxes[0] = Math::SpatialVector(0., 0., 1., 0., 0., 0.);
     265                 :        120 :             mJointAxes[1] = Math::SpatialVector(0., 1., 0., 0., 0., 0.);
     266                 :        120 :             mJointAxes[2] = Math::SpatialVector(1., 0., 0., 0., 0., 0.);
     267                 :            :         }
     268                 :        316 :         else if (type == JointTypeEulerXYZ)
     269                 :            :         {
     270                 :          7 :             mDoFCount = 3;
     271                 :            : 
     272                 :         28 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     273                 :            : 
     274                 :          7 :             mJointAxes[0] = Math::SpatialVector(1., 0., 0., 0., 0., 0.);
     275                 :          7 :             mJointAxes[1] = Math::SpatialVector(0., 1., 0., 0., 0., 0.);
     276                 :          7 :             mJointAxes[2] = Math::SpatialVector(0., 0., 1., 0., 0., 0.);
     277                 :            :         }
     278                 :        309 :         else if (type == JointTypeEulerYXZ)
     279                 :            :         {
     280                 :         65 :             mDoFCount = 3;
     281                 :            : 
     282                 :        260 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     283                 :            : 
     284                 :         65 :             mJointAxes[0] = Math::SpatialVector(0., 1., 0., 0., 0., 0.);
     285                 :         65 :             mJointAxes[1] = Math::SpatialVector(1., 0., 0., 0., 0., 0.);
     286                 :         65 :             mJointAxes[2] = Math::SpatialVector(0., 0., 1., 0., 0., 0.);
     287                 :            :         }
     288                 :        244 :         else if (type == JointTypeTranslationXYZ)
     289                 :            :         {
     290                 :         80 :             mDoFCount = 3;
     291                 :            : 
     292                 :        320 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     293                 :            : 
     294                 :         80 :             mJointAxes[0] = Math::SpatialVector(0., 0., 0., 1., 0., 0.);
     295                 :         80 :             mJointAxes[1] = Math::SpatialVector(0., 0., 0., 0., 1., 0.);
     296                 :         80 :             mJointAxes[2] = Math::SpatialVector(0., 0., 0., 0., 0., 1.);
     297                 :            :         }
     298                 :        164 :         else if ((type >= JointType1DoF) && (type <= JointType6DoF))
     299                 :            :         {
     300                 :            :             // create a joint and allocate memory for it.
     301                 :            :             // Warning: the memory does not get initialized by this function!
     302                 :          3 :             mDoFCount = type - JointType1DoF + 1;
     303                 :         15 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     304                 :            :         }
     305                 :        161 :         else if (type == JointTypeCustom)
     306                 :            :         {
     307                 :            :             // This constructor cannot be used for a JointTypeCustom because
     308                 :            :             // we have no idea what mDoFCount is.
     309                 :          1 :             throw RdlException("Error: Invalid use of Joint constructor Joint(JointType type). Only allowed when type != JointTypeCustom");
     310                 :            :         }
     311                 :        160 :         else if ((type != JointTypeFixed) && (type != JointTypeFloatingBase))
     312                 :            :         {
     313                 :          1 :             throw RdlException("Error: Invalid use of Joint constructor Joint(JointType type).");
     314                 :            :         }
     315                 :        664 :     }
     316                 :            : 
     317                 :         69 :     Joint(JointType type, int degreesOfFreedom) : mJointAxes(nullptr), mJointType(type), mDoFCount(0), q_index(0), custom_joint_index(-1)
     318                 :            :     {
     319                 :         69 :         if (type == JointTypeCustom)
     320                 :            :         {
     321                 :         68 :             mDoFCount = degreesOfFreedom;
     322                 :        192 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     323                 :            : 
     324                 :        192 :             for (unsigned int i = 0; i < mDoFCount; ++i)
     325                 :            :             {
     326                 :        124 :                 mJointAxes[i] = Math::SpatialVector(0., 0., 0., 0., 0., 0.);
     327                 :            :             }
     328                 :            :         }
     329                 :            :         else
     330                 :            :         {
     331                 :          1 :             throw RdlException("Error: Invalid use of Joint constructor Joint(JointType type, int degreesOfFreedom). Only allowed when type  == JointTypeCustom.");
     332                 :            :         }
     333                 :         68 :     }
     334                 :            : 
     335                 :      14189 :     Joint(const Joint& joint) : mJointType(joint.mJointType), mDoFCount(joint.mDoFCount), q_index(joint.q_index), custom_joint_index(joint.custom_joint_index)
     336                 :            :     {
     337                 :      29373 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     338                 :            : 
     339                 :      29373 :         for (unsigned int i = 0; i < mDoFCount; i++)
     340                 :            :         {
     341                 :      15184 :             mJointAxes[i] = joint.mJointAxes[i];
     342                 :            :         }
     343                 :      14189 :     }
     344                 :            : 
     345                 :       3782 :     Joint& operator=(const Joint& joint)
     346                 :            :     {
     347                 :       3782 :         if (this != &joint)
     348                 :            :         {
     349                 :       3782 :             if (mDoFCount > 0)
     350                 :            :             {
     351                 :       2260 :                 assert(mJointAxes);
     352                 :       2260 :                 delete[] mJointAxes;
     353                 :            :             }
     354                 :       3782 :             mJointType = joint.mJointType;
     355                 :       3782 :             mDoFCount = joint.mDoFCount;
     356                 :       3782 :             custom_joint_index = joint.custom_joint_index;
     357                 :       7762 :             mJointAxes = new Math::SpatialVector[mDoFCount];
     358                 :            : 
     359                 :       7762 :             for (unsigned int i = 0; i < mDoFCount; i++)
     360                 :            :             {
     361                 :       3980 :                 mJointAxes[i] = joint.mJointAxes[i];
     362                 :            :             }
     363                 :            : 
     364                 :       3782 :             q_index = joint.q_index;
     365                 :            :         }
     366                 :       3782 :         return *this;
     367                 :            :     }
     368                 :            : 
     369                 :      20868 :     ~Joint()
     370                 :            :     {
     371                 :      20868 :         if (mJointAxes)
     372                 :            :         {
     373                 :      20037 :             assert(mJointAxes);
     374                 :      20037 :             delete[] mJointAxes;
     375                 :      20037 :             mJointAxes = nullptr;
     376                 :      20037 :             mDoFCount = 0;
     377                 :      20037 :             custom_joint_index = -1;
     378                 :            :         }
     379                 :      20868 :     }
     380                 :            : 
     381                 :            :     /** \brief Constructs a joint from the given cartesian parameters.
     382                 :            :      *
     383                 :            :      * This constructor creates all the required spatial values for the given
     384                 :            :      * cartesian parameters.
     385                 :            :      *
     386                 :            :      * \param joint_type whether the joint is revolute or prismatic
     387                 :            :      * \param joint_axis the axis of rotation or translation
     388                 :            :      */
     389                 :        370 :     Joint(const JointType joint_type, const Math::Vector3d& joint_axis) : mDoFCount(1), q_index(0), custom_joint_index(-1)
     390                 :            :     {
     391                 :        740 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     392                 :            : 
     393                 :            :         // Some assertions, as we concentrate on simple cases
     394                 :            : 
     395                 :            :         // Only rotation around the Z-axis
     396                 :        370 :         assert(joint_type == JointTypeRevolute || joint_type == JointTypePrismatic);
     397                 :            : 
     398                 :        370 :         mJointType = joint_type;
     399                 :            : 
     400                 :        370 :         if (joint_type == JointTypeRevolute)
     401                 :            :         {
     402                 :            :             // make sure we have a unit axis
     403                 :         13 :             mJointAxes[0].set(joint_axis[0], joint_axis[1], joint_axis[2], 0., 0., 0.);
     404                 :            :         }
     405                 :        357 :         else if (joint_type == JointTypePrismatic)
     406                 :            :         {
     407                 :            :             // make sure we have a unit axis
     408                 :        357 :             assert(joint_axis.squaredNorm() == 1.);
     409                 :            : 
     410                 :        357 :             mJointAxes[0].set(0., 0., 0., joint_axis[0], joint_axis[1], joint_axis[2]);
     411                 :            :         }
     412                 :        370 :     }
     413                 :            : 
     414                 :            :     /** \brief Constructs a 1 DoF joint with the given motion subspaces.
     415                 :            :      *
     416                 :            :      * The motion subspaces are of the format:
     417                 :            :      * \f[ (r_x, r_y, r_z, t_x, t_y, t_z) \f]
     418                 :            :      *
     419                 :            :      * \note So far only pure rotations or pure translations are supported.
     420                 :            :      *
     421                 :            :      * \param axis_0 Motion subspace for axis 0
     422                 :            :      */
     423                 :       3498 :     explicit Joint(const Math::SpatialVector& axis_0) : mDoFCount(1), q_index(0), custom_joint_index(-1)
     424                 :            :     {
     425                 :       6996 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     426                 :       3498 :         mJointAxes[0] = Math::SpatialVector(axis_0);
     427                 :            : 
     428                 :       3498 :         if (axis_0 == Math::SpatialVector(1., 0., 0., 0., 0., 0.))
     429                 :            :         {
     430                 :        650 :             mJointType = JointTypeRevoluteX;
     431                 :            :         }
     432                 :       2848 :         else if (axis_0 == Math::SpatialVector(0., 1., 0., 0., 0., 0.))
     433                 :            :         {
     434                 :       1304 :             mJointType = JointTypeRevoluteY;
     435                 :            :         }
     436                 :       1544 :         else if (axis_0 == Math::SpatialVector(0., 0., 1., 0., 0., 0.))
     437                 :            :         {
     438                 :       1223 :             mJointType = JointTypeRevoluteZ;
     439                 :            :         }
     440                 :            :         else
     441                 :            :         {
     442                 :        321 :             mJointType = JointType1DoF;
     443                 :            :         }
     444                 :       3498 :         validate_spatial_axis(mJointAxes[0]);
     445                 :       3498 :     }
     446                 :            : 
     447                 :            :     /** \brief Constructs a 2 DoF joint with the given motion subspaces.
     448                 :            :      *
     449                 :            :      * The motion subspaces are of the format:
     450                 :            :      * \f[ (r_x, r_y, r_z, t_x, t_y, t_z) \f]
     451                 :            :      *
     452                 :            :      * \note So far only pure rotations or pure translations are supported.
     453                 :            :      *
     454                 :            :      * \param axis_0 Motion subspace for axis 0
     455                 :            :      * \param axis_1 Motion subspace for axis 1
     456                 :            :      */
     457                 :         63 :     Joint(const Math::SpatialVector& axis_0, const Math::SpatialVector& axis_1) : mJointType(JointType2DoF), mDoFCount(2), q_index(0), custom_joint_index(-1)
     458                 :            :     {
     459                 :        189 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     460                 :         63 :         mJointAxes[0] = axis_0;
     461                 :         63 :         mJointAxes[1] = axis_1;
     462                 :            : 
     463                 :         63 :         validate_spatial_axis(mJointAxes[0]);
     464                 :         63 :         validate_spatial_axis(mJointAxes[1]);
     465                 :         63 :     }
     466                 :            : 
     467                 :            :     /** \brief Constructs a 3 DoF joint with the given motion subspaces.
     468                 :            :      *
     469                 :            :      * The motion subspaces are of the format:
     470                 :            :      * \f[ (r_x, r_y, r_z, t_x, t_y, t_z) \f]
     471                 :            :      *
     472                 :            :      * \note So far only pure rotations or pure translations are supported.
     473                 :            :      *
     474                 :            :      * \param axis_0 Motion subspace for axis 0
     475                 :            :      * \param axis_1 Motion subspace for axis 1
     476                 :            :      * \param axis_2 Motion subspace for axis 2
     477                 :            :      */
     478                 :        128 :     Joint(const Math::SpatialVector& axis_0, const Math::SpatialVector& axis_1, const Math::SpatialVector& axis_2)
     479                 :        128 :       : mJointType(JointType3DoF), mDoFCount(3), q_index(0), custom_joint_index(-1)
     480                 :            :     {
     481                 :        512 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     482                 :            : 
     483                 :        128 :         mJointAxes[0] = axis_0;
     484                 :        128 :         mJointAxes[1] = axis_1;
     485                 :        128 :         mJointAxes[2] = axis_2;
     486                 :            : 
     487                 :        128 :         validate_spatial_axis(mJointAxes[0]);
     488                 :        128 :         validate_spatial_axis(mJointAxes[1]);
     489                 :        128 :         validate_spatial_axis(mJointAxes[2]);
     490                 :        128 :     }
     491                 :            : 
     492                 :            :     /** \brief Constructs a 4 DoF joint with the given motion subspaces.
     493                 :            :      *
     494                 :            :      * The motion subspaces are of the format:
     495                 :            :      * \f[ (r_x, r_y, r_z, t_x, t_y, t_z) \f]
     496                 :            :      *
     497                 :            :      * \note So far only pure rotations or pure translations are supported.
     498                 :            :      *
     499                 :            :      * \param axis_0 Motion subspace for axis 0
     500                 :            :      * \param axis_1 Motion subspace for axis 1
     501                 :            :      * \param axis_2 Motion subspace for axis 2
     502                 :            :      * \param axis_3 Motion subspace for axis 3
     503                 :            :      */
     504                 :          1 :     Joint(const Math::SpatialVector& axis_0, const Math::SpatialVector& axis_1, const Math::SpatialVector& axis_2, const Math::SpatialVector& axis_3)
     505                 :          1 :       : mJointType(JointType4DoF), mDoFCount(4), q_index(0), custom_joint_index(-1)
     506                 :            :     {
     507                 :          5 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     508                 :            : 
     509                 :          1 :         mJointAxes[0] = axis_0;
     510                 :          1 :         mJointAxes[1] = axis_1;
     511                 :          1 :         mJointAxes[2] = axis_2;
     512                 :          1 :         mJointAxes[3] = axis_3;
     513                 :            : 
     514                 :          1 :         validate_spatial_axis(mJointAxes[0]);
     515                 :          1 :         validate_spatial_axis(mJointAxes[1]);
     516                 :          1 :         validate_spatial_axis(mJointAxes[2]);
     517                 :          1 :         validate_spatial_axis(mJointAxes[3]);
     518                 :          1 :     }
     519                 :            : 
     520                 :            :     /** \brief Constructs a 5 DoF joint with the given motion subspaces.
     521                 :            :      *
     522                 :            :      * The motion subspaces are of the format:
     523                 :            :      * \f[ (r_x, r_y, r_z, t_x, t_y, t_z) \f]
     524                 :            :      *
     525                 :            :      * \note So far only pure rotations or pure translations are supported.
     526                 :            :      *
     527                 :            :      * \param axis_0 Motion subspace for axis 0
     528                 :            :      * \param axis_1 Motion subspace for axis 1
     529                 :            :      * \param axis_2 Motion subspace for axis 2
     530                 :            :      * \param axis_3 Motion subspace for axis 3
     531                 :            :      * \param axis_4 Motion subspace for axis 4
     532                 :            :      */
     533                 :          1 :     Joint(const Math::SpatialVector& axis_0, const Math::SpatialVector& axis_1, const Math::SpatialVector& axis_2, const Math::SpatialVector& axis_3,
     534                 :            :           const Math::SpatialVector& axis_4)
     535                 :          1 :       : mJointType(JointType5DoF), mDoFCount(5), q_index(0), custom_joint_index(-1)
     536                 :            :     {
     537                 :          6 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     538                 :            : 
     539                 :          1 :         mJointAxes[0] = axis_0;
     540                 :          1 :         mJointAxes[1] = axis_1;
     541                 :          1 :         mJointAxes[2] = axis_2;
     542                 :          1 :         mJointAxes[3] = axis_3;
     543                 :          1 :         mJointAxes[4] = axis_4;
     544                 :            : 
     545                 :          1 :         validate_spatial_axis(mJointAxes[0]);
     546                 :          1 :         validate_spatial_axis(mJointAxes[1]);
     547                 :          1 :         validate_spatial_axis(mJointAxes[2]);
     548                 :          1 :         validate_spatial_axis(mJointAxes[3]);
     549                 :          1 :         validate_spatial_axis(mJointAxes[4]);
     550                 :          1 :     }
     551                 :            : 
     552                 :            :     /** \brief Constructs a 6 DoF joint with the given motion subspaces.
     553                 :            :      *
     554                 :            :      * The motion subspaces are of the format:
     555                 :            :      * \f[ (r_x, r_y, r_z, t_x, t_y, t_z) \f]
     556                 :            :      *
     557                 :            :      * \note So far only pure rotations or pure translations are supported.
     558                 :            :      *
     559                 :            :      * \param axis_0 Motion subspace for axis 0
     560                 :            :      * \param axis_1 Motion subspace for axis 1
     561                 :            :      * \param axis_2 Motion subspace for axis 2
     562                 :            :      * \param axis_3 Motion subspace for axis 3
     563                 :            :      * \param axis_4 Motion subspace for axis 4
     564                 :            :      * \param axis_5 Motion subspace for axis 5
     565                 :            :      */
     566                 :         92 :     Joint(const Math::SpatialVector& axis_0, const Math::SpatialVector& axis_1, const Math::SpatialVector& axis_2, const Math::SpatialVector& axis_3,
     567                 :            :           const Math::SpatialVector& axis_4, const Math::SpatialVector& axis_5)
     568                 :         92 :       : mJointType(JointType6DoF), mDoFCount(6), q_index(0), custom_joint_index(-1)
     569                 :            :     {
     570                 :        644 :         mJointAxes = new Math::SpatialVector[mDoFCount];
     571                 :            : 
     572                 :         92 :         mJointAxes[0] = axis_0;
     573                 :         92 :         mJointAxes[1] = axis_1;
     574                 :         92 :         mJointAxes[2] = axis_2;
     575                 :         92 :         mJointAxes[3] = axis_3;
     576                 :         92 :         mJointAxes[4] = axis_4;
     577                 :         92 :         mJointAxes[5] = axis_5;
     578                 :            : 
     579                 :         92 :         validate_spatial_axis(mJointAxes[0]);
     580                 :         92 :         validate_spatial_axis(mJointAxes[1]);
     581                 :         92 :         validate_spatial_axis(mJointAxes[2]);
     582                 :         92 :         validate_spatial_axis(mJointAxes[3]);
     583                 :         92 :         validate_spatial_axis(mJointAxes[4]);
     584                 :         92 :         validate_spatial_axis(mJointAxes[5]);
     585                 :         92 :     }
     586                 :            : 
     587                 :            :     /** \brief Checks whether we have pure rotational or translational axis.
     588                 :            :      *
     589                 :            :      * This function is mainly used to print out warnings when specifying an
     590                 :            :      * axis that might not be intended.
     591                 :            :      */
     592                 :       4570 :     bool validate_spatial_axis(Math::SpatialVector& axis)
     593                 :            :     {
     594                 :       4570 :         if (fabs(axis.norm() - 1.0) > 1.0e-8)
     595                 :            :         {
     596                 :          1 :             std::cerr << "Warning: joint axis is not unit!" << std::endl;
     597                 :            :         }
     598                 :            : 
     599                 :       4570 :         bool axis_rotational = false;
     600                 :       4570 :         bool axis_translational = false;
     601                 :            : 
     602                 :       4570 :         Math::Vector3d rotation(axis[0], axis[1], axis[2]);
     603                 :       4570 :         Math::Vector3d translation(axis[3], axis[4], axis[5]);
     604                 :            : 
     605                 :       4570 :         if (fabs(translation.norm()) < 1.0e-8)
     606                 :            :         {
     607                 :       3958 :             axis_rotational = true;
     608                 :            :         }
     609                 :            : 
     610                 :       4570 :         if (fabs(rotation.norm()) < 1.0e-8)
     611                 :            :         {
     612                 :        611 :             axis_translational = true;
     613                 :            :         }
     614                 :            : 
     615                 :       4570 :         return axis_rotational || axis_translational;
     616                 :            :     }
     617                 :            : 
     618                 :            :     /// \brief The spatial axes of the joint
     619                 :            :     Math::SpatialVector* mJointAxes;
     620                 :            : 
     621                 :            :     /// \brief Type of joint
     622                 :            :     JointType mJointType;
     623                 :            : 
     624                 :            :     /// \brief Number of degrees of freedom of the joint. Note: CustomJoints
     625                 :            :     // have here a value of 0 and their actual numbers of degrees of freedom
     626                 :            :     // can be obtained using the CustomJoint structure.
     627                 :            :     unsigned int mDoFCount;
     628                 :            :     unsigned int q_index;
     629                 :            :     unsigned int custom_joint_index;
     630                 :            : };
     631                 :            : 
     632                 :            : /** \brief Computes all variables for a joint model and updates the body frame as well as the body's
     633                 :            :  * center of mass frame
     634                 :            :  *
     635                 :            :  *      By appropriate modification of this function all types of joints can be
     636                 :            :  *      modeled. See RobotDynamics::CustomJoint
     637                 :            :  *
     638                 :            :  * \param model    the rigid body model
     639                 :            :  * \param joint_id the id of the joint we are interested in. This will be used to determine the type of joint and also the
     640                 :            :  **entries of \f[ q, \dot{q} \f].
     641                 :            :  * \param q        joint state variables
     642                 :            :  * \param qdot     joint velocity variables
     643                 :            :  */
     644                 :            : void jcalc(Model& model, unsigned int joint_id, const Math::VectorNd& q, const Math::VectorNd& qdot);
     645                 :            : 
     646                 :            : Math::SpatialTransform jcalc_XJ(Model& model, unsigned int joint_id, const Math::VectorNd& q);
     647                 :            : 
     648                 :            : void jcalc_X_lambda_S(Model& model, unsigned int joint_id, const Math::VectorNd& q);
     649                 :            : 
     650                 :            : /**
     651                 :            :  * @struct CustomJoint
     652                 :            :  * @brief CustomJoint is a struct used to create a joint with user defined parameters. This is
     653                 :            :  * accomplished by overriding the RobotDynamics::Joint::jcalc methods that calculate each joints
     654                 :            :  * kinematic parameters
     655                 :            :  */
     656                 :            : struct CustomJoint
     657                 :            : {
     658                 :            :     /**
     659                 :            :      * @brief Constructor
     660                 :            :      */
     661                 :         95 :     CustomJoint() : mDoFCount(0)
     662                 :            :     {
     663                 :         95 :     }
     664                 :            : 
     665                 :            :     /**
     666                 :            :      * @brief Destructor
     667                 :            :      */
     668                 :         95 :     virtual ~CustomJoint()
     669                 :         95 :     {
     670                 :         95 :     }
     671                 :            : 
     672                 :            :     /**
     673                 :            :      * @param model
     674                 :            :      * @param joint_id
     675                 :            :      * @param q
     676                 :            :      * @param qdot
     677                 :            :      */
     678                 :            :     virtual void jcalc(Model& model, unsigned int joint_id, const Math::VectorNd& q, const Math::VectorNd& qdot) = 0;
     679                 :            : 
     680                 :            :     virtual void jcalc_X_lambda_S(Model& model, unsigned int joint_id, const Math::VectorNd& q) = 0;
     681                 :            : 
     682                 :            :     unsigned int mDoFCount;    /**< Degrees of freedom of the joint */
     683                 :            :     Math::SpatialTransform XJ; /**< Joint state transform. Transform from parent */
     684                 :            :     Math::MatrixNd S;          /**< Motion subspace map */
     685                 :            :     Math::MatrixNd S_o;        /**< Motion subspace map */
     686                 :            :     Math::MatrixNd U;
     687                 :            :     Math::MatrixNd Dinv;
     688                 :            :     Math::VectorNd u;
     689                 :            :     Math::VectorNd d_u;
     690                 :            :     Math::VectorNd ndof0_vec; /**< mDoFCount x 1 vector of zeros */
     691                 :            : };
     692                 :            : }  // namespace RobotDynamics
     693                 :            : 
     694                 :            : /* RDL_JOINT_H */
     695                 :            : #endif  // ifndef __RDL_JOINT_H__

Generated by: LCOV version 1.14