LCOV - code coverage report
Current view: top level - src/rdl/rdl_dynamics/include/rdl_dynamics - rdl_mathutils.hpp (source / functions) Hit Total Coverage
Test: projectcoverage.info Lines: 78 92 84.8 %
Date: 2024-12-13 18:04:46 Functions: 9 9 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_MATHUTILS_H__
       7                 :            : #define __RDL_MATHUTILS_H__
       8                 :            : 
       9                 :            : /**
      10                 :            :  * @file rdl_mathutils.hpp
      11                 :            :  */
      12                 :            : 
      13                 :            : #include <assert.h>
      14                 :            : #include <cmath>
      15                 :            : 
      16                 :            : #include "rdl_dynamics/rdl_eigenmath.hpp"
      17                 :            : 
      18                 :            : namespace RobotDynamics
      19                 :            : {
      20                 :            : struct Model;
      21                 :            : 
      22                 :            : namespace Math
      23                 :            : {
      24                 :            : /**
      25                 :            :  * @enum LinearSolver
      26                 :            :  * @brief Available solver methods for the linear systems.
      27                 :            :  */
      28                 :            : enum LinearSolver
      29                 :            : {
      30                 :            :     LinearSolverUnknown = 0,
      31                 :            :     LinearSolverPartialPivLU,
      32                 :            :     LinearSolverColPivHouseholderQR,
      33                 :            :     LinearSolverHouseholderQR,
      34                 :            :     LinearSolverLLT,
      35                 :            :     LinearSolverLast,
      36                 :            : };
      37                 :            : 
      38                 :            : extern Vector3d Vector3dZero;
      39                 :            : extern Matrix3d Matrix3dIdentity;
      40                 :            : extern Matrix3d Matrix3dZero;
      41                 :            : extern Quaternion QuaternionIdentity;
      42                 :            : 
      43                 :            : extern SpatialVector SpatialVectorZero;
      44                 :            : extern SpatialMatrix SpatialMatrixIdentity;
      45                 :            : extern SpatialMatrix SpatialMatrixZero;
      46                 :            : 
      47                 :            : inline VectorNd vectorFromPtr(unsigned int n, double* ptr)
      48                 :            : {
      49                 :            :     // TODO: use memory mapping operators for Eigen
      50                 :            :     VectorNd result(n);
      51                 :            : 
      52                 :            :     for (unsigned int i = 0; i < n; i++)
      53                 :            :     {
      54                 :            :         result[i] = ptr[i];
      55                 :            :     }
      56                 :            : 
      57                 :            :     return result;
      58                 :            : }
      59                 :            : 
      60                 :            : inline MatrixNd matrixFromPtr(unsigned int rows, unsigned int cols, double* ptr, bool row_major = true)
      61                 :            : {
      62                 :            :     MatrixNd result(rows, cols);
      63                 :            : 
      64                 :            :     if (row_major)
      65                 :            :     {
      66                 :            :         for (unsigned int i = 0; i < rows; i++)
      67                 :            :         {
      68                 :            :             for (unsigned int j = 0; j < cols; j++)
      69                 :            :             {
      70                 :            :                 result(i, j) = ptr[i * cols + j];
      71                 :            :             }
      72                 :            :         }
      73                 :            :     }
      74                 :            :     else
      75                 :            :     {
      76                 :            :         for (unsigned int i = 0; i < rows; i++)
      77                 :            :         {
      78                 :            :             for (unsigned int j = 0; j < cols; j++)
      79                 :            :             {
      80                 :            :                 result(i, j) = ptr[i + j * rows];
      81                 :            :             }
      82                 :            :         }
      83                 :            :     }
      84                 :            : 
      85                 :            :     return result;
      86                 :            : }
      87                 :            : 
      88                 :            : /// \brief Solves a linear system using gaussian elimination with pivoting
      89                 :            : bool linSolveGaussElimPivot(MatrixNd A, VectorNd b, VectorNd& x);
      90                 :            : 
      91                 :            : /** \brief Translates the inertia matrix to a new center. */
      92                 :            : Matrix3d parallel_axis(const Matrix3d& inertia, double mass, const Vector3d& com);
      93                 :            : 
      94                 :            : /**
      95                 :            :  * @brief convert zyx euler angles and angle rates to angular velocity
      96                 :            :  * @param xyz_angles (yaw, pitch, roll) euler angles
      97                 :            :  * @param xyz_angle_rates (yaw_dot, pitch_dot, roll_dot)
      98                 :            :  * @return angular velocities (wx, wy, wz)
      99                 :            :  */
     100                 :          8 : inline Vector3d angular_velocity_from_zyx_angle_rates(const Vector3d& zyx_angles, const Vector3d& zyx_angle_rates)
     101                 :            : {
     102                 :          8 :     double sy = sin(zyx_angles[1]);
     103                 :          8 :     double cy = cos(zyx_angles[1]);
     104                 :          8 :     double sx = sin(zyx_angles[2]);
     105                 :          8 :     double cx = cos(zyx_angles[2]);
     106                 :            : 
     107                 :          8 :     return Vector3d(zyx_angle_rates[2] - sy * zyx_angle_rates[0], cx * zyx_angle_rates[1] + sx * cy * zyx_angle_rates[0],
     108                 :         24 :                     -sx * zyx_angle_rates[1] + cx * cy * zyx_angle_rates[0]);
     109                 :            : }
     110                 :            : 
     111                 :            : /**
     112                 :            :  * @brief convert xyz euler angles and angle rates to angular velocity
     113                 :            :  * @param xyz_angles (roll, pitch, yaw) euler angles
     114                 :            :  * @param xyz_angle_rates (roll_dot, pitch_dot, yaw_dot)
     115                 :            :  * @return angular velocities (wx, wy, wz)
     116                 :            :  */
     117                 :          2 : inline Vector3d angular_velocity_from_xyz_angle_rates(const Vector3d& xyz_angles, const Vector3d& xyz_angle_rates)
     118                 :            : {
     119                 :          2 :     double s1 = sin(xyz_angles[1]);
     120                 :          2 :     double c1 = cos(xyz_angles[1]);
     121                 :          2 :     double s2 = sin(xyz_angles[2]);
     122                 :          2 :     double c2 = cos(xyz_angles[2]);
     123                 :            : 
     124                 :          2 :     return Vector3d(c2 * c1 * xyz_angle_rates[0] + s2 * xyz_angle_rates[1], -s2 * c1 * xyz_angle_rates[0] + c2 * xyz_angle_rates[1],
     125                 :          6 :                     s1 * xyz_angle_rates[0] + xyz_angle_rates[2]);
     126                 :            : }
     127                 :            : 
     128                 :            : /**
     129                 :            :  * @brief compute the 3x3 jacobian matrix that when multiplied by the angular velocity, ordered (wx, wy, wz) returns the angular velocity vector, note that
     130                 :            :  * the ordering of the returned angle rates is (yaw_dot, pitch_Dot, roll_dot)
     131                 :            :  * @param zyx_angles yaw/pitch/roll euler angles, ordered (yaw, pitch, roll)
     132                 :            :  * @param singularity threshold, if the cosine of pitch is less than this, then it is considered at singularity and will return a matrix of zeros and
     133                 :            :  * set errno to EDOM, signifying a domain error
     134                 :            :  * @return jacobian matrix, S, that when multiplied by angular velocity, v as in S*v returns a vector of angle rates
     135                 :            :  */
     136                 :          1 : inline Matrix3d angular_velocity_to_zyx_angle_rates_jacobian(const Vector3d& zyx_angles, double singularity_threshold = 1.e-10)
     137                 :            : {
     138                 :          1 :     double c1 = cos(zyx_angles[1]);
     139                 :          1 :     double t1 = tan(zyx_angles[1]);
     140                 :          1 :     double s2 = sin(zyx_angles[2]);
     141                 :          1 :     double c2 = cos(zyx_angles[2]);
     142                 :            : 
     143                 :          1 :     if (c1 < singularity_threshold)
     144                 :            :     {
     145                 :          0 :         errno = EDOM;
     146                 :          0 :         std::cerr << "Domain error - unable to convert angular velocities to ZYX euler rates with pitch = pi/2" << std::endl;
     147                 :          0 :         return Matrix3dZero;
     148                 :            :     }
     149                 :            : 
     150                 :          2 :     return Matrix3d(0., s2 / c1, c2 / c1, 0., c2, -s2, 1., s2 * t1, c2 * t1);
     151                 :            : }
     152                 :            : 
     153                 :            : /**
     154                 :            :  * @brief compute the 3x3 jacobian matrix that when multiplied by the angular velocity, ordered (wx, wy, wz) returns the angular velocity vector, note that
     155                 :            :  * the ordering of the returned angle rates is (roll_dot, pitch_dot, yaw_dot)
     156                 :            :  * @param xyz_angles roll/pitch/yaw euler angles, ordered (roll, pitch, yaw)
     157                 :            :  * @param singularity threshold, if the cosine of pitch is less than this, then it is considered at singularity and will return a matrix of zeros and
     158                 :            :  * set errno to EDOM, signifying a domain error
     159                 :            :  * @return jacobian matrix, S, that when multiplied by angular velocity, v as in S*v returns a vector of angle rates
     160                 :            :  */
     161                 :          1 : inline Matrix3d angular_velocity_to_xyz_angle_rates_jacobian(const Vector3d& xyz_angles, double singularity_threshold = 1.e-10)
     162                 :            : {
     163                 :          1 :     double c1 = cos(xyz_angles[1]);
     164                 :          1 :     double t1 = tan(xyz_angles[1]);
     165                 :          1 :     double s2 = sin(xyz_angles[2]);
     166                 :          1 :     double c2 = cos(xyz_angles[2]);
     167                 :            : 
     168                 :          1 :     if (c1 < singularity_threshold)
     169                 :            :     {
     170                 :          0 :         errno = EDOM;
     171                 :          0 :         std::cerr << "Domain error - unable to convert angular velocities to XYZ euler rates with pitch = pi/2" << std::endl;
     172                 :          0 :         return Matrix3dZero;
     173                 :            :     }
     174                 :            : 
     175                 :          2 :     return Matrix3d(c2 / c1, -s2 / c1, 0., s2, c2, 0., -c2 * t1, s2 * t1, 1.);
     176                 :            : }
     177                 :            : 
     178                 :            : /**
     179                 :            :  * @brief convert angular velocity to zyx angle rates
     180                 :            :  * @param zyx_angles yaw/pitch/roll euler angles, ordered (yaw, pitch, roll)
     181                 :            :  * @param angular_velocity angular velocity (x, y, z)
     182                 :            :  * @param singularity threshold, if the cosine of pitch is less than this, then it is considered at singularity and will return a matrix of zeros and
     183                 :            :  * set errno to EDOM, signifying a domain error
     184                 :            :  * @return given zyx angles and angular velocity, a vector of angle rates orderd (yaw_dot, pitch_dot, roll_dot)
     185                 :            :  */
     186                 :          3 : inline Vector3d angular_velocity_to_zyx_angle_rates(const Vector3d& zyx_angles, const Vector3d& angular_velocity, double singularity_threshold = 1.e-10)
     187                 :            : {
     188                 :          3 :     double c1 = cos(zyx_angles[1]);
     189                 :          3 :     double t1 = tan(zyx_angles[1]);
     190                 :          3 :     double s2 = sin(zyx_angles[2]);
     191                 :          3 :     double c2 = cos(zyx_angles[2]);
     192                 :            : 
     193                 :          3 :     if (c1 < singularity_threshold)
     194                 :            :     {
     195                 :          0 :         errno = EDOM;
     196                 :          0 :         std::cerr << "unable to compute angle rates from angular velocity due to singularity" << std::endl;
     197                 :          0 :         return Vector3dZero;
     198                 :            :     }
     199                 :            : 
     200                 :          3 :     return Vector3d((s2 / c1) * angular_velocity[1] + (c2 / c1) * angular_velocity[2], c2 * angular_velocity[1] - s2 * angular_velocity[2],
     201                 :          9 :                     angular_velocity[0] + s2 * t1 * angular_velocity[1] + c2 * t1 * angular_velocity[2]);
     202                 :            : }
     203                 :            : 
     204                 :            : /**
     205                 :            :  * @brief convert angular velocity to xyz angle rates
     206                 :            :  * @param xyz_angles yaw/pitch/roll euler angles, ordered (roll, pitch, yaw)
     207                 :            :  * @param angular_velocity angular velocity (x, y, z)
     208                 :            :  * @param singularity threshold, if the cosine of pitch is less than this, then it is considered at singularity and will return a vector of zeros and
     209                 :            :  * set errno to EDOM, signifying a domain error
     210                 :            :  * @return given xyz angles and angular velocity, a vector of angle rates orderd (roll_dot, pitch_dot, yaw_dot)
     211                 :            :  */
     212                 :          3 : inline Vector3d angular_velocity_to_xyz_angle_rates(const Vector3d& xyz_angles, const Vector3d& angular_velocity, double singularity_threshold = 1.e-10)
     213                 :            : {
     214                 :          3 :     double c1 = cos(xyz_angles[1]);
     215                 :          3 :     double t1 = tan(xyz_angles[1]);
     216                 :          3 :     double s2 = sin(xyz_angles[2]);
     217                 :          3 :     double c2 = cos(xyz_angles[2]);
     218                 :            : 
     219                 :          3 :     if (c1 < singularity_threshold)
     220                 :            :     {
     221                 :          0 :         errno = EDOM;
     222                 :          0 :         std::cerr << "unable to compute jacobian matrix for XYZ angles" << std::endl;
     223                 :          0 :         return Vector3dZero;
     224                 :            :     }
     225                 :            : 
     226                 :          3 :     return Vector3d((c2 / c1) * angular_velocity[0] - (s2 / c1) * angular_velocity[1], s2 * angular_velocity[0] + c2 * angular_velocity[1],
     227                 :          9 :                     -c2 * t1 * angular_velocity[0] + s2 * t1 * angular_velocity[1] + angular_velocity[2]);
     228                 :            : }
     229                 :            : 
     230                 :          1 : inline Vector3d global_angular_velocity_from_rates(const Vector3d& zyx_angles, const Vector3d& zyx_rates)
     231                 :            : {
     232                 :            :     double s0, c0, s1, c1;
     233                 :          1 :     s0 = sin(zyx_angles[0]);
     234                 :          1 :     c0 = cos(zyx_angles[0]);
     235                 :          1 :     s1 = sin(zyx_angles[1]);
     236                 :          1 :     c1 = cos(zyx_angles[1]);
     237                 :            : 
     238                 :          1 :     Matrix3d RzT(c0, s0, 0., -s0, c0, 0., 0., 0., 1.);
     239                 :          1 :     RzT.transposeInPlace();
     240                 :          1 :     Matrix3d RyT(c1, 0., -s1, 0., 1., 0., s1, 0., c1);
     241                 :          1 :     RyT.transposeInPlace();
     242                 :            : 
     243                 :          2 :     return Vector3d(Vector3d(0., 0., zyx_rates[0]) + RzT * Vector3d(0., zyx_rates[1], 0.) + RzT * RyT * Vector3d(zyx_rates[2], 0., 0.));
     244                 :            : }
     245                 :            : 
     246                 :            : /**
     247                 :            :  * @brief calculate angular acceleration from zyx angles, angle rates, and angle accelerations
     248                 :            :  * @param zyx_angles (yaw, pitch, roll) euler angles
     249                 :            :  * @param zyx_angle_rates (yaw_dot, pitch_dot, roll_dot) angle rates
     250                 :            :  * @param zyx_angle_accelerations (yaw_ddot, pitch_ddot, roll_ddot) angle accelerations
     251                 :            :  *
     252                 :            :  * @return angular accelerations (wx_dot, wy_dot, wz_dot)
     253                 :            :  */
     254                 :          1 : inline Vector3d angular_acceleration_from_zyx_angle_rates(const Vector3d& zyx_angles, const Vector3d& zyx_angle_rates, const Vector3d& zyx_angle_rates_dot)
     255                 :            : {
     256                 :          1 :     double sy = sin(zyx_angles[1]);
     257                 :          1 :     double cy = cos(zyx_angles[1]);
     258                 :          1 :     double sx = sin(zyx_angles[2]);
     259                 :          1 :     double cx = cos(zyx_angles[2]);
     260                 :          1 :     double xdot = zyx_angle_rates[2];
     261                 :          1 :     double ydot = zyx_angle_rates[1];
     262                 :          1 :     double zdot = zyx_angle_rates[0];
     263                 :          1 :     double xddot = zyx_angle_rates_dot[2];
     264                 :          1 :     double yddot = zyx_angle_rates_dot[1];
     265                 :          1 :     double zddot = zyx_angle_rates_dot[0];
     266                 :            : 
     267                 :          0 :     return Vector3d(xddot - (cy * ydot * zdot + sy * zddot), -sx * xdot * ydot + cx * yddot + cx * xdot * cy * zdot + sx * (-sy * ydot * zdot + cy * zddot),
     268                 :          2 :                     -cx * xdot * ydot - sx * yddot - sx * xdot * cy * zdot + cx * (-sy * ydot * zdot + cy * zddot));
     269                 :            : }
     270                 :            : 
     271                 :            : /**
     272                 :            :  * @brief calculate angular acceleration from zyx angles, angle rates, and angle accelerations
     273                 :            :  * @param xyz_angles (roll, pitch, yaw) euler angles
     274                 :            :  * @param xyz_angle_rates (roll_dot, pitch_dot, yaw_dot) angle rates
     275                 :            :  * @param xyz_angle_accelerations (roll_ddot, pitch_ddot, yaw_ddot) angle accelerations
     276                 :            :  *
     277                 :            :  * @return angular accelerations (wx_dot, wy_dot, wz_dot)
     278                 :            :  */
     279                 :          1 : inline Vector3d angular_acceleration_from_xyz_angle_rates(const Vector3d& xyz_angles, const Vector3d& xyz_angle_rates, const Vector3d& xyz_angle_rates_dot)
     280                 :            : {
     281                 :          1 :     double s1 = sin(xyz_angles[1]);
     282                 :          1 :     double c1 = cos(xyz_angles[1]);
     283                 :          1 :     double s2 = sin(xyz_angles[2]);
     284                 :          1 :     double c2 = cos(xyz_angles[2]);
     285                 :            : 
     286                 :          1 :     double xdot = xyz_angle_rates[0];
     287                 :          1 :     double ydot = xyz_angle_rates[1];
     288                 :          1 :     double zdot = xyz_angle_rates[2];
     289                 :            : 
     290                 :          1 :     double xddot = xyz_angle_rates_dot[0];
     291                 :          1 :     double yddot = xyz_angle_rates_dot[1];
     292                 :          1 :     double zddot = xyz_angle_rates_dot[2];
     293                 :          0 :     return Vector3d(c2 * c1 * xddot + s2 * yddot + (-s2 * c1 * zdot - c2 * s1 * ydot) * xdot + c2 * zdot * ydot,
     294                 :          2 :                     -s2 * c1 * xddot + c2 * yddot + (-c2 * c1 * zdot + s2 * s1 * ydot) * xdot - s2 * zdot * ydot, s1 * xddot + zddot + c1 * ydot * xdot);
     295                 :            : }
     296                 :            : 
     297                 :            : void SparseFactorizeLTL(Model& model, Math::MatrixNd& H);
     298                 :            : 
     299                 :            : void SparseMultiplyHx(Model& model, Math::MatrixNd& L);
     300                 :            : 
     301                 :            : void SparseMultiplyLx(Model& model, Math::MatrixNd& L);
     302                 :            : 
     303                 :            : void SparseMultiplyLTx(Model& model, Math::MatrixNd& L);
     304                 :            : 
     305                 :            : void SparseSolveLx(Model& model, Math::MatrixNd& L, Math::VectorNd& x);
     306                 :            : 
     307                 :            : void SparseSolveLTx(Model& model, Math::MatrixNd& L, Math::VectorNd& x);
     308                 :            : }  // namespace Math
     309                 :            : }  // namespace RobotDynamics
     310                 :            : 
     311                 :            : /* __RDL_MATHUTILS_H__ */
     312                 :            : #endif  // ifndef __RDL_MATHUTILS_H__

Generated by: LCOV version 1.14