LCOV - code coverage report
Current view: top level - src/rdl/rdl_dynamics/include/rdl_dynamics - Body.hpp (source / functions) Hit Total Coverage
Test: projectcoverage.info Lines: 138 138 100.0 %
Date: 2024-12-13 18:04:46 Functions: 20 20 100.0 %
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_BODY_HPP
       7                 :            : #define RDL_BODY_HPP
       8                 :            : 
       9                 :            : #include <rdl_dynamics/RigidBodyInertia.hpp>
      10                 :            : #include <rdl_dynamics/rdl_mathutils.hpp>
      11                 :            : #include <assert.h>
      12                 :            : #include <iostream>
      13                 :            : #include <rdl_dynamics/RdlExceptions.hpp>
      14                 :            : 
      15                 :            : namespace RobotDynamics
      16                 :            : {
      17                 :            : /**
      18                 :            :  * @struct A compact struct for storing the drag data for a body
      19                 :            :  */
      20                 :            : struct DragData
      21                 :            : {
      22                 :          2 :     DragData(const std::vector<double>& linear_drag, const std::vector<double>& quadratic_drag)
      23                 :          2 :     {
      24                 :          2 :         assert(linear_drag.size() == 6 && quadratic_drag.size() == 6);
      25                 :         14 :         for (unsigned int i = 0; i < 6; i++)
      26                 :            :         {
      27                 :         12 :             this->linearDrag[i] = linear_drag[i];
      28                 :         12 :             this->quadraticDrag[i] = quadratic_drag[i];
      29                 :            :         }
      30                 :          2 :     }
      31                 :            : 
      32                 :         45 :     DragData(const Math::SpatialVector& linear_drag, const Math::SpatialVector& quadratic_drag)
      33                 :         45 :     {
      34                 :         45 :         this->linearDrag = linear_drag;
      35                 :         45 :         this->quadraticDrag = quadratic_drag;
      36                 :         45 :     }
      37                 :            : 
      38                 :       3994 :     DragData()
      39                 :       3994 :     {
      40                 :       3994 :         zero();
      41                 :       3994 :     }
      42                 :            : 
      43                 :      15365 :     DragData(const DragData& dragData)
      44                 :      15365 :     {
      45                 :      15365 :         this->linearDrag = dragData.linearDrag;
      46                 :      15365 :         this->quadraticDrag = dragData.quadraticDrag;
      47                 :      15365 :     }
      48                 :            : 
      49                 :       7727 :     void zero()
      50                 :            :     {
      51                 :       7727 :         linearDrag.setZero();
      52                 :       7727 :         quadraticDrag.setZero();
      53                 :       7727 :     }
      54                 :            : 
      55                 :       1383 :     DragData& operator=(const DragData& dragData)
      56                 :            :     {
      57                 :       1383 :         this->linearDrag = dragData.linearDrag;
      58                 :       1383 :         this->quadraticDrag = dragData.quadraticDrag;
      59                 :       1383 :         return *this;
      60                 :            :     }
      61                 :            : 
      62                 :        399 :     void operator+=(const DragData& dragData)
      63                 :            :     {
      64                 :        399 :         linearDrag += dragData.linearDrag;
      65                 :        399 :         quadraticDrag += dragData.quadraticDrag;
      66                 :        399 :     }
      67                 :            : 
      68                 :            :     Math::SpatialVector linearDrag;    /**< 6 coefficients for the linear portion of the drag effect */
      69                 :            :     Math::SpatialVector quadraticDrag; /**< 6 coefficients for the quadratic portion of the drag effect */
      70                 :            : };
      71                 :            : 
      72                 :        399 : inline DragData operator+(DragData dragData1, const DragData& dragData2)
      73                 :            : {
      74                 :        399 :     dragData1 += dragData2;
      75                 :        399 :     return dragData1;
      76                 :            : }
      77                 :            : 
      78                 :            : /** \brief Describes all properties of a single body
      79                 :            :  *
      80                 :            :  * A Body contains information about mass, the location of its center of
      81                 :            :  * mass, the ineria tensor in the center of mass as well as information
      82                 :            :  * for hydrodynamics such as center of buoyancy, volume, and shape parameters
      83                 :            :  * for modeling fluid added mass/drag effects. This class is
      84                 :            :  * designed to use the given information and transform it such that it can
      85                 :            :  * directly be used by the spatial algebra.
      86                 :            :  */
      87                 :            : struct Body
      88                 :            : {
      89                 :       1244 :     Body()
      90                 :       1244 :       : mMass(0.)
      91                 :       1244 :       , mCenterOfMass(0., 0., 0.)
      92                 :       1244 :       , mInertia(Math::Matrix3d::Zero(3, 3))
      93                 :       1244 :       , volume(0.)
      94                 :       1244 :       , mCenterOfBuoyancy(0., 0., 0.)
      95                 :       1244 :       , addedMassMatrix(Math::SpatialMatrixZero)
      96                 :       1244 :       , mIsVirtual(false)
      97                 :            :     {
      98                 :       1244 :         dragData.zero();
      99                 :       1244 :     };
     100                 :            : 
     101                 :      14728 :     Body(const Body& body)
     102                 :      14728 :       : mMass(body.mMass)
     103                 :      14728 :       , mCenterOfMass(body.mCenterOfMass)
     104                 :      14728 :       , mInertia(body.mInertia)
     105                 :      14728 :       , volume(body.volume)
     106                 :      14728 :       , mCenterOfBuoyancy(body.mCenterOfBuoyancy)
     107                 :      14728 :       , addedMassMatrix(body.addedMassMatrix)
     108                 :      14728 :       , dragData(body.dragData)
     109                 :      14728 :       , mIsVirtual(body.mIsVirtual){};
     110                 :            : 
     111                 :       1151 :     Body& operator=(const Body& body)
     112                 :            :     {
     113                 :       1151 :         if (this != &body)
     114                 :            :         {
     115                 :       1151 :             mMass = body.mMass;
     116                 :       1151 :             mInertia = body.mInertia;
     117                 :       1151 :             mCenterOfMass = body.mCenterOfMass;
     118                 :       1151 :             mIsVirtual = body.mIsVirtual;
     119                 :       1151 :             mCenterOfBuoyancy = body.mCenterOfBuoyancy;
     120                 :       1151 :             volume = body.volume;
     121                 :       1151 :             addedMassMatrix = body.addedMassMatrix;
     122                 :       1151 :             dragData = body.dragData;
     123                 :            :         }
     124                 :            : 
     125                 :       1151 :         return *this;
     126                 :            :     }
     127                 :            : 
     128                 :            :     /** \brief Constructs a body from mass, center of mass, radii of gyration, the center of buoyancy,
     129                 :            :      * added mass matrix, drag data, and the volume taken up by the body
     130                 :            :      *
     131                 :            :      * This constructor eases the construction of a new body as all the
     132                 :            :      * required parameters can be specified as parameters to the
     133                 :            :      * constructor. These are then used to generate the spatial inertia
     134                 :            :      * matrix which is expressed at the origin.
     135                 :            :      *
     136                 :            :      * \param mass the mass of the body
     137                 :            :      * \param com  the position of the center of mass in the bodies coordinates
     138                 :            :      * \param gyration_radii the radii of gyration at the center of mass of the body
     139                 :            :      * \param centerOfBuoyancy The center of buoyancy for the body
     140                 :            :      * \param volume The volume taken up by the body
     141                 :            :      * \param addedMassMatrix The hydrodynamic added mass matrix
     142                 :            :      * \param dragData Hydrodynamic drag data struct for the body
     143                 :            :      */
     144                 :         53 :     Body(const double& mass, const Math::Vector3d& com, const Math::Vector3d& gyration_radii, const Math::Vector3d& centerOfBuoyancy, const double volume,
     145                 :            :          const Math::SpatialMatrix& addedMassMatrix, const DragData& dragData)
     146                 :         53 :       : mMass(mass), mCenterOfMass(com), volume(volume), mCenterOfBuoyancy(centerOfBuoyancy), addedMassMatrix(addedMassMatrix), dragData(dragData), mIsVirtual(false)
     147                 :            :     {
     148                 :         53 :         mInertia = Math::Matrix3d(gyration_radii[0], 0., 0., 0., gyration_radii[1], 0., 0., 0., gyration_radii[2]);
     149                 :         53 :     }
     150                 :            : 
     151                 :            :     /** \brief Constructs a body from mass, center of mass, radii of gyration, the center of buoyancy,
     152                 :            :      * and hydrodynamic parameters
     153                 :            :      *
     154                 :            :      * This constructor eases the construction of a new body as all the
     155                 :            :      * required parameters can be specified as parameters to the
     156                 :            :      * constructor. These are then used to generate the spatial inertia
     157                 :            :      * matrix which is expressed at the origin.
     158                 :            :      *
     159                 :            :      * \param mass the mass of the body
     160                 :            :      * \param com  the position of the center of mass in the bodies coordinates
     161                 :            :      * \param gyration_radii the radii of gyration at the center of mass of the body
     162                 :            :      * \param centerOfBuoyancy The center of buoyancy for the body
     163                 :            :      * \param volume The volume taken up by the body
     164                 :            :      * \param addedMassMatrix The hydrodynamic added mass matrix for the body
     165                 :            :      */
     166                 :         10 :     Body(const double& mass, const Math::Vector3d& com, const Math::Vector3d& gyration_radii, const Math::Vector3d& centerOfBuoyancy, const double volume,
     167                 :            :          const Math::SpatialMatrix& addedMassMatrix)
     168                 :         10 :       : mMass(mass), mCenterOfMass(com), volume(volume), mCenterOfBuoyancy(centerOfBuoyancy), addedMassMatrix(addedMassMatrix), mIsVirtual(false)
     169                 :            :     {
     170                 :         10 :         dragData.zero();
     171                 :         10 :         mInertia = Math::Matrix3d(gyration_radii[0], 0., 0., 0., gyration_radii[1], 0., 0., 0., gyration_radii[2]);
     172                 :         10 :     }
     173                 :            : 
     174                 :            :     /** \brief Constructs a body from mass, center of mass, radii of gyration. Hydrodynamic terms are set such that
     175                 :            :      * they will have no effect on the dynamics
     176                 :            :      *
     177                 :            :      * This constructor eases the construction of a new body as all the
     178                 :            :      * required parameters can be specified as parameters to the
     179                 :            :      * constructor. These are then used to generate the spatial inertia
     180                 :            :      * matrix which is expressed at the origin.
     181                 :            :      *
     182                 :            :      * \param mass the mass of the body
     183                 :            :      * \param com  the position of the center of mass in the bodies coordinates
     184                 :            :      * \param gyration_radii the radii of gyration at the center of mass of the body
     185                 :            :      */
     186                 :       1722 :     Body(const double& mass, const Math::Vector3d& com, const Math::Vector3d& gyration_radii)
     187                 :       1722 :       : mMass(mass), mCenterOfMass(com), volume(0.), mCenterOfBuoyancy(Math::Vector3dZero), mIsVirtual(false)
     188                 :            :     {
     189                 :       1722 :         mInertia = Math::Matrix3d(gyration_radii[0], 0., 0., 0., gyration_radii[1], 0., 0., 0., gyration_radii[2]);
     190                 :       1722 :         dragData.zero();
     191                 :       1722 :         addedMassMatrix.setZero();
     192                 :       1722 :     }
     193                 :            : 
     194                 :            :     /** \brief Constructs a body from mass, center of mass, a 3x3 inertia matrix, the center of buoyancy,
     195                 :            :      * and hydrodynamic parameters
     196                 :            :      *
     197                 :            :      * This constructor eases the construction of a new body as all the
     198                 :            :      * required parameters can simply be specified as parameters to the
     199                 :            :      * constructor. These are then used to generate the spatial inertia
     200                 :            :      * matrix which is expressed at the origin.
     201                 :            :      *
     202                 :            :      * \param mass the mass of the body
     203                 :            :      * \param com  the position of the center of mass in the bodies coordinates
     204                 :            :      * \param inertia_C the inertia at the center of mass
     205                 :            :      * \param centerOfBuoyancy The center of buoyancy for the body
     206                 :            :      * \param volume The volume taken up by the body
     207                 :            :      * \param addedMassMatrix Hydrodynamic added mass matrix for the body
     208                 :            :      * \param dragData The drag data for this body
     209                 :            :      */
     210                 :        262 :     Body(const double& mass, const Math::Vector3d& com, const Math::Matrix3d& inertia_C, const Math::Vector3d& centerOfBuoyancy, const double volume,
     211                 :            :          const Math::SpatialMatrix& addedMassMatrix, const DragData& dragData)
     212                 :        262 :       : mMass(mass)
     213                 :        262 :       , mCenterOfMass(com)
     214                 :        262 :       , mInertia(inertia_C)
     215                 :        262 :       , volume(volume)
     216                 :        262 :       , mCenterOfBuoyancy(centerOfBuoyancy)
     217                 :        262 :       , addedMassMatrix(addedMassMatrix)
     218                 :        262 :       , dragData(dragData)
     219                 :        262 :       , mIsVirtual(false)
     220                 :            :     {
     221                 :        262 :     }
     222                 :            : 
     223                 :            :     /** \brief Constructs a body from mass, center of mass, a 3x3 inertia matrix, the center of buoyancy,
     224                 :            :      * and hydrodynamic parameters
     225                 :            :      *
     226                 :            :      * This constructor eases the construction of a new body as all the
     227                 :            :      * required parameters can simply be specified as parameters to the
     228                 :            :      * constructor. These are then used to generate the spatial inertia
     229                 :            :      * matrix which is expressed at the origin.
     230                 :            :      *
     231                 :            :      * \param mass the mass of the body
     232                 :            :      * \param com  the position of the center of mass in the bodies coordinates
     233                 :            :      * \param inertia_C the inertia at the center of mass
     234                 :            :      * \param centerOfBuoyancy The center of buoyancy for the body
     235                 :            :      * \param volume The volume taken up by the body
     236                 :            :      * \param addedMassMatrix The hydrodynamic added mass matrix for the body
     237                 :            :      */
     238                 :        620 :     Body(const double& mass, const Math::Vector3d& com, const Math::Matrix3d& inertia_C, const Math::Vector3d& centerOfBuoyancy, const double volume,
     239                 :            :          const Math::SpatialMatrix addedMassMatrix)
     240                 :        620 :       : mMass(mass), mCenterOfMass(com), mInertia(inertia_C), volume(volume), mCenterOfBuoyancy(centerOfBuoyancy), addedMassMatrix(addedMassMatrix), mIsVirtual(false)
     241                 :            :     {
     242                 :        620 :         dragData.zero();
     243                 :        620 :     }
     244                 :            : 
     245                 :            :     /** \brief Constructs a body from mass, center of mass, a 3x3 inertia matrix. Hydrodynamic terms are set such that
     246                 :            :      * they will have no dynamic effects
     247                 :            :      *
     248                 :            :      * This constructor eases the construction of a new body as all the
     249                 :            :      * required parameters can simply be specified as parameters to the
     250                 :            :      * constructor. These are then used to generate the spatial inertia
     251                 :            :      * matrix which is expressed at the origin.
     252                 :            :      *
     253                 :            :      * \param mass the mass of the body
     254                 :            :      * \param com  the position of the center of mass in the bodies coordinates
     255                 :            :      * \param inertia_C the inertia at the center of mass
     256                 :            :      */
     257                 :        137 :     Body(const double& mass, const Math::Vector3d& com, const Math::Matrix3d& inertia_C)
     258                 :        137 :       : mMass(mass), mCenterOfMass(com), mInertia(inertia_C), volume(0.), mCenterOfBuoyancy(Math::Vector3dZero), mIsVirtual(false)
     259                 :            :     {
     260                 :        137 :         addedMassMatrix.setZero();
     261                 :        137 :         dragData.zero();
     262                 :        137 :     }
     263                 :            : 
     264                 :            :     /** \brief Joins inertial parameters of two bodies to create a composite
     265                 :            :      * body.
     266                 :            :      *
     267                 :            :      * This function can be used to join inertial parameters of two bodies
     268                 :            :      * to create a composite body that has the inertial properties as if the
     269                 :            :      * two bodies were joined by a fixed joint.
     270                 :            :      *
     271                 :            :      * \note The drag terms and added mass matrices for both bodies will simply be added
     272                 :            :      * together
     273                 :            :      *
     274                 :            :      * \param transform The frame transformation from the origin of the
     275                 :            :      * original body to the origin of the added body
     276                 :            :      * \param other_body The other body that will be merged with *this.
     277                 :            :      */
     278                 :        491 :     void join(const Math::SpatialTransform& transform, const Body& other_body)
     279                 :            :     {
     280                 :            :         // nothing to do if we join a massles body to the current.
     281                 :        491 :         if (other_body.mMass == 0. && other_body.mInertia == Math::Matrix3d::Zero())
     282                 :            :         {
     283                 :         91 :             return;
     284                 :            :         }
     285                 :            : 
     286                 :        400 :         double other_mass = other_body.mMass;
     287                 :        400 :         double new_mass = mMass + other_mass;
     288                 :            : 
     289                 :        400 :         double other_volume = other_body.volume;
     290                 :        400 :         double new_volume = volume + other_volume;
     291                 :            : 
     292                 :        400 :         if (new_mass == 0.)
     293                 :            :         {
     294                 :          1 :             throw RdlException("Error: cannot join bodies as both have zero mass!");
     295                 :            :         }
     296                 :            : 
     297                 :        399 :         Math::Vector3d other_com = transform.E.transpose() * other_body.mCenterOfMass + transform.r;
     298                 :        399 :         Math::Vector3d new_com = (1. / new_mass) * (mMass * mCenterOfMass + other_mass * other_com);
     299                 :        399 :         Math::Vector3d new_cob = mCenterOfBuoyancy;
     300                 :        399 :         if (new_volume != 0.)
     301                 :            :         {
     302                 :        267 :             Math::Vector3d other_cob = transform.E.transpose() * other_body.mCenterOfBuoyancy + transform.r;
     303                 :        267 :             new_cob = (1. / new_volume) * (volume * mCenterOfBuoyancy + other_volume * other_cob);
     304                 :            :         }
     305                 :            : 
     306                 :            :         // We have to transform the inertia of other_body to the new COM. This
     307                 :            :         // is done in 4 steps:
     308                 :            :         //
     309                 :            :         // 1. Transform the inertia from other origin to other COM
     310                 :            :         // 2. Rotate the inertia that it is aligned to the frame of this body
     311                 :            :         // 3. Transform inertia of other_body to the origin of the frame of
     312                 :            :         // this body
     313                 :            :         // 4. Sum the two inertias
     314                 :            :         // 5. Transform the summed inertia to the new COM
     315                 :            : 
     316                 :        399 :         Math::RigidBodyInertia other_rbi = Math::createFromMassComInertiaC(other_body.mMass, other_body.mCenterOfMass, other_body.mInertia);
     317                 :        399 :         Math::RigidBodyInertia this_rbi = Math::createFromMassComInertiaC(mMass, mCenterOfMass, mInertia);
     318                 :            : 
     319                 :        399 :         Math::Matrix3d inertia_other = other_rbi.toMatrix().block<3, 3>(0, 0);
     320                 :            : 
     321                 :            :         // 1. Transform the inertia from other origin to other COM
     322                 :        399 :         Math::Matrix3d other_com_cross = other_body.mCenterOfMass.toTildeForm();
     323                 :        399 :         Math::Matrix3d inertia_other_com = inertia_other - other_mass * other_com_cross * other_com_cross.transpose();
     324                 :            : 
     325                 :            :         // 2. Rotate the inertia that it is aligned to the frame of this body
     326                 :        399 :         Math::Matrix3d inertia_other_com_rotated = transform.E.transpose() * inertia_other_com * transform.E;
     327                 :            : 
     328                 :            :         // 3. Transform inertia of other_body to the origin of the frame of this body
     329                 :        399 :         Math::Matrix3d inertia_other_com_rotated_this_origin = Math::parallel_axis(inertia_other_com_rotated, other_mass, other_com);
     330                 :            : 
     331                 :            :         // 4. Sum the two inertias
     332                 :        399 :         Math::Matrix3d inertia_summed = Math::Matrix3d(this_rbi.toMatrix().block<3, 3>(0, 0)) + inertia_other_com_rotated_this_origin;
     333                 :            : 
     334                 :            :         // 5. Transform the summed inertia to the new COM
     335                 :        399 :         Math::Matrix3d new_inertia = inertia_summed - new_mass * new_com.toTildeForm() * new_com.toTildeForm().transpose();
     336                 :            : 
     337                 :        399 :         Math::SpatialMatrix new_added_mass_matrix = this->addedMassMatrix + other_body.addedMassMatrix;
     338                 :        399 :         DragData new_drag_data = this->dragData + other_body.dragData;
     339                 :            : 
     340                 :        399 :         *this = Body(new_mass, new_com, new_inertia, new_cob, new_volume, new_added_mass_matrix, new_drag_data);
     341                 :            :     }
     342                 :            : 
     343                 :      18151 :     ~Body(){};
     344                 :            : 
     345                 :            :     /// \brief The mass of the body
     346                 :            :     double mMass;
     347                 :            :     /// \brief The position of the center of mass in body coordinates
     348                 :            :     Math::Vector3d mCenterOfMass;
     349                 :            :     /// \brief Inertia matrix at the center of mass
     350                 :            :     Math::Matrix3d mInertia;
     351                 :            : 
     352                 :            :     double volume;                       /**< Volume taken up by body. */
     353                 :            :     Math::Vector3d mCenterOfBuoyancy;    /**< Center of buoyancy for a body */
     354                 :            :     Math::SpatialMatrix addedMassMatrix; /**< The hydrodynamic added mass for the body */
     355                 :            :     DragData dragData;                   /**< The hydrodynamic drag data for the body */
     356                 :            :     bool mIsVirtual;
     357                 :            : };
     358                 :            : 
     359                 :            : /** \brief Keeps the information of a body and how it is attached to another body.
     360                 :            :  *
     361                 :            :  * When using fixed bodies, i.e. a body that is attached to anothe via a
     362                 :            :  * fixed joint, the attached body is merged onto its parent. By doing so
     363                 :            :  * adding fixed joints do not have an impact on runtime.
     364                 :            :  */
     365                 :            : struct FixedBody
     366                 :            : {
     367                 :            :     /// \brief The mass of the body
     368                 :            :     double mMass;
     369                 :            :     /// \brief The position of the center of mass in body coordinates
     370                 :            :     Math::Vector3d mCenterOfMass;
     371                 :            :     /// \brief The spatial inertia that contains both mass and inertia information
     372                 :            :     Math::Matrix3d mInertia;
     373                 :            :     double volume;                       /**< Volume taken up by body. */
     374                 :            :     Math::Vector3d mCenterOfBuoyancy;    /**< Center of buoyancy for a body */
     375                 :            :     Math::SpatialMatrix addedMassMatrix; /**< The hydrodynamic added mass for the body */
     376                 :            :     DragData dragData;                   /**< The hydrodynamic drag data for the body */
     377                 :            : 
     378                 :            :     /// \brief Id of the movable body that this fixed body is attached to.
     379                 :            :     unsigned int mMovableParent;
     380                 :            :     /// \brief Transforms spatial quantities expressed for the parent to the
     381                 :            :     // fixed body.
     382                 :            :     Math::SpatialTransform mParentTransform;
     383                 :            :     Math::SpatialTransform mBaseTransform;
     384                 :            : 
     385                 :        484 :     static FixedBody CreateFromBody(const Body& body)
     386                 :            :     {
     387                 :        484 :         FixedBody fbody;
     388                 :            : 
     389                 :        484 :         fbody.mMass = body.mMass;
     390                 :        484 :         fbody.mCenterOfMass = body.mCenterOfMass;
     391                 :        484 :         fbody.mInertia = body.mInertia;
     392                 :        484 :         fbody.mCenterOfBuoyancy = body.mCenterOfBuoyancy;
     393                 :        484 :         fbody.volume = body.volume;
     394                 :        484 :         fbody.addedMassMatrix = body.addedMassMatrix;
     395                 :        484 :         fbody.dragData = body.dragData;
     396                 :            : 
     397                 :        484 :         return fbody;
     398                 :            :     }
     399                 :            : };
     400                 :            : }  // namespace RobotDynamics
     401                 :            : 
     402                 :            : #endif

Generated by: LCOV version 1.14