十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

从LIPM到强化学习:机器人跑步核心控制技术解析

从LIPM到强化学习:机器人跑步核心控制技术解析 最近科技圈值得关注的一条新闻和中国机器人创下的百米纪录有关。很多人看到的是“机器人能跑了”但运动控制工程师眼中的东西不太一样这更像一次全行业能力的整体攀峰把高维、强耦合、时变的物理系统稳定控制到“跑起来”的程度中间涉及的硬件、算法、仿真和调试每一条都值得单独写一篇技术博客。更值得注意的是相关话题在技术社区里的搜索热词明显升温比如人形机器人、四足机器人、宇树机器人电路板拆解、ROS2机器人开发、ABB/KUKA工业机器人调试等。这说明很多开发者已经不满足于围观新闻而是想搞清楚“跑步”背后到底有什么技术以及自己能不能快速入门。这篇文章不以复述新闻为目的只讲技术链路。读完你会掌握机器人跑步到底难在物理原理的哪一层跑步控制常用的 ZMP、LIPM、MPC、WBC、强化学习分别在干什么如何从零搭建一个机器人运动仿真环境并用 Python 写一个可运行的最小步态控制 Demo从仿真到真实机器人指标验证、安全边界和工程协作怎么设计。1. 机器人创下百米纪录技术含量到底在哪1.1 跑步不是走路的进阶而是控制体系的迁移很多非技术背景的人觉得跑步就是走路的加速版。对机器人来说这个认知偏差非常致命。走路时机器人几乎全程保持至少一条腿与地面接触地面反作用力持续支撑身体控制器的压力相对小。跑步则完全不同它是一种“腾空相”与“触地相”交替出现的周期运动。腾空时机器人双脚离地没有任何地面支撑只能依靠惯性和预期的落点规划来维持状态触地时整个身体质量产生的冲击力又会在几十毫秒内通过关节吸收并转化为下一步的推进力。这意味着控制器的执行周期必须足够快通常要跑到 1kHz 甚至更高才能在短瞬内完成状态估计、力学解算和关节力矩输出。对比工业机器人更容易理解这一点。在工厂场景里ABB、KUKA 这类工业机械臂的轨迹通常是确定且可重复的工作区域内的人和障碍物也被严格控制。它们的核心是位置精度和重复定位精度而不是动态平衡。而跑步机器人面对的环境充满扰动地面材质、重心偏移、电池电压下降都会直接影响控制效果。它更像在操控一个“随时可能从自行车上摔下来的人”而不是在操作一台精密机床。1.2 从“敢跑”到“跑得稳”每个环节都是变量如果你看过机器人跑步的测试录像会发现不少 Demo 并不是一帆风顺地跑完全程而是频繁出现上半身大幅摆动、落点偏移、触地瞬间重心歪斜甚至摔倒在终点线之前。这背后的本质原因只有一个跑步机器人是一个高维、强耦合的时变系统基于简单模型的控制策略无法覆盖所有真实状态边界。工业界早年解决双足行走用的是 ZMP 判据强调“压力中心始终落在支撑多边形内”。这个方法在低速行走时很有效但在跑步这种强动态工况下ZMP 方法很难直接满足约束。于是研究者转向了“模型预测控制 全身控制”的组合再后来加入强化学习让策略本身学会在仿真中试错从而逼近更接近人类跑步的动态动作。这些技术研究最终共同构成了“机器人跑步”这件事的底层支撑。百米纪录的意义不是速度本身而是把高维动态系统稳定控制住的能力。这正是运动控制领域一次实打实的工程突破。2. 机器人跑步的核心概念与原理在继续实操之前先把几个绕不开的概念讲清楚。每个术语我会先给通俗解释再给出技术定义和它在跑步场景里的作用。2.1 自由度自由度是指机器人身上可以独立运动的关节数量。人形机器人通常有十几个到几十个自由度四足机器人虽然腿少但每条腿也有多个主动关节。通俗理解你手腕能转、肘能弯、肩膀能抬这些可以独立控制的旋转/平移动作就是自由度。跑步时机器人的自由度不仅“多”而且“耦合”——膝关节弯曲会改变质心高度髋关节旋转会影响前进方向一个关节的力矩异常会通过动态链传递到全身。自由度越多理论上动作表达能力越强控制难度也越大。2.2 动力学方程动力学方程描述的是“关节力矩与运动状态之间的数学关系”。简单说就是你给出每个关节应该出多大的力方程会告诉你机器人会怎么动。跑步控制里的动力学方程比工业机械臂复杂得多。机械臂基座固定末端轨迹可以提前规划跑步机器人基座是悬浮的地面反作用力、惯性力、科里奥利力全都要在毫秒级时间内计算。实际工程项目中很少有人手推完整动力学方程而是依赖物理引擎或自动求导工具来生成运动方程。但核心思想没有变控制器知道了“当前状态”需要算出“下一步该输出多大关节力矩”才能让机器人朝期望方向运动。2.3 ZMP 零力矩点ZMP 是双足/四足机器人控制里最经典的概念之一。它定义的是地面反作用力与重力合力的作用点这个点如果落在支撑多边形之外机器人就会失去平衡开始翻转。你可以把 ZMP 理解成“你站在滑板上的压力中心”。滑板静止时你的重心垂直投影必须落在滑板范围内滑板移动时你要不断调整脚底压力分布让压力中心始终留在可控区域内。跑步时ZMP 约束从“全程有效”变成“只在支撑相有效”腾空相没有任何支撑多边形可用。因此现代跑步控制器还需要引入另一套模型来处理腾空阶段。2.4 LIPM 线性倒立摆模型LIPM 是跑步控制里最常用的一种简化模型。它把机器人等效为一个“质心固定高度”的倒立摆支撑点看作脚底接触点。这个模型的价值在于把复杂的全身动力学浓缩成几个关键变量质心位置、质心速度和支撑点位置。跑步控制器的第一层规划往往就是先根据 LIPM 算出质心轨迹再根据轨迹反推每个关节的目标角度和力矩。LIPM 虽然简化了很多但它抓住了运动控制的主干尤其适合用来快速验证算法逻辑是很多双足机器人项目的“第一步模型”。2.5 MPC 与 WBCMPCModel Predictive Control模型预测控制是一种在每一控制周期内用当前状态与动力学模型预测未来一段时间内的系统行为并求取最优控制序列的方法。它非常适合处理跑步中的约束条件比如关节角度限制、力矩上限和地面反作用力范围。WBCWhole-Body Control全身控制则是把任务落实到每个关节的优化框架。MPC 可以算出“质心应该以什么轨迹运动”WBC 负责把这些高层任务映射到“每个关节该输出多少力矩”同时兼顾平衡、接触力、执行器限幅等多个目标。简单说MPC 负责“策略层”WBC 负责“执行层”。两者配合才可能让机器人在跑步这种强动态场景下既“有目标”又“能落地”。2.6 强化学习强化学习在机器人跑步领域越来越常见。核心思路是让机器人策略在一个仿真环境里不断与环境交互收到奖励或惩罚信号最终学到在复杂状态下如何决策动作。与 MPC 相比强化学习不依赖精确的动力学模型更适合处理难以手工建模的接触摩擦、落地冲击和关节非线性。它的问题是训练成本高、仿真到实机迁移困难。目前很多团队的做法是先用仿真训练策略再用少量真实机器人数据微调或者把强化学习策略与 MPC/WBC 结合成混合控制器。2.7 跑步步态的周期结构|The assistant|跑步步态与行走步态的最大差异是存在明显腾空相。以双足人形机器人为例一个完整跑步周期通常分为支撑相、腾空相和触地相。阶段状态控制任务支撑相单腿或双腿着地吸收冲击、调整质心、蓄力向前腾空相双脚离地收缩腿部、调整姿态、准备落地触地相脚刚接触地面缓冲冲击、防止速度损失、快速过渡到支撑相四足机器人原理类似但因为四条腿提供了更大的支撑多边形平衡难度略低所以很多四足项目可以更早展示高速奔跑、跳跃甚至翻滚动作。这也是为什么在热搜词里四足机器人的关注度一直不低的原因之一。3. 跑步机器人的硬件选型与系统架构硬件是机器人跑步的基础。没有足够强的执行器、传感器和计算单元任何高级算法都无从谈起。这一节主要整理“要让机器人跑起来需要哪几类核心硬件”。3.1 关节执行器决定跑步能力的上限跑步对关节执行器的要求非常高。常见方案有三类方案优势局限无框力矩电机 谐波减速器扭矩密度高、精度高成本高、散热难、减速器柔性强盘式电机 行星减速器响应快、结构紧凑制造工艺要求高、批量一致性难保证直驱电机外转子力控精确、无齿隙体积重量大、峰值扭矩相对有限跑步机器人的关节不仅要能在静止时输出大扭矩还要在高速旋转时提供足够功率。每次触地冲击都会反馈到电机输出端如果减速器刚度不足电机和控制器的“判断”就会受到迟滞影响表现就是落地瞬间抖动或失控。从成本与工程难度看无框力矩电机 谐波减速器是目前人形/高动态四足机器人最主流的选择。但电机选型之外还要考虑驱动器带宽与散热。长时间跑步测试时关节温度常常上升得比预期快一旦驱动器过热降额力矩不足就会直接导致摔倒。3.2 传感与状态估计跑步控制必须具备高带宽、低延迟的状态反馈部件主要包括IMU惯性测量单元测量三轴加速度和角速度是机身姿态估计的核心传感器。关节编码器测量每个关节的角度和角速度用于位置环和速度环控制。六维力/力矩传感器安装在脚底或腕部用于检测地面反作用力进而计算 ZMP 和接触状态。在实际系统中这些传感器数据不能单独使用。IMU 有漂移编码器有量化误差力传感器有噪声。控制循环里通常需要用扩展卡尔曼滤波EKF或互补滤波把多源数据融合起来得到更准确的机身状态估计。3.3 计算与通信架构跑步控制频率通常要达到 1kHz 甚至更高。一条典型的控制链路是IMU / 编码器 / 力传感器 ↓ 高频采集 MCU或机载计算机 ↓ 控制解算 关节驱动器 ↓ 电机输出通信协议常见的有 EtherCAT、CAN FD 或私有高速总线。若使用 ROS2则需要把所有传感器数据封装成 Topic供上层算法订阅。这里要特别提醒ROS2 是上层软件生态底层关节伺服往往仍由 MCU 实时控制。把 ROS2 直接用于 1kHz 关节力矩环延迟和抖动通常难以接受。因此稳定架构通常是“底层 MCU 负责实时控制上层工控机或开发板负责 AI 策略和感知ROS2 只做跨节点通信”。4. 从零搭建机器人运动仿真环境对没有实验条件的开发者来说仿真就是最好的“第二基地”。你可以在电脑上先跑通控制算法再决定是否迁移到实机。4.1 为什么先做仿真仿真可以无限次摔倒不烧电机不出安全事故还能反复调整物理参数。更重要的是当前很多开源的机器人模型和算法生态都围绕仿真构建从仿真起步的技术路径最平滑。主流仿真平台有MuJoCo物理引擎开源且效率高支持接触力求解、柔体建模研究双足/四足机器人非常合适。PyBulletPython 接口方便安装简单适合快速原型。Gazebo ROS2适合需要与导航、SLAM、多传感器融合结合的机器人项目。Isaac Sim / Isaac Lab适合大规模强化学习训练和合成数据生成。如果你刚开始接触建议从 MuJoCo 或 PyBullet 入手它们轻量、容易上手可以在自己的电脑上快速跑通最小 Demo。4.2 环境安装示例以 Python 3.10 为例在命令行中执行# 创建虚拟环境 conda create -n robot_sim python3.10 -y conda activate robot_sim # 安装核心依赖 pip install numpy scipy matplotlib mujoco # 如果喜欢 PyBullet也可以安装 pip install pybullet # 验证 MuJoCo 版本 python -c import mujoco; print(mujoco.__version__)安装完成后可以尝试加载 MuJoCo 自带的人形机器人模型。不同版本的 MuJoCo 自带模型路径略有差异请以你本机安装后的文件结构为准。4.3 跑通一个最小仿真模型下面这段代码演示如何用 MuJoCo 加载一个人形机器人模型并前进若干仿真步。它本身不会产生什么有效运动但能验证仿真环境是否可用。import mujoco # 请将路径替换为你本机的实际模型路径 model_path /path/to/humanoid.xml model mujoco.MjModel.from_xml_path(model_path) data mujoco.MjData(model) # 前进 1000 个仿真步 for i in range(1000): mujoco.mj_step(model, data) # 输出机器人前向位置 print(仿真完成机器人前向位置, data.qpos[0])如果这段代码能正常输出位置说明 MuJoCo 安装正确仿真环境可用。PyBullet 的加载方式更轻量一些默认安装包自带四足机器人和地面模型示例代码如下import pybullet as p import pybullet_data import time p.connect(p.GUI) p.setAdditionalSearchPath(pybullet_data.getDataPath()) # 加载地面 p.loadURDF(plane.urdf) # 加载四足机器人模型 robot_id p.loadURDF(quadruped/quadruped.urdf) # 设置重力 p.setGravity(0, 0, -9.81) # 简单示例遍历前 240 个仿真步设置关节目标位置 num_joints p.getNumJoints(robot_id) for _ in range(240): target_positions [0.5] * num_joints p.setJointMotorControlArray( robot_id, jointIndicesrange(num_joints), controlModep.POSITION_CONTROL, targetPositionstarget_positions, ) p.stepSimulation() time.sleep(1.0 / 240.0)这里把每个关节目标设成 0.5只是为了演示 API 用法。真正的步态控制必须结合逆运动学、步态相位和动力学约束来规划目标位置。5. 最小步态控制实现LIPM ZMP 示例下面用 Python 实现一个跑步控制中很常用的线性倒立摆模型LIPM并在此基础上演示如何计算落脚点和 ZMP 稳定性判断。代码不依赖实体机器人可以在仿真环境里继续扩展。5.1 LIPM 模型 Python 实现import numpy as np class LIPM: def __init__(self, z_h, g9.81): self.z_h z_h self.g g self.omega np.sqrt(g / z_h) def predict(self, state, foothold_x, T): 状态: [x, vx] 质心位置与水平速度 foothold_x: 支撑脚的水平位置 T: 预测时间 x, vx state A np.array([ [np.cosh(self.omega * T), np.sinh(self.omega * T) / self.omega], [self.omega * np.sinh(self.omega * T), np.cosh(self.omega * T)] ]) B np.array([ [1 - np.cosh(self.omega * T)], [-self.omega * np.sinh(self.omega * T)] ]) next_state A np.array([x, vx]) B.flatten() * foothold_x return next_state # 初始化跑步场景质心高度 0.9m runner LIPM(z_h0.9) # 当前质心位置 0速度 1.5m/s state np.array([0.0, 1.5]) # 假设支撑脚位置为 0 foothold 0.0 # 预测未来 0.2 秒的质心状态 T_step 0.2 next_state runner.predict(state, foothold, T_step) print(下一步质心状态, next_state)代码逻辑解释state表示当前质心的位置和水平速度。predict方法用 LIPM 的解析解快速推算出未来某个时刻的质心状态。输出结果是一个二维数组分别代表未来的位置和速度。在实际跑步控制器中我们可以用这个预测结果来决定“下一步脚落点到哪里”从而维持目标速度。5.2 规划落脚点的简易闭环下面的函数基于目标速度用 LIPM 模型计算出期望落脚点并输出预测后的质心状态def step_control(state, target_speed, z_h0.9, T_step0.2): model LIPM(z_h) x, vx state # 期望落脚点 当前质心位置 目标速度 × 单步时间 target_foothold x target_speed * T_step # 预测下一步质心状态 next_state model.predict(state, target_foothold, T_step) return target_foothold, next_state # 测试目标速度 2.0 m/s state np.array([0.0, 1.5]) foothold, next_state step_control(state, target_speed2.0) print(目标落脚点, foothold) print(预测下一步状态, next_state)在跑步控制里这个“目标落脚点”会被进一步转换为髋关节和膝关节的目标角度带动整条腿迈到预定落点。速度越高落脚点就离当前质心越远对腿部摆动速度和关节驱动能力的要求也会增加。5.3 ZMP 稳定性判断示例ZMP 是否落在支撑多边形内是判断机器人是否稳定的重要依据。下面给出一个简化示例def check_zmp_in_polygon(zmp_x, zmp_y, polygon): 检查 ZMP 是否落在支撑多边形内 polygon: [(x1, y1), (x2, y2), ...] 顶点列表 这里简化为矩形边界判断 min_x min(p[0] for p in polygon) max_x max(p[0] for p in polygon) min_y min(p[1] for p in polygon) max_y max(p[1] for p in polygon) return min_x zmp_x max_x and min_y zmp_y max_y # 示例支撑脚落在 x0, y0 附近支撑区域约为 0.2m × 0.2m support_polygon [(-0.1, -0.1), (0.1, -0.1), (0.1, 0.1), (-0.1, 0.1)] # 当前 ZMP 位置 zmp_x, zmp_y 0.02, -0.03 print(ZMP 是否合规, check_zmp_in_polygon(zmp_x, zmp_y, support_polygon))如果 ZMP 靠近支撑多边形边缘说明稳定裕度不足下一步控制器就需要调整姿态或落点把 ZMP 重新拉回中心区域。5.4 强化学习策略接入控制循环的框架如果你选择走强化学习路线控制循环大致如下。这里用伪代码展示结构重点在于说明 RL 策略与底层仿真之间的交互方式。# 伪代码RL 步态控制循环 def get_observation(data): # 状态观测质心位置、速度、关节角度、关节角速度、上一动作 return np.concatenate([ data.qpos[:3], # 机身位置 data.qvel[:3], # 机身速度 data.qpos[7:], # 关节角度 data.qvel[6:], # 关节角速度 ]) def compute_action(obs, policy): # 将 obs 输入策略网络得到动作向量 return policy(obs) for step in range(max_steps): obs get_observation(data) action compute_action(obs, policy) # 将 action 映射为关节目标位置或力矩增量 set_joint_action(action) mujoco.mj_step(model, data)实际工程中set_joint_action会根据策略输出是“目标位置”还是“力矩增量”来做不同处理。如果是位置控制模式策略输出经过 PD 控制器变成力矩如果是力矩控制模式策略输出直接作为关节力矩目标。高频循环保证了策略的实时性同时需要把状态估计放在get_observation中完成确保策略输入的是融合后的准确状态。6. 运行结果与效果验证写完控制代码后不能只满足于“机器人没倒”。你需要有明确指标来判断是否真的“跑起来了”。6.1 主要验证指标指标说明靠谱的参考范围质心
返回列表