跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++AI算法

双足机器人 2-RSS-1U 并联踝关节设计与运动学分析

双足机器人踝关节设计直接影响动态性能,串联结构惯量大且刚度低,并联结构更优。深入解析 2-RSS-1U 并联机构,涵盖机械参数优化、运动学建模及雅可比矩阵推导。通过逆运动学解析解与正运动学牛顿迭代法,实现了从目标姿态到电机角度的精确映射。文末提供基于 Eigen 库的 C++ 实现代码,辅助开发者理解并联踝关节控制逻辑。

w795471发布于 2026/4/8更新于 2026/10/2277 浏览
双足机器人 2-RSS-1U 并联踝关节设计与运动学分析

双足机器人 2-RSS-1U 并联踝关节设计与运动学分析

在双足机器人的设计中,脚踝往往是被低估的关键环节。相比于复杂的平衡算法,物理层面的脚踝灵活性直接决定了行走的稳定性与动态性能。串联结构虽然控制简单,但在高动态场景下存在惯量大、刚度不足的硬伤;而并联结构通过将电机上置,显著降低了末端转动惯量,成为高性能人形机器人的主流选择。

机构构型对比:串联 vs 并联

串联构型

这是最直观的实现方式,Pitch(俯仰)和 Roll(侧滚)两个自由度通过电机堆叠实现。一个电机驱动 Pitch 轴,另一个安装在其上驱动 Roll 轴。

  • 优势:控制逻辑简单,每个电机的运动与独立自由度对应,运动学解算直接。
  • 劣势:
    • 转动惯量大:末端电机及减速器成为上一级关节的额外负载,导致摆腿速度慢、能耗高。
    • 刚度较低:悬臂梁式受力结构,轴承和齿轮箱易成为薄弱点,承载能力弱。

并联构型

将驱动器布置在固定基座(小腿),通过连杆机构共同驱动移动平台(脚掌)。

  • 挑战:运动学耦合复杂,单个电机运动会同时影响 Pitch 和 Roll。
  • 核心优势:
    • 低转动惯量:质量最大的部件上移至小腿,利于快速动态行走和跑跳。
    • 高刚度与承载力:闭环结构天然抗冲击能力强,支撑更稳定。

综合来看,尽管并联控制算法更复杂,但其在物理性能上的巨大优势使其成为高动态运动的必然选择。

机构设计:2-RSS-1U 方案

我们参考了相关文献,最终选择了 2-RSS-1U 这一并联构型。

并联踝关节结构示意图

该名称精确描述了机械结构:

  • 2-RSS:包含两条相同的 R-S-S 运动链。
    • R (Revolute):位于小腿的主动驱动旋转关节。
    • S (Spherical):两个球形关节,分别位于连杆中段和连接脚掌处,提供空间自由度。
  • 1-U:中心被动万向节,其交叉转轴定义了脚掌的 Pitch 和 Roll 运动。

相比 UPU 或 UPS 等其他构型,RSS 结构在力矩传递上表现更佳,力矩传递比在运动空间内变化更小,有利于复杂地形下的精确力控制。

关键参数优化

设计阶段重点关注了几何参数对运动范围的影响:

  • l_bar:电机驱动臂长度。
  • l_rod:中间连杆长度。
  • l_spacing:两条运动链间距。

采用论文推荐参数(l_bar=85mm, l_rod=135mm, l_spacing=43mm),在保证紧凑的同时,实现了 Roll 方向 [-20°, 20°] 和 Pitch 方向 [-58°, 42°] 的宽阔运动范围。

运动学解算:从姿态到电机指令

建立精确数学模型是实现有效控制的前提,主要包括逆运动学、正运动学和雅可比矩阵求解。

1. 逆运动学 (IK)

给定脚掌目标姿态 (q_roll, q_pitch),计算电机角度 (θ1, θ2)。

  • 求解逻辑:转化为几何约束问题。
    1. 根据目标姿态确定脚掌平台的旋转矩阵。
    2. 计算连杆与脚掌连接点的三维坐标。
    3. 利用连杆长度约束构建空间几何方程。
    4. 求解解析解。

该问题存在封闭形式的解析解,计算速度快且无奇异性,为实时位置控制奠定基础。

2. 雅可比矩阵 (Jacobian)

雅可比矩阵建立了关节空间速度与任务空间速度之间的线性关系。

  • 关节空间:电机角度 θ = [θ₁, θ₂]ᵀ,速度 θ̇。
  • 任务空间:脚掌姿态 q = [q_roll, q_pitch]ᵀ,角速度 q̇。

关系式为:θ̇ = J * q̇

其中 J 是逆运动学函数关于时间的偏导数矩阵。它是并联机构控制的精髓:

  • 速度控制:将期望的脚掌角速度映射为电机角速度。
  • 力矩控制:通过转置矩阵 J^T 建立末端力矩与电机电驱力的关系,支持柔顺控制和力矩伺服。

3. 正运动学 (FK)

根据编码器读数反算脚掌实际姿态。由于无法直接求得解析解,我们采用牛顿 - 拉夫逊迭代法。

  1. 定义误差函数:e(q) = θ_actual - f_IK(q_guess)。
  2. 迭代更新:q_{k+1} = q_k + J⁻¹(q_k) * e(q_k)。
  3. 收敛判断:重复直至误差小于阈值。该方法收敛极快,通常几次迭代即可满足实时性要求。

C++ 实现示例

为了便于工程落地,以下提供了基于 Eigen 库的逆运动学 C++ 实现。代码封装了参数初始化、单执行器解算及整体 IK 求解逻辑。

#include <Eigen/Dense>
#include <iostream>
#include <cmath>
#include <stdexcept>

// 并联机构几何参数结构体
struct ExternalParameters {
    double pm_ankle_a_1[3] = {0.0, 53, 180}; // 执行器 1 的 A 点坐标 [mm]
    double pm_ankle_c_1[3] = {-70.0, 53, 0.0}; // 执行器 1 的 C 点初始坐标 [mm]
    double pm_ankle_bar_rod_1[2] = {70, 180}; // 执行器 1 连杆长度 [法兰杆,连杆] [mm]
    double pm_ankle_a_2[3] = {0.0, -53, 100.0}; // 执行器 2 的 A 点坐标 [mm]
    double pm_ankle_c_2[3] = {-70.0, -53, 0.0}; // 执行器 2 的 C 点初始坐标 [mm]
    double pm_ankle_bar_rod_2[2] = {70, 100}; // 执行器 2 连杆长度 [法兰杆,连杆] [mm]
};

// 单个执行器的几何参数
struct AnkleActuatorParams {
    Eigen::Vector3d r_Ai_0;      // A 点在基坐标系下的位置向量 [mm]
    Eigen::Vector3d r_Ci_0_initial; // C 点在初始姿态下的位置向量 [mm]
    double l_bar;                // 法兰杆长度 [mm]
    double l_rod;                // 连杆长度 [mm]
    double alpha_offset_rad;     // 电机零位偏移 [rad]
    double l_bar_sq;             // l_bar 的平方,用于加速计算 [mm^2]
    double l_rod_sq;             // l_rod 的平方,用于加速计算 [mm^2]

    AnkleActuatorParams() : l_bar(0), l_rod(0), alpha_offset_rad(0), l_bar_sq(0), l_rod_sq(0) {}

    AnkleActuatorParams(const Eigen::Vector3d& r_ai_0, const Eigen::Vector3d& r_ci_0_initial,
                        double lbar, double lrod, double alpha_rad = 0.0)
        : r_Ai_0(r_ai_0), r_Ci_0_initial(r_ci_0_initial), l_bar(lbar), l_rod(lrod), alpha_offset_rad(alpha_rad) {
        if (l_bar <= 1e-9) throw std::runtime_error("l_bar 必须大于零");
        l_bar_sq = l_bar * l_bar;
        l_rod_sq = l_rod * l_rod;
    }
};

// 绕 X 轴旋转的旋转矩阵
Eigen::Matrix3d Rx(double angle_rad) {
    return Eigen::AngleAxisd(angle_rad, Eigen::Vector3d::UnitX()).toRotationMatrix();
}

// 绕 Y 轴旋转的旋转矩阵
Eigen::Matrix3d Ry(double angle_rad) {
    return Eigen::AngleAxisd(angle_rad, Eigen::Vector3d::UnitY()).toRotationMatrix();
}

// 计算单个执行器的逆运动学
std::pair<double, bool> calculate_single_theta_i_internal(double q_roll_rad, double q_pitch_rad,
                                                          const AnkleActuatorParams& params) {
    const Eigen::Vector3d& r_Ai = params.r_Ai_0;
    Eigen::Matrix3d X_rot = Ry(q_pitch_rad) * Rx(q_roll_rad);
    Eigen::Vector3d r_Ci = X_rot * params.r_Ci_0_initial;
    Eigen::Vector3d r_Ci_minus_r_Ai = r_Ci - r_Ai;

    double a_val = r_Ci_minus_r_Ai.x();
    double b_val = (r_Ai - r_Ci).z();
    double norm_sq_r_Ci_minus_r_Ai = r_Ci_minus_r_Ai.squaredNorm();

    if (params.l_bar < 1e-9) {
        std::cerr << "错误:l_bar 接近零" << std::endl;
        return {0.0, false};
    }

    double c_val = (params.l_rod_sq - params.l_bar_sq - norm_sq_r_Ci_minus_r_Ai) / (2.0 * params.l_bar);

    double den_asin = a_val * a_val + b_val * b_val;
    double inner_sqrt_term = a_val * a_val + b_val * b_val - c_val * c_val;

    if (inner_sqrt_term < -1e-9) {
        std::cerr << "错误:配置不可达,平方根项为负 (" << inner_sqrt_term << ")" << std::endl;
        return {0.0, false};
    }
    if (inner_sqrt_term < 0) inner_sqrt_term = 0;

    double num_asin = b_val * c_val + std::abs(a_val) * std::sqrt(inner_sqrt_term);
    if (std::abs(den_asin) < 1e-12) {
        std::cerr << "错误:arcsin 分母接近零" << std::endl;
        if (std::abs(num_asin) < 1e-9) {
            std::cout << "警告:奇异构型,theta 未定义" << std::endl;
        }
        return {0.0, false};
    }

    double arg_asin = num_asin / den_asin;
    if (std::abs(arg_asin) > 1.0 + 1e-9) {
        std::cerr << "错误:arcsin 参数超出定义域 [-1, 1]: " << arg_asin << std::endl;
        return {0.0, false};
    }
    arg_asin = std::max(-1.0, std::min(1.0, arg_asin));

    double theta_i_rad = std::asin(arg_asin);
    theta_i_rad += params.alpha_offset_rad;
    return {theta_i_rad, true};
}

// 并联机构逆解结果
struct AnkleIKSolution {
    double theta_1_rad; // 执行器 1 的电机角度 [rad]
    bool success_1;     // 执行器 1 计算是否成功
    double theta_2_rad; // 执行器 2 的电机角度 [rad]
    bool success_2;     // 执行器 2 计算是否成功

    AnkleIKSolution() : theta_1_rad(0), success_1(false), theta_2_rad(0), success_2(false) {}
};

// 计算并联机构的逆运动学
AnkleIKSolution calculate_ankle_ik_both_actuators(double q_roll_rad, double q_pitch_rad,
                                                  const AnkleActuatorParams& params_1,
                                                  const AnkleActuatorParams& params_2) {
    AnkleIKSolution solution;
    auto result_1 = calculate_single_theta_i_internal(q_roll_rad, q_pitch_rad, params_1);
    solution.theta_1_rad = result_1.first;
    solution.success_1 = result_1.second;

    auto result_2 = calculate_single_theta_i_internal(q_roll_rad, q_pitch_rad, params_2);
    solution.theta_2_rad = result_2.first;
    solution.success_2 = result_2.second;

    return solution;
}

// 并联机构控制类
class PMAnkle {
public:
    ExternalParameters ext_params;
    AnkleActuatorParams params_1;
    AnkleActuatorParams params_2;

    PMAnkle() {}

    void PMankleInit() {
        Eigen::Vector3d r_A_1_vec(ext_params.pm_ankle_a_1[0], ext_params.pm_ankle_a_1[1], ext_params.pm_ankle_a_1[2]);
        Eigen::Vector3d r_C_1_vec(ext_params.pm_ankle_c_1[0], ext_params.pm_ankle_c_1[1], ext_params.pm_ankle_c_1[2]);
        double L_bar_1 = ext_params.pm_ankle_bar_rod_1[0];
        double L_rod_1 = ext_params.pm_ankle_bar_rod_1[1];
        params_1 = AnkleActuatorParams(r_A_1_vec, r_C_1_vec, L_bar_1, L_rod_1, 0.0);

        Eigen::Vector3d r_A_2_vec(ext_params.pm_ankle_a_2[0], ext_params.pm_ankle_a_2[1], ext_params.pm_ankle_a_2[2]);
        Eigen::Vector3d r_C_2_vec(ext_params.pm_ankle_c_2[0], ext_params.pm_ankle_c_2[1], ext_params.pm_ankle_c_2[2]);
        double L_bar_2 = ext_params.pm_ankle_bar_rod_2[0];
        double L_rod_2 = ext_params.pm_ankle_bar_rod_2[1];
        params_2 = AnkleActuatorParams(r_A_2_vec, r_C_2_vec, L_bar_2, L_rod_2, 0.0);

        std::cout << "并联机构初始化完成" << std::endl;
        std::cout << " 执行器 1 - L_bar: " << params_1.l_bar << " mm, L_rod: " << params_1.l_rod << " mm" << std::endl;
        std::cout << " 执行器 2 - L_bar: " << params_2.l_bar << " mm, L_rod: " << params_2.l_rod << " mm" << std::endl;
    }

    AnkleIKSolution getAnkleMotorAngles(double q_roll_rad, double q_pitch_rad) {
        return calculate_ankle_ik_both_actuators(q_roll_rad, q_pitch_rad, params_1, params_2);
    }
};

int main() {
    PMAnkle ankle_ankle;
    std::cout << "=== 踝关节并联机构逆运动学求解 ===" << std::endl;
    ankle_ankle.PMankleInit();

    double q_roll_deg = 10.0;
    double q_pitch_deg = 10.0;
    double q_roll_rad = q_roll_deg * M_PI / 180.0;
    double q_pitch_rad = q_pitch_deg * M_PI / 180.0;

    std::cout << "\n目标姿态角:" << std::endl;
    std::cout << " Roll: " << q_roll_deg << " 度 (" << q_roll_rad << " rad)" << std::endl;
    std::cout << " Pitch: " << q_pitch_deg << " 度 (" << q_pitch_rad << " rad)" << std::endl;

    AnkleIKSolution solution = ankle_ankle.getAnkleMotorAngles(q_roll_rad, q_pitch_rad);
    std::cout << "\n电机角度:" << std::endl;
    if (solution.success_1) {
        std::cout << " 电机 1: " << solution.theta_1_rad * 180.0 / M_PI << " 度 (" << solution.theta_1_rad << " rad)" << std::endl;
    } else {
        std::cout << " 电机 1: 计算失败" << std::endl;
    }
    if (solution.success_2) {
        std::cout << " 电机 2: " << solution.theta_2_rad * 180.0 / M_PI << " 度 (" << solution.theta_2_rad << " rad)" << std::endl;
    } else {
        std::cout << " 电机 2: 计算失败" << std::endl;
    }
    return 0;
}

编译时请确保链接 Eigen 库:g++ -std=c++17 -O2 -I/usr/include/eigen3 pm_ankle_example.cpp -o pm_ankle_example。修改 ExternalParameters 中的尺寸参数和目标角度,即可验证不同构型下的运动学解算结果。

目录

  1. 双足机器人 2-RSS-1U 并联踝关节设计与运动学分析
  2. 机构构型对比:串联 vs 并联
  3. 串联构型
  4. 并联构型
  5. 机构设计:2-RSS-1U 方案
  6. 关键参数优化
  7. 运动学解算:从姿态到电机指令
  8. 1. 逆运动学 (IK)
  9. 2. 雅可比矩阵 (Jacobian)
  10. 3. 正运动学 (FK)
  11. C++ 实现示例

更多推荐文章

查看全部
  • Java8 与 Java7 JVM 内存模型对比
  • MonkeyCode:重新定义 AI 编程协作流程
  • Java 核心语法与并发编程实战:66 个关键代码示例
  • FastAPI+Python 前后端交互实战:用户登录注册与信息管理
  • PRIDE-PPPAR 多 GNSS 精密单点定位软件安装配置指南
  • Python 内存暴涨原因分析及缓存优化与资源回收实践
  • 使用文心一言为智能体设计稳定调用工作流的提示词
  • Milvus 实战:Attu 可视化安装与 Python 整合指南
  • Python 开发 MongoDB 数据库 MCP Server 实战指南
  • OpenClaw 从 0 到 1 安装与运维指南:配置、QQ 机器人接入及故障排查
  • 基于 Docker 和 Ollama 本地部署 DeepSeek 大模型
  • MediaPipe Web 端接入实战:从 CDN 到工程化落地
  • 5 个维度掌握 python-okx 库:API 整合与量化交易实战
  • 基于 Spring Boot 的智驿 AI 系统毕业设计项目功能与技术栈
  • Claude Code 添加 MCP 服务器配置指南
  • Linux 从入门到实践:CentOS 服务器配置与用户管理指南
  • MySQL 8.0 安装与 MySQL Workbench 使用指南
  • 8 款流行 Python 可视化工具包对比与使用场景分析
  • HarmonyOS 5.0 端侧 AI 智能工业质检 APP 开发实战
  • Ubuntu Datasophon 1.2.1 集成 ClickHouse 组件解决方案

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • RSA密钥对生成器

    生成新的随机RSA私钥和公钥pem证书。 在线工具,RSA密钥对生成器在线工具,online

  • Mermaid 预览与可视化编辑

    基于 Mermaid.js 实时预览流程图、时序图等图表,支持源码编辑与即时渲染。 在线工具,Mermaid 预览与可视化编辑在线工具,online

  • 随机西班牙地址生成器

    随机生成西班牙地址(支持马德里、加泰罗尼亚、安达卢西亚、瓦伦西亚筛选),支持数量快捷选择、显示全部与下载。 在线工具,随机西班牙地址生成器在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online