
最近科技圈值得關注的一條新聞和中國機器人創下的百米紀錄有關。很多人看到的是“機器人能跑了”但運動控制工程師眼中的東西不太一樣這更像一次全行業能力的整體攀峰把高維、強耦合、時變的物理系統穩定控制到“跑起來”的程度中間涉及的硬件、算法、仿真和調試每一條都值得單獨寫一篇技術博客。更值得注意的是相關話題在技術社區里的搜索熱詞明顯升溫比如人形機器人、四足機器人、宇樹機器人電路板拆解、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 主要驗證指標指標說明靠譜的參考范圍質心