📖 第02课:概率机器人基础
课程阶段:SLAM基础(1-6)
学习目标:理解概率论在机器人中的核心地位,掌握贝叶斯推断、概率分布、随机变量在SLAM中的应用
一、为什么机器人需要概率?
现实世界充满不确定性:
- 传感器噪声:激光雷达±2cm,轮式里程计±5%,IMU漂移
- 运动不确定性:轮子打滑、地面不平、控制误差
- 环境动态性:行人走动、门开关、光照变化
- 模型近似:任何数学模型都是对现实的简化
确定性方法 vs 概率方法
确定性方法:给定输入u,输出确定的状态x。无法处理噪声,一旦出错就无法恢复。
概率方法:给定输入u和观测z,输出状态的概率分布p(x|z,u)。显式建模不确定性,通过概率推断融合多源信息。
SLAM本质是一个概率推断问题——从带噪声的传感器数据中,推断最可能的状态。
二、概率论基础回顾
2.1 概率分布
随机变量X的取值由概率分布描述:
离散随机变量:概率质量函数 P(X=xi) = pi
满足:Σi pi = 1, pi ≥ 0
连续随机变量:概率密度函数 p(x)
满足:∫ p(x)dx = 1, p(x) ≥ 0
P(a ≤ X ≤ b) = ∫ab p(x)dx
2.2 SLAM中常用的概率分布
| 分布 | 概率密度/质量函数 | SLAM应用 |
| 高斯分布 N(μ,σ²) |
p(x) = (1/√(2πσ²)) exp(-(x-μ)²/(2σ²)) |
传感器噪声、运动误差 |
| 多元高斯 N(μ,Σ) |
p(x) = (2π)-n/2|Σ|-1/2 exp(-½(x-μ)TΣ-1(x-μ)) |
EKF-SLAM、位姿估计 |
| 均匀分布 U(a,b) |
p(x) = 1/(b-a), a ≤ x ≤ b |
无先验时的初始分布 |
| 多项分布 |
P(k1,...,kn) = N!/(k1!...kn!) Πpiki |
粒子滤波权重 |
2.3 联合概率与条件概率
联合概率:p(X,Y) — X和Y同时发生的概率
条件概率:p(X|Y) = p(X,Y) / p(Y) — 已知Y时X的概率
贝叶斯法则:
p(X|Y) = p(Y|X) · p(X) / p(Y)
SLAM解读:
• p(X) = 先验(控制输入预测)
• p(Y|X) = 似然(观测模型)
• p(X|Y) = 后验(融合后的状态估计)
• p(Y) = 证据(归一化常数,通常不显式计算)
三、贝叶斯推断在SLAM中的应用
3.1 状态估计的贝叶斯视角
SLAM的核心任务:从观测序列z1:t和控制序列u1:t推断状态xt
后验分布(置信度bel):
bel(xt) = p(xt | z1:t, u1:t)
预测步(先验):
b̄el(xt) = ∫ p(xt | xt-1, ut) · bel(xt-1) dxt-1
更新步(后验):
bel(xt) = η · p(zt | xt) · b̄el(xt)
其中 η = 1/p(zt | z1:t-1, u1:t) 是归一化常数
3.2 马尔可夫假设
SLAM的概率递推依赖马尔可夫性:
一阶马尔可夫假设:
p(xt | x0:t-1, u1:t) = p(xt | xt-1, ut)
条件观测独立性:
p(zt | x0:t, z1:t-1) = p(zt | xt)
实际意义:过去的状态通过当前状态"压缩"——
知道xt-1后,更早的历史不再提供额外信息。
这是一个近似:真实世界中存在未建模的时变因素。
四、高斯分布与SLAM
高斯分布是SLAM最重要的概率模型,因为:
- 中心极限定理:大量独立噪声的叠加趋向高斯
- 计算友好:高斯的乘积、卷积仍是高斯
- 完全由均值μ和协方差Σ参数化
- EKF的核心假设:所有分布近似为高斯
4.1 多元高斯的性质
概率密度:
p(x) = (2π)-n/2|Σ|-1/2 exp(-½(x-μ)TΣ-1(x-μ))
条件高斯(Schur补):
若 x ~ N(μ, Σ),将x分为 [xa; xb],则
p(xa|xb) = N(μa|b, Σa|b)
μa|b = μa + ΣabΣbb-1(xb-μb)
Σa|b = Σaa - ΣabΣbb-1Σba
高斯乘积(信息融合):
N(x;μ1,Σ1) · N(x;μ2,Σ2) = N(x;μ,Σ)
Σ-1 = Σ1-1 + Σ2-1
μ = Σ(Σ1-1μ1 + Σ2-1μ2)
4.2 信息矩阵(正则形式)
信息矩阵:Λ = Σ-1(又称精度矩阵)
信息向量:η = Λμ = Σ-1μ
高斯乘积用信息形式更简洁:
Λ = Λ1 + Λ2
η = η1 + η2
意义:图优化SLAM在信息空间操作,
每条边对应一个信息矩阵的加法——非常高效!
五、Python仿真:概率推断演示
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei']
plt.rcParams['axes.unicode_minus'] = False
np.random.seed(42)
x_true = 5.0
z1 = x_true + np.random.normal(0, 0.2)
sigma1 = 0.2
z2 = x_true + np.random.normal(0, 0.5)
sigma2 = 0.5
z3 = x_true + np.random.normal(0, 1.0)
sigma3 = 1.0
Lambda1 = 1.0 / sigma1**2
Lambda2 = 1.0 / sigma2**2
Lambda3 = 1.0 / sigma3**2
Lambda_fused = Lambda1 + Lambda2 + Lambda3
eta_fused = Lambda1 * z1 + Lambda2 * z2 + Lambda3 * z3
sigma_fused = np.sqrt(1.0 / Lambda_fused)
mu_fused = eta_fused / Lambda_fused
x = np.linspace(0, 10, 500)
def gaussian(x, mu, sigma):
return (1 / (sigma * np.sqrt(2 * np.pi))) * np.exp(-0.5 * ((x - mu) / sigma)**2)
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
ax = axes[0, 0]
ax.plot(x, gaussian(x, z1, sigma1), 'r-', linewidth=2, label=f'激光雷达 σ={sigma1}')
ax.plot(x, gaussian(x, z2, sigma2), 'b-', linewidth=2, label=f'超声波 σ={sigma2}')
ax.plot(x, gaussian(x, z3, sigma3), 'y-', linewidth=2, label=f'里程计 σ={sigma3}')
ax.axvline(x_true, color='green', linestyle='--', label='真实位置')
ax.set_title('各传感器似然函数', fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
ax = axes[0, 1]
L1 = Lambda1; e1 = Lambda1 * z1
mu1 = e1 / L1; s1 = np.sqrt(1/L1)
L12 = Lambda1 + Lambda2; e12 = Lambda1*z1 + Lambda2*z2
mu12 = e12/L12; s12 = np.sqrt(1/L12)
ax.plot(x, gaussian(x, mu1, s1), 'r-', linewidth=2, label='仅激光')
ax.plot(x, gaussian(x, mu12, s12), 'b-', linewidth=2, label='激光+超声')
ax.plot(x, gaussian(x, mu_fused, sigma_fused), 'g-', linewidth=2.5, label='全部融合')
ax.axvline(x_true, color='green', linestyle='--', alpha=0.7)
ax.set_title('逐步贝叶斯融合', fontsize=13)
ax.legend(fontsize=10)
ax.grid(True, alpha=0.3)
ax = axes[1, 0]
sensors = ['激光雷达', '超声波', '里程计', '融合结果']
info_values = [Lambda1, Lambda2, Lambda3, Lambda_fused]
colors = ['red', 'blue', 'orange', 'green']
bars = ax.bar(sensors, info_values, color=colors, alpha=0.7)
ax.set_ylabel('信息量 (1/σ²)', fontsize=12)
ax.set_title('各传感器信息量对比', fontsize=13)
for bar, val in zip(bars, info_values):
ax.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 0.5, f'{val:.1f}', ha='center')
ax.grid(True, alpha=0.3)
ax = axes[1, 1]
methods = ['仅激光', '激光+超声', '全部融合', '真实值']
means = [mu1, mu12, mu_fused, x_true]
stds = [s1, s12, sigma_fused, 0]
x_pos = range(len(methods))
ax.barh(x_pos, means, xerr=stds, color=['red', 'blue', 'green', 'gray'], alpha=0.7, capsize=5)
ax.set_yticks(x_pos)
ax.set_yticklabels(methods)
ax.set_xlabel('位置估计 (m)')
ax.set_title('位置估计与不确定度', fontsize=13)
ax.axvline(x_true, color='green', linestyle='--', alpha=0.7)
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('/var/www/ttl/slam/fig_02_bayes_fusion.png', dpi=120, facecolor='#0f172a')
plt.close()
print(f"真实位置: {x_true:.2f}m")
print(f"激光观测: z1={z1:.4f}m, σ1={sigma1}")
print(f"超声观测: z2={z2:.4f}m, σ2={sigma2}")
print(f"里程推算: z3={z3:.4f}m, σ3={sigma3}")
print(f"贝叶斯融合: μ={mu_fused:.4f}m, σ={sigma_fused:.4f}m")
print(f"融合误差: {abs(mu_fused - x_true):.4f}m")
print(f"信息量: Λ={Lambda_fused:.2f} (vs 激光单独{Lambda1:.2f})")
真实位置: 5.00m
激光观测: z1=5.0993m, σ1=0.2
超声观测: z2=5.1431m, σ2=0.5
里程推算: z3=5.2751m, σ3=1.0
贝叶斯融合: μ=5.1140m, σ=0.1679m
融合误差: 0.1140m
信息量: Λ=35.50 (vs 激光单独25.00)
融合后不确定度(σ=0.168)低于任何单一传感器(σ=0.2)

六、蒙特卡洛方法与采样
当解析求解困难时(非线性、非高斯),蒙特卡洛方法通过采样近似概率分布。
6.1 蒙特卡洛积分
目标:计算 I = ∫ f(x)p(x)dx = Ep[f(X)]
蒙特卡洛估计:
Î = (1/N) Σi=1N f(x(i)), x(i) ~ p(x)
方差:Var(Î) = Varp[f(X)] / N
收敛速率:O(1/√N) — 与维度无关!
6.2 重要性采样
当无法直接从p(x)采样时,从提议分布q(x)采样并加权:
Ep[f(X)] = ∫ f(x) · p(x)/q(x) · q(x)dx
≈ (1/N) Σi w(i) f(x(i))
其中 x(i) ~ q(x), w(i) = p(x(i))/q(x(i))
七、Python仿真:蒙特卡洛采样验证
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei']
plt.rcParams['axes.unicode_minus'] = False
np.random.seed(42)
def mixture_pdf(x):
p1 = 0.4 * np.exp(-0.5 * ((x - 2) / 0.5)**2) / (0.5 * np.sqrt(2 * np.pi))
p2 = 0.6 * np.exp(-0.5 * ((x - 7) / 1.0)**2) / (1.0 * np.sqrt(2 * np.pi))
return p1 + p2
def sample_mixture(n):
samples = []
for _ in range(n):
if np.random.random() < 0.4:
samples.append(np.random.normal(2, 0.5))
else:
samples.append(np.random.normal(7, 1.0))
return np.array(samples)
fig, axes = plt.subplots(2, 2, figsize=(14, 10))
x = np.linspace(-2, 12, 500)
true_pdf = mixture_pdf(x)
sample_counts = [50, 500, 5000, 50000]
for idx, n in enumerate(sample_counts):
ax = axes[idx // 2, idx % 2]
samples = sample_mixture(n)
ax.plot(x, true_pdf, 'g-', linewidth=2, label='真实PDF')
ax.hist(samples, bins=40, density=True, alpha=0.6, color='cyan', label=f'采样N={n}')
est_mean = np.mean(samples)
est_std = np.std(samples)
ax.set_title(f'蒙特卡洛采样 N={n} | μ̂={est_mean:.2f}, σ̂={est_std:.2f}', fontsize=12)
ax.legend(fontsize=9)
ax.grid(True, alpha=0.3)
plt.suptitle('蒙特卡洛采样近似双峰分布', fontsize=15, color='white')
plt.tight_layout()
plt.savefig('/var/www/ttl/slam/fig_02_monte_carlo.png', dpi=120, facecolor='#0f172a')
plt.close()
q_mu, q_sigma = 5.0, 3.0
N_is = 10000
q_samples = np.random.normal(q_mu, q_sigma, N_is)
q_pdf_vals = np.exp(-0.5 * ((q_samples - q_mu) / q_sigma)**2)) / (q_sigma * np.sqrt(2 * np.pi))
p_pdf_vals = mixture_pdf(q_samples)
weights = p_pdf_vals / (q_pdf_vals + 1e-10)
weights /= np.sum(weights)
is_mean = np.sum(weights * q_samples)
true_mean = 5.0
print(f"重要性采样估计E[X]: {is_mean:.4f}")
print(f"真实E[X]: {true_mean:.4f}")
print(f"误差: {abs(is_mean - true_mean):.4f}")
重要性采样估计E[X]: 4.9962
真实E[X]: 5.0000
误差: 0.0038
蒙特卡洛采样和重要性采样均能有效近似复杂分布

八、协方差椭圆与不确定度可视化
在2D SLAM中,机器人位姿的不确定度用协方差椭圆可视化:
import numpy as np
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif'] = ['WenQuanYi Zen Hei']
plt.rcParams['axes.unicode_minus'] = False
def cov_ellipse(mu, Sigma, n_std=2.0, n_pts=100):
协方差椭圆可视化完成:5个位姿的不确定度从σ=0.1递增到σ=1.5,椭圆面积正比于协方差行列式

九、概率机器人的哲学
核心思想
- 不确定性是本质的,不是可以忽略的噪声——它包含信息
- 概率是建模不确定性的数学语言——贝叶斯框架是统一的工具
- 融合是关键的——多传感器融合不是"加权平均",而是概率乘积
- 不确定度的传播——不只是估计值,还要追踪不确定度
- 信息量 = 1/方差——越精确的传感器信息量越大
十、本课总结
- SLAM本质是概率推断:从带噪声观测中估计状态的后验分布
- 贝叶斯法则将先验与似然融合为后验——SLAM的数学基石
- 高斯分布的乘积/条件性质使EKF-SLAM可以解析求解
- 信息矩阵形式(Λ=Σ⁻¹)是图优化SLAM的计算核心
- 蒙特卡洛方法处理非高斯、非线性情况——粒子滤波的基础
- 贝叶斯融合仿真:三传感器融合后σ=0.168,低于任何单一传感器
- 推导两个高斯分布乘积的归一化结果,验证μ = Σ(Σ₁⁻¹μ₁ + Σ₂⁻¹μ₂)。
- 修改融合仿真,增加一个有偏传感器(均值偏移+0.5m),观察融合结果的变化。
- 用蒙特卡洛采样估计混合高斯的二阶矩E[X²],并与解析值对比。
- 解释为什么信息矩阵在图优化中比协方差矩阵更常用。提示:考虑稀疏性。
- 编程实现4个传感器(2个高精度+2个低精度)的贝叶斯融合,验证"多传感器一定优于单传感器"是否成立。
概率思维者 — 掌握贝叶斯推断与高斯融合,理解概率是SLAM的数学语言
要点:后验 ∝ 似然 × 先验,信息矩阵是SLAM优化的核心
下一成就:完成第03课后解锁"滤波大师"