【MR】现代机器人学-算法库函数分析(C++版停止2024.4.7) ...

打印 上一主题 下一主题

主题 210|帖子 210|积分 630

算法库提供以下函数的实现

  

  • NearZero: 判断一个值是否可以忽略为0。
  • ad: 计算给定6维向量的6x6矩阵[adV]。
  • Normalize: 返回输入向量的归一化版本。
  • VecToso3: 返回角速率向量的反对称矩阵表示。
  • so3ToVec: 返回由反对称矩阵表示的角速率向量。
  • AxisAng3: 将指数旋转转换为其单独的分量。
  • MatrixExp3: 将指数旋转转换为旋转矩阵。
  • MatrixLog3: 计算旋转矩阵的矩阵对数。
  • RpToTrans: 将旋转矩阵和位置向量组合成一个特别欧几里得群(SE3)齐次变动矩阵。
  • TransToRp: 从变动矩阵表示中分离出旋转矩阵和位置向量。
  • VecTose3: 将空间速率向量转换为变动矩阵。
  • se3ToVec: 将变动矩阵转换为空间速率向量。
  • Adjoint: 提供变动矩阵的伴随表示。
  • MatrixExp6: 螺旋轴的旋转扩展。
  • MatrixLog6: 计算齐次变动矩阵的矩阵对数。
  • FKinSpace: 计算末了实行器框架(用于当前空间位置计算)。
  • FKinBody: 计算末了实行器框架(用于当前身段位置计算)。
  • JacobianSpace: 给出空间雅可比矩阵。
  • JacobianBody: 给出身段雅可比矩阵。
  • TransInv: 反转齐次变动矩阵。
  • RotInv: 反转旋转矩阵。
  • ScrewToAxis: 将螺旋轴的参数描述转换为归一化螺旋轴。
  • AxisAng6: 将6维指数坐标转换为螺旋轴-角度情势。
  • ProjectToSO3: 将一个矩阵投影到SO(3)。
  • ProjectToSE3: 将一个矩阵投影到SE(3)。
  • DistanceToSO3: 返回Frobenius范数以描述矩阵M与SO(3)流形的距离。
  • DistanceToSE3: 返回Frobenius范数以描述矩阵T与SE(3)流形的距离。
  • TestIfSO3: 如果矩阵M靠近或在SO(3)流形上,返回true。
  • TestIfSE3: 如果矩阵T靠近或在SE(3)流形上,返回true。
  • IKinBody: 计算开链机器人在身段坐标系中的逆运动学。
  • IKinSpace: 计算开链机器人在空间坐标系中的逆运动学。
  • InverseDynamics: 利用前后牛顿-欧拉迭代求解方程。
  • GravityForces: 计算动力学方程中的重力项。
  • MassMatrix: 计算关节串联链的数值惯性矩阵。
  • VelQuadraticForces: 计算科里奥利和离心项向量。
  • EndEffectorForces: 计算末了实行器力所需的关节力和力矩。
  • ForwardDynamics: 通过求解方程计算关节加速率。
  • EulerStep: 利用一阶欧拉积分计算下一个时间步的关节角度和速率。
  • InverseDynamicsTrajectory: 计算沿给定轨迹移动串联链所需的关节力/力矩。
  • ForwardDynamicsTrajectory: 计算给定开环关节力/力矩历史的串联链运动。
  • ComputedTorque: 计算特定时间点的关节控制力矩。
  • CubicTimeScaling: 计算三次时间缩放的s(t)。
  • QuinticTimeScaling: 计算五次时间缩放的s(t)。
  • JointTrajectory: 计算关节空间中的直线轨迹。
  • ScrewTrajectory: 计算对应于空间螺旋轴螺旋运动的轨迹列表。
  • CartesianTrajectory: 计算对应于末了实行器框架原点沿直线运动的轨迹列表。
  • SimulateControl: 计算给定开环关节力/力矩历史的串联链运动。
  
以下对源码文件 modern_robotics.cpp  lib_test.cpp  modern_robotics.h 进行了中文逐行注释。

  
modern_robotics.cpp:

  1. #include "../include/modern_robotics.h" // 包含现代机器人库的头文件
  2. /*
  3. * modernRobotics.cpp
  4. * 从modern_robotics.py改编而来,由modernrobotics.org提供
  5. * 提供有用的雅可比矩阵和框架表示函数
  6. */
  7. #include <Eigen/Dense> // 包含Eigen库,用于矩阵和向量运算
  8. #include <cmath> // 包含cmath库,用于数学运算
  9. #include <vector> // 包含vector库,用于动态数组
  10. # define M_PI 3.14159265358979323846  /* 定义圆周率常量 */
  11. namespace mr { // 定义mr命名空间
  12.   /* 函数:判断一个值是否可以忽略为0
  13.    * 输入:要检查的double类型值
  14.    * 返回:布尔值,true表示可以忽略,false表示不能忽略
  15.    */
  16.   bool NearZero(const double val) {
  17.     return (std::abs(val) < .000001); // 如果绝对值小于0.000001,则认为可以忽略
  18.   }
  19.   /*
  20.    * 函数:计算给定6维向量的6x6矩阵[adV]
  21.    * 输入:Eigen::VectorXd (6x1) 向量
  22.    * 输出:Eigen::MatrixXd (6x6) 矩阵
  23.    * 备注:可用于计算李括号[V1, V2] = [adV1]V2
  24.    */
  25.   Eigen::MatrixXd ad(Eigen::VectorXd V) {
  26.     Eigen::Matrix3d omgmat = VecToso3(Eigen::Vector3d(V(0), V(1), V(2))); // 提取前3个元素并转换为反对称矩阵
  27.     Eigen::MatrixXd result(6, 6); // 定义6x6矩阵
  28.     result.topLeftCorner<3, 3>() = omgmat; // 左上角3x3子矩阵为omgmat
  29.     result.topRightCorner<3, 3>() = Eigen::Matrix3d::Zero(3, 3); // 右上角3x3子矩阵为零矩阵
  30.     result.bottomLeftCorner<3, 3>() = VecToso3(Eigen::Vector3d(V(3), V(4), V(5))); // 左下角3x3子矩阵为后3个元素转换的反对称矩阵
  31.     result.bottomRightCorner<3, 3>() = omgmat; // 右下角3x3子矩阵为omgmat
  32.     return result; // 返回结果矩阵
  33.   }
  34.   /* 函数:返回输入向量的归一化版本
  35.    * 输入:Eigen::MatrixXd 矩阵
  36.    * 输出:Eigen::MatrixXd 矩阵
  37.    * 备注:MatrixXd用于行向量的情况,需要复制,因MatrixXd转换的便利性而有用
  38.    */
  39.   Eigen::MatrixXd Normalize(Eigen::MatrixXd V) {
  40.     V.normalize(); // 对向量进行归一化
  41.     return V; // 返回归一化后的向量
  42.   }
  43.   /* 函数:返回角速度向量的反对称矩阵表示
  44.    * 输入:Eigen::Vector3d 3x1角速度向量
  45.    * 返回:Eigen::MatrixXd 3x3反对称矩阵
  46.    */
  47.   Eigen::Matrix3d VecToso3(const Eigen::Vector3d& omg) {
  48.     Eigen::Matrix3d m_ret; // 定义3x3矩阵
  49.     m_ret << 0, -omg(2), omg(1), // 填充矩阵元素
  50.       omg(2), 0, -omg(0),
  51.       -omg(1), omg(0), 0;
  52.     return m_ret; // 返回反对称矩阵
  53.   }
  54.   /* 函数:返回由反对称矩阵表示的角速度向量
  55.    * 输入:Eigen::MatrixXd 3x3反对称矩阵
  56.    * 返回:Eigen::Vector3d 3x1角速度向量
  57.    */
  58.   Eigen::Vector3d so3ToVec(const Eigen::MatrixXd& so3mat) {
  59.     Eigen::Vector3d v_ret; // 定义3x1向量
  60.     v_ret << so3mat(2, 1), so3mat(0, 2), so3mat(1, 0); // 提取矩阵元素填充向量
  61.     return v_ret; // 返回角速度向量
  62.   }
  63.   /* 函数:将指数旋转转换为其单独的分量
  64.    * 输入:指数旋转(以旋转轴和旋转角度表示的旋转矩阵)
  65.    * 返回:旋转轴和旋转角度[x, y, z, theta]
  66.    */
  67.   Eigen::Vector4d AxisAng3(const Eigen::Vector3d& expc3) {
  68.     Eigen::Vector4d v_ret; // 定义4x1向量
  69.     v_ret << Normalize(expc3), expc3.norm(); // 归一化旋转轴并计算旋转角度
  70.     return v_ret; // 返回结果向量
  71.   }
  72.   /* 函数:将指数旋转转换为旋转矩阵
  73.    * 输入:旋转的指数表示
  74.    * 返回:旋转矩阵
  75.    */
  76.   Eigen::Matrix3d MatrixExp3(const Eigen::Matrix3d& so3mat) {
  77.     Eigen::Vector3d omgtheta = so3ToVec(so3mat); // 将反对称矩阵转换为角速度向量
  78.     Eigen::Matrix3d m_ret = Eigen::Matrix3d::Identity(); // 定义单位矩阵
  79.     if (NearZero(so3mat.norm())) { // 如果矩阵的范数接近零
  80.       return m_ret; // 返回单位矩阵
  81.     }
  82.     else {
  83.       double theta = (AxisAng3(omgtheta))(3); // 提取旋转角度
  84.       Eigen::Matrix3d omgmat = so3mat * (1 / theta); // 计算归一化的反对称矩阵
  85.       return m_ret + std::sin(theta) * omgmat + ((1 - std::cos(theta)) * (omgmat * omgmat)); // 返回旋转矩阵
  86.     }
  87.   }
  88. }
  89.   /* 函数:计算旋转矩阵的矩阵对数
  90.    * 输入:旋转矩阵
  91.    * 返回:旋转的矩阵对数
  92.    */
  93.   Eigen::Matrix3d MatrixLog3(const Eigen::Matrix3d& R) {
  94.     double acosinput = (R.trace() - 1) / 2.0; // 计算acos的输入值
  95.     Eigen::MatrixXd m_ret = Eigen::MatrixXd::Zero(3, 3); // 初始化3x3零矩阵
  96.     if (acosinput >= 1) // 如果acos的输入值大于等于1
  97.       return m_ret; // 返回零矩阵
  98.     else if (acosinput <= -1) { // 如果acos的输入值小于等于-1
  99.       Eigen::Vector3d omg; // 定义3x1向量
  100.       if (!NearZero(1 + R(2, 2))) // 如果1 + R(2, 2)不接近零
  101.         omg = (1.0 / std::sqrt(2 * (1 + R(2, 2)))) * Eigen::Vector3d(R(0, 2), R(1, 2), 1 + R(2, 2)); // 计算角速度向量
  102.       else if (!NearZero(1 + R(1, 1))) // 如果1 + R(1, 1)不接近零
  103.         omg = (1.0 / std::sqrt(2 * (1 + R(1, 1)))) * Eigen::Vector3d(R(0, 1), 1 + R(1, 1), R(2, 1)); // 计算角速度向量
  104.       else // 否则
  105.         omg = (1.0 / std::sqrt(2 * (1 + R(0, 0)))) * Eigen::Vector3d(1 + R(0, 0), R(1, 0), R(2, 0)); // 计算角速度向量
  106.       m_ret = VecToso3(M_PI * omg); // 计算反对称矩阵
  107.       return m_ret; // 返回反对称矩阵
  108.     }
  109.     else { // 否则
  110.       double theta = std::acos(acosinput); // 计算旋转角度
  111.       m_ret = theta / 2.0 / sin(theta) * (R - R.transpose()); // 计算矩阵对数
  112.       return m_ret; // 返回矩阵对数
  113.     }
  114.   }
  115.   /* 函数:将旋转矩阵和位置向量组合成一个特殊欧几里得群(SE3)齐次变换矩阵
  116.    * 输入:旋转矩阵(R),位置向量(p)
  117.    * 返回:矩阵T = [ [R, p],
  118.    *         [0, 1] ]
  119.    */
  120.   Eigen::MatrixXd RpToTrans(const Eigen::Matrix3d& R, const Eigen::Vector3d& p) {
  121.     Eigen::MatrixXd m_ret(4, 4); // 定义4x4矩阵
  122.     m_ret << R, p, // 填充旋转矩阵和位置向量
  123.       0, 0, 0, 1; // 填充最后一行
  124.     return m_ret; // 返回齐次变换矩阵
  125.   }
  126.   /* 函数:从变换矩阵表示中分离出旋转矩阵和位置向量
  127.    * 输入:齐次变换矩阵
  128.    * 返回:包含旋转矩阵和位置向量的std::vector
  129.    */
  130.   std::vector<Eigen::MatrixXd> TransToRp(const Eigen::MatrixXd& T) {
  131.     std::vector<Eigen::MatrixXd> Rp_ret; // 定义向量用于存储结果
  132.     Eigen::Matrix3d R_ret; // 定义3x3旋转矩阵
  133.     // 获取左上角3x3子矩阵
  134.     R_ret = T.block<3, 3>(0, 0);
  135.     Eigen::Vector3d p_ret(T(0, 3), T(1, 3), T(2, 3)); // 提取位置向量
  136.     Rp_ret.push_back(R_ret); // 将旋转矩阵添加到结果向量中
  137.     Rp_ret.push_back(p_ret); // 将位置向量添加到结果向量中
  138.     return Rp_ret; // 返回结果向量
  139.   }
  140.   /* 函数:将空间速度向量转换为变换矩阵
  141.    * 输入:空间速度向量[角速度,线速度]
  142.    * 返回:变换矩阵
  143.    */
  144.   Eigen::MatrixXd VecTose3(const Eigen::VectorXd& V) {
  145.     // 分离角速度(指数表示)和线速度
  146.     Eigen::Vector3d exp(V(0), V(1), V(2)); // 提取角速度
  147.     Eigen::Vector3d linear(V(3), V(4), V(5)); // 提取线速度
  148.     // 将值填充到变换矩阵的适当部分
  149.     Eigen::MatrixXd m_ret(4, 4); // 定义4x4矩阵
  150.     m_ret << VecToso3(exp), linear, // 填充角速度的反对称矩阵和线速度
  151.       0, 0, 0, 0; // 填充最后一行
  152.     return m_ret; // 返回变换矩阵
  153.   }
  154.   /* 函数:将变换矩阵转换为空间速度向量
  155.    * 输入:变换矩阵
  156.    * 返回:空间速度向量[角速度,线速度]
  157.    */
  158.   Eigen::VectorXd se3ToVec(const Eigen::MatrixXd& T) {
  159.     Eigen::VectorXd m_ret(6); // 定义6x1向量
  160.     m_ret << T(2, 1), T(0, 2), T(1, 0), T(0, 3), T(1, 3), T(2, 3); // 提取矩阵元素填充向量
  161.     return m_ret; // 返回空间速度向量
  162.   }
  163.   /* 函数:提供变换矩阵的伴随表示
  164.    *       用于改变空间速度向量的参考系
  165.    * 输入:4x4变换矩阵SE(3)
  166.    * 返回:6x6矩阵的伴随表示
  167.    */
  168.   Eigen::MatrixXd Adjoint(const Eigen::MatrixXd& T) {
  169.     std::vector<Eigen::MatrixXd> R = TransToRp(T); // 将变换矩阵分解为旋转矩阵和位置向量
  170.     Eigen::MatrixXd ad_ret(6, 6); // 定义6x6矩阵
  171.     ad_ret = Eigen::MatrixXd::Zero(6, 6); // 初始化为零矩阵
  172.     Eigen::MatrixXd zeroes = Eigen::MatrixXd::Zero(3, 3); // 定义3x3零矩阵
  173.     ad_ret << R[0], zeroes, // 填充旋转矩阵和零矩阵
  174.       VecToso3(R[1]) * R[0], R[0]; // 填充位置向量的反对称矩阵乘以旋转矩阵和旋转矩阵
  175.     return ad_ret; // 返回伴随矩阵
  176.   }
  177.   /* 函数:螺旋轴的旋转扩展
  178.    * 输入:指数坐标的se3矩阵表示(变换矩阵)
  179.    * 返回:表示旋转的6x6矩阵
  180.    */
  181.   Eigen::MatrixXd MatrixExp6(const Eigen::MatrixXd& se3mat) {
  182.     // 从变换矩阵中提取角速度向量
  183.     Eigen::Matrix3d se3mat_cut = se3mat.block<3, 3>(0, 0); // 提取3x3子矩阵
  184.     Eigen::Vector3d omgtheta = so3ToVec(se3mat_cut); // 将3x3子矩阵转换为角速度向量
  185.     Eigen::MatrixXd m_ret(4, 4); // 定义4x4矩阵
  186.     // 如果旋转可以忽略,m_ret = [[单位矩阵, 角速度]]
  187.     //                        [    0    ,    1    ]]
  188.     if (NearZero(omgtheta.norm())) {
  189.       // 重用之前的变量,它们具有所需的大小
  190.       se3mat_cut = Eigen::MatrixXd::Identity(3, 3); // 定义3x3单位矩阵
  191.       omgtheta << se3mat(0, 3), se3mat(1, 3), se3mat(2, 3); // 提取线速度
  192.       m_ret << se3mat_cut, omgtheta, // 填充单位矩阵和线速度
  193.         0, 0, 0, 1; // 填充最后一行
  194.       return m_ret; // 返回变换矩阵
  195.     }
  196.     // 如果旋转不可忽略,参考MR第105页
  197.     else {
  198.       double theta = (AxisAng3(omgtheta))(3); // 提取旋转角度
  199.       Eigen::Matrix3d omgmat = se3mat.block<3, 3>(0, 0) / theta; // 计算归一化的反对称矩阵
  200.       Eigen::Matrix3d expExpand = Eigen::MatrixXd::Identity(3, 3) * theta + (1 - std::cos(theta)) * omgmat + ((theta - std::sin(theta)) * (omgmat * omgmat)); // 计算旋转矩阵的指数扩展
  201.       Eigen::Vector3d linear(se3mat(0, 3), se3mat(1, 3), se3mat(2, 3)); // 提取线速度
  202.       Eigen::Vector3d GThetaV = (expExpand * linear) / theta; // 计算GThetaV
  203.       m_ret << MatrixExp3(se3mat_cut), GThetaV, // 填充旋转矩阵和GThetaV
  204.         0, 0, 0, 1; // 填充最后一行
  205.       return m_ret; // 返回变换矩阵
  206.     }
  207.   }
  208.   /* 函数:计算变换矩阵的矩阵对数
  209.    * 输入:变换矩阵
  210.    * 返回:变换矩阵的矩阵对数
  211.    */
  212.   Eigen::MatrixXd MatrixLog6(const Eigen::MatrixXd& T) {
  213.     Eigen::MatrixXd m_ret(4, 4); // 定义4x4矩阵
  214.     auto rp = mr::TransToRp(T); // 将变换矩阵分解为旋转矩阵和位置向量
  215.     Eigen::Matrix3d omgmat = MatrixLog3(rp.at(0)); // 计算旋转矩阵的矩阵对数
  216.     Eigen::Matrix3d zeros3d = Eigen::Matrix3d::Zero(3, 3); // 定义3x3零矩阵
  217.     if (NearZero(omgmat.norm())) { // 如果旋转矩阵的范数接近零
  218.       m_ret << zeros3d, rp.at(1), // 填充零矩阵和位置向量
  219.         0, 0, 0, 0; // 填充最后一行
  220.     }
  221.     else {
  222.       double theta = std::acos((rp.at(0).trace() - 1) / 2.0); // 计算旋转角度
  223.       Eigen::Matrix3d logExpand1 = Eigen::MatrixXd::Identity(3, 3) - omgmat / 2.0; // 计算logExpand1
  224.       Eigen::Matrix3d logExpand2 = (1.0 / theta - 1.0 / std::tan(theta / 2.0) / 2) * omgmat * omgmat / theta; // 计算logExpand2
  225.       Eigen::Matrix3d logExpand = logExpand1 + logExpand2; // 计算logExpand
  226.       m_ret << omgmat, logExpand * rp.at(1), // 填充旋转矩阵和logExpand乘以位置向量
  227.         0, 0, 0, 0; // 填充最后一行
  228.     }
  229.     return m_ret; // 返回矩阵对数
  230.   }
  231.   /* 函数:计算末端执行器框架(用于当前空间位置计算)
  232.    * 输入:末端执行器的初始配置(位置和方向)
  233.    *       机械臂在初始位置时的关节螺旋轴在空间框架中的表示
  234.    *       关节坐标列表
  235.    * 返回:表示关节在指定坐标时末端执行器框架的变换矩阵
  236.    * 备注:FK表示正向运动学
  237.    */
  238.   Eigen::MatrixXd FKinSpace(const Eigen::MatrixXd& M, const Eigen::MatrixXd& Slist, const Eigen::VectorXd& thetaList) {
  239.     Eigen::MatrixXd T = M; // 初始化变换矩阵为初始配置
  240.     for (int i = (thetaList.size() - 1); i > -1; i--) { // 遍历关节坐标列表
  241.       T = MatrixExp6(VecTose3(Slist.col(i) * thetaList(i))) * T; // 计算每个关节的变换矩阵并相乘
  242.     }
  243.     return T; // 返回末端执行器的变换矩阵
  244.   }
  245.   /*
  246.    * 函数:计算末端执行器框架(用于当前身体位置计算)
  247.    * 输入:末端执行器的初始配置(位置和方向)
  248.    *       机械臂在初始位置时的关节螺旋轴在身体框架中的表示
  249.    *       关节坐标列表
  250.    * 返回:表示关节在指定坐标时末端执行器框架的变换矩阵
  251.    * 备注:FK表示正向运动学
  252.    */
  253.   Eigen::MatrixXd FKinBody(const Eigen::MatrixXd& M, const Eigen::MatrixXd& Blist, const Eigen::VectorXd& thetaList) {
  254.     Eigen::MatrixXd T = M; // 初始化变换矩阵为初始配置
  255.     for (int i = 0; i < thetaList.size(); i++) { // 遍历关节坐标列表
  256.       T = T * MatrixExp6(VecTose3(Blist.col(i) * thetaList(i))); // 计算每个关节的变换矩阵并相乘
  257.     }
  258.     return T; // 返回末端执行器的变换矩阵
  259.   }
  260.   /* 函数:计算空间雅可比矩阵
  261.    * 输入:初始位置的螺旋轴,关节配置
  262.    * 返回:6xn的空间雅可比矩阵
  263.    */
  264.   Eigen::MatrixXd JacobianSpace(const Eigen::MatrixXd& Slist, const Eigen::MatrixXd& thetaList) {
  265.     Eigen::MatrixXd Js = Slist; // 初始化空间雅可比矩阵为螺旋轴列表
  266.     Eigen::MatrixXd T = Eigen::MatrixXd::Identity(4, 4); // 初始化4x4单位矩阵
  267.     Eigen::VectorXd sListTemp(Slist.col(0).size()); // 定义临时向量存储螺旋轴
  268.     for (int i = 1; i < thetaList.size(); i++) { // 遍历关节配置
  269.       sListTemp << Slist.col(i - 1) * thetaList(i - 1); // 计算当前关节的螺旋轴
  270.       T = T * MatrixExp6(VecTose3(sListTemp)); // 计算变换矩阵
  271.       // std::cout << "array: " << sListTemp << std::endl;
  272.       Js.col(i) = Adjoint(T) * Slist.col(i); // 计算雅可比矩阵的列
  273.     }
  274.     return Js; // 返回空间雅可比矩阵
  275.   }
  276.   /*
  277.    * 函数:计算身体雅可比矩阵
  278.    * 输入:身体位置的螺旋轴,关节配置
  279.    * 返回:6xn的身体雅可比矩阵
  280.    */
  281.   Eigen::MatrixXd JacobianBody(const Eigen::MatrixXd& Blist, const Eigen::MatrixXd& thetaList) {
  282.     Eigen::MatrixXd Jb = Blist; // 初始化身体雅可比矩阵为螺旋轴列表
  283.     Eigen::MatrixXd T = Eigen::MatrixXd::Identity(4, 4); // 初始化4x4单位矩阵
  284.     Eigen::VectorXd bListTemp(Blist.col(0).size()); // 定义临时向量存储螺旋轴
  285.     for (int i = thetaList.size() - 2; i >= 0; i--) { // 逆序遍历关节配置
  286.       bListTemp << Blist.col(i + 1) * thetaList(i + 1); // 计算当前关节的螺旋轴
  287.       T = T * MatrixExp6(VecTose3(-1 * bListTemp)); // 计算变换矩阵
  288.       // std::cout << "array: " << sListTemp << std::endl;
  289.       Jb.col(i) = Adjoint(T) * Blist.col(i); // 计算雅可比矩阵的列
  290.     }
  291.     return Jb; // 返回身体雅可比矩阵
  292.   }
  293.   /* 函数:计算变换矩阵的逆
  294.    * 输入:变换矩阵
  295.    * 返回:变换矩阵的逆
  296.    */
  297.   Eigen::MatrixXd TransInv(const Eigen::MatrixXd& transform) {
  298.     auto rp = mr::TransToRp(transform); // 将变换矩阵分解为旋转矩阵和位置向量
  299.     auto Rt = rp.at(0).transpose(); // 计算旋转矩阵的转置
  300.     auto t = -(Rt * rp.at(1)); // 计算位置向量的逆
  301.     Eigen::MatrixXd inv(4, 4); // 定义4x4矩阵
  302.     inv = Eigen::MatrixXd::Zero(4, 4); // 初始化为零矩阵
  303.     inv.block(0, 0, 3, 3) = Rt; // 填充旋转矩阵的转置
  304.     inv.block(0, 3, 3, 1) = t; // 填充位置向量的逆
  305.     inv(3, 3) = 1; // 填充最后一行
  306.     return inv; // 返回逆矩阵
  307.   }
  308.   /* 函数:计算旋转矩阵的逆
  309.    * 输入:旋转矩阵
  310.    * 返回:旋转矩阵的逆
  311.    */
  312.   Eigen::MatrixXd RotInv(const Eigen::MatrixXd& rotMatrix) {
  313.     return rotMatrix.transpose(); // 返回旋转矩阵的转置
  314.   }
  315.   /* 函数:将螺旋轴转换为轴向量
  316.    * 输入:位置向量q,方向向量s,螺旋轴的螺距h
  317.    * 返回:6维轴向量
  318.    */
  319.   Eigen::VectorXd ScrewToAxis(Eigen::Vector3d q, Eigen::Vector3d s, double h) {
  320.     Eigen::VectorXd axis(6); // 定义6维向量
  321.     axis.segment(0, 3) = s; // 填充方向向量
  322.     axis.segment(3, 3) = q.cross(s) + (h * s); // 计算并填充位置向量
  323.     return axis; // 返回轴向量
  324.   }
  325.   /* 函数:将指数坐标转换为轴角表示
  326.    * 输入:6维指数坐标
  327.    * 返回:7维轴角表示
  328.    */
  329.   Eigen::VectorXd AxisAng6(const Eigen::VectorXd& expc6) {
  330.     Eigen::VectorXd v_ret(7); // 定义7维向量
  331.     double theta = Eigen::Vector3d(expc6(0), expc6(1), expc6(2)).norm(); // 计算旋转角度
  332.     if (NearZero(theta)) // 如果旋转角度接近零
  333.       theta = Eigen::Vector3d(expc6(3), expc6(4), expc6(5)).norm(); // 计算平移量的范数
  334.     v_ret << expc6 / theta, theta; // 填充轴角表示
  335.     return v_ret; // 返回轴角表示
  336.   }
  337.   /* 函数:将矩阵投影到SO(3)群
  338.    * 输入:矩阵M
  339.    * 返回:SO(3)群的矩阵
  340.    */
  341.   Eigen::MatrixXd ProjectToSO3(const Eigen::MatrixXd& M) {
  342.     Eigen::JacobiSVD<Eigen::MatrixXd> svd(M, Eigen::ComputeFullU | Eigen::ComputeFullV); // 计算奇异值分解
  343.     Eigen::MatrixXd R = svd.matrixU() * svd.matrixV().transpose(); // 计算旋转矩阵
  344.     if (R.determinant() < 0) // 如果行列式小于0
  345.       // 在这种情况下,结果可能远离M;反转第三列的符号
  346.       R.col(2) *= -1;
  347.     return R; // 返回旋转矩阵
  348.   }
  349.   /* 函数:将矩阵投影到SE(3)群
  350.    * 输入:矩阵M
  351.    * 返回:SE(3)群的矩阵
  352.    */
  353.   Eigen::MatrixXd ProjectToSE3(const Eigen::MatrixXd& M) {
  354.     Eigen::Matrix3d R = M.block<3, 3>(0, 0); // 提取旋转矩阵
  355.     Eigen::Vector3d t = M.block<3, 1>(0, 3); // 提取位置向量
  356.     Eigen::MatrixXd T = RpToTrans(ProjectToSO3(R), t); // 计算SE(3)群的矩阵
  357.     return T; // 返回SE(3)群的矩阵
  358.   }
  359.   /* 函数:计算矩阵到SO(3)群的距离
  360.    * 输入:3x3矩阵M
  361.    * 返回:距离
  362.    */
  363.   double DistanceToSO3(const Eigen::Matrix3d& M) {
  364.     if (M.determinant() > 0) // 如果行列式大于0
  365.       return (M.transpose() * M - Eigen::Matrix3d::Identity()).norm(); // 计算距离
  366.     else
  367.       return 1.0e9; // 返回一个大值表示距离很远
  368.   }
  369.   /* 函数:计算矩阵到SE(3)群的距离
  370.    * 输入:4x4矩阵T
  371.    * 返回:距离
  372.    */
  373.   double DistanceToSE3(const Eigen::Matrix4d& T) {
  374.     Eigen::Matrix3d matR = T.block<3, 3>(0, 0); // 提取旋转矩阵
  375.     if (matR.determinant() > 0) { // 如果行列式大于0
  376.       Eigen::Matrix4d m_ret; // 定义4x4矩阵
  377.       m_ret << matR.transpose() * matR, Eigen::Vector3d::Zero(3), // 计算距离矩阵
  378.         T.row(3);
  379.       m_ret = m_ret - Eigen::Matrix4d::Identity(); // 计算距离
  380.       return m_ret.norm(); // 返回距离
  381.     }
  382.     else
  383.       return 1.0e9; // 返回一个大值表示距离很远
  384.   }
  385.   /* 函数:测试矩阵是否属于SO(3)群
  386.    * 输入:3x3矩阵M
  387.    * 返回:布尔值,表示矩阵是否属于SO(3)群
  388.    */
  389.   bool TestIfSO3(const Eigen::Matrix3d& M) {
  390.     return std::abs(DistanceToSO3(M)) < 1e-3; // 判断矩阵到SO(3)群的距离是否小于1e-3
  391.   }
  392.   /* 函数:测试矩阵是否属于SE(3)群
  393.    * 输入:4x4矩阵T
  394.    * 返回:布尔值,表示矩阵是否属于SE(3)群
  395.    */
  396.   bool TestIfSE3(const Eigen::Matrix4d& T) {
  397.     return std::abs(DistanceToSE3(T)) < 1e-3; // 判断矩阵到SE(3)群的距离是否小于1e-3
  398.   }
  399.   /* 函数:计算逆运动学(身体坐标系)
  400.    * 输入:螺旋轴列表Blist,末端执行器的初始配置M,目标变换矩阵T,关节角度列表thetalist,角速度误差阈值eomg,线速度误差阈值ev
  401.    * 返回:布尔值,表示是否成功找到解
  402.    */
  403.   bool IKinBody(const Eigen::MatrixXd& Blist, const Eigen::MatrixXd& M, const Eigen::MatrixXd& T,
  404.     Eigen::VectorXd& thetalist, double eomg, double ev) {
  405.     int i = 0; // 迭代次数
  406.     int maxiterations = 20; // 最大迭代次数
  407.     Eigen::MatrixXd Tfk = FKinBody(M, Blist, thetalist); // 计算当前关节角度下的末端执行器变换矩阵
  408.     Eigen::MatrixXd Tdiff = TransInv(Tfk) * T; // 计算变换矩阵差
  409.     Eigen::VectorXd Vb = se3ToVec(MatrixLog6(Tdiff)); // 计算变换矩阵对数
  410.     Eigen::Vector3d angular(Vb(0), Vb(1), Vb(2)); // 提取角速度
  411.     Eigen::Vector3d linear(Vb(3), Vb(4), Vb(5)); // 提取线速度
  412.     bool err = (angular.norm() > eomg || linear.norm() > ev); // 判断误差是否超过阈值
  413.     Eigen::MatrixXd Jb; // 定义雅可比矩阵
  414.     while (err && i < maxiterations) { // 迭代求解
  415.       Jb = JacobianBody(Blist, thetalist); // 计算雅可比矩阵
  416.       thetalist += Jb.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(Vb); // 更新关节角度
  417.       i += 1; // 增加迭代次数
  418.       // 迭代计算
  419.       Tfk = FKinBody(M, Blist, thetalist); // 计算当前关节角度下的末端执行器变换矩阵
  420.       Tdiff = TransInv(Tfk) * T; // 计算变换矩阵差
  421.       Vb = se3ToVec(MatrixLog6(Tdiff)); // 计算变换矩阵对数
  422.       angular = Eigen::Vector3d(Vb(0), Vb(1), Vb(2)); // 提取角速度
  423.       linear = Eigen::Vector3d(Vb(3), Vb(4), Vb(5)); // 提取线速度
  424.       err = (angular.norm() > eomg || linear.norm() > ev); // 判断误差是否超过阈值
  425.     }
  426.     return !err; // 返回是否成功找到解
  427.   }
  428.   /* 函数:计算逆运动学(空间坐标系)
  429.    * 输入:螺旋轴列表Slist,末端执行器的初始配置M,目标变换矩阵T,关节角度列表thetalist,角速度误差阈值eomg,线速度误差阈值ev
  430.    * 返回:布尔值,表示是否成功找到解
  431.    */
  432.   bool IKinSpace(const Eigen::MatrixXd& Slist, const Eigen::MatrixXd& M, const Eigen::MatrixXd& T,
  433.     Eigen::VectorXd& thetalist, double eomg, double ev) {
  434.     int i = 0; // 迭代次数
  435.     int maxiterations = 20; // 最大迭代次数
  436.     Eigen::MatrixXd Tfk = FKinSpace(M, Slist, thetalist); // 计算当前关节角度下的末端执行器变换矩阵
  437.     Eigen::MatrixXd Tdiff = TransInv(Tfk) * T; // 计算变换矩阵差
  438.     Eigen::VectorXd Vs = Adjoint(Tfk) * se3ToVec(MatrixLog6(Tdiff)); // 计算变换矩阵对数并转换到空间坐标系
  439.     Eigen::Vector3d angular(Vs(0), Vs(1), Vs(2)); // 提取角速度
  440.     Eigen::Vector3d linear(Vs(3), Vs(4), Vs(5)); // 提取线速度
  441.     bool err = (angular.norm() > eomg || linear.norm() > ev); // 判断误差是否超过阈值
  442.     Eigen::MatrixXd Js; // 定义雅可比矩阵
  443.     while (err && i < maxiterations) { // 迭代求解
  444.       Js = JacobianSpace(Slist, thetalist); // 计算雅可比矩阵
  445.       thetalist += Js.bdcSvd(Eigen::ComputeThinU | Eigen::ComputeThinV).solve(Vs); // 更新关节角度
  446.       i += 1; // 增加迭代次数
  447.       // 迭代计算
  448.       Tfk = FKinSpace(M, Slist, thetalist); // 计算当前关节角度下的末端执行器变换矩阵
  449.       Tdiff = TransInv(Tfk) * T; // 计算变换矩阵差
  450.       Vs = Adjoint(Tfk) * se3ToVec(MatrixLog6(Tdiff)); // 计算变换矩阵对数并转换到空间坐标系
  451.       angular = Eigen::Vector3d(Vs(0), Vs(1), Vs(2)); // 提取角速度
  452.       linear = Eigen::Vector3d(Vs(3), Vs(4), Vs(5)); // 提取线速度
  453.       err = (angular.norm() > eomg || linear.norm() > ev); // 判断误差是否超过阈值
  454.     }
  455.     return !err; // 返回是否成功找到解
  456.   }
  457.   /*
  458.   * 函数:使用前向-后向牛顿-欧拉迭代求解方程:
  459.   * taulist = Mlist(thetalist) * ddthetalist + c(thetalist, dthetalist) ...
  460.   *           + g(thetalist) + Jtr(thetalist) * Ftip
  461.   * 输入:
  462.   *  thetalist: 关节变量的n维向量
  463.   *  dthetalist: 关节速度的n维向量
  464.   *  ddthetalist: 关节加速度的n维向量
  465.   *  g: 重力向量g
  466.   *  Ftip: 末端执行器施加的空间力,以{n+1}坐标系表示
  467.   *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  468.   *  Glist: 链接的空间惯性矩阵Gi
  469.   *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  470.   *
  471.   * 输出:
  472.   *  taulist: 所需关节力/力矩的n维向量
  473.   *
  474.   */
  475.   Eigen::VectorXd InverseDynamics(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& dthetalist, const Eigen::VectorXd& ddthetalist,
  476.                   const Eigen::VectorXd& g, const Eigen::VectorXd& Ftip, const std::vector<Eigen::MatrixXd>& Mlist,
  477.                   const std::vector<Eigen::MatrixXd>& Glist, const Eigen::MatrixXd& Slist) {
  478.       // 列表的大小
  479.     int n = thetalist.size();
  480.     Eigen::MatrixXd Mi = Eigen::MatrixXd::Identity(4, 4); // 初始化4x4单位矩阵
  481.     Eigen::MatrixXd Ai = Eigen::MatrixXd::Zero(6, n); // 初始化6xn零矩阵
  482.     std::vector<Eigen::MatrixXd> AdTi; // 定义伴随矩阵列表
  483.     for (int i = 0; i < n + 1; i++) {
  484.       AdTi.push_back(Eigen::MatrixXd::Zero(6, 6)); // 初始化6x6零矩阵并添加到伴随矩阵列表中
  485.     }
  486.     Eigen::MatrixXd Vi = Eigen::MatrixXd::Zero(6, n + 1); // 初始化6x(n+1)零矩阵,用于存储速度
  487.     Eigen::MatrixXd Vdi = Eigen::MatrixXd::Zero(6, n + 1); // 初始化6x(n+1)零矩阵,用于存储加速度
  488.     Vdi.block(3, 0, 3, 1) = -g; // 设置初始加速度为重力向量的负值
  489.     AdTi[n] = mr::Adjoint(mr::TransInv(Mlist[n])); // 计算末端执行器的伴随矩阵
  490.     Eigen::VectorXd Fi = Ftip; // 初始化末端执行器施加的力
  491.     Eigen::VectorXd taulist = Eigen::VectorXd::Zero(n); // 初始化关节力/力矩的n维向量
  492.     // 前向迭代
  493.     for (int i = 0; i < n; i++) {
  494.       Mi = Mi * Mlist[i]; // 更新变换矩阵
  495.       Ai.col(i) = mr::Adjoint(mr::TransInv(Mi)) * Slist.col(i); // 计算螺旋轴的伴随表示
  496.       AdTi[i] = mr::Adjoint(mr::MatrixExp6(mr::VecTose3(Ai.col(i) * -thetalist(i)))
  497.                 * mr::TransInv(Mlist[i])); // 计算伴随矩阵
  498.       Vi.col(i + 1) = AdTi[i] * Vi.col(i) + Ai.col(i) * dthetalist(i); // 计算速度
  499.       Vdi.col(i + 1) = AdTi[i] * Vdi.col(i) + Ai.col(i) * ddthetalist(i)
  500.                + ad(Vi.col(i + 1)) * Ai.col(i) * dthetalist(i); // 计算加速度
  501.     }
  502.     // 后向迭代
  503.     for (int i = n - 1; i >= 0; i--) {
  504.       Fi = AdTi[i + 1].transpose() * Fi + Glist[i] * Vdi.col(i + 1)
  505.            - ad(Vi.col(i + 1)).transpose() * (Glist[i] * Vi.col(i + 1)); // 计算力
  506.       taulist(i) = Fi.transpose() * Ai.col(i); // 计算关节力/力矩
  507.     }
  508.     return taulist; // 返回关节力/力矩的n维向量
  509.   }
  510.   /*
  511.    * 函数:此函数调用InverseDynamics,设置Ftip = 0,dthetalist = 0,ddthetalist = 0。
  512.    * 目的是计算动力学方程中的一个重要项
  513.    * 输入:
  514.    *  thetalist: 关节变量的n维向量
  515.    *  g: 重力向量g
  516.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  517.    *  Glist: 链接的空间惯性矩阵Gi
  518.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  519.    *
  520.    * 输出:
  521.    *  grav: 显示重力对动力学影响的3维向量
  522.    *
  523.    */
  524.   Eigen::VectorXd GravityForces(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& g,
  525.                   const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist, const Eigen::MatrixXd& Slist) {
  526.       int n = thetalist.size(); // 获取关节变量的数量
  527.     Eigen::VectorXd dummylist = Eigen::VectorXd::Zero(n); // 初始化n维零向量
  528.     Eigen::VectorXd dummyForce = Eigen::VectorXd::Zero(6); // 初始化6维零向量
  529.     Eigen::VectorXd grav = mr::InverseDynamics(thetalist, dummylist, dummylist, g,
  530.                                                 dummyForce, Mlist, Glist, Slist); // 调用InverseDynamics计算重力影响
  531.     return grav; // 返回重力影响向量
  532.   }
  533.   /*
  534.      * 函数:此函数调用InverseDynamics n次,每次传递一个单元素为1的ddthetalist向量,其他输入为零。
  535.    * 每次调用InverseDynamics生成一个列,这些列组合起来形成惯性矩阵。
  536.    *
  537.    * 输入:
  538.    *  thetalist: 关节变量的n维向量
  539.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  540.    *  Glist: 链接的空间惯性矩阵Gi
  541.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  542.    *
  543.    * 输出:
  544.    *  M: 给定配置thetalist的n关节串联链的数值惯性矩阵M(thetalist)
  545.    */
  546.   Eigen::MatrixXd MassMatrix(const Eigen::VectorXd& thetalist,
  547.                                 const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist, const Eigen::MatrixXd& Slist) {
  548.     int n = thetalist.size(); // 获取关节变量的数量
  549.     Eigen::VectorXd dummylist = Eigen::VectorXd::Zero(n); // 初始化n维零向量
  550.     Eigen::VectorXd dummyg = Eigen::VectorXd::Zero(3); // 初始化3维零向量
  551.     Eigen::VectorXd dummyforce = Eigen::VectorXd::Zero(6); // 初始化6维零向量
  552.     Eigen::MatrixXd M = Eigen::MatrixXd::Zero(n, n); // 初始化n x n零矩阵
  553.     for (int i = 0; i < n; i++) { // 遍历每个关节变量
  554.       Eigen::VectorXd ddthetalist = Eigen::VectorXd::Zero(n); // 初始化n维零向量
  555.       ddthetalist(i) = 1; // 设置当前关节变量的加速度为1
  556.       M.col(i) = mr::InverseDynamics(thetalist, dummylist, ddthetalist,
  557.                              dummyg, dummyforce, Mlist, Glist, Slist); // 调用InverseDynamics计算惯性矩阵的列
  558.     }
  559.     return M; // 返回惯性矩阵
  560.   }
  561.   /*
  562.      * 函数:此函数调用InverseDynamics,设置g = 0,Ftip = 0,ddthetalist = 0。
  563.    *
  564.    * 输入:
  565.    *  thetalist: 关节变量的n维向量
  566.    *  dthetalist: 关节速度的列表
  567.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  568.    *  Glist: 链接的空间惯性矩阵Gi
  569.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  570.    *
  571.    * 输出:
  572.    *  c: 给定thetalist和dthetalist的科里奥利和离心项向量c(thetalist,dthetalist)
  573.    */
  574.   Eigen::VectorXd VelQuadraticForces(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& dthetalist,
  575.                                 const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist, const Eigen::MatrixXd& Slist) {
  576.     int n = thetalist.size(); // 获取关节变量的数量
  577.     Eigen::VectorXd dummylist = Eigen::VectorXd::Zero(n); // 初始化n维零向量
  578.     Eigen::VectorXd dummyg = Eigen::VectorXd::Zero(3); // 初始化3维零向量
  579.     Eigen::VectorXd dummyforce = Eigen::VectorXd::Zero(6); // 初始化6维零向量
  580.     Eigen::VectorXd c = mr::InverseDynamics(thetalist, dthetalist, dummylist,
  581.                              dummyg, dummyforce, Mlist, Glist, Slist); // 调用InverseDynamics计算科里奥利和离心项向量
  582.     return c; // 返回科里奥利和离心项向量
  583.   }
  584.   /*
  585.      * 函数:此函数调用InverseDynamics,设置g = 0,dthetalist = 0,ddthetalist = 0。
  586.    *
  587.    * 输入:
  588.    *  thetalist: 关节变量的n维向量
  589.    *  Ftip: 末端执行器施加的空间力,以{n+1}坐标系表示
  590.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  591.    *  Glist: 链接的空间惯性矩阵Gi
  592.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  593.    *
  594.    * 输出:
  595.    *  JTFtip: 仅为产生末端执行器力Ftip所需的关节力和力矩
  596.    */
  597.   Eigen::VectorXd EndEffectorForces(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& Ftip,
  598.                 const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist, const Eigen::MatrixXd& Slist) {
  599.     int n = thetalist.size(); // 获取关节变量的数量
  600.     Eigen::VectorXd dummylist = Eigen::VectorXd::Zero(n); // 初始化n维零向量
  601.     Eigen::VectorXd dummyg = Eigen::VectorXd::Zero(3); // 初始化3维零向量
  602.     Eigen::VectorXd JTFtip = mr::InverseDynamics(thetalist, dummylist, dummylist,
  603.                              dummyg, Ftip, Mlist, Glist, Slist); // 调用InverseDynamics计算关节力和力矩
  604.     return JTFtip; // 返回关节力和力矩
  605.   }
  606.   /*
  607.    * 函数:通过求解以下方程计算ddthetalist:
  608.    * Mlist(thetalist) * ddthetalist = taulist - c(thetalist,dthetalist)
  609.    *                                  - g(thetalist) - Jtr(thetalist) * Ftip
  610.    * 输入:
  611.    *  thetalist: 关节变量的n维向量
  612.    *  dthetalist: 关节速度的n维向量
  613.    *  taulist: 关节力/力矩的n维向量
  614.    *  g: 重力向量g
  615.    *  Ftip: 末端执行器施加的空间力,以{n+1}坐标系表示
  616.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  617.    *  Glist: 链接的空间惯性矩阵Gi
  618.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  619.    *
  620.    * 输出:
  621.    *  ddthetalist: 计算得到的关节加速度
  622.    *
  623.    */
  624.   Eigen::VectorXd ForwardDynamics(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& dthetalist, const Eigen::VectorXd& taulist,
  625.                   const Eigen::VectorXd& g, const Eigen::VectorXd& Ftip, const std::vector<Eigen::MatrixXd>& Mlist,
  626.                   const std::vector<Eigen::MatrixXd>& Glist, const Eigen::MatrixXd& Slist) {
  627.     Eigen::VectorXd totalForce = taulist - mr::VelQuadraticForces(thetalist, dthetalist, Mlist, Glist, Slist)
  628.                                 - mr::GravityForces(thetalist, g, Mlist, Glist, Slist)
  629.                                              - mr::EndEffectorForces(thetalist, Ftip, Mlist, Glist, Slist); // 计算总力
  630.     Eigen::MatrixXd M = mr::MassMatrix(thetalist, Mlist, Glist, Slist); // 计算质量矩阵
  631.     // 使用LDLT分解,因为M是正定矩阵
  632.         Eigen::VectorXd ddthetalist = M.ldlt().solve(totalForce); // 求解关节加速度
  633.     return ddthetalist; // 返回关节加速度
  634.   }
  635.   /* 函数:使用欧拉法更新关节角度和速度
  636.    * 输入:
  637.    *  thetalist: 关节角度的向量
  638.    *  dthetalist: 关节速度的向量
  639.    *  ddthetalist: 关节加速度的向量
  640.    *  dt: 时间步长
  641.    */
  642.   void EulerStep(Eigen::VectorXd& thetalist, Eigen::VectorXd& dthetalist, const Eigen::VectorXd& ddthetalist, double dt) {
  643.     thetalist += dthetalist * dt; // 更新关节角度
  644.     dthetalist += ddthetalist * dt; // 更新关节速度
  645.     return;
  646.   }
  647.   /* 函数:计算逆动力学轨迹
  648.    * 输入:
  649.    *  thetamat: 关节角度矩阵
  650.    *  dthetamat: 关节速度矩阵
  651.    *  ddthetamat: 关节加速度矩阵
  652.    *  g: 重力向量g
  653.    *  Ftipmat: 末端执行器施加的空间力矩阵
  654.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  655.    *  Glist: 链接的空间惯性矩阵Gi
  656.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  657.    *
  658.    * 输出:
  659.    *  taumat: 关节力/力矩矩阵
  660.    */
  661.   Eigen::MatrixXd InverseDynamicsTrajectory(const Eigen::MatrixXd& thetamat, const Eigen::MatrixXd& dthetamat, const Eigen::MatrixXd& ddthetamat,
  662.     const Eigen::VectorXd& g, const Eigen::MatrixXd& Ftipmat, const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist,
  663.     const Eigen::MatrixXd& Slist) {
  664.     Eigen::MatrixXd thetamatT = thetamat.transpose(); // 转置关节角度矩阵
  665.     Eigen::MatrixXd dthetamatT = dthetamat.transpose(); // 转置关节速度矩阵
  666.     Eigen::MatrixXd ddthetamatT = ddthetamat.transpose(); // 转置关节加速度矩阵
  667.     Eigen::MatrixXd FtipmatT = Ftipmat.transpose(); // 转置末端执行器力矩阵
  668.     int N = thetamat.rows();  // 轨迹点数量
  669.     int dof = thetamat.cols(); // 自由度数量
  670.     Eigen::MatrixXd taumatT = Eigen::MatrixXd::Zero(dof, N); // 初始化关节力/力矩矩阵
  671.     for (int i = 0; i < N; ++i) { // 遍历每个轨迹点
  672.       taumatT.col(i) = InverseDynamics(thetamatT.col(i), dthetamatT.col(i), ddthetamatT.col(i), g, FtipmatT.col(i), Mlist, Glist, Slist); // 计算关节力/力矩
  673.     }
  674.     Eigen::MatrixXd taumat = taumatT.transpose(); // 转置关节力/力矩矩阵
  675.     return taumat; // 返回关节力/力矩矩阵
  676.   }
  677.   /*
  678.    * 函数:计算正向动力学轨迹
  679.    * 输入:
  680.    *  thetalist: 关节角度的向量
  681.    *  dthetalist: 关节速度的向量
  682.    *  taumat: 力/力矩矩阵
  683.    *  g: 重力向量
  684.    *  Ftipmat: 末端执行器施加的空间力矩阵
  685.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  686.    *  Glist: 链接的空间惯性矩阵Gi
  687.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  688.    *  dt: 时间步长
  689.    *  intRes: 积分分辨率
  690.    * 输出:
  691.    *  JointTraj_ret: 包含关节角度和速度轨迹的向量
  692.    */
  693.   std::vector<Eigen::MatrixXd> ForwardDynamicsTrajectory(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& dthetalist, const Eigen::MatrixXd& taumat,
  694.     const Eigen::VectorXd& g, const Eigen::MatrixXd& Ftipmat, const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist,
  695.     const Eigen::MatrixXd& Slist, double dt, int intRes) {
  696.     Eigen::MatrixXd taumatT = taumat.transpose(); // 转置力/力矩矩阵
  697.     Eigen::MatrixXd FtipmatT = Ftipmat.transpose(); // 转置末端执行器力矩阵
  698.     int N = taumat.rows();  // 力/力矩点的数量
  699.     int dof = taumat.cols(); // 自由度数量
  700.     Eigen::MatrixXd thetamatT = Eigen::MatrixXd::Zero(dof, N); // 初始化关节角度矩阵
  701.     Eigen::MatrixXd dthetamatT = Eigen::MatrixXd::Zero(dof, N); // 初始化关节速度矩阵
  702.     thetamatT.col(0) = thetalist; // 设置初始关节角度
  703.     dthetamatT.col(0) = dthetalist; // 设置初始关节速度
  704.     Eigen::VectorXd thetacurrent = thetalist; // 当前关节角度
  705.     Eigen::VectorXd dthetacurrent = dthetalist; // 当前关节速度
  706.     Eigen::VectorXd ddthetalist; // 关节加速度
  707.     for (int i = 0; i < N - 1; ++i) { // 遍历每个力/力矩点
  708.       for (int j = 0; j < intRes; ++j) { // 进行积分分辨率次迭代
  709.         ddthetalist = ForwardDynamics(thetacurrent, dthetacurrent, taumatT.col(i), g, FtipmatT.col(i), Mlist, Glist, Slist); // 计算关节加速度
  710.         EulerStep(thetacurrent, dthetacurrent, ddthetalist, 1.0 * dt / intRes); // 使用欧拉法更新关节角度和速度
  711.       }
  712.       thetamatT.col(i + 1) = thetacurrent; // 更新关节角度矩阵
  713.       dthetamatT.col(i + 1) = dthetacurrent; // 更新关节速度矩阵
  714.     }
  715.     std::vector<Eigen::MatrixXd> JointTraj_ret; // 定义返回的关节轨迹向量
  716.     JointTraj_ret.push_back(thetamatT.transpose()); // 添加关节角度轨迹
  717.     JointTraj_ret.push_back(dthetamatT.transpose()); // 添加关节速度轨迹
  718.     return JointTraj_ret; // 返回关节轨迹向量
  719.   }
  720.   /* 函数:计算关节力矩
  721.    * 输入:
  722.    *  thetalist: 关节角度的向量
  723.    *  dthetalist: 关节速度的向量
  724.    *  eint: 积分误差
  725.    *  g: 重力向量
  726.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  727.    *  Glist: 链接的空间惯性矩阵Gi
  728.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  729.    *  thetalistd: 期望关节角度
  730.    *  dthetalistd: 期望关节速度
  731.    *  ddthetalistd: 期望关节加速度
  732.    *  Kp: 比例增益
  733.    *  Ki: 积分增益
  734.    *  Kd: 微分增益
  735.    * 输出:
  736.    *  tau_computed: 计算得到的关节力矩
  737.    */
  738.   Eigen::VectorXd ComputedTorque(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& dthetalist, const Eigen::VectorXd& eint,
  739.     const Eigen::VectorXd& g, const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist,
  740.     const Eigen::MatrixXd& Slist, const Eigen::VectorXd& thetalistd, const Eigen::VectorXd& dthetalistd, const Eigen::VectorXd& ddthetalistd,
  741.     double Kp, double Ki, double Kd) {
  742.     Eigen::VectorXd e = thetalistd - thetalist;  // 位置误差
  743.     Eigen::VectorXd tau_feedforward = MassMatrix(thetalist, Mlist, Glist, Slist) * (Kp * e + Ki * (eint + e) + Kd * (dthetalistd - dthetalist)); // 前馈力矩
  744.     Eigen::VectorXd Ftip = Eigen::VectorXd::Zero(6); // 初始化末端执行器力
  745.     Eigen::VectorXd tau_inversedyn = InverseDynamics(thetalist, dthetalist, ddthetalistd, g, Ftip, Mlist, Glist, Slist); // 逆动力学力矩
  746.     Eigen::VectorXd tau_computed = tau_feedforward + tau_inversedyn; // 计算总力矩
  747.     return tau_computed; // 返回计算得到的关节力矩
  748.   }
  749.   /* 函数:三次时间缩放
  750.    * 输入:
  751.    *  Tf: 总时间
  752.    *  t: 当前时间
  753.    * 输出:
  754.    *  st: 缩放后的时间
  755.    */
  756.   double CubicTimeScaling(double Tf, double t) {
  757.     double timeratio = 1.0 * t / Tf; // 计算时间比率
  758.     double st = 3 * pow(timeratio, 2) - 2 * pow(timeratio, 3); // 计算三次时间缩放
  759.     return st; // 返回缩放后的时间
  760.   }
  761.   /* 函数:五次时间缩放
  762.    * 输入:
  763.    *  Tf: 总时间
  764.    *  t: 当前时间
  765.    * 输出:
  766.    *  st: 缩放后的时间
  767.    */
  768.   double QuinticTimeScaling(double Tf, double t) {
  769.     double timeratio = 1.0 * t / Tf; // 计算时间比率
  770.     double st = 10 * pow(timeratio, 3) - 15 * pow(timeratio, 4) + 6 * pow(timeratio, 5); // 计算五次时间缩放
  771.     return st; // 返回缩放后的时间
  772.   }
  773.   /* 函数:计算关节轨迹
  774.    * 输入:
  775.    *  thetastart: 初始关节角度
  776.    *  thetaend: 结束关节角度
  777.    *  Tf: 总时间
  778.    *  N: 轨迹点数量
  779.    *  method: 时间缩放方法(3表示三次,5表示五次)
  780.    * 输出:
  781.    *  traj: 关节轨迹矩阵
  782.    */
  783.   Eigen::MatrixXd JointTrajectory(const Eigen::VectorXd& thetastart, const Eigen::VectorXd& thetaend, double Tf, int N, int method) {
  784.     double timegap = Tf / (N - 1); // 计算时间间隔
  785.     Eigen::MatrixXd trajT = Eigen::MatrixXd::Zero(thetastart.size(), N); // 初始化轨迹矩阵
  786.     double st;
  787.     for (int i = 0; i < N; ++i) { // 遍历每个轨迹点
  788.       if (method == 3)
  789.         st = CubicTimeScaling(Tf, timegap * i); // 三次时间缩放
  790.       else
  791.         st = QuinticTimeScaling(Tf, timegap * i); // 五次时间缩放
  792.       trajT.col(i) = st * thetaend + (1 - st) * thetastart; // 计算轨迹点
  793.     }
  794.     Eigen::MatrixXd traj = trajT.transpose(); // 转置轨迹矩阵
  795.     return traj; // 返回关节轨迹矩阵
  796.   }
  797.   /* 函数:计算螺旋轨迹
  798.    * 输入:
  799.    *  Xstart: 初始变换矩阵
  800.    *  Xend: 结束变换矩阵
  801.    *  Tf: 总时间
  802.    *  N: 轨迹点数量
  803.    *  method: 时间缩放方法(3表示三次,5表示五次)
  804.    * 输出:
  805.    *  traj: 螺旋轨迹向量
  806.    */
  807.   std::vector<Eigen::MatrixXd> ScrewTrajectory(const Eigen::MatrixXd& Xstart, const Eigen::MatrixXd& Xend, double Tf, int N, int method) {
  808.     double timegap = Tf / (N - 1); // 计算时间间隔
  809.     std::vector<Eigen::MatrixXd> traj(N); // 初始化轨迹向量
  810.     double st;
  811.     for (int i = 0; i < N; ++i) { // 遍历每个轨迹点
  812.       if (method == 3)
  813.         st = CubicTimeScaling(Tf, timegap * i); // 三次时间缩放
  814.       else
  815.         st = QuinticTimeScaling(Tf, timegap * i); // 五次时间缩放
  816.       Eigen::MatrixXd Ttemp = MatrixLog6(TransInv(Xstart) * Xend); // 计算变换矩阵对数
  817.       traj.at(i) = Xstart * MatrixExp6(Ttemp * st); // 计算轨迹点
  818.     }
  819.     return traj; // 返回螺旋轨迹向量
  820.   }
  821.   /*
  822.    * 函数:计算笛卡尔轨迹
  823.    * 输入:
  824.    *  Xstart: 初始变换矩阵
  825.    *  Xend: 结束变换矩阵
  826.    *  Tf: 总时间
  827.    *  N: 轨迹点数量
  828.    *  method: 时间缩放方法(3表示三次,5表示五次)
  829.    * 输出:
  830.    *  traj: 笛卡尔轨迹向量
  831.    */
  832.   std::vector<Eigen::MatrixXd> CartesianTrajectory(const Eigen::MatrixXd& Xstart, const Eigen::MatrixXd& Xend, double Tf, int N, int method) {
  833.     double timegap = Tf / (N - 1); // 计算时间间隔
  834.     std::vector<Eigen::MatrixXd> traj(N); // 初始化轨迹向量
  835.     std::vector<Eigen::MatrixXd> Rpstart = TransToRp(Xstart); // 将初始变换矩阵分解为旋转矩阵和位置向量
  836.     std::vector<Eigen::MatrixXd> Rpend = TransToRp(Xend); // 将结束变换矩阵分解为旋转矩阵和位置向量
  837.     Eigen::Matrix3d Rstart = Rpstart[0]; Eigen::Vector3d pstart = Rpstart[1]; // 提取初始旋转矩阵和位置向量
  838.     Eigen::Matrix3d Rend = Rpend[0]; Eigen::Vector3d pend = Rpend[1]; // 提取结束旋转矩阵和位置向量
  839.     double st;
  840.     for (int i = 0; i < N; ++i) { // 遍历每个轨迹点
  841.       if (method == 3)
  842.         st = CubicTimeScaling(Tf, timegap * i); // 三次时间缩放
  843.       else
  844.         st = QuinticTimeScaling(Tf, timegap * i); // 五次时间缩放
  845.       Eigen::Matrix3d Ri = Rstart * MatrixExp3(MatrixLog3(Rstart.transpose() * Rend) * st); // 计算当前旋转矩阵
  846.       Eigen::Vector3d pi = st * pend + (1 - st) * pstart; // 计算当前位置向量
  847.       Eigen::MatrixXd traji(4, 4); // 定义4x4变换矩阵
  848.       traji << Ri, pi, // 填充旋转矩阵和位置向量
  849.         0, 0, 0, 1; // 填充最后一行
  850.       traj.at(i) = traji; // 将当前变换矩阵添加到轨迹向量中
  851.     }
  852.     return traj; // 返回笛卡尔轨迹向量
  853.   }
  854.   /*
  855.    * 函数:模拟控制
  856.    * 输入:
  857.    *  thetalist: 关节角度的向量
  858.    *  dthetalist: 关节速度的向量
  859.    *  g: 重力向量
  860.    *  Ftipmat: 末端执行器施加的空间力矩阵
  861.    *  Mlist: 链接帧{i}相对于{i-1}在初始位置的列表
  862.    *  Glist: 链接的空间惯性矩阵Gi
  863.    *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  864.    *  thetamatd: 期望关节角度矩阵
  865.    *  dthetamatd: 期望关节速度矩阵
  866.    *  ddthetamatd: 期望关节加速度矩阵
  867.    *  gtilde: 估计的重力向量
  868.    *  Mtildelist: 估计的链接帧列表
  869.    *  Gtildelist: 估计的空间惯性矩阵列表
  870.    *  Kp: 比例增益
  871.    *  Ki: 积分增益
  872.    *  Kd: 微分增益
  873.    *  dt: 时间步长
  874.    *  intRes: 积分分辨率
  875.    * 输出:
  876.    *  ControlTauTraj_ret: 包含关节力矩和角度轨迹的向量
  877.    */
  878.   std::vector<Eigen::MatrixXd> SimulateControl(const Eigen::VectorXd& thetalist, const Eigen::VectorXd& dthetalist, const Eigen::VectorXd& g,
  879.     const Eigen::MatrixXd& Ftipmat, const std::vector<Eigen::MatrixXd>& Mlist, const std::vector<Eigen::MatrixXd>& Glist,
  880.     const Eigen::MatrixXd& Slist, const Eigen::MatrixXd& thetamatd, const Eigen::MatrixXd& dthetamatd, const Eigen::MatrixXd& ddthetamatd,
  881.     const Eigen::VectorXd& gtilde, const std::vector<Eigen::MatrixXd>& Mtildelist, const std::vector<Eigen::MatrixXd>& Gtildelist,
  882.     double Kp, double Ki, double Kd, double dt, int intRes) {
  883.     Eigen::MatrixXd FtipmatT = Ftipmat.transpose(); // 转置末端执行器力矩阵
  884.     Eigen::MatrixXd thetamatdT = thetamatd.transpose(); // 转置期望关节角度矩阵
  885.     Eigen::MatrixXd dthetamatdT = dthetamatd.transpose(); // 转置期望关节速度矩阵
  886.     Eigen::MatrixXd ddthetamatdT = ddthetamatd.transpose(); // 转置期望关节加速度矩阵
  887.     int m = thetamatdT.rows(); int n = thetamatdT.cols(); // 获取矩阵的行数和列数
  888.     Eigen::VectorXd thetacurrent = thetalist; // 当前关节角度
  889.     Eigen::VectorXd dthetacurrent = dthetalist; // 当前关节速度
  890.     Eigen::VectorXd eint = Eigen::VectorXd::Zero(m); // 初始化积分误差
  891.     Eigen::MatrixXd taumatT = Eigen::MatrixXd::Zero(m, n); // 初始化关节力矩矩阵
  892.     Eigen::MatrixXd thetamatT = Eigen::MatrixXd::Zero(m, n); // 初始化关节角度矩阵
  893.     Eigen::VectorXd taulist; // 关节力矩向量
  894.     Eigen::VectorXd ddthetalist; // 关节加速度向量
  895.     for (int i = 0; i < n; ++i) { // 遍历每个时间步
  896.       taulist = ComputedTorque(thetacurrent, dthetacurrent, eint, gtilde, Mtildelist, Gtildelist, Slist, thetamatdT.col(i),
  897.         dthetamatdT.col(i), ddthetamatdT.col(i), Kp, Ki, Kd); // 计算关节力矩
  898.       for (int j = 0; j < intRes; ++j) { // 进行积分分辨率次迭代
  899.         ddthetalist = ForwardDynamics(thetacurrent, dthetacurrent, taulist, g, FtipmatT.col(i), Mlist, Glist, Slist); // 计算关节加速度
  900.         EulerStep(thetacurrent, dthetacurrent, ddthetalist, dt / intRes); // 使用欧拉法更新关节角度和速度
  901.       }
  902.       taumatT.col(i) = taulist; // 更新关节力矩矩阵
  903.       thetamatT.col(i) = thetacurrent; // 更新关节角度矩阵
  904.       eint += dt * (thetamatdT.col(i) - thetacurrent); // 更新积分误差
  905.     }
  906.     std::vector<Eigen::MatrixXd> ControlTauTraj_ret; // 定义返回的控制轨迹向量
  907.     ControlTauTraj_ret.push_back(taumatT.transpose()); // 添加关节力矩轨迹
  908.     ControlTauTraj_ret.push_back(thetamatT.transpose()); // 添加关节角度轨迹
  909.     return ControlTauTraj_ret; // 返回控制轨迹向量
  910.   }
复制代码
库测试 lib_test.cpp

  1. #include <iostream> // 包含输入输出流库
  2. #include <Eigen/Dense> // 包含Eigen库,用于矩阵和向量运算
  3. #include "../include/modern_robotics.h" // 包含现代机器人库的头文件
  4. #include "gtest/gtest.h" // 包含Google测试框架的头文件
  5. # define M_PI 3.14159265358979323846  /* 定义圆周率常量 */
  6. /* 测试函数:VecToSO3Test */
  7. TEST(MRTest, VecToSO3Test) {
  8.   Eigen::Vector3d vec(1, 2, 3); // 定义3维向量
  9.   Eigen::Matrix3d result(3, 3); // 定义3x3矩阵
  10.   result << 0, -3, 2, // 填充矩阵元素
  11.     3, 0, -1,
  12.     -2, 1, 0;
  13.   EXPECT_EQ(result, mr::VecToso3(vec)); // 断言VecToso3函数的输出与预期结果相等
  14. }
  15. /* 测试函数:JacobianSpaceTest */
  16. TEST(MRTest, JacobianSpaceTest) {
  17.   Eigen::MatrixXd s_list(6, 3); // 定义6x3矩阵,用于存储螺旋轴
  18.   s_list << 0, 0, 0, // 填充矩阵元素
  19.     0, 1, -1,
  20.     1, 0, 0,
  21.     0, -0.0711, 0.0711,
  22.     0, 0, 0,
  23.     0, 0, -0.2795;
  24.   Eigen::VectorXd theta(3); // 定义3维向量,用于存储关节角度
  25.   theta << 1.0472, 1.0472, 1.0472; // 填充向量元素
  26.   Eigen::MatrixXd result(6, 3); // 定义6x3矩阵,用于存储预期结果
  27.   result << 0, -0.866, 0.866, // 填充矩阵元素
  28.     0, 0.5, -0.5,
  29.     1, 0, 0,
  30.     0, -0.0355, -0.0855,
  31.     0, -0.0615, -0.1481,
  32.     0, 0, -0.1398;
  33.   Eigen::MatrixXd tmp_result = mr::JacobianSpace(s_list, theta); // 计算空间雅可比矩阵
  34.   // std::cout << tmp_result << std::endl;
  35.   ASSERT_TRUE(mr::JacobianSpace(s_list, theta).isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  36. }
  37. /* 测试函数:JacobianBodyTest */
  38. TEST(MRTest, JacobianBodyTest) {
  39.   Eigen::MatrixXd b_list(6, 3); // 定义6x3矩阵,用于存储螺旋轴
  40.   b_list << 0, 0, 0, // 填充矩阵元素
  41.     0, 1, -1,
  42.     1, 0, 0,
  43.     0.0425, 0, 0,
  44.     0.5515, 0, 0,
  45.     0, -0.5515, 0.2720;
  46.   Eigen::VectorXd theta(3); // 定义3维向量,用于存储关节角度
  47.   theta << 0, 0, 1.5708; // 填充向量元素
  48.   Eigen::MatrixXd result(6, 3); // 定义6x3矩阵,用于存储预期结果
  49.   result << 1, 0, 0, // 填充矩阵元素
  50.     0, 1, -1,
  51.     0, 0, 0,
  52.     0, -0.2795, 0,
  53.     0.2795, 0, 0,
  54.     -0.0425, -0.2720, 0.2720;
  55.   Eigen::MatrixXd tmp_result = mr::JacobianBody(b_list, theta); // 计算身体雅可比矩阵
  56.   // std::cout << tmp_result << std::endl;
  57.   ASSERT_TRUE(mr::JacobianBody(b_list, theta).isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  58. }
  59. /* 测试函数:adTest */
  60. TEST(MRTest, adTest) {
  61.   Eigen::VectorXd V(6); // 定义6维向量
  62.   V << 1, 2, 3, 4, 5, 6; // 填充向量元素
  63.   Eigen::MatrixXd result(6, 6); // 定义6x6矩阵,用于存储预期结果
  64.   result << 0, -3, 2, 0, 0, 0, // 填充矩阵元素
  65.     3, 0, -1, 0, 0, 0,
  66.     -2, 1, 0, 0, 0, 0,
  67.     0, -6, 5, 0, -3, 2,
  68.     6, 0, -4, 3, 0, -1,
  69.     -5, 4, 0, -2, 1, 0;
  70.   ASSERT_TRUE(mr::ad(V).isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  71. }
  72. /* 测试函数:TransInvTest */
  73. TEST(MRTest, TransInvTest) {
  74.   Eigen::MatrixXd input(4, 4); // 定义4x4矩阵,用于存储输入变换矩阵
  75.   input << 1, 0, 0, 0, // 填充矩阵元素
  76.     0, 0, -1, 0,
  77.     0, 1, 0, 3,
  78.     0, 0, 0, 1;
  79.   Eigen::MatrixXd result(4, 4); // 定义4x4矩阵,用于存储预期结果
  80.   result << 1, 0, 0, 0, // 填充矩阵元素
  81.     0, 0, 1, -3,
  82.     0, -1, 0, 0,
  83.     0, 0, 0, 1;
  84.   auto inv = mr::TransInv(input); // 计算变换矩阵的逆
  85.   ASSERT_TRUE(inv.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  86. }
  87. /* 测试函数:RotInvTest */
  88. TEST(MRTest, RotInvTest) {
  89.   Eigen::MatrixXd input(3, 3); // 定义3x3矩阵,用于存储输入旋转矩阵
  90.   input << 0, 0, 1, // 填充矩阵元素
  91.     1, 0, 0,
  92.     0, 1, 0;
  93.   Eigen::MatrixXd result(3, 3); // 定义3x3矩阵,用于存储预期结果
  94.   result << 0, 1, 0, // 填充矩阵元素
  95.     0, 0, 1,
  96.     1, 0, 0;
  97.   auto inv = mr::RotInv(input); // 计算旋转矩阵的逆
  98.   ASSERT_TRUE(inv.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  99. }
  100. /* 测试函数:ScrewToAxisTest */
  101. TEST(MRTest, ScrewToAxisTest) {
  102.   Eigen::Vector3d q, s; // 定义3维向量q和s
  103.   q << 3, 0, 1; // 填充向量q的元素
  104.   s << 0, 0, 1; // 填充向量s的元素
  105.   double h = 2; // 定义螺距
  106.   Eigen::VectorXd axis = mr::ScrewToAxis(q, s, h); // 计算螺旋轴
  107.   Eigen::VectorXd result(6); // 定义6维向量,用于存储预期结果
  108.   result << 0, 0, 1, 0, -3, 2; // 填充向量元素
  109.   ASSERT_TRUE(axis.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  110. }
  111. /* 测试函数:FKInBodyTest */
  112. TEST(MRTest, FKInBodyTest) {
  113.   Eigen::MatrixXd M(4, 4); // 定义4x4矩阵,用于存储初始变换矩阵
  114.   M << -1, 0, 0, 0, // 填充矩阵元素
  115.     0, 1, 0, 6,
  116.     0, 0, -1, 2,
  117.     0, 0, 0, 1;
  118.   Eigen::MatrixXd Blist(6, 3); // 定义6x3矩阵,用于存储螺旋轴列表
  119.   Blist << 0, 0, 0, // 填充矩阵元素
  120.     0, 0, 0,
  121.     -1, 0, 1,
  122.     2, 0, 0,
  123.     0, 1, 0,
  124.     0, 0, 0.1;
  125.   Eigen::VectorXd thetaList(3); // 定义3维向量,用于存储关节角度
  126.   thetaList << M_PI / 2.0, 3, M_PI; // 填充向量元素
  127.   Eigen::MatrixXd result(4, 4); // 定义4x4矩阵,用于存储预期结果
  128.   result << 0, 1, 0, -5, // 填充矩阵元素
  129.     1, 0, 0, 4,
  130.     0, 0, -1, 1.68584073,
  131.     0, 0, 0, 1;
  132.   Eigen::MatrixXd FKCal = mr::FKinBody(M, Blist, thetaList); // 计算正向运动学
  133.   ASSERT_TRUE(FKCal.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  134. }
  135. /* 测试函数:FKInSpaceTest */
  136. TEST(MRTest, FKInSpaceTest) {
  137.   Eigen::MatrixXd M(4, 4); // 定义4x4矩阵,用于存储初始变换矩阵
  138.   M << -1, 0, 0, 0, // 填充矩阵元素
  139.     0, 1, 0, 6,
  140.     0, 0, -1, 2,
  141.     0, 0, 0, 1;
  142.   Eigen::MatrixXd Slist(6, 3); // 定义6x3矩阵,用于存储螺旋轴列表
  143.   Slist << 0, 0, 0, // 填充矩阵元素
  144.     0, 0, 0,
  145.     1, 0, -1,
  146.     4, 0, -6,
  147.     0, 1, 0,
  148.     0, 0, -0.1;
  149.   Eigen::VectorXd thetaList(3); // 定义3维向量,用于存储关节角度
  150.   thetaList << M_PI / 2.0, 3, M_PI; // 填充向量元素
  151.   Eigen::MatrixXd result(4, 4); // 定义4x4矩阵,用于存储预期结果
  152.   result << 0, 1, 0, -5, // 填充矩阵元素
  153.     1, 0, 0, 4,
  154.     0, 0, -1, 1.68584073,
  155.     0, 0, 0, 1;
  156.   Eigen::MatrixXd FKCal = mr::FKinBody(M, Slist, thetaList); // 计算正向运动学
  157.   ASSERT_TRUE(FKCal.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  158. }
  159. /* 测试函数:AxisAng6Test */
  160. TEST(MRTest, AxisAng6Test) {
  161.   Eigen::VectorXd input(6); // 定义6维向量,用于存储输入数据
  162.   Eigen::VectorXd result(7); // 定义7维向量,用于存储预期结果
  163.   input << 1.0, 0.0, 0.0, 1.0, 2.0, 3.0; // 填充输入向量元素
  164.   result << 1.0, 0.0, 0.0, 1.0, 2.0, 3.0, 1.0; // 填充预期结果向量元素
  165.   Eigen::VectorXd output = mr::AxisAng6(input); // 计算轴角表示
  166.   ASSERT_TRUE(output.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  167. }
  168. /* 测试函数:MatrixLog6Test */
  169. TEST(MRTest, MatrixLog6Test) {
  170.   Eigen::MatrixXd Tinput(4, 4); // 定义4x4矩阵,用于存储输入变换矩阵
  171.   Eigen::MatrixXd result(4, 4); // 定义4x4矩阵,用于存储预期结果
  172.   Tinput << 1, 0, 0, 0, // 填充矩阵元素
  173.     0, 0, -1, 0,
  174.     0, 1, 0, 3,
  175.     0, 0, 0, 1;
  176.   result << 0, 0, 0, 0, // 填充矩阵元素
  177.     0, 0, -1.57079633, 2.35619449,
  178.     0, 1.57079633, 0, 2.35619449,
  179.     0, 0, 0, 0;
  180.   Eigen::MatrixXd Toutput = mr::MatrixLog6(Tinput); // 计算变换矩阵的对数
  181.   ASSERT_TRUE(Toutput.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  182. }
  183. /* 测试函数:DistanceToSO3Test */
  184. TEST(MRTest, DistanceToSO3Test) {
  185.   Eigen::Matrix3d input; // 定义3x3矩阵,用于存储输入数据
  186.   double result = 0.088353; // 定义预期结果
  187.   input << 1.0, 0.0, 0.0, // 填充矩阵元素
  188.     0.0, 0.1, -0.95,
  189.     0.0, 1.0, 0.1;
  190.   EXPECT_NEAR(result, mr::DistanceToSO3(input), 3); // 断言计算结果与预期结果近似相等
  191. }
  192. /* 测试函数:DistanceToSE3Test */
  193. TEST(MRTest, DistanceToSE3Test) {
  194.   Eigen::Matrix4d input; // 定义4x4矩阵,用于存储输入数据
  195.   double result = 0.134931; // 定义预期结果
  196.   input << 1.0, 0.0, 0.0, 1.2, // 填充矩阵元素
  197.     0.0, 0.1, -0.95, 1.5,
  198.     0.0, 1.0, 0.1, -0.9,
  199.     0.0, 0.0, 0.1, 0.98;
  200.   EXPECT_NEAR(result, mr::DistanceToSE3(input), 3); // 断言计算结果与预期结果近似相等
  201. }
  202. /* 测试函数:TestIfSO3Test */
  203. TEST(MRTest, TestIfSO3Test) {
  204.   Eigen::Matrix3d input; // 定义3x3矩阵,用于存储输入数据
  205.   bool result = false; // 定义预期结果
  206.   input << 1.0, 0.0, 0.0, // 填充矩阵元素
  207.     0.0, 0.1, -0.95,
  208.     0.0, 1.0, 0.1;
  209.   ASSERT_EQ(result, mr::TestIfSO3(input)); // 断言计算结果与预期结果相等
  210. }
  211. /* 测试函数:TestIfSE3Test */
  212. TEST(MRTest, TestIfSE3Test) {
  213.   Eigen::Matrix4d input; // 定义4x4矩阵,用于存储输入数据
  214.   bool result = false; // 定义预期结果
  215.   input << 1.0, 0.0, 0.0, 1.2, // 填充矩阵元素
  216.     0.0, 0.1, -0.95, 1.5,
  217.     0.0, 1.0, 0.1, -0.9,
  218.     0.0, 0.0, 0.1, 0.98;
  219.   ASSERT_EQ(result, mr::TestIfSE3(input)); // 断言计算结果与预期结果相等
  220. }
  221. /* 测试函数:IKinBodyTest */
  222. TEST(MRTest, IKinBodyTest) {
  223.   Eigen::MatrixXd BlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  224.   BlistT << 0, 0, -1, 2, 0, 0, // 填充矩阵元素
  225.     0, 0, 0, 0, 1, 0,
  226.     0, 0, 1, 0, 0, 0.1;
  227.   Eigen::MatrixXd Blist = BlistT.transpose(); // 转置矩阵
  228.   Eigen::Matrix4d M; // 定义4x4矩阵,用于存储初始变换矩阵
  229.   M << -1, 0, 0, 0, // 填充矩阵元素
  230.     0, 1, 0, 6,
  231.     0, 0, -1, 2,
  232.     0, 0, 0, 1;
  233.   Eigen::Matrix4d T; // 定义4x4矩阵,用于存储目标变换矩阵
  234.   T << 0, 1, 0, -5, // 填充矩阵元素
  235.     1, 0, 0, 4,
  236.     0, 0, -1, 1.6858,
  237.     0, 0, 0, 1;
  238.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  239.   thetalist << 1.5, 2.5, 3; // 填充向量元素
  240.   double eomg = 0.01; // 定义角速度误差阈值
  241.   double ev = 0.001; // 定义线速度误差阈值
  242.   bool b_result = true; // 定义预期结果
  243.   Eigen::VectorXd theta_result(3); // 定义3维向量,用于存储预期关节角度
  244.   theta_result << 1.57073819, 2.999667, 3.14153913; // 填充向量元素
  245.   bool iRet = mr::IKinBody(Blist, M, T, thetalist, eomg, ev); // 调用IKinBody函数
  246.   ASSERT_EQ(b_result, iRet); // 断言计算结果与预期结果相等
  247.   ASSERT_TRUE(thetalist.isApprox(theta_result, 4)); // 断言计算关节角度与预期结果近似相等
  248. }
  249. /* 测试函数:IKinSpaceTest */
  250. TEST(MRTest, IKinSpaceTest) {
  251.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  252.   SlistT << 0, 0, 1, 4, 0, 0, // 填充矩阵元素
  253.     0, 0, 0, 0, 1, 0,
  254.     0, 0, -1, -6, 0, -0.1;
  255.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  256.   Eigen::Matrix4d M; // 定义4x4矩阵,用于存储初始变换矩阵
  257.   M << -1, 0, 0, 0, // 填充矩阵元素
  258.     0, 1, 0, 6,
  259.     0, 0, -1, 2,
  260.     0, 0, 0, 1;
  261.   Eigen::Matrix4d T; // 定义4x4矩阵,用于存储目标变换矩阵
  262.   T << 0, 1, 0, -5, // 填充矩阵元素
  263.     1, 0, 0, 4,
  264.     0, 0, -1, 1.6858,
  265.     0, 0, 0, 1;
  266.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  267.   thetalist << 1.5, 2.5, 3; // 填充向量元素
  268.   double eomg = 0.01; // 定义角速度误差阈值
  269.   double ev = 0.001; // 定义线速度误差阈值
  270.   bool b_result = true; // 定义预期结果
  271.   Eigen::VectorXd theta_result(3); // 定义3维向量,用于存储预期关节角度
  272.   theta_result << 1.57073783, 2.99966384, 3.1415342; // 填充向量元素
  273.   bool iRet = mr::IKinSpace(Slist, M, T, thetalist, eomg, ev); // 调用IKinSpace函数
  274.   ASSERT_EQ(b_result, iRet); // 断言计算结果与预期结果相等
  275.   ASSERT_TRUE(thetalist.isApprox(theta_result, 4)); // 断言计算关节角度与预期结果近似相等
  276. }
  277. /* 测试函数:AdjointTest */
  278. TEST(MRTest, AdjointTest) {
  279.   Eigen::Matrix4d T; // 定义4x4矩阵,用于存储变换矩阵
  280.   T << 1, 0, 0, 0, // 填充矩阵元素
  281.     0, 0, -1, 0,
  282.     0, 1, 0, 3,
  283.     0, 0, 0, 1;
  284.   Eigen::MatrixXd result(6, 6); // 定义6x6矩阵,用于存储预期结果
  285.   result <<
  286.     1, 0, 0, 0, 0, 0, // 填充矩阵元素
  287.     0, 0, -1, 0, 0, 0,
  288.     0, 1, 0, 0, 0, 0,
  289.     0, 0, 3, 1, 0, 0,
  290.     3, 0, 0, 0, 0, -1,
  291.     0, 0, 0, 0, 1, 0;
  292.   ASSERT_TRUE(mr::Adjoint(T).isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  293. }
  294. /* 测试函数:InverseDynamicsTest */
  295. TEST(MRTest, InverseDynamicsTest) {
  296.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  297.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  298.   Eigen::VectorXd dthetalist(3); // 定义3维向量,用于存储关节速度
  299.   dthetalist << 0.1, 0.2, 0.3; // 填充向量元素
  300.   Eigen::VectorXd ddthetalist(3); // 定义3维向量,用于存储关节加速度
  301.   ddthetalist << 2, 1.5, 1; // 填充向量元素
  302.   Eigen::VectorXd g(3); // 定义3维向量,用于存储重力向量
  303.   g << 0, 0, -9.8; // 填充向量元素
  304.   Eigen::VectorXd Ftip(6); // 定义6维向量,用于存储末端执行器力
  305.   Ftip << 1, 1, 1, 1, 1, 1; // 填充向量元素
  306.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  307.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  308.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  309.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  310.     0, 1, 0, 0,
  311.     0, 0, 1, 0.089159,
  312.     0, 0, 0, 1;
  313.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  314.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  315.     0, 1, 0, 0.13585,
  316.     -1, 0, 0, 0,
  317.     0, 0, 0, 1;
  318.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  319.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  320.     0, 1, 0, -0.1197,
  321.     0, 0, 1, 0.395, // 填充矩阵元素
  322.     0, 0, 0, 1;
  323.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  324.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  325.     0, 1, 0, 0,
  326.     0, 0, 1, 0.14225,
  327.     0, 0, 0, 1;
  328.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  329.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  330.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  331.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  332.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  333.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  334.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  335.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  336.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  337.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  338.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  339.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  340.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  341.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  342.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  343.     0, 1, 0, -0.089, 0, 0,
  344.     0, 1, 0, -0.089, 0, 0.425;
  345.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  346.   Eigen::VectorXd taulist = mr::InverseDynamics(thetalist, dthetalist, ddthetalist, g,
  347.     Ftip, Mlist, Glist, Slist); // 调用InverseDynamics函数计算关节力矩
  348.   Eigen::VectorXd result(3); // 定义3维向量,用于存储预期结果
  349.   result << 74.6962, -33.0677, -3.23057; // 填充向量元素
  350.   ASSERT_TRUE(taulist.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  351. }
  352. /* 测试函数:GravityForcesTest */
  353. TEST(MRTest, GravityForcesTest) {
  354.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  355.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  356.   Eigen::VectorXd g(3); // 定义3维向量,用于存储重力向量
  357.   g << 0, 0, -9.8; // 填充向量元素
  358.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  359.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  360.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  361.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  362.     0, 1, 0, 0,
  363.     0, 0, 1, 0.089159,
  364.     0, 0, 0, 1;
  365.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  366.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  367.     0, 1, 0, 0.13585,
  368.     -1, 0, 0, 0,
  369.     0, 0, 0, 1;
  370.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  371.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  372.     0, 1, 0, -0.1197,
  373.     0, 0, 1, 0.395,
  374.     0, 0, 0, 1;
  375.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  376.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  377.     0, 1, 0, 0,
  378.     0, 0, 1, 0.14225,
  379.     0, 0, 0, 1;
  380.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  381.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  382.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  383.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  384.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  385.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  386.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  387.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  388.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  389.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  390.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  391.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  392.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  393.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  394.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  395.     0, 1, 0, -0.089, 0, 0,
  396.     0, 1, 0, -0.089, 0, 0.425;
  397.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  398.   Eigen::VectorXd grav = mr::GravityForces(thetalist, g, Mlist, Glist, Slist); // 调用GravityForces函数计算重力影响
  399.   Eigen::VectorXd result(3); // 定义3维向量,用于存储预期结果
  400.   result << 28.4033, -37.6409, -5.4416; // 填充向量元素
  401.   ASSERT_TRUE(grav.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  402. }
  403. /* 测试函数:MassMatrixTest */
  404. TEST(MRTest, MassMatrixTest) {
  405.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  406.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  407.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  408.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  409.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  410.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  411.     0, 1, 0, 0,
  412.     0, 0, 1, 0.089159,
  413.     0, 0, 0, 1;
  414.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  415.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  416.     0, 1, 0, 0.13585,
  417.     -1, 0, 0, 0,
  418.     0, 0, 0, 1;
  419.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  420.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  421.     0, 1, 0, -0.1197,
  422.     0, 0, 1, 0.395,
  423.     0, 0, 0, 1;
  424.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  425.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  426.     0, 1, 0, 0,
  427.     0, 0, 1, 0.14225,
  428.     0, 0, 0, 1;
  429.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  430.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  431.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  432.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  433.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  434.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  435.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  436.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  437.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  438.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  439.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  440.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  441.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  442.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  443.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  444.     0, 1, 0, -0.089, 0, 0,
  445.     0, 1, 0, -0.089, 0, 0.425;
  446.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  447.   Eigen::MatrixXd M = mr::MassMatrix(thetalist, Mlist, Glist, Slist); // 调用MassMatrix函数计算质量矩阵
  448.   Eigen::MatrixXd result(3, 3); // 定义3x3矩阵,用于存储预期结果
  449.   result << 22.5433, -0.3071, -0.0072, // 填充矩阵元素
  450.     -0.3071, 1.9685, 0.4322,
  451.     -0.0072, 0.4322, 0.1916;
  452.   ASSERT_TRUE(M.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  453. }
  454. /* 测试函数:VelQuadraticForcesTest */
  455. TEST(MRTest, VelQuadraticForcesTest) {
  456.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  457.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  458.   Eigen::VectorXd dthetalist(3); // 定义3维向量,用于存储关节速度
  459.   dthetalist << 0.1, 0.2, 0.3; // 填充向量元素
  460.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  461.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  462.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  463.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  464.     0, 1, 0, 0,
  465.     0, 0, 1, 0.089159,
  466.     0, 0, 0, 1;
  467.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  468.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  469.     0, 1, 0, 0.13585,
  470.     -1, 0, 0, 0,
  471.     0, 0, 0, 1;
  472.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  473.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  474.     0, 1, 0, -0.1197,
  475.     0, 0, 1, 0.395,
  476.     0, 0, 0, 1;
  477.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  478.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  479.     0, 1, 0, 0,
  480.     0, 0, 1, 0.14225,
  481.     0, 0, 0, 1;
  482.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  483.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  484.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  485.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  486.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  487.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  488.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  489.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  490.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  491.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  492.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  493.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  494.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  495.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  496.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  497.     0, 1, 0, -0.089, 0, 0,
  498.     0, 1, 0, -0.089, 0, 0.425;
  499.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  500.   Eigen::VectorXd c = mr::VelQuadraticForces(thetalist, dthetalist, Mlist, Glist, Slist); // 调用VelQuadraticForces函数计算速度二次项力
  501.   Eigen::VectorXd result(3); // 定义3维向量,用于存储预期结果
  502.   result << 0.2645, -0.0551, -0.0069; // 填充向量元素
  503.   ASSERT_TRUE(c.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  504. }
  505. /* 测试函数:EndEffectorForcesTest */
  506. TEST(MRTest, EndEffectorForcesTest) {
  507.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  508.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  509.   Eigen::VectorXd Ftip(6); // 定义6维向量,用于存储末端执行器力
  510.   Ftip << 1, 1, 1, 1, 1, 1; // 填充向量元素
  511.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  512.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  513.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  514.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  515.     0, 1, 0, 0,
  516.     0, 0, 1, 0.089159,
  517.     0, 0, 0, 1;
  518.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  519.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  520.     0, 1, 0, 0.13585,
  521.     -1, 0, 0, 0,
  522.     0, 0, 0, 1;
  523.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  524.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  525.     0, 1, 0, -0.1197,
  526.     0, 0, 1, 0.395,
  527.     0, 0, 0, 1;
  528.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  529.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  530.     0, 1, 0, 0,
  531.     0, 0, 1, 0.14225,
  532.     0, 0, 0, 1;
  533.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  534.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  535.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  536.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  537.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  538.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  539.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  540.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  541.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  542.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  543.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  544.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  545.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  546.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  547.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  548.     0, 1, 0, -0.089, 0, 0,
  549.     0, 1, 0, -0.089, 0, 0.425;
  550.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  551.   Eigen::VectorXd JTFtip = mr::EndEffectorForces(thetalist, Ftip, Mlist, Glist, Slist); // 调用EndEffectorForces函数计算末端执行器力
  552.   Eigen::VectorXd result(3); // 定义3维向量,用于存储预期结果
  553.   result << 1.4095, 1.8577, 1.3924; // 填充向量元素
  554.   ASSERT_TRUE(JTFtip.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  555. }
  556. /* 测试函数:ForwardDynamicsTest */
  557. TEST(MRTest, ForwardDynamicsTest) {
  558.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  559.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  560.   Eigen::VectorXd dthetalist(3); // 定义3维向量,用于存储关节速度
  561.   dthetalist << 0.1, 0.2, 0.3; // 填充向量元素
  562.   Eigen::VectorXd taulist(3); // 定义3维向量,用于存储关节力矩
  563.   taulist << 0.5, 0.6, 0.7; // 填充向量元素
  564.   Eigen::VectorXd g(3); // 定义3维向量,用于存储重力向量
  565.   g << 0, 0, -9.8; // 填充向量元素
  566.   Eigen::VectorXd Ftip(6); // 定义6维向量,用于存储末端执行器力
  567.   Ftip << 1, 1, 1, 1, 1, 1; // 填充向量元素
  568.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  569.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  570.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  571.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  572.     0, 1, 0, 0,
  573.     0, 0, 1, 0.089159,
  574.     0, 0, 0, 1;
  575.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  576.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  577.     0, 1, 0, 0.13585,
  578.     -1, 0, 0, 0,
  579.     0, 0, 0, 1;
  580.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  581.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  582.     0, 1, 0, -0.1197,
  583.     0, 0, 1, 0.395,
  584.     0, 0, 0, 1;
  585.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  586.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  587.     0, 1, 0, 0,
  588.     0, 0, 1, 0.14225,
  589.     0, 0, 0, 1;
  590.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  591.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  592.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  593.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  594.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  595.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  596.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  597.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  598.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  599.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  600.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  601.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  602.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  603.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  604.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  605.     0, 1, 0, -0.089, 0, 0,
  606.     0, 1, 0, -0.089, 0, 0.425;
  607.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  608.   Eigen::VectorXd ddthetalist = mr::ForwardDynamics(thetalist, dthetalist, taulist, g,
  609.     Ftip, Mlist, Glist, Slist); // 调用ForwardDynamics函数计算关节加速度
  610.   Eigen::VectorXd result(3); // 定义3维向量,用于存储预期结果
  611.   result << -0.9739, 25.5847, -32.9150; // 填充向量元素
  612.   ASSERT_TRUE(ddthetalist.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  613. }
  614. /* 测试函数:EulerStepTest */
  615. TEST(MRTest, EulerStepTest) {
  616.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  617.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  618.   Eigen::VectorXd dthetalist(3); // 定义3维向量,用于存储关节速度
  619.   dthetalist << 0.1, 0.2, 0.3; // 填充向量元素
  620.   Eigen::VectorXd ddthetalist(3); // 定义3维向量,用于存储关节加速度
  621.   ddthetalist << 2, 1.5, 1; // 填充向量元素
  622.   double dt = 0.1; // 定义时间步长
  623.   mr::EulerStep(thetalist, dthetalist, ddthetalist, dt); // 调用EulerStep函数更新关节角度和速度
  624.   Eigen::VectorXd result_thetalistNext(3); // 定义3维向量,用于存储预期的下一步关节角度
  625.   result_thetalistNext << 0.11, 0.12, 0.13; // 填充向量元素
  626.   Eigen::VectorXd result_dthetalistNext(3); // 定义3维向量,用于存储预期的下一步关节速度
  627.   result_dthetalistNext << 0.3, 0.35, 0.4; // 填充向量元素
  628.   ASSERT_TRUE(thetalist.isApprox(result_thetalistNext, 4)); // 断言计算结果与预期结果近似相等
  629.   ASSERT_TRUE(dthetalist.isApprox(result_dthetalistNext, 4)); // 断言计算结果与预期结果近似相等
  630. }
  631. /* 测试函数:ComputedTorqueTest */
  632. TEST(MRTest, ComputedTorqueTest) {
  633.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  634.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  635.   Eigen::VectorXd dthetalist(3); // 定义3维向量,用于存储关节速度
  636.   dthetalist << 0.1, 0.2, 0.3; // 填充向量元素
  637.   Eigen::VectorXd eint(3); // 定义3维向量,用于存储积分误差
  638.   eint << 0.2, 0.2, 0.2; // 填充向量元素
  639.   Eigen::VectorXd g(3); // 定义3维向量,用于存储重力向量
  640.   g << 0, 0, -9.8; // 填充向量元素
  641.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  642.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  643.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  644.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  645.     0, 1, 0, 0,
  646.     0, 0, 1, 0.089159,
  647.     0, 0, 0, 1;
  648.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  649.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  650.     0, 1, 0, 0.13585,
  651.     -1, 0, 0, 0,
  652.     0, 0, 0, 1;
  653.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  654.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  655.     0, 1, 0, -0.1197,
  656.     0, 0, 1, 0.395,
  657.     0, 0, 0, 1;
  658.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  659.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  660.     0, 1, 0, 0,
  661.     0, 0, 1, 0.14225,
  662.     0, 0, 0, 1;
  663.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  664.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  665.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  666.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  667.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  668.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  669.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  670.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  671.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  672.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  673.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  674.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  675.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  676.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  677.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  678.     0, 1, 0, -0.089, 0, 0,
  679.     0, 1, 0, -0.089, 0, 0.425;
  680.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  681.   Eigen::VectorXd thetalistd(3); // 定义3维向量,用于存储期望关节角度
  682.   thetalistd << 1.0, 1.0, 1.0; // 填充向量元素
  683.   Eigen::VectorXd dthetalistd(3); // 定义3维向量,用于存储期望关节速度
  684.   dthetalistd << 2, 1.2, 2; // 填充向量元素
  685.   Eigen::VectorXd ddthetalistd(3); // 定义3维向量,用于存储期望关节加速度
  686.   ddthetalistd << 0.1, 0.1, 0.1; // 填充向量元素
  687.   double Kp = 1.3; // 定义比例增益
  688.   double Ki = 1.2; // 定义积分增益
  689.   double Kd = 1.1; // 定义微分增益
  690.   Eigen::VectorXd taulist = mr::ComputedTorque(thetalist, dthetalist, eint, g,
  691.     Mlist, Glist, Slist, thetalistd, dthetalistd, ddthetalistd, Kp, Ki, Kd); // 调用ComputedTorque函数计算关节力矩
  692.   Eigen::VectorXd result(3); // 定义3维向量,用于存储预期结果
  693.   result << 133.00525246, -29.94223324, -3.03276856; // 填充向量元素
  694.   ASSERT_TRUE(taulist.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  695. }
  696. /* 测试函数:CubicTimeScalingTest */
  697. TEST(MRTest, CubicTimeScalingTest) {
  698.   double Tf = 2.0; // 定义总时间
  699.   double t = 0.6; // 定义当前时间
  700.   double result = 0.216; // 定义预期结果
  701.   EXPECT_NEAR(result, mr::CubicTimeScaling(Tf, t), 3); // 断言计算结果与预期结果近似相等
  702. }
  703. /* 测试函数:QuinticTimeScalingTest */
  704. TEST(MRTest, QuinticTimeScalingTest) {
  705.   double Tf = 2.0; // 定义总时间
  706.   double t = 0.6; // 定义当前时间
  707.   double result = 0.16308; // 定义预期结果
  708.   EXPECT_NEAR(result, mr::QuinticTimeScaling(Tf, t), 3); // 断言计算结果与预期结果近似相等
  709. }
  710. /* 测试函数:JointTrajectoryTest */
  711. TEST(MRTest, JointTrajectoryTest) {
  712.   int dof = 8; // 定义自由度数量
  713.   Eigen::VectorXd thetastart(dof); // 定义向量,用于存储初始关节角度
  714.   thetastart << 1, 0, 0, 1, 1, 0.2, 0, 1; // 填充向量元素
  715.   Eigen::VectorXd thetaend(dof); // 定义向量,用于存储结束关节角度
  716.   thetaend << 1.2, 0.5, 0.6, 1.1, 2, 2, 0.9, 1; // 填充向量元素
  717.   double Tf = 4.0; // 定义总时间
  718.   int N = 6; // 定义轨迹点数量
  719.   int method = 3; // 定义时间缩放方法
  720.   Eigen::MatrixXd result(N, dof); // 定义矩阵,用于存储预期结果
  721.   result << 1, 0, 0, 1, 1, 0.2, 0, 1, // 填充矩阵元素
  722.     1.0208, 0.052, 0.0624, 1.0104, 1.104, 0.3872, 0.0936, 1,
  723.     1.0704, 0.176, 0.2112, 1.0352, 1.352, 0.8336, 0.3168, 1,
  724.     1.1296, 0.324, 0.3888, 1.0648, 1.648, 1.3664, 0.5832, 1,
  725.     1.1792, 0.448, 0.5376, 1.0896, 1.896, 1.8128, 0.8064, 1,
  726.     1.2, 0.5, 0.6, 1.1, 2, 2, 0.9, 1;
  727.   Eigen::MatrixXd traj = mr::JointTrajectory(thetastart, thetaend, Tf, N, method); // 调用JointTrajectory函数计算关节轨迹
  728.   ASSERT_TRUE(traj.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  729. }
  730. /* 测试函数:ScrewTrajectoryTest */
  731. TEST(MRTest, ScrewTrajectoryTest) {
  732.   Eigen::MatrixXd Xstart(4, 4); // 定义4x4矩阵,用于存储初始变换矩阵
  733.   Xstart << 1, 0, 0, 1, // 填充矩阵元素
  734.     0, 1, 0, 0,
  735.     0, 0, 1, 1,
  736.     0, 0, 0, 1;
  737.   Eigen::MatrixXd Xend(4, 4); // 定义4x4矩阵,用于存储结束变换矩阵
  738.   Xend << 0, 0, 1, 0.1, // 填充矩阵元素
  739.     1, 0, 0, 0,
  740.     0, 1, 0, 4.1,
  741.     0, 0, 0, 1;
  742.   double Tf = 5.0; // 定义总时间
  743.   int N = 4; // 定义轨迹点数量
  744.   int method = 3; // 定义时间缩放方法
  745.   std::vector<Eigen::MatrixXd> result(N); // 定义向量,用于存储预期结果
  746.   result[0] = Xstart; // 设置初始变换矩阵
  747.   Eigen::Matrix4d X12; // 定义4x4矩阵,用于存储中间变换矩阵
  748.   X12 << 0.904, -0.25, 0.346, 0.441, // 填充矩阵元素
  749.     0.346, 0.904, -0.25, 0.529,
  750.     -0.25, 0.346, 0.904, 1.601,
  751.     0, 0, 0, 1;
  752.   Eigen::Matrix4d X23; // 定义4x4矩阵,用于存储中间变换矩阵
  753.   X23 << 0.346, -0.25, 0.904, -0.117, // 填充矩阵元素
  754.     0.904, 0.346, -0.25, 0.473,
  755.     -0.25, 0.904, 0.346, 3.274,
  756.     0, 0, 0, 1;
  757.   result[1] = X12; // 设置中间变换矩阵
  758.   result[2] = X23; // 设置中间变换矩阵
  759.   result[3] = Xend; // 设置结束变换矩阵
  760.   std::vector<Eigen::MatrixXd> traj = mr::ScrewTrajectory(Xstart, Xend, Tf, N, method); // 调用ScrewTrajectory函数计算螺旋轨迹
  761.   for (int i = 0; i < N; ++i) { // 遍历每个轨迹点
  762.     ASSERT_TRUE(traj[i].isApprox(result[i], 4)); // 断言计算结果与预期结果近似相等
  763.   }
  764. }
  765. /* 测试函数:CartesianTrajectoryTest */
  766. TEST(MRTest, CartesianTrajectoryTest) {
  767.   Eigen::MatrixXd Xstart(4, 4); // 定义4x4矩阵,用于存储初始变换矩阵
  768.   Xstart << 1, 0, 0, 1, // 填充矩阵元素
  769.     0, 1, 0, 0,
  770.     0, 0, 1, 1,
  771.     0, 0, 0, 1;
  772.   Eigen::MatrixXd Xend(4, 4); // 定义4x4矩阵,用于存储结束变换矩阵
  773.   Xend << 0, 0, 1, 0.1, // 填充矩阵元素
  774.     1, 0, 0, 0,
  775.     0, 1, 0, 4.1,
  776.     0, 0, 0, 1;
  777.   double Tf = 5.0; // 定义总时间
  778.   int N = 4; // 定义轨迹点数量
  779.   int method = 5; // 定义时间缩放方法
  780.   std::vector<Eigen::MatrixXd> result(N); // 定义向量,用于存储预期结果
  781.   result[0] = Xstart; // 设置初始变换矩阵
  782.   Eigen::Matrix4d X12; // 定义4x4矩阵,用于存储中间变换矩阵
  783.   X12 << 0.937, -0.214, 0.277, 0.811, // 填充矩阵元素
  784.     0.277, 0.937, -0.214, 0,
  785.     -0.214, 0.277, 0.937, 1.651,
  786.     0, 0, 0, 1;
  787.   Eigen::Matrix4d X23; // 定义4x4矩阵,用于存储中间变换矩阵
  788.   X23 << 0.277, -0.214, 0.937, 0.289, // 填充矩阵元素
  789.     0.937, 0.277, -0.214, 0,
  790.     -0.214, 0.937, 0.277, 3.449,
  791.     0, 0, 0, 1;
  792.   result[1] = X12; // 设置中间变换矩阵
  793.   result[2] = X23; // 设置中间变换矩阵
  794.   result[3] = Xend; // 设置结束变换矩阵
  795.   std::vector<Eigen::MatrixXd> traj = mr::CartesianTrajectory(Xstart, Xend, Tf, N, method); // 调用CartesianTrajectory函数计算笛卡尔轨迹
  796.   for (int i = 0; i < N; ++i) { // 遍历每个轨迹点
  797.     ASSERT_TRUE(traj[i].isApprox(result[i], 4)); // 断言计算结果与预期结果近似相等
  798.   }
  799. }
  800. /* 测试函数:InverseDynamicsTrajectoryTest */
  801. TEST(MRTest, InverseDynamicsTrajectoryTest) {
  802.   int dof = 3; // 定义自由度数量
  803.   Eigen::VectorXd thetastart(dof); // 定义向量,用于存储初始关节角度
  804.   thetastart << 0, 0, 0; // 填充向量元素
  805.   Eigen::VectorXd thetaend(dof); // 定义向量,用于存储结束关节角度
  806.   thetaend << M_PI / 2, M_PI / 2, M_PI / 2; // 填充向量元素
  807.   double Tf = 3.0; // 定义总时间
  808.   int N = 1000; // 定义轨迹点数量
  809.   int method = 5; // 定义时间缩放方法
  810.   Eigen::MatrixXd traj = mr::JointTrajectory(thetastart, thetaend, Tf, N, method); // 计算关节轨迹
  811.   Eigen::MatrixXd thetamat = traj; // 关节角度矩阵
  812.   Eigen::MatrixXd dthetamat = Eigen::MatrixXd::Zero(N, dof); // 初始化关节速度矩阵
  813.   Eigen::MatrixXd ddthetamat = Eigen::MatrixXd::Zero(N, dof); // 初始化关节加速度矩阵
  814.   double dt = Tf / (N - 1.0); // 计算时间步长
  815.   for (int i = 0; i < N - 1; ++i) { // 遍历每个时间步
  816.     dthetamat.row(i + 1) = (thetamat.row(i + 1) - thetamat.row(i)) / dt; // 计算关节速度
  817.     ddthetamat.row(i + 1) = (dthetamat.row(i + 1) - dthetamat.row(i)) / dt; // 计算关节加速度
  818.   }
  819.   Eigen::VectorXd g(3); // 定义向量,用于存储重力向量
  820.   g << 0, 0, -9.8; // 填充向量元素
  821.   Eigen::MatrixXd Ftipmat = Eigen::MatrixXd::Zero(N, 6); // 初始化末端执行器力矩阵
  822.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  823.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  824.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  825.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  826.     0, 1, 0, 0,
  827.     0, 0, 1, 0.089159,
  828.     0, 0, 0, 1;
  829.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  830.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  831.     0, 1, 0, 0.13585,
  832.     -1, 0, 0, 0,
  833.     0, 0, 0, 1;
  834.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  835.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  836.     0, 1, 0, -0.1197,
  837.     0, 0, 1, 0.395,
  838.     0, 0, 0, 1;
  839.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  840.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  841.     0, 1, 0, 0,
  842.     0, 0, 1, 0.14225,
  843.     0, 0, 0, 1;
  844.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  845.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  846.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  847.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  848.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  849.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  850.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  851.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  852.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  853.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  854.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  855.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  856.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  857.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  858.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  859.     0, 1, 0, -0.089, 0, 0,
  860.     0, 1, 0, -0.089, 0, 0.425;
  861.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  862.   int numTest = 3; // 定义测试点数量
  863.   Eigen::MatrixXd result(numTest, dof); // 定义矩阵,用于存储预期结果
  864.   Eigen::VectorXd tau_timestep_beg(3); // 定义向量,用于存储起始时间步的关节力矩
  865.   tau_timestep_beg << 13.22970794, -36.262108, -4.181341; // 填充向量元素
  866.   Eigen::VectorXd tau_timestep_mid(3); // 定义向量,用于存储中间时间步的关节力矩
  867.   tau_timestep_mid << 115.55863434, -22.05129215, 1.00916115; // 填充向量元素
  868.   Eigen::VectorXd tau_timestep_end(3); // 定义向量,用于存储结束时间步的关节力矩
  869.   tau_timestep_end << 81.12700926, -23.20753925, 2.48432708; // 填充向量元素
  870.   result << tau_timestep_beg.transpose(), // 填充矩阵元素
  871.     tau_timestep_mid.transpose(),
  872.     tau_timestep_end.transpose();
  873.   Eigen::MatrixXd taumat = mr::InverseDynamicsTrajectory(thetamat, dthetamat, ddthetamat, g, Ftipmat, Mlist, Glist, Slist); // 调用InverseDynamicsTrajectory函数计算关节力矩轨迹
  874.   Eigen::MatrixXd taumat_timestep(numTest, dof); // 定义矩阵,用于存储测试点的关节力矩
  875.   taumat_timestep << taumat.row(0), // 填充矩阵元素
  876.     taumat.row(int(N / 2) - 1),
  877.     taumat.row(N - 1);
  878.   ASSERT_TRUE(taumat_timestep.isApprox(result, 4)); // 断言计算结果与预期结果近似相等
  879. }
  880. /* 测试函数:ForwardDynamicsTrajectoryTest */
  881. TEST(MRTest, ForwardDynamicsTrajectoryTest) {
  882.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  883.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  884.   Eigen::VectorXd dthetalist(3); // 定义3维向量,用于存储关节速度
  885.   dthetalist << 0.1, 0.2, 0.3; // 填充向量元素
  886.   int N = 10, dof = 3; // 定义轨迹点数量和自由度数量
  887.   Eigen::MatrixXd taumat(N, 3); // 定义矩阵,用于存储关节力矩
  888.   taumat << 3.63, -6.58, -5.57, // 填充矩阵元素
  889.     3.74, -5.55, -5.5,
  890.     4.31, -0.68, -5.19,
  891.     5.18, 5.63, -4.31,
  892.     5.85, 8.17, -2.59,
  893.     5.78, 2.79, -1.7,
  894.     4.99, -5.3, -1.19,
  895.     4.08, -9.41, 0.07,
  896.     3.56, -10.1, 0.97,
  897.     3.49, -9.41, 1.23;
  898.   Eigen::VectorXd g(3); // 定义向量,用于存储重力向量
  899.   g << 0, 0, -9.8; // 填充向量元素
  900.   Eigen::MatrixXd Ftipmat = Eigen::MatrixXd::Zero(N, 6); // 初始化末端执行器力矩阵
  901.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  902.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  903.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  904.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  905.     0, 1, 0, 0,
  906.     0, 0, 1, 0.089159,
  907.     0, 0, 0, 1;
  908.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  909.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  910.     0, 1, 0, 0.13585,
  911.     -1, 0, 0, 0,
  912.     0, 0, 0, 1;
  913.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  914.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  915.     0, 1, 0, -0.1197,
  916.     0, 0, 1, 0.395,
  917.     0, 0, 0, 1;
  918.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  919.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  920.     0, 1, 0, 0,
  921.     0, 0, 1, 0.14225,
  922.     0, 0, 0, 1;
  923.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  924.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  925.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  926.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  927.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  928.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  929.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  930.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  931.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  932.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  933.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  934.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  935.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  936.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  937.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  938.     0, 1, 0, -0.089, 0, 0,
  939.     0, 1, 0, -0.089, 0, 0.425;
  940.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  941.   double dt = 0.1; // 定义时间步长
  942.   int intRes = 8; // 定义积分分辨率
  943.   Eigen::MatrixXd result_thetamat(N, dof); // 定义矩阵,用于存储预期的关节角度轨迹
  944.   Eigen::MatrixXd result_dthetamat(N, dof); // 定义矩阵,用于存储预期的关节速度轨迹
  945.   result_thetamat << 0.1, 0.1, 0.1, // 填充矩阵元素
  946.     0.10643138, 0.2625997, -0.22664947,
  947.     0.10197954, 0.71581297, -1.22521632,
  948.     0.0801044, 1.33930884, -2.28074132,
  949.     0.0282165, 2.11957376, -3.07544297,
  950.     -0.07123855, 2.87726666, -3.83289684,
  951.     -0.20136466, 3.397858, -4.83821609,
  952.     -0.32380092, 3.73338535, -5.98695747,
  953.     -0.41523262, 3.85883317, -7.01130559,
  954.     -0.4638099, 3.63178793, -7.63190052;
  955.   result_dthetamat << 0.1, 0.2, 0.3, // 填充矩阵元素
  956.     0.01212502, 3.42975773, -7.74792602,
  957.     -0.13052771, 5.55997471, -11.22722784,
  958.     -0.35521041, 7.11775879, -9.18173035,
  959.     -0.77358795, 8.17307573, -7.05744594,
  960.     -1.2350231, 6.35907497, -8.99784746,
  961.     -1.31426299, 4.07685875, -11.18480509,
  962.     -1.06794821, 2.49227786, -11.69748583,
  963.     -0.70264871, -0.55925705, -8.16067131,
  964.     -0.1455669, -4.57149985, -3.43135114;
  965.   std::vector<Eigen::MatrixXd> traj = mr::ForwardDynamicsTrajectory(thetalist, dthetalist, taumat, g, Ftipmat, Mlist, Glist, Slist, dt, intRes); // 调用ForwardDynamicsTrajectory函数计算正向动力学轨迹
  966.   Eigen::MatrixXd traj_theta = traj.at(0); // 获取关节角度轨迹
  967.   Eigen::MatrixXd traj_dtheta = traj.at(1); // 获取关节速度轨迹
  968.   ASSERT_TRUE(traj_theta.isApprox(result_thetamat, 4)); // 断言计算结果与预期结果近似相等
  969.   ASSERT_TRUE(traj_dtheta.isApprox(result_dthetamat, 4)); // 断言计算结果与预期结果近似相等
  970. }
  971. /* 测试函数:SimulateControlTest */
  972. TEST(MRTest, SimulateControlTest) {
  973.   Eigen::VectorXd thetalist(3); // 定义3维向量,用于存储关节角度
  974.   thetalist << 0.1, 0.1, 0.1; // 填充向量元素
  975.   Eigen::VectorXd dthetalist(3); // 定义3维向量,用于存储关节速度
  976.   dthetalist << 0.1, 0.2, 0.3; // 填充向量元素
  977.   Eigen::VectorXd g(3); // 定义3维向量,用于存储重力向量
  978.   g << 0, 0, -9.8; // 填充向量元素
  979.   std::vector<Eigen::MatrixXd> Mlist; // 定义矩阵列表,用于存储变换矩阵
  980.   std::vector<Eigen::MatrixXd> Glist; // 定义矩阵列表,用于存储惯性矩阵
  981.   Eigen::Matrix4d M01; // 定义4x4矩阵,用于存储变换矩阵
  982.   M01 << 1, 0, 0, 0, // 填充矩阵元素
  983.     0, 1, 0, 0,
  984.     0, 0, 1, 0.089159,
  985.     0, 0, 0, 1;
  986.   Eigen::Matrix4d M12; // 定义4x4矩阵,用于存储变换矩阵
  987.   M12 << 0, 0, 1, 0.28, // 填充矩阵元素
  988.     0, 1, 0, 0.13585,
  989.     -1, 0, 0, 0,
  990.     0, 0, 0, 1;
  991.   Eigen::Matrix4d M23; // 定义4x4矩阵,用于存储变换矩阵
  992.   M23 << 1, 0, 0, 0, // 填充矩阵元素
  993.     0, 1, 0, -0.1197,
  994.     0, 0, 1, 0.395,
  995.     0, 0, 0, 1;
  996.   Eigen::Matrix4d M34; // 定义4x4矩阵,用于存储变换矩阵
  997.   M34 << 1, 0, 0, 0, // 填充矩阵元素
  998.     0, 1, 0, 0,
  999.     0, 0, 1, 0.14225,
  1000.     0, 0, 0, 1;
  1001.   Mlist.push_back(M01); // 将变换矩阵添加到列表中
  1002.   Mlist.push_back(M12); // 将变换矩阵添加到列表中
  1003.   Mlist.push_back(M23); // 将变换矩阵添加到列表中
  1004.   Mlist.push_back(M34); // 将变换矩阵添加到列表中
  1005.   Eigen::VectorXd G1(6); // 定义6维向量,用于存储惯性矩阵元素
  1006.   G1 << 0.010267, 0.010267, 0.00666, 3.7, 3.7, 3.7; // 填充向量元素
  1007.   Eigen::VectorXd G2(6); // 定义6维向量,用于存储惯性矩阵元素
  1008.   G2 << 0.22689, 0.22689, 0.0151074, 8.393, 8.393, 8.393; // 填充向量元素
  1009.   Eigen::VectorXd G3(6); // 定义6维向量,用于存储惯性矩阵元素
  1010.   G3 << 0.0494433, 0.0494433, 0.004095, 2.275, 2.275, 2.275; // 填充向量元素
  1011.   Glist.push_back(G1.asDiagonal()); // 将惯性矩阵添加到列表中
  1012.   Glist.push_back(G2.asDiagonal()); // 将惯性矩阵添加到列表中
  1013.   Glist.push_back(G3.asDiagonal()); // 将惯性矩阵添加到列表中
  1014.   Eigen::MatrixXd SlistT(3, 6); // 定义3x6矩阵,用于存储螺旋轴列表
  1015.   SlistT << 1, 0, 1, 0, 1, 0, // 填充矩阵元素
  1016.     0, 1, 0, -0.089, 0, 0,
  1017.     0, 1, 0, -0.089, 0, 0.425;
  1018.   Eigen::MatrixXd Slist = SlistT.transpose(); // 转置矩阵
  1019.   double dt = 0.01; // 定义时间步长
  1020.   Eigen::VectorXd thetaend(3); // 定义向量,用于存储结束关节角度
  1021.   thetaend << M_PI / 2, M_PI / 2, M_PI / 2; // 填充向量元素
  1022.   double Tf = 1.0; // 定义总时间
  1023.   int N = int(1.0 * Tf / dt); // 计算轨迹点数量
  1024.   int method = 5; // 定义时间缩放方法
  1025.   Eigen::MatrixXd traj = mr::JointTrajectory(thetalist, thetaend, Tf, N, method); // 计算关节轨迹
  1026.   Eigen::MatrixXd thetamatd = traj; // 期望关节角度矩阵
  1027.   Eigen::MatrixXd dthetamatd = Eigen::MatrixXd::Zero(N, 3); // 初始化期望关节速度矩阵
  1028.   Eigen::MatrixXd ddthetamatd = Eigen::MatrixXd::Zero(N, 3); // 初始化期望关节加速度矩阵
  1029.   dt = Tf / (N - 1.0); // 计算时间步长
  1030.   for (int i = 0; i < N - 1; ++i) { // 遍历每个时间步
  1031.     dthetamatd.row(i + 1) = (thetamatd.row(i + 1) - thetamatd.row(i)) / dt; // 计算期望关节速度
  1032.     ddthetamatd.row(i + 1) = (dthetamatd.row(i + 1) - dthetamatd.row(i)) / dt; // 计算期望关节加速度
  1033.   }
  1034.   Eigen::VectorXd gtilde(3); // 定义向量,用于存储估计的重力向量
  1035.   gtilde << 0.8, 0.2, -8.8; // 填充向量元素
  1036.   std::vector<Eigen::MatrixXd> Mtildelist; // 定义矩阵列表,用于存储估计的变换矩阵
  1037.   std::vector<Eigen::MatrixXd> Gtildelist; // 定义矩阵列表,用于存储估计的惯性矩阵
  1038.   Eigen::Matrix4d Mhat01; // 定义4x4矩阵,用于存储估计的变换矩阵
  1039.   Mhat01 << 1, 0, 0, 0, // 填充矩阵元素
  1040.     0, 1, 0, 0,
  1041.     0, 0, 1, 0.1,
  1042.     0, 0, 0, 1;
  1043.   Eigen::Matrix4d Mhat12; // 定义4x4矩阵,用于存储估计的变换矩阵
  1044.   Mhat12 << 0, 0, 1, 0.3, // 填充矩阵元素
  1045.     0, 1, 0, 0.2,
  1046.     -1, 0, 0, 0,
  1047.     0, 0, 0, 1;
  1048.   Eigen::Matrix4d Mhat23; // 定义4x4矩阵,用于存储估计的变换矩阵
  1049.   Mhat23 << 1, 0, 0, 0, // 填充矩阵元素
  1050.     0, 1, 0, -0.2,
  1051.     0, 0, 1, 0.4,
  1052.     0, 0, 0, 1;
  1053.   Eigen::Matrix4d Mhat34; // 定义4x4矩阵,用于存储估计的变换矩阵
  1054.   Mhat34 << 1, 0, 0, 0, // 填充矩阵元素
  1055.     0, 1, 0, 0,
  1056.     0, 0, 1, 0.2,
  1057.     0, 0, 0, 1;
  1058.   Mtildelist.push_back(Mhat01); // 将估计的变换矩阵添加到列表中
  1059.   Mtildelist.push_back(Mhat12); // 将估计的变换矩阵添加到列表中
  1060.   Mtildelist.push_back(Mhat23); // 将估计的变换矩阵添加到列表中
  1061.   Mtildelist.push_back(Mhat34); // 将估计的变换矩阵添加到列表中
  1062.   Eigen::VectorXd Ghat1(6); // 定义6维向量,用于存储估计的惯性矩阵元素
  1063.   Ghat1 << 0.1, 0.1, 0.1, 4, 4, 4; // 填充向量元素
  1064.   Eigen::VectorXd Ghat2(6); // 定义6维向量,用于存储估计的惯性矩阵元素
  1065.   Ghat2 << 0.3, 0.3, 0.1, 9, 9, 9; // 填充向量元素
  1066.   Eigen::VectorXd Ghat3(6); // 定义6维向量,用于存储估计的惯性矩阵元素
  1067.   Ghat3 << 0.1, 0.1, 0.1, 3, 3, 3; // 填充向量元素
  1068.   Gtildelist.push_back(Ghat1.asDiagonal()); // 将估计的惯性矩阵添加到列表中
  1069.   Gtildelist.push_back(Ghat2.asDiagonal()); // 将估计的惯性矩阵添加到列表中
  1070.   Gtildelist.push_back(Ghat3.asDiagonal()); // 将估计的惯性矩阵添加到列表中
  1071.   Eigen::MatrixXd Ftipmat = Eigen::MatrixXd::Ones(N, 6); // 初始化末端执行器力矩阵
  1072.   double Kp = 20.0; // 定义比例增益
  1073.   double Ki = 10.0; // 定义积分增益
  1074.   double Kd = 18.0; // 定义微分增益
  1075.   int intRes = 8; // 定义积分分辨率
  1076.   int numTest = 3;  // 定义测试点数量
  1077.   Eigen::MatrixXd result_taumat(numTest, 3); // 定义矩阵,用于存储预期的关节力矩
  1078.   Eigen::MatrixXd result_thetamat(numTest, 3); // 定义矩阵,用于存储预期的关节角度
  1079.   Eigen::VectorXd tau_timestep_beg(3); // 定义向量,用于存储起始时间步的关节力矩
  1080.   tau_timestep_beg << -14.2640765, -54.06797429, -11.265448; // 填充向量元素
  1081.   Eigen::VectorXd tau_timestep_mid(3); // 定义向量,用于存储中间时间步的关节力矩
  1082.   tau_timestep_mid << 31.98269367, 9.89625811, 1.47810165; // 填充向量元素
  1083.   Eigen::VectorXd tau_timestep_end(3); // 定义向量,用于存储结束时间步的关节力矩
  1084.   tau_timestep_end << 57.04391384, 4.75360586, -1.66561523; // 填充向量元素
  1085.   result_taumat << tau_timestep_beg.transpose(), // 填充矩阵元素
  1086.     tau_timestep_mid.transpose(),
  1087.     tau_timestep_end.transpose();
  1088.   Eigen::VectorXd theta_timestep_beg(3); // 定义向量,用于存储起始时间步的关节角度
  1089.   theta_timestep_beg << 0.10092029, 0.10190511, 0.10160667; // 填充向量元素
  1090.   Eigen::VectorXd theta_timestep_mid(3); // 定义向量,用于存储中间时间步的关节角度
  1091.   theta_timestep_mid << 0.85794085, 1.55124503, 2.80130978; // 填充向量元素
  1092.   Eigen::VectorXd theta_timestep_end(3); // 定义向量,用于存储结束时间步的关节角度
  1093.   theta_timestep_end << 1.56344023, 3.07994906, 4.52269971; // 填充向量元素
  1094.   result_thetamat << theta_timestep_beg.transpose(), // 填充矩阵元素
  1095.     theta_timestep_mid.transpose(),
  1096.     theta_timestep_end.transpose();
  1097.   std::vector<Eigen::MatrixXd> controlTraj = mr::SimulateControl(thetalist, dthetalist, g, Ftipmat, Mlist, Glist, Slist, thetamatd, dthetamatd,
  1098.     ddthetamatd, gtilde, Mtildelist, Gtildelist, Kp, Ki, Kd, dt, intRes); // 调用SimulateControl函数模拟控制
  1099.   Eigen::MatrixXd traj_tau = controlTraj.at(0); // 获取关节力矩轨迹
  1100.   Eigen::MatrixXd traj_theta = controlTraj.at(1); // 获取关节角度轨迹
  1101.   Eigen::MatrixXd traj_tau_timestep(numTest, 3); // 定义矩阵,用于存储测试点的关节力矩
  1102.   traj_tau_timestep << traj_tau.row(0), // 填充矩阵元素
  1103.     traj_tau.row(int(N / 2) - 1),
  1104.     traj_tau.row(N - 1);
  1105.   Eigen::MatrixXd traj_theta_timestep(numTest, 3); // 定义矩阵,用于存储测试点的关节角度
  1106.   traj_theta_timestep << traj_theta.row(0), // 填充矩阵元素
  1107.     traj_theta.row(int(N / 2) - 1),
  1108.     traj_theta.row(N - 1);
  1109.   ASSERT_TRUE(traj_tau_timestep.isApprox(result_taumat, 4)); // 断言计算结果与预期结果近似相等
  1110.   ASSERT_TRUE(traj_theta_timestep.isApprox(result_thetamat, 4)); // 断言计算结果与预期结果近似相等
  1111. }
复制代码
头文件 modern_robotics.h 

  1. #pragma once // 防止头文件被重复包含
  2. #include <Eigen/Dense> // 包含Eigen库,用于矩阵和向量运算
  3. #include <vector> // 包含标准库vector,用于存储动态数组
  4. namespace mr { // 定义命名空间mr
  5. /*
  6. * 函数:判断一个值是否可以忽略为0
  7. * 输入:需要检查的double类型值
  8. * 返回:布尔值,true表示可以忽略,false表示不能忽略
  9. */
  10. bool NearZero(const double); // 声明NearZero函数
  11. /*
  12. * 函数:计算给定6维向量的6x6矩阵[adV]
  13. * 输入:Eigen::VectorXd (6x1) 6维向量
  14. * 输出:Eigen::MatrixXd (6x6) 6x6矩阵
  15. * 备注:可用于计算李括号[V1, V2] = [adV1]V2
  16. */
  17. Eigen::MatrixXd ad(Eigen::VectorXd); // 声明ad函数
  18. /*
  19. * 函数:返回输入向量的归一化版本
  20. * 输入:Eigen::MatrixXd 矩阵
  21. * 输出:Eigen::MatrixXd 矩阵
  22. * 备注:MatrixXd用于行向量的情况,需要复制,因MatrixXd的类型转换而有用
  23. */
  24. Eigen::MatrixXd Normalize(Eigen::MatrixXd); // 声明Normalize函数
  25. /*
  26. * 函数:返回角速度向量的反对称矩阵表示
  27. * 输入:Eigen::Vector3d 3x1角速度向量
  28. * 返回:Eigen::MatrixXd 3x3反对称矩阵
  29. */
  30. Eigen::Matrix3d VecToso3(const Eigen::Vector3d&); // 声明VecToso3函数
  31. /*
  32. * 函数:返回由反对称矩阵表示的角速度向量
  33. * 输入:Eigen::MatrixXd 3x3反对称矩阵
  34. * 返回:Eigen::Vector3d 3x1角速度向量
  35. */
  36. Eigen::Vector3d so3ToVec(const Eigen::MatrixXd&); // 声明so3ToVec函数
  37. /*
  38. * 函数:将指数旋转转换为其单独的分量
  39. * 输入:指数旋转(旋转矩阵,包含旋转轴和旋转角度)
  40. * 返回:旋转轴和旋转角度[x, y, z, theta]
  41. */
  42. Eigen::Vector4d AxisAng3(const Eigen::Vector3d&); // 声明AxisAng3函数
  43. /*
  44. * 函数:将指数旋转转换为旋转矩阵
  45. * 输入:指数旋转表示的旋转
  46. * 返回:旋转矩阵
  47. */
  48. Eigen::Matrix3d MatrixExp3(const Eigen::Matrix3d&); // 声明MatrixExp3函数
  49. /*
  50. * 函数:计算旋转矩阵的矩阵对数
  51. * 输入:旋转矩阵
  52. * 返回:旋转的矩阵对数
  53. */
  54. Eigen::Matrix3d MatrixLog3(const Eigen::Matrix3d&); // 声明MatrixLog3函数
  55. /*
  56. * 函数:将旋转矩阵和位置向量组合成一个特殊欧几里得群(SE3)齐次变换矩阵
  57. * 输入:旋转矩阵(R),位置向量(p)
  58. * 返回:矩阵T = [ [R, p],
  59. *                [0, 1] ]
  60. */
  61. Eigen::MatrixXd RpToTrans(const Eigen::Matrix3d&, const Eigen::Vector3d&); // 声明RpToTrans函数
  62. /*
  63. * 函数:从变换矩阵表示中分离出旋转矩阵和位置向量
  64. * 输入:齐次变换矩阵
  65. * 返回:包含旋转矩阵和位置向量的std::vector
  66. */
  67. std::vector<Eigen::MatrixXd> TransToRp(const Eigen::MatrixXd&); // 声明TransToRp函数
  68. /*
  69. * 函数:将空间速度向量转换为变换矩阵
  70. * 输入:空间速度向量[角速度,线速度]
  71. * 返回:变换矩阵
  72. */
  73. Eigen::MatrixXd VecTose3(const Eigen::VectorXd&); // 声明VecTose3函数
  74. /*
  75. * 函数:将变换矩阵转换为空间速度向量
  76. * 输入:变换矩阵
  77. * 返回:空间速度向量[角速度,线速度]
  78. */
  79. Eigen::VectorXd se3ToVec(const Eigen::MatrixXd&); // 声明se3ToVec函数
  80. /*
  81. * 函数:提供变换矩阵的伴随表示
  82. *       用于改变空间速度向量的参考系
  83. * 输入:4x4变换矩阵SE(3)
  84. * 返回:6x6矩阵的伴随表示
  85. */
  86. Eigen::MatrixXd Adjoint(const Eigen::MatrixXd&);
  87. /*
  88. * 函数:螺旋轴的旋转扩展
  89. * 输入:指数坐标的se3矩阵表示(变换矩阵)
  90. * 返回:表示旋转的6x6矩阵
  91. */
  92. Eigen::MatrixXd MatrixExp6(const Eigen::MatrixXd&);
  93. /*
  94. * 函数:计算齐次变换矩阵的矩阵对数
  95. * 输入:R:SE3中的变换矩阵
  96. * 返回:R的矩阵对数
  97. */
  98. Eigen::MatrixXd MatrixLog6(const Eigen::MatrixXd&);
  99. /*
  100. * 函数:计算末端执行器框架(用于当前空间位置计算)
  101. * 输入:末端执行器的初始配置(位置和方向)
  102. *       当机械臂处于初始位置时的关节螺旋轴
  103. *       关节坐标列表
  104. * 返回:表示关节在指定坐标时末端执行器框架的变换矩阵
  105. * 备注:FK表示正向运动学
  106. */
  107. Eigen::MatrixXd FKinSpace(const Eigen::MatrixXd&, const Eigen::MatrixXd&, const Eigen::VectorXd&);
  108. /*
  109. * 函数:计算末端执行器框架(用于当前身体位置计算)
  110. * 输入:末端执行器的初始配置(位置和方向)
  111. *       当机械臂处于初始位置时的关节螺旋轴
  112. *       关节坐标列表
  113. * 返回:表示关节在指定坐标时末端执行器框架的变换矩阵
  114. * 备注:FK表示正向运动学
  115. */
  116. Eigen::MatrixXd FKinBody(const Eigen::MatrixXd&, const Eigen::MatrixXd&, const Eigen::VectorXd&);
  117. /*
  118. * 函数:给出空间雅可比矩阵
  119. * 输入:初始位置的螺旋轴,关节配置
  120. * 返回:6xn空间雅可比矩阵
  121. */
  122. Eigen::MatrixXd JacobianSpace(const Eigen::MatrixXd&, const Eigen::MatrixXd&);
  123. /*
  124. * 函数:给出身体雅可比矩阵
  125. * 输入:身体位置的螺旋轴,关节配置
  126. * 返回:6xn身体雅可比矩阵
  127. */
  128. Eigen::MatrixXd JacobianBody(const Eigen::MatrixXd&, const Eigen::MatrixXd&);
  129. /*
  130. * 反转齐次变换矩阵
  131. * 输入:齐次变换矩阵T
  132. * 返回:T的逆矩阵
  133. */
  134. Eigen::MatrixXd TransInv(const Eigen::MatrixXd&);
  135. /*
  136. * 反转旋转矩阵
  137. * 输入:旋转矩阵R
  138. * 返回:R的逆矩阵
  139. */
  140. Eigen::MatrixXd RotInv(const Eigen::MatrixXd&);
  141. /*
  142. * 将螺旋轴的参数描述转换为归一化螺旋轴
  143. * 输入:
  144. * q:螺旋轴上的一点
  145. * s:螺旋轴方向的单位向量
  146. * h:螺旋轴的螺距
  147. * 返回:由输入描述的归一化螺旋轴
  148. */
  149. Eigen::VectorXd ScrewToAxis(Eigen::Vector3d q, Eigen::Vector3d s, double h);
  150. /*
  151. * 函数:将6维指数坐标转换为螺旋轴-角度形式
  152. * 输入:
  153. * expc6:刚体运动的6维指数坐标 S*theta
  154. * 返回:对应的归一化螺旋轴S;沿/绕S移动的距离theta,形式为[S, theta]
  155. * 备注:返回std::map<S, theta>是否更好?
  156. */
  157. Eigen::VectorXd AxisAng6(const Eigen::VectorXd&);
  158. /*
  159. * 函数:将一个矩阵投影到SO(3)
  160. * 输入:
  161. * M: 一个接近SO(3)的矩阵,将其投影到SO(3)
  162. * 返回:SO(3)中最接近的矩阵R
  163. * 使用奇异值分解将矩阵mat投影到SO(3)中最接近的矩阵
  164. * (参见http://hades.mech.northwestern.edu/index.php/Modern_Robotics_Linear_Algebra_Review)。
  165. * 此函数仅适用于接近SO(3)的矩阵。
  166. */
  167. Eigen::MatrixXd ProjectToSO3(const Eigen::MatrixXd&);
  168. /*
  169. * 函数:将一个矩阵投影到SE(3)
  170. * 输入:
  171. * M: 一个接近SE(3)的4x4矩阵,将其投影到SE(3)
  172. * 返回:SE(3)中最接近的矩阵T
  173. * 使用奇异值分解将矩阵mat投影到SE(3)中最接近的矩阵
  174. * (参见http://hades.mech.northwestern.edu/index.php/Modern_Robotics_Linear_Algebra_Review)。
  175. * 此函数仅适用于接近SE(3)的矩阵。
  176. */
  177. Eigen::MatrixXd ProjectToSE3(const Eigen::MatrixXd&);
  178. /*
  179. * 函数:返回Frobenius范数以描述矩阵M与SO(3)流形的距离
  180. * 输入:
  181. * M: 一个3x3矩阵
  182. * 输出:
  183. * 返回矩阵mat到SO(3)流形的距离,使用以下方法:
  184. * 如果det(M) <= 0,返回一个大数。
  185. * 如果det(M) > 0,返回norm(M^T*M - I)。
  186. */
  187. double DistanceToSO3(const Eigen::Matrix3d&);
  188. /*
  189. * 函数:返回Frobenius范数以描述矩阵T与SE(3)流形的距离
  190. * 输入:
  191. * T: 一个4x4矩阵
  192. * 输出:
  193. * 返回矩阵T到SE(3)流形的距离,使用以下方法:
  194. * 计算矩阵T的前三行前三列子矩阵matR的行列式。
  195. * 如果det(matR) <= 0,返回一个大数。
  196. * 如果det(matR) > 0,将mat的前三行前三列子矩阵替换为matR^T*matR,
  197. * 并将mat的第四列的前三个元素设为零。然后返回norm(T - I)。
  198. */
  199. double DistanceToSE3(const Eigen::Matrix4d&);
  200. /*
  201. * 函数:如果矩阵M接近或在SO(3)流形上,返回true
  202. * 输入:
  203. * M: 一个3x3矩阵
  204. * 输出:
  205. * 如果M非常接近或在SO(3)中,返回true,否则返回false
  206. */
  207. bool TestIfSO3(const Eigen::Matrix3d&);
  208. /*
  209. * 函数:如果矩阵T接近或在SE(3)流形上,返回true
  210. * 输入:
  211. * T: 一个4x4矩阵
  212. * 输出:
  213. * 如果T非常接近或在SE(3)中,返回true,否则返回false
  214. */
  215. bool TestIfSE3(const Eigen::Matrix4d&);
  216. /*
  217. * 函数:计算开链机器人在身体坐标系中的逆运动学
  218. * 输入:
  219. * Blist: 末端执行器在初始位置时的关节螺旋轴,以轴为列的矩阵格式
  220. * M: 末端执行器的初始配置
  221. * T: 末端执行器的期望配置Tsd
  222. * thetalist[in][out]: 关节角的初始猜测和结果输出,接近满足Tsd
  223. * eomg: 末端执行器方向误差的小正容差。返回的关节角必须使末端执行器方向误差小于eomg
  224. * ev: 末端执行器线性位置误差的小正容差。返回的关节角必须使末端执行器位置误差小于ev
  225. * 输出:
  226. * success: 逻辑值,TRUE表示函数找到了解决方案,FALSE表示在最大迭代次数内未找到满足eomg和ev容差的解决方案
  227. * thetalist[in][out]: 在指定容差内实现T的关节角
  228. */
  229. bool IKinBody(const Eigen::MatrixXd&, const Eigen::MatrixXd&, const Eigen::MatrixXd&, Eigen::VectorXd&, double, double);
  230. /*
  231. * 函数:计算开链机器人在空间坐标系中的逆运动学
  232. * 输入:
  233. * Slist: 机械臂在初始位置时的关节螺旋轴,以轴为列的矩阵格式
  234. * M: 末端执行器的初始配置
  235. * T: 末端执行器的期望配置Tsd
  236. * thetalist[in][out]: 关节角的初始猜测和结果输出,接近满足Tsd
  237. * eomg: 末端执行器方向误差的小正容差。返回的关节角必须使末端执行器方向误差小于eomg
  238. * ev: 末端执行器线性位置误差的小正容差。返回的关节角必须使末端执行器位置误差小于ev
  239. * 输出:
  240. * success: 逻辑值,TRUE表示函数找到了解决方案,FALSE表示在最大迭代次数内未找到满足eomg和ev容差的解决方案
  241. * thetalist[in][out]: 在指定容差内实现T的关节角
  242. */
  243. bool IKinSpace(const Eigen::MatrixXd&, const Eigen::MatrixXd&, const Eigen::MatrixXd&, Eigen::VectorXd&, double, double);
  244. /*
  245. * 函数:使用前后牛顿-欧拉迭代求解方程:
  246. * taulist = Mlist(thetalist) * ddthetalist + c(thetalist, dthetalist) ...
  247. *           + g(thetalist) + Jtr(thetalist) * Ftip
  248. * 输入:
  249. *  thetalist: 关节变量的n维向量
  250. *  dthetalist: 关节速度的n维向量
  251. *  ddthetalist: 关节加速度的n维向量
  252. *  g: 重力向量g
  253. *  Ftip: 由末端执行器施加的空间力,以{n+1}坐标系表示
  254. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  255. *  Glist: 各连杆的空间惯性矩阵Gi
  256. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  257. *
  258. * 输出:
  259. *  taulist: 所需关节力/力矩的n维向量
  260. *
  261. */
  262. Eigen::VectorXd InverseDynamics(const Eigen::VectorXd&, const Eigen::VectorXd&, const Eigen::VectorXd&,
  263.                                    const Eigen::VectorXd&, const Eigen::VectorXd&, const std::vector<Eigen::MatrixXd>&,
  264.                                    const std::vector<Eigen::MatrixXd>&, const Eigen::MatrixXd&);
  265. /*
  266. * 函数:调用InverseDynamics函数,设置Ftip = 0, dthetalist = 0, 和
  267. *   ddthetalist = 0。目的是计算动力学方程中的一个重要项      
  268. * 输入:
  269. *  thetalist: 关节变量的n维向量
  270. *  g: 重力向量g
  271. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  272. *  Glist: 各连杆的空间惯性矩阵Gi
  273. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  274. *
  275. * 输出:
  276. *  grav: 显示重力对动力学影响的3维向量
  277. *
  278. */
  279. Eigen::VectorXd GravityForces(const Eigen::VectorXd&, const Eigen::VectorXd&,
  280.                                 const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&, const Eigen::MatrixXd&);
  281. /*
  282. * 函数:调用InverseDynamics函数n次,每次传递一个
  283. * ddthetalist向量,其中一个元素等于1,所有其他
  284. * 输入设置为零。每次调用InverseDynamics生成一个
  285. * 列,这些列被组装成惯性矩阵。      
  286. *
  287. * 输入:
  288. *  thetalist: 关节变量的n维向量
  289. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  290. *  Glist: 各连杆的空间惯性矩阵Gi
  291. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  292. *
  293. * 输出:
  294. *  M: 在给定配置thetalist下n关节串联链的数值惯性矩阵M(thetalist)
  295. */
  296. Eigen::MatrixXd MassMatrix(const Eigen::VectorXd&,
  297.                                 const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&, const Eigen::MatrixXd&);
  298. /*
  299. * 函数:调用InverseDynamics函数,设置g = 0, Ftip = 0, 和
  300. * ddthetalist = 0。      
  301. *
  302. * 输入:
  303. *  thetalist: 关节变量的n维向量
  304. *  dthetalist: 关节速度列表
  305. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  306. *  Glist: 各连杆的空间惯性矩阵Gi
  307. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  308. *
  309. * 输出:
  310. *  c: 给定thetalist和dthetalist的科里奥利和离心项向量c(thetalist,dthetalist)
  311. */
  312. Eigen::VectorXd VelQuadraticForces(const Eigen::VectorXd&, const Eigen::VectorXd&,
  313.                             const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&, const Eigen::MatrixXd&);
  314. /*
  315. * 函数:调用InverseDynamics函数,设置g = 0, dthetalist = 0, 和
  316. * ddthetalist = 0。  
  317. *
  318. * 输入:
  319. *  thetalist: 关节变量的n维向量
  320. *  Ftip: 由末端执行器施加的空间力,以{n+1}坐标系表示
  321. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  322. *  Glist: 各连杆的空间惯性矩阵Gi
  323. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  324. *
  325. * 输出:
  326. *  JTFtip: 仅用于产生末端执行器力Ftip所需的关节力和力矩
  327. */
  328. Eigen::VectorXd EndEffectorForces(const Eigen::VectorXd&, const Eigen::VectorXd&,
  329.                             const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&, const Eigen::MatrixXd&);
  330. /*
  331. * 函数:通过求解以下方程计算ddthetalist:
  332. * Mlist(thetalist) * ddthetalist = taulist - c(thetalist,dthetalist)
  333. *                                  - g(thetalist) - Jtr(thetalist) * Ftip
  334. * 输入:
  335. *  thetalist: 关节变量的n维向量
  336. *  dthetalist: 关节速度的n维向量
  337. *  taulist: 关节力/力矩的n维向量
  338. *  g: 重力向量g
  339. *  Ftip: 由末端执行器施加的空间力,以{n+1}坐标系表示
  340. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  341. *  Glist: 各连杆的空间惯性矩阵Gi
  342. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  343. *
  344. * 输出:
  345. *  ddthetalist: 结果关节加速度
  346. *
  347. */
  348. Eigen::VectorXd ForwardDynamics(const Eigen::VectorXd&, const Eigen::VectorXd&, const Eigen::VectorXd&,
  349.                                    const Eigen::VectorXd&, const Eigen::VectorXd&, const std::vector<Eigen::MatrixXd>&,
  350.                                    const std::vector<Eigen::MatrixXd>&, const Eigen::MatrixXd&);
  351. /*
  352. * 函数:使用一阶欧拉积分计算下一个时间步的关节角度和速度
  353. * 输入:
  354. *  thetalist[in]: 关节变量的n维向量
  355. *  dthetalist[in]: 关节速度的n维向量
  356. *  ddthetalist: 关节加速度的n维向量
  357. *  dt: 时间步长delta t
  358. *
  359. * 输出:
  360. *  thetalist[out]: 一阶欧拉积分后经过dt时间的关节变量向量
  361. *  dthetalist[out]: 一阶欧拉积分后经过dt时间的关节速度向量
  362. */
  363. void EulerStep(Eigen::VectorXd&, Eigen::VectorXd&, const Eigen::VectorXd&, double);
  364. /*
  365. * 函数:使用逆动力学计算沿给定轨迹移动串联链所需的关节力/力矩
  366. * 输入:
  367. *  thetamat: 机器人关节变量的N x n矩阵(N:轨迹时间步点数;n:机器人关节数)
  368. *  dthetamat: 机器人关节速度的N x n矩阵
  369. *  ddthetamat: 机器人关节加速度的N x n矩阵
  370. *  g: 重力向量g
  371. *  Ftipmat: 由末端执行器施加的空间力的N x 6矩阵(如果没有末端力,用户应输入零矩阵)
  372. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  373. *  Glist: 各连杆的空间惯性矩阵Gi
  374. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  375. *
  376. * 输出:
  377. *  taumat: 指定轨迹的关节力/力矩的N x n矩阵,其中每一行是每个时间步的关节力/力矩向量
  378. */
  379. Eigen::MatrixXd InverseDynamicsTrajectory(const Eigen::MatrixXd&, const Eigen::MatrixXd&, const Eigen::MatrixXd&,
  380.   const Eigen::VectorXd&, const Eigen::MatrixXd&, const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&,
  381.   const Eigen::MatrixXd&);
  382. /*
  383. * 函数:给定开环关节力/力矩历史,计算串联链的运动
  384. * 输入:
  385. *  thetalist: 初始关节变量的n维向量
  386. *  dthetalist: 初始关节速度的n维向量
  387. *  taumat: 关节力/力矩的N x n矩阵,其中每一行是任意时间步的关节努力
  388. *  g: 重力向量g
  389. *  Ftipmat: 由末端执行器施加的空间力的N x 6矩阵(如果没有末端力,用户应输入零矩阵)
  390. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  391. *  Glist: 各连杆的空间惯性矩阵Gi
  392. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  393. *  dt: 连续关节力/力矩之间的时间步长
  394. *  intRes: 积分分辨率是在每个时间步之间进行积分(欧拉)的次数。
  395. *      必须是大于或等于1的整数值
  396. *
  397. * 输出:std::vector包含[thetamat, dthetamat]
  398. *  thetamat: 由指定关节力/力矩产生的关节角度的N x n矩阵
  399. *  dthetamat: 关节速度的N x n矩阵
  400. */
  401. std::vector<Eigen::MatrixXd> ForwardDynamicsTrajectory(const Eigen::VectorXd&, const Eigen::VectorXd&, const Eigen::MatrixXd&,
  402.   const Eigen::VectorXd&, const Eigen::MatrixXd&, const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&,
  403.   const Eigen::MatrixXd&, double, int);
  404. /*
  405. * 函数:计算特定时间点的关节控制力矩
  406. * 输入:
  407. *  thetalist: 关节变量的n维向量
  408. *  dthetalist: 关节速度的n维向量
  409. *  eint: 关节误差的时间积分的n维向量
  410. *  g: 重力向量g
  411. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  412. *  Glist: 各连杆的空间惯性矩阵Gi
  413. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  414. *  thetalistd: 参考关节变量的n维向量
  415. *  dthetalistd: 参考关节速度的n维向量
  416. *  ddthetalistd: 参考关节加速度的n维向量
  417. *  Kp: 反馈比例增益(每个关节相同)
  418. *  Ki: 反馈积分增益(每个关节相同)
  419. *  Kd: 反馈微分增益(每个关节相同)
  420. *
  421. * 输出:
  422. *  tau_computed: 由反馈线性化控制器在当前时刻计算的关节力/力矩向量
  423. */
  424. Eigen::VectorXd ComputedTorque(const Eigen::VectorXd&, const Eigen::VectorXd&, const Eigen::VectorXd&,
  425.   const Eigen::VectorXd&, const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&,
  426.   const Eigen::MatrixXd&, const Eigen::VectorXd&, const Eigen::VectorXd&, const Eigen::VectorXd&, double, double, double);
  427. /*
  428. * 函数:计算三次时间缩放的s(t)
  429. * 输入:
  430. *  Tf: 从静止到静止的运动总时间(秒)
  431. *  t: 当前时间t,满足0 < t < Tf
  432. *
  433. * 输出:
  434. *  st: 对应于三次多项式运动的路径参数,该运动在开始和结束时速度为零
  435. */
  436. double CubicTimeScaling(double, double);
  437. /*
  438. * 函数:计算五次时间缩放的s(t)
  439. * 输入:
  440. *  Tf: 从静止到静止的运动总时间(秒)
  441. *  t: 当前时间t,满足0 < t < Tf
  442. *
  443. * 输出:
  444. *  st: 对应于五次多项式运动的路径参数,该运动在开始和结束时速度和加速度为零
  445. */
  446. double QuinticTimeScaling(double, double);
  447. /*
  448. * 函数:计算关节空间中的直线轨迹
  449. * 输入:
  450. *  thetastart: 初始关节变量
  451. *  thetaend: 最终关节变量
  452. *  Tf: 从静止到静止的运动总时间(秒)
  453. *  N: 离散轨迹表示中的点数N > 1(开始和停止)
  454. *  method: 时间缩放方法,其中3表示三次(三级多项式)时间缩放,5表示五次(五级多项式)时间缩放
  455. *
  456. * 输出:
  457. *  traj: 轨迹为N x n矩阵,其中每一行是某一时刻的n维关节变量向量。第一行是thetastart,N行是thetaend。每行之间的时间间隔为Tf / (N - 1)
  458. */
  459. Eigen::MatrixXd JointTrajectory(const Eigen::VectorXd&, const Eigen::VectorXd&, double, int, int);
  460. /*
  461. * 函数:计算对应于空间螺旋轴螺旋运动的N个SE(3)矩阵的轨迹列表
  462. * 输入:
  463. *  Xstart: 初始末端执行器配置
  464. *  Xend: 最终末端执行器配置
  465. *  Tf: 从静止到静止的运动总时间(秒)
  466. *  N: 离散轨迹表示中的点数N > 1(开始和停止)
  467. *  method: 时间缩放方法,其中3表示三次(三级多项式)时间缩放,5表示五次(五级多项式)时间缩放
  468. *
  469. * 输出:
  470. *  traj: 离散轨迹为N个SE(3)矩阵的列表,时间间隔为Tf/(N-1)。列表中的第一个是Xstart,N个是Xend
  471. */
  472. std::vector<Eigen::MatrixXd> ScrewTrajectory(const Eigen::MatrixXd&, const Eigen::MatrixXd&, double, int, int);
  473. /*
  474. * 函数:计算对应于末端执行器框架原点沿直线运动的N个SE(3)矩阵的轨迹列表
  475. * 输入:
  476. *  Xstart: 初始末端执行器配置
  477. *  Xend: 最终末端执行器配置
  478. *  Tf: 从静止到静止的运动总时间(秒)
  479. *  N: 离散轨迹表示中的点数N > 1(开始和停止)
  480. *  method: 时间缩放方法,其中3表示三次(三级多项式)时间缩放,5表示五次(五级多项式)时间缩放
  481. *
  482. * 输出:
  483. *  traj: 离散轨迹为N个SE(3)矩阵的列表,时间间隔为Tf/(N-1)。列表中的第一个是Xstart,N个是Xend
  484. * 备注:
  485. *  此函数类似于ScrewTrajectory,不同之处在于末端执行器框架的原点沿直线运动,与旋转运动解耦。
  486. */
  487. std::vector<Eigen::MatrixXd> CartesianTrajectory(const Eigen::MatrixXd&, const Eigen::MatrixXd&, double, int, int);
  488. /*
  489. * 函数:给定开环关节力/力矩历史,计算串联链的运动
  490. * 输入:
  491. *  thetalist: 初始关节变量的n维向量
  492. *  dthetalist: 初始关节速度的n维向量
  493. *  g: 重力向量g
  494. *  Ftipmat: 由末端执行器施加的空间力的N x 6矩阵(如果没有末端力,用户应输入零矩阵)
  495. *  Mlist: 初始位置时各连杆相对于前一个连杆的坐标系列表
  496. *  Glist: 各连杆的空间惯性矩阵Gi
  497. *  Slist: 关节在空间坐标系中的螺旋轴Si,以螺旋轴为列的矩阵格式
  498. *  thetamatd: 参考轨迹中的期望关节变量的N x n矩阵
  499. *  dthetamatd: 期望关节速度的N x n矩阵
  500. *  ddthetamatd: 期望关节加速度的N x n矩阵
  501. *  gtilde: 基于实际机器人模型的重力向量(上面给出的实际值)
  502. *  Mtildelist: 基于实际机器人模型的连杆框架位置(上面给出的实际值)
  503. *  Gtildelist: 基于实际机器人模型的连杆空间惯性(上面给出的实际值)
  504. *  Kp: 反馈比例增益(每个关节相同)
  505. *  Ki: 反馈积分增益(每个关节相同)
  506. *  Kd: 反馈微分增益(每个关节相同)
  507. *  dt: 参考轨迹点之间的时间步长
  508. *  intRes: 积分分辨率是在每个时间步之间进行积分(欧拉)的次数。
  509. *      必须是大于或等于1的整数值
  510. *
  511. * 输出:std::vector包含[taumat, thetamat]
  512. *  taumat: 控制器命令的关节力/力矩的N x n矩阵,其中每一行的n个力/力矩对应于单个时间点
  513. *  thetamat: 实际关节角度的N x n矩阵
  514. */
  515. std::vector<Eigen::MatrixXd> SimulateControl(const Eigen::VectorXd&, const Eigen::VectorXd&, const Eigen::VectorXd&,
  516.   const Eigen::MatrixXd&, const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&,
  517.   const Eigen::MatrixXd&, const Eigen::MatrixXd&, const Eigen::MatrixXd&, const Eigen::MatrixXd&,
  518.   const Eigen::VectorXd&, const std::vector<Eigen::MatrixXd>&, const std::vector<Eigen::MatrixXd>&,
  519.   double, double, double, double, int);
  520. }
复制代码
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

星球的眼睛

高级会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表