机器人全身控制浅谈:理解 WBC 的原理

机器人全身控制浅谈:理解 WBC 的原理

概念

WBC(Whole-Body Control,全身控制)是什么?机器人是由“各关节”组成的,其不是“各关节各玩各的”而是一个耦合的整体。在某个时刻可能要做很多事情,比如保持平衡(重心别出圈)、手/脚要动作到目标位置、躯干姿态不能乱、关节不能超限、脚下不能打滑。这些都是一系列任务的组合。

WBC的核心就是把这些任务(目标)和约束(物理/安全)写进一个小型优化问题,在每个控制周期(几百hz~1Khz)求解,得到**“当下这毫秒,各关节应该怎么动/用多大力”**。

一句话总结就是WBC就是用优化的方法求解出要给“关节多少力“”以便让机器的各个关节一起配合完成多个目标,且不违反物理与安全约束。

原理

动力学方程

要解释WBC的原理,那必须绕不开动力学方程,这里就先对动力学方程做个简单介绍。

M(q)v˙+h(q,v)=STτ+JcTλ M(q)\dot{v} + h(q,v) = S^T \tau + J_c^T \lambda M(q)v˙+h(q,v)=STτ+JcT​λ

配合接触约束:

Jcv=0,λ∈摩擦锥 J_c v = 0,\quad \lambda \in \text{摩擦锥} Jc​v=0,λ∈摩擦锥

通俗理解公式就是:“惯性 × 加速度 + 自然出现的力 = 电机能给的力 + 地面/物体的反力”

公式左边:机器人自身的自然物理

  • M(q)v˙M(q)\dot{v}M(q)v˙:惯性项。M(q)M(q)M(q)是质量矩阵,描述机器人在不同姿态下的惯性特性。$\dot{v} 是广义加速度(关节加速度或身体的加速度);其意义就像是广义加速度(关节加速度或身体的加速度);其意义就像是广义加速度(关节加速度或身体的加速度);其意义就像F=ma里面的里面的里面的ma$,表示加速一个有惯性的物体需要的力
  • h(q,v)h(q,v)h(q,v):重力+速度相关项(科氏力、离心力)。如果机器人静止,这里主要就是重力。如果在运动,这里就会出现"速度带来的额外力",类似开车转弯时身体被甩出去的感觉。

公式右边:外界能提供的“驱动力”

  • STτS^T \tauSTτ:电机能施加的关节力矩。τ\tauτ电机产生的力矩(控制器的输出),STS^TST选择矩阵,把电机力矩映射到广义坐标系中。
  • JcTλJ_c^T \lambdaJcT​λ:接触点反力。λ\lambdaλ来自地面或物体的力(约束反作用力),JcJ_cJc​接触点的雅可比,把关节速度映射到接触点速度。JcTλJ_c^T \lambdaJcT​λ把“地面推脚的力”转换回“关节的力”。

直观记忆就是类比现实生活中的推车子:

  • 你推车:电机力矩τ\tauτ。
  • 地面支撑车子:接触反力λ\lambdaλ。
  • 车子有质量,要加速就得克服惯性:M(q)v˙M(q)\dot{v}M(q)v˙。
  • 重力和转弯的惯性: h(q,v)h(q,v)h(q,v)。

接触力约束

还要满足接触力约束Jcv=0,λ∈摩擦锥J_c v = 0,\quad \lambda \in \text{摩擦锥}Jc​v=0,λ∈摩擦锥,其中Jcv=0J_c v = 0Jc​v=0意义是接触点速度为0,比如机器人脚贴在地上不滑、不穿透;λ∈摩擦锥\quad \lambda \in \text{摩擦锥}λ∈摩擦锥意义是接触力必须满足摩擦模型,脚不会不穷大摩擦,力要在摩擦椎范围内。

公式中涉及到一个雅可比,什么是雅可比JcJcJc?

假设有一个机械臂:

  • 关节角度:就像是控制的"按钮"。
  • 手末端的位置:就是最终关心的"结果"。

那么问题就是关节角度动一动,末端的位置会怎么动了?这个"关节空间的微小变化"影响到“末端空间的微小变化”。这样一个映射关系,就是雅可比矩阵JJJ。

图中红色箭头表示关节角度的小变化Δθ1,Δθ2\Delta \theta_1 , \Delta \theta_2Δθ1​,Δθ2​。红色箭头的变换导致绿色箭头末端位置的变化:Δx,Δy\Delta x , \Delta yΔx,Δy。雅可比矩阵 JJJ 就是把

[Δθ1Δθ2]⟶[ΔxΔy] \begin{bmatrix}\Delta \theta_1 \\ \Delta \theta_2\end{bmatrix} \longrightarrow \begin{bmatrix}\Delta x \\ \Delta y\end{bmatrix} [Δθ1​Δθ2​​]⟶[ΔxΔy​]

因此如果想要末端动多少就用JJJ,想算末端力传回关节多少就用JTJ^TJT。

总结一下雅可比JJJ就是关节空间和任务空间的桥梁,作用就是我们关节动多少,末端/接触点动多少。

动力学方程在WBC中的用处?

动力学方程是机器人身体运动的"牛顿定律",我们来看看WBC的目标是什么?WBC不只是让机器人"走"或"站",而是要全身协调,比如要去抓杯子,脚要保持不滑,躯干要保持平衡,关节力矩不能超过电机限制。所以WBC的本质是解一个优化问题,找出一组关节力矩τ\tauτ,既能完成任务目标,又满足动力学方程和约束

优化问题

WBC的核心思路是把机器人全身的目标任务转化为优化问题,在满足物理规律和约束条件的前提下,求出最合适的一组关节力矩τ\tauτ。

具体一点在WBC中求解的决策变量通常是如下三个:

x=[v˙τλ] x = \begin{bmatrix} \dot{v} \\ \tau \\ \lambda \end{bmatrix} x=​v˙τλ​​

  • 最优的关节力矩τ\tauτ。
  • 接触点反力λ\lambdaλ。
  • 机器人下一步的加速度$\dot{v} $。

优化问题转换为数学的目标函数如下

min⁡x∥Jtaskv˙−v˙des∥2+∥τ∥2+∥λ∥2 \min_{x} \| J_{\text{task}} \dot{v} - \dot{v}_{\text{des}} \|^2 + \| \tau \|^2 + \| \lambda \|^2 xmin​∥Jtask​v˙−v˙des​∥2+∥τ∥2+∥λ∥2

公式中Jtaskv˙−v˙desJ_{\text{task}} \dot{v} - \dot{v}_{\text{des}}Jtask​v˙−v˙des​表示实际加速度与期望加速度的误差,Jtaskv˙J_{\text{task}} \dot{v}Jtask​v˙是在当前关节加速度下,末端/任务空的实际加速度,而v˙des\dot{v}_{\text{des}}v˙des​是我们期望任务空间实现的期望加速度(比如手往前加速 0.5 m/s²,质心保持 0 加速度)。

同时优化问题还要满足以下约束条件:

  • 动力学约束:M(q)v˙+h(q,v)=STτ+JcTλM(q)\dot{v} + h(q,v) = S^T \tau + J_c^T \lambdaM(q)v˙+h(q,v)=STτ+JcT​λ。这是硬约束,控制器必须遵守。
  • 接触约束:Jcv=0J_c v = 0Jc​v=0,接触点不能乱动(不滑、不穿透)。
  • 摩擦约束:λ∈Kfric\lambda \in \mathcal{K}_{\text{fric}}λ∈Kfric​,接触力必须符合摩擦模型(不能无限大)。
  • 力矩限制:τmin⁡≤τ≤τmax⁡\tau_{\min} \leq \tau \leq \tau_{\max}τmin​≤τ≤τmax​。

总结一下优化问题的目标函数意思就是要满足任务误差最小化(手/身体/质心的加速度跟踪目标),同时要满足能量或力矩最小化(不能浪费力),同时满足接触力正则化(力要稳定不能乱跳)。

方程有了,怎么求解了?

这个目标函数是一个二次型,符合QP,所以可以用现成的QP求解器来解,例如:OSQP、qpOASES、Gurobi(商业求解器)、CPLEX(商业求解器)、CVXPy(Python 封装,常用于原型),这里就不过多阐述了。

总结一下WBC核心就是要解决一个优化问题:二次目标(误差最小 + 力矩正则) + 动力学/接触/摩擦/限幅约束。其求解的方式通常使用QP 求解器(实时、高效、全局最优)。求解的结果是关节力矩τ\tauτ(给电机执行),同时还得到加速度v˙\dot{v}v˙和接触力λ\lambdaλ。

示例

接下来我们调用cvxpy库看看示例,直观体验一下。

import cvxpy as cp import numpy as np # ---- 机械臂参数 ---- l1, l2 =1.0,1.0 m1, m2 =1.0,1.0 theta1, theta2 = np.deg2rad(45), np.deg2rad(30)# ---- 雅可比(末端位置对关节的导数)---- J_task = np.array([[-l1*np.sin(theta1)- l2*np.sin(theta1+theta2),-l2*np.sin(theta1+theta2)],[ l1*np.cos(theta1)+ l2*np.cos(theta1+theta2), l2*np.cos(theta1+theta2)]])# ---- 动力学质量矩阵 M(简化版)---- M = np.array([[m1*l1**2+ m2*(l1**2+ l2**2+2*l1*l2*np.cos(theta2)), m2*(l2**2+ l1*l2*np.cos(theta2))],[m2*(l2**2+ l1*l2*np.cos(theta2)), m2*l2**2]]) h = np.zeros(2)# 忽略重力/科氏项# ---- 接触约束:假设末端y方向不能动(竖直方向约束)---- Jc = np.array([[0,1]]) @ J_task # 取末端y方向的行# ---- 变量 ---- ddq = cp.Variable(2)# 关节加速度 tau = cp.Variable(2)# 力矩 lam = cp.Variable(1)# 接触力 (竖直反作用力)# ---- 期望任务加速度(末端x方向=1.0, y方向=0.0)---- xddot_des = np.array([1.0,0.0])# ---- 目标函数:末端任务 + 力矩/接触力正则 ---- objective = cp.Minimize( cp.sum_squares(J_task @ ddq - xddot_des)+0.01*cp.sum_squares(tau)+0.01*cp.sum_squares(lam))# ---- 约束 ---- constraints =[ M @ ddq + h == tau + Jc.T @ lam,# 动力学方程 Jc @ ddq ==0,# 接触点不加速 tau >=-10, tau <=10, lam >=0# 接触力必须向上推]# ---- 求解 ---- prob = cp.Problem(objective, constraints) prob.solve()print("Optimal joint accelerations:", ddq.value)print("Optimal torques:", tau.value)print("Optimal contact force λ:", lam.value)print("End-effector acc achieved:", J_task @ ddq.value)print("Desired end-effector acc :", xddot_des)

上面的示例中可以分为几部分:

(1)任务

末端(手)在水平 xxx 方向产生 1.0m/s21.0 \text{m/s}^21.0m/s2 的加速度。在垂直 yyy 方向不要加速(因为手撑在桌子上,不应该离开桌面)。

数学写法:

x¨des=[1.0,0.0]T \ddot{x}_{des} = [1.0,0.0]^T x¨des​=[1.0,0.0]T

(2)决策变量

优化器要决定的量是

q¨=[θ¨1,θ¨2]T,τ=[τ1,τ2]T,λ \ddot{q} = [\ddot{\theta}_1,\ddot{\theta}_2]^T, \quad \tau = [\tau_1,\tau_2]^T, \quad \lambda q¨​=[θ¨1​,θ¨2​]T,τ=[τ1​,τ2​]T,λ

(3)要优化的目标函数

最小化

min⁡q¨, τ, λ∥Jtaskq¨−x¨des∥2+0.01∥τ∥2+0.01∥λ∥2 \min_{\ddot{q},\;\tau,\;\lambda}\| J_{\text{task}} \ddot{q} - \ddot{x}_{des} \|^2+ 0.01 \|\tau\|^2+ 0.01 \|\lambda\|^2 q¨​,τ,λmin​∥Jtask​q¨​−x¨des​∥2+0.01∥τ∥2+0.01∥λ∥2

(4)约束条件

  • 动力学约束:M(q)q¨+h(q,q˙)=τ+JcTλM(q)\ddot{q} + h(q,\dot{q}) = \tau + J_c^T \lambdaM(q)q¨​+h(q,q˙​)=τ+JcT​λ
  • 接触约束:Jcq¨=0J_c \ddot{q} = 0Jc​q¨​=0
  • 力矩范围:−10≤τi≤10-10 \leq \tau_i \leq 10−10≤τi​≤10
  • 接触力非负:λ≥0\lambda \geq 0λ≥0

(5)输出结果

最后调用

prob = cp.Problem(objective, constraints) prob.solve()

求解得出结果:

Optimal joint accelerations:[0.50615867-1.88900987] Optimal torques:[-1.12977187-0.94450493] Optimal contact force λ:[1.29515155e-23] End-effector acc achieved:[9.77823461e-01-5.00938335e-17] Desired end-effector acc :[1.0.]

QP 解出来的就是

  • 最优关节加速度:q¨\ddot{q}q¨​
  • 最优关节力矩:τ\tauτ
  • 接触反力:λ\lambdaλ
  • 实际末端加速度:x¨=Jtaskq¨\ddot{x} = J_{\text{task}} \ddot{q}x¨=Jtask​q¨​

并与期望值 x¨des\ddot{x}_{des}x¨des​ 对比。

上面的代码中只截取了关键部分,下面是绘制图像的效果如下,可以直观体会看看:

WBC与MPC

上一篇文章我们分析了MPC,那么MPC与WBC什么关系了?

MPC在WBC之上,MPC作为决策层做"未来几步的规划",比如预测未来1S内,质心应该怎么移动,脚该放哪里,其输出的是期望的任务轨迹。WBC是在下层,拿到MPC给的任务(目标加速度/姿态/接触序列)在动力学和接触约束下,求解QP得到当下这一瞬间的关节力矩τ\tauτ。简而言之MPC决定“机器人未来要往哪走”,WBC决定“当前每个关节该怎么出力”。

举个例子:双足机器人走路

  • MPC:优化未来 1 秒的 质心轨迹、摆腿位置、支撑相切换。输出:期望的 x¨des\ddot{x}_{des}x¨des​(质心加速度)、脚的落点计划。
  • WBC:把这些期望当作任务输入,解 QP ,输出关节力矩 τ\tauτ,同时计算接触力 λ\lambdaλ,保证机器人在每一步不摔倒。

Read more

AI 的智能体专栏:手把手教你用豆包打造专属 Python 智能管家,轻松解决编程难题

AI 的智能体专栏:手把手教你用豆包打造专属 Python 智能管家,轻松解决编程难题

AI 的智能体专栏:手把手教你用豆包打造专属 Python 智能管家,轻松解决编程难题 AI 的智能体专栏:手把手教你用豆包打造专属 Python 智能管家,轻松解决编程难题,本文介绍了如何利用豆包平台打造专属Python智能管家。首先简述豆包平台的核心优势,接着说明创建前的准备工作,包括注册账号、明确定位和收集训练资料。随后详细讲解创建流程,从新建智能体、基础设置、能力配置到测试优化,还提及集成代码执行环境等高级功能扩展,以及使用技巧与实际应用案例。该智能官能解决多种Python编程问题,可提升学习效率和问题解决速度,是实用的个性化编程助手。 前言     人工智能学习合集专栏是 AI 学习者的实用工具。它像一个全面的 AI 知识库,把提示词设计、AI 创作、智能绘图等多个细分领域的知识整合起来。无论你是刚接触 AI 的新手,还是有一定基础想提升的人,都能在这里找到合适的内容。从最基础的工具操作方法,到背后深层的技术原理,专栏都有讲解,还搭配了实例教程和实战案例。这些内容能帮助学习者一步步搭建完整的 AI 知识体系,让大家快速从入门进步到精通,

By Ne0inhk
Python 多线程日志错乱:logging.Handler 的并发问题

Python 多线程日志错乱:logging.Handler 的并发问题

Python 多线程日志错乱:logging.Handler 的并发问题 🌟 Hello,我是摘星! 🌈 在彩虹般绚烂的技术栈中,我是那个永不停歇的色彩收集者。 🦋 每一个优化都是我培育的花朵,每一个特性都是我放飞的蝴蝶。 🔬 每一次代码审查都是我的显微镜观察,每一次重构都是我的化学实验。 🎵 在编程的交响乐中,我既是指挥家也是演奏者。让我们一起,在技术的音乐厅里,奏响属于程序员的华美乐章。 目录 Python 多线程日志错乱:logging.Handler 的并发问题 摘要 1. 问题现象与复现 1.1 典型的日志错乱场景 2. logging模块的线程安全机制分析 2.1 Handler级别的线程安全 2.2 锁竞争的性能影响分析 3. 深入源码:竞态条件的根本原因 3.1 Handler.emit()方法的竞态分析 3.2 I/O操作的原子性问题

By Ne0inhk

从Python到AI的完整成长路径:新手少走90%弯路,一步步落地不迷茫

很多人想学AI,却总卡在第一步——不知道Python学到什么程度才算够,也不清楚从代码到AI模型到底要跨过哪些坎,要么盲目啃理论,要么瞎找项目练手,最后半途而废。 作为从零基础Python入门,一步步走到AI实战、整理过机器学习项目合集的过来人,我把从Python到AI的完整过程拆成4个核心阶段,没有晦涩术语,每一步都有明确目标和实操方向,新手照着走,就能平稳过渡,不迷茫、不踩坑。 第一阶段:Python打底——不是全学,而是学“AI刚需部分” 很多人误区:把Python从基础语法到爬虫、Web开发全学一遍,浪费半年时间,其实AI方向不需要全学Python,只需要掌握核心工具包和基础语法,够写AI相关代码就行,1-2个月就能搞定。 必学内容(优先级从高到低): 1. 基础语法(快速过):变量、数据类型、循环、条件判断、函数、类与对象,不用深究复杂语法,能看懂代码、写简单逻辑即可; 2. AI三大核心库(重中之重): 1. NumPy:数组运算、

By Ne0inhk
【测试基础】Python 核心语法,一篇搞定测试脚本开发基础

【测试基础】Python 核心语法,一篇搞定测试脚本开发基础

🔥个人主页: 中草药  🔥专栏:【Java】登神长阶 史诗般的Java成神之路 本文不做Python以及Pycharm安装的详细教程,请大家自行查阅资料,或到官网去下载         Python作为一门 “优雅且强大” 的编程语言,Python 凭借易上手、用途广的特点,成为很多人入门编程的首选。无论是数据分析、人工智能,还是 Web 开发、自动化脚本,Python 都能胜任。但想要用好 Python,扎实的基础语法是关键 —— 本文将结合系统的语法知识,从 “计算器” 级别的简单运算,到数据持久化的文件操作,带你一站式吃透 Python 核心语法,让你看完就能上手写代码! 变量与数据类型:程序的"原材料仓库"         变量就像快递盒,用来装不同类型的数据;数据类型则是快递盒上的标签,告诉我们里面装的是文件、水果还是电子产品。类型系统其实是在对变量进行 "归类"

By Ne0inhk