机器人运动控制学习5——状态估计 State Estimation进阶
接触估计 Contact Estimation
这一课在人形机器 人里非常关键,因为从这里开始,你会发现:
光知道身体姿态还不够,机器人还必须知道自己现在“靠什么支撑”。
机器人并没有“脚底感觉”,机器人必须自己判断:
我哪只脚现在真的接触地面?
传感器
↓
┌─────────────────┐
│ 状态估计 │
│ │
│ 身体姿态 │
│ 身体速度 │
│ 身体位置 │
│ 关节状态 │
│ 接触状态 ← 新的 │
└────────┬────────┘
↓
MPC/WBC
所以:
“脚有没有踩地”本身就是机器人状态的一部分。
机器人怎么判断脚踩没踩地?
足底力传感器
比如脚底测到:
Fz = 400 N
很明显:
这只脚正在承受机器人重量。
于是:
contact = true
滞回 Hysteresis
不用一个阈值:
30 N
而是使用两个阈值:
接触阈值:40 N
离地阈值:20 N
于是:
从离地变成接触
必须:
Fz > 40 N
才宣布:
踩地了。
已经踩地以后
只有:
Fz < 20 N
才宣布:
离地了。
中间:
20 ~ 40 N
怎么办?
保持之前状态。
这样刚才:
35
28
40
32
就不会疯狂:
0 1 0 1
来回切。
这是工程控制中特别常见的思想:
不要因为传感器一点点抖动,就不断改变系统状态。
但是如果没有脚底力传感器怎么办?有些机器人可以结合:
关节编码器
+
IMU
+
电机力矩
+
运动学
去推测。例如机器人认为:
脚正在往下运动
突然发现:
脚的位置不再继续下降
同时:
关节力矩发生变化
那么:
很可能脚碰地了。
所以接触状态不一定必须靠一个传感器,也可以:多信息融合
现在把编码器、IMU、接触一起放进去
你之前学的东西终于可以合起来了:
IMU
┌─────┴─────┐
↓ ↓
角速度 加速度
│ │
└─────┬─────┘
↓
身体运动预测
│
│
编码器 ─────────┼────→ 腿部运动学
│
↓
状态估计器
↑
│
脚接触状态
│
足底力 / 力矩 / 运动学
│
↓
┌──────────────┐
│ Base姿态 │
│ Base速度 │
│ Base位置 │
│ 关节状态 │
│ 接触状态 │
└───────┬──────┘
↓
WBC/MPC
这已经非常接近真正人形机器人的系统结构了。
Base
以后你会经常看到:
base
base_pos
base_vel
base_quat
base_omega
这里的 base 可以粗略理解:
机器人身体主体的参考坐标系。
在人形机器人里通常会选择类似:
pelvis
torso
base link
作为主体,于是状态估计很重要的任务就是估:
Base position
Base orientation
Base linear velocity
Base angular velocity
翻译:
身体在哪里
身体朝哪
身体移动多快
身体旋转多快
“接触”和“无滑动接触”
必须区分:
Contact
和:
Stable Contact
也就是:
接触地面
不等于:
牢牢固定在地面
所以高级一点的状态估计还要判断:
有没有打滑?
例如:
脚底力:
说我踩地
但是运动学估出来:
脚相对于世界似乎在横向快速移动
同时 IMU 也发现:
身体运动和预期对不上
那么:
这只脚可能正在滑。
这时候状态估计器应该:
降低这只脚的信息可信度
而不是死信它。你会发现:
状态估计真正核心不是“算一个公式”,而是不断判断“现在该相信谁”。
刚开始可能觉得状态估计就是:
IMU滤一滤
其实远远不是。
人形机器人真正需要的状态可能包括:
关节位置 q
关节速度 dq
身体姿态 R / quaternion
身体角速度 ω
身体位置 p
身体线速度 v
左脚是否接触
右脚是否接触
脚是否打滑
甚至还可能包括:
IMU bias
外力
地面状态
所以:
State Estimation
真正可以理解成:
把一堆不完美的传感器信息拼起来,尽可能还原机器人此时此刻真实的物理状态。
真实机器人
│
┌─────────────────┼─────────────────┐
↓ ↓ ↓
编码器 IMU 足部信息
│ │ │
└─────────────────┼─────────────────┘
↓
State Estimator
│
┌──────────────┼───────────────┐
↓ ↓ ↓
q、dq Base状态 Contact状态
│ │ │
└──────────────┼───────────────┘
↓
MPC / WBC
↓
控制命令
↓
电机
↓
机器人
这一张图,你后面会反复用。
Base Velocity Estimation
编码器
+
IMU
+
支撑脚接触
+
机器人运动学
↓
Base Velocity
也就是:
机器人怎么知道自己的身体正在往哪个方向移动、移动多快。
编码器能测:
髋关节角
膝关节角
踝关节角
肩关节角
……
还能估:
各个关节转得多快
也就是:
q
dq
但是编码器不知道:
整个机器人相对于房间到底有没有移动。
关节运动 ≠ 整个机器人在世界中的运动。
IMU主要给你:
陀螺仪
→ 角速度
加速度计
→ 比力 / 与重力相关的加速度测量
它没有一个传感器直接说:
“现在机器人向前 0.43 m/s”
没有。所以 Base Velocity 必须:估出来,这就是为什么它属于:
State Estimation
加速度积分
我们先假装世界很完美,如果机器人向前加速:
a = 1 m/s²
那么1秒后大概:
v = 1 m/s
所以理论上:
加速度
↓ 积分
速度
重力
加速度计受到姿态影响特别大,因为我们真正想知道:
机器人平移加速度
但传感器读数里会混进:
重力方向
所以需要先知道:
机器人当前姿态
再把重力分量处理掉。链路大概是:
Accelerometer
↓
原始测量
↓
利用姿态估计
↓
处理重力影响
↓
得到线性加速度估计
↓
积分
↓
速度
Leg Odometry 腿式里程计
它的核心思想之一就是:
利用腿部编码器 + 运动学 + 支撑脚约束,反推出身体的运动。
大致:
编码器 q、dq
↓
腿部运动学
↓
算脚相对 Base 的运动
↓
知道支撑脚世界速度 ≈ 0
↓
反推出 Base velocity
IMU
/ \
/ \
加速度 角速度
│ │
│ │
└──────┬──────┘
│
▼
Base预测
▲
│
编码器 q、dq
│
▼
腿部运动学
│
▼
支撑脚约束
│
▼
Base速度修正
这才是真正的 Sensor Fusion 传感器融合
IMU的优点
IMU更新很快。对:
突然运动
身体快速转动
短时间动态变化
非常敏感,所以:
短时间变化通常很好。
IMU的问题
主要是:
bias
噪声
重力处理误差
积分漂移
所以:
时间长了容易漂。
腿部运动学的优点
如果:
支撑脚真的牢牢踩地
那么:
脚速度≈0
是一个很强的物理约束,可以帮助纠正:
IMU速度漂移
腿部运动学的问题
假如:
脚打滑
那:
脚速度≈0
这条假设就错了,于是 Leg Odometry 也会骗人。
具体的走路过程理解
假设机器人正在向前走,当前:
左脚 = 支撑
右脚 = 摆动
状态估计开始工作。
第一步:IMU
IMU告诉我们:
身体角速度
身体加速度
比如:
身体正在稍微向前加速
第二步:编码器
编码器告诉我们:
左腿髋关节速度
左膝速度
左踝速度
也就是:
dq_left
第三步:运动学
根据:
q_left
+
dq_left
计算:
左脚相对于Base怎么运动
比如:
向后0.45 m/s
第四步:接触估计
系统判断:
左脚 = 稳定接触
因此:
左脚世界速度 ≈ 0
第五步:反推
于是:
Base大约向前0.45m/s
第六步:和IMU融合
IMU可能预测:
0.48 m/s
腿运动学估计:
0.45 m/s
状态估计器综合后可能输出:
0.46 m/s
注意,这里的数字只是为了理解。
真正系统不会简单地:
(0.48+0.45)/2
完事,而会根据:
传感器噪声
可信度
接触状态
历史状态
模型
做融合。
EKF 和 KF
因为机器人运动通常是:
旋转
三维姿态
非线性运动学
不是简单的:
直线匀速小车
很多关系不是简单线性的。
“浮动基座机器人” Floating-base Robot
浮动基座机器人。
为什么?
机械臂通常:
底座
████████████
固定在桌子上
所以 Base:
位置固定
你根本不用估:
base velocity
但人形机器人:
O
/|\
|
/ \
整个身体可以:
前后移动
左右移动
上下移动
翻滚
俯仰
转向
所以 Base 并没有固定在世界上。
这就叫:
Floating Base。
因此状态里除了关节:
q_joint
还必须考虑:
Base position
Base orientation
Base velocity
Base angular velocity
状态估计的输出
你以后看人形机器人代码,可能会看到类似:
state.base_position
state.base_velocity
state.base_orientation
state.base_angular_velocity
state.joint_position
state.joint_velocity
state.left_contact
state.right_contact
也可能名称完全不同。
但意思差不多:
身体位置
身体速度
身体姿态
身体角速度
关节位置
关节速度
左右脚接触状态
然后:
State Estimator
↓
MPC
↓
WBC
编码器
↓
q、dq
↓
知道机器人关节怎么动
陀螺仪
↓
身体角速度
↓
帮助估计姿态变化
加速度计
↓
身体受到的惯性/重力相关信息
↓
帮助预测运动
姿态估计
↓
知道身体朝哪
↓
正确处理重力方向
Contact Estimation
↓
知道哪只脚踩地
Leg Kinematics
↓
利用支撑脚约束
↓
估计Base Velocity
Kalman / EKF
↓
融合所有信息
最终:
State Estimate
│
├─ q
├─ dq
├─ base position
├─ base velocity
├─ base orientation
├─ base angular velocity
└─ contact state
再交给:
MPC / WBC
这已经非常接近真正的人形机器人运控架构了。
┌──────────────┐
│ Encoder │
│ q / dq │
└──────┬───────┘
│
↓
Leg Kinematics
│
│
┌──────────────┐ │
│ IMU │ │
│ gyro / acc │ │
└──────┬───────┘ │
│ │
↓ ↓
Orientation Foot Velocity
Estimation │
│ │
│ ┌──────┴──────┐
│ │ Contact │
│ │ Estimation │
│ └──────┬──────┘
│ │
└─────────┬──────────┘
↓
┌──────────────────┐
│ State Estimator │
│ EKF / etc. │
└────────┬─────────┘
↓
┌──────────────────┐
│ Base position │
│ Base velocity │
│ Base orientation │
│ Base omega │
│ q / dq │
│ Contact │
└────────┬─────────┘
↓
MPC / WBC
↓
Robot
加速度积分能得到速度,但:
积分会放大 bias、噪声和姿态误差,长期会漂。
利用:
编码器
+
腿部运动学
+
支撑脚约束
可以反推出:
Base velocity
这就是腿式里程计的重要思想。
IMU负责:
短时间快速预测。
支撑脚/腿部运动学负责:
提供物理约束、纠正漂移。
滤波器负责:
把它们融合起来。
IMU
↘
编码器 → State Estimator → Base State → MPC/WBC
↗
接触
而不是:
某一个传感器
↓
直接得到机器人真实状态
机器人永远没有这么幸运。
Odometry —— 里程计
最直觉的理解:
速度
↓
不断累积
↓
位置
比如机器人向前以:
1 m/s
走1秒。那大概前进:
1 m
再走1秒:
2 m
所以:
当前位置
=
上一时刻的位置
+
这一小段时间走过的距离
程序思维大概就是:
position = position + velocity * dt;
例如控制周期:
dt = 0.01 s
当前速度:
vx = 0.5 m/s
这一帧就大概前进:
0.5 × 0.01
=
0.005 m
也就是5毫米。然后下一帧继续加。
机器人领域里的 odometry :
根据自身传感器,估计“我相对于刚开始的位置,移动了多少”。
它通常告诉你的是相对运动。
而不是:
“我现在在东京某实验室的精确经纬度和绝对坐标。”
Leg Odometry
上一课我们讲过:
编码器 q、dq
+
支撑脚
+
腿部运动学
↓
Base Velocity
现在只要继续:
Base Velocity
↓
积分
↓
Base Position
于是:
Encoder
↓
Leg Kinematics
↓
支撑脚约束
↓
Base Velocity
↓
时间积分
↓
Base Position
这就是腿式机器人 odometry 的基本思路之一。甚至可以不用先算速度,直接利用支撑脚位置
还有另外一种直觉。假设机器人左脚落地以后,我们说:
左脚在世界的位置暂时固定
例如:
left_foot_world =
(1.0, 0.1, 0)
编码器告诉我们:
Base相对于左脚在哪里
那么反过来:
已知左脚世界位置
+
腿部正运动学
↓
推算Base世界位置
例如:
地面
────────────● 左脚
\
\
[Base]
脚作为锚点,这时候机器人身体怎么移动,可以通过腿的几何关系推出来,但机器人走一步之后,锚点变了,比如:
阶段1
左脚支撑
右脚向前迈
此时:
左脚 = 世界锚点
然后右脚落地:
阶段2
左右脚都接触
接下来左脚抬起来:
阶段3
右脚支撑
现在:
右脚 = 新的世界锚点
于是整个过程中:
左脚锚定
↓
右脚落地
↓
锚点切换
↓
右脚锚定
↓
左脚落地
↓
再次切换
这就是腿式机器人走路时很典型的过程。
“外部纠偏”
假设机器人 odometry 认为:
我在 x = 10.4 m
但另一个外部传感器告诉它:
实际上你应该在 x = 9.9 m
那状态估计器就可以发现:
我漂了0.5 m
然后进行修正。
所以完整思路逐渐变成:
IMU
+
Encoder
+
Leg Odometry
↓
高频运动估计
↓
但是会漂
↓
外部定位信息
↓
修正漂移
谁可以提供外部位置参考?
-
GPS / GNSS:室外可以直接给全球位置参考,但室内通常不好用。
-
VIO:Visual-Inertial Odometry,视觉+IMU,根据摄像头看到的环境特征估运动。
-
LiDAR Odometry / SLAM:用激光雷达扫描环境,根据前后扫描的匹配估计机器人移动。
-
Motion Capture:实验室里的光学动作捕捉系统可以非常准确地给机器人世界位置。
-
UWB / Beacon:通过外部基站提供位置约束。
这些东西看起来五花八门,其实共同目的就是:
给机器人一个来自“外部世界”的参考,不让自己的内部 odometry 无限漂下去。
Localization
Odometry:我从刚才到现在动了多少。
Localization:我现在到底在地图的哪里。
例如:
Odometry:
我向前走了5米。
而:
Localization:
我现在位于实验室地图坐标
x = 12.3
y = 4.7
所以可以粗略理解:
Odometry
↓
关注相对运动
Localization
↓
关注世界/地图中的位置
当然实际工程里两者会深度融合,不一定严格分开。
State Estimation 和 Localization
State Estimation 更大。
它问:
机器人现在整个状态是什么?
可能包括:
Base Position
Base Velocity
Base Orientation
Base Angular Velocity
q
dq
Contact State
IMU Bias
...
而 Localization 主要关心:
我在哪里
+
我朝哪个方向
所以你可以把关系暂时理解成:
State Estimation
│
┌────────────┼────────────┐
↓ ↓ ↓
Orientation Velocity Position
│
↓
Localization
不是严格的数学分类,但非常适合你现在建立框架。
odom
机器人根据自己的传感器“推算出来的局部运动坐标系”。
它不是某个传感器,也不是某个关节,而通常是一个坐标系 / 里程计参考系,在 ROS / ROS2 里,你以后经常会看到:
map
↓
odom
↓
base_link
这里分别可以先这样理解:
-
map:全局世界坐标系,强调“我在整个地图哪里” -
odom:局部连续坐标系,强调“我从启动以后走了多少” -
base_link:机器人身体自身的坐标系
例如机器人启动时:
odom 原点
O
|
|
Robot
假设机器人向前走了 1 m。
那么可能有:
base_link 相对 odom:
x = 1.0 m
y = 0
yaw = 0
也就是说:
机器人根据编码器、IMU等信息估计:
“我相对于刚开始的位置,往前走了1米。”
这就是 odometry,中文叫:里程计 / 里程估计,所以常见 TF 树:
map
│
└── odom
│
└── base_link
│
├── torso
├── left_foot
├── right_foot
└── ...
对人形机器人来说怎么理解?
例如你的机器人刚启动:
odom原点
↓
机器人骨盆附近
机器人往前走:
odom
O────────────────→
Robot
你可以问:
机器人 base_link
相对于 odom
走了多远?
比如:
x = 2.3 m
y = 0.1 m
yaw = 5°
这表示:
从里程计参考系看,机器人已经向前移动约2.3m,横向偏了0.1m,朝向转了5°。
odom 和我们刚才讲的 World 有什么区别?
这个地方很关键。
我们前面为了讲运动学,经常用:
World
泛指“外部固定参考系”。
但在真正 ROS 系统里,可能会进一步细分成:
map
odom
base_link
所以你可以暂时理解:
World
是一个泛称。而:
odom
是实际工程中一种具体的世界参考系——由里程计积分得到的局部世界坐标系。
odom 和 base_link 一定不要混
base_link:
跟着机器人身体一起走。
odom:
通常固定在机器人启动附近,不跟着机器人移动。
例如机器人往前走:
odom
O
|
|-----------> base_link
机器人继续走:
odom
O
|
|---------------------> base_link
所以:
odom → base_link
这个 Transform 一直在变化。
一句话记住
odom
=
机器人通过编码器、IMU等状态估计得到的
“从启动位置开始,我现在移动到哪里了”
的参考坐标系
而它最大的特点:
连续、平滑,但会累计漂移。
你现在顺便把这三个记住就够了:
map = 全局定位参考系
odom = 局部里程计参考系
base_link = 机器人本体参考系
等我们后面讲 ROS2 TF 时,我会专门把 map → odom → base_link → pelvis/foot/hand 这整棵树给你彻底讲通。
控制状态和导航状态
这是一个非常工程化的概念,导航系统关心:
我在整个地图里准确在哪
控制系统更在意:
我最近这10毫秒到底怎么动了
控制需要:
高频
低延迟
连续
平滑
而全局定位可能:
频率比较低
偶尔修正
甚至发生跳变
所以真正机器人系统里,可能不会把某个全局定位结果:
原封不动
直接塞给底层控制器,而会进行融合和坐标系管理。
EKF
现在 EKF 又多了一层含义,状态可能是:
x =
Base position
Base velocity
Base orientation
IMU bias
...
IMU负责:
快速预测
腿部 odometry:
提供支撑约束
视觉或者 LiDAR:
提供环境参考
于是:
IMU
│
↓
预测
│
▼
┌─────────────┐
Encoder →│ │← Leg Odometry
│ EKF / State │
Vision →│ Estimator │← LiDAR
│ │
└──────┬──────┘
↓
Base State Estimate
你现在再看“多传感器融合”这句话,应该不再只是一个抽象词了。
状态估计 —— 可信度
IMU:
短期很可信
长期位置不可信
支撑脚:
稳定接触时很可信
打滑时不可信
视觉:
看到丰富纹理时可信
黑暗/快速运动时可能变差
LiDAR:
结构丰富环境很好
某些退化环境可能不好
于是状态估计器真正不断做的是:
根据当前情况决定“这一刻更应该相信谁”。
这其实就是你前面学 Kalman Filter 时那个思想的机器人版本:
预测有多可信?
测量有多可信?
↓
决定各相信多少
IMU
┌─────┴─────┐
↓ ↓
角速度 加速度
│ │
└─────┬─────┘
↓
短期运动预测
│
│
Encoder q,dq ─────┤
│ │
↓ │
Leg Kinematics │
│ │
↓ │
Contact / Foot │
Constraint │
│ │
└──────┬────┘
↓
Local Odometry
│
┌─────┴─────┐
↓ ↓
Base Velocity Base Position
│ │
└─────┬─────┘
↓
State Estimator
↑
外部定位信息
Vision/LiDAR/GNSS
│
↓
长期漂移修正
Odometry
=
“我移动了多少?”
Localization
=
“我现在在世界哪里?”
State Estimation
=
“我现在整个机器人是什么状态?”
其中:
State Estimation
范围最大。
DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。
更多推荐

所有评论(0)