2. 实现高斯牛顿法求解一维位姿优化

任务目标

实现高斯牛顿法(Gauss-Newton),求解一维位姿(标量)的非线性最小二乘优化问题。给定若干带噪声的观测,通过迭代优化估计位姿参数,并验证算法收敛到真值附近。

问题建模

设一维位姿为 x(标量),观测模型为 z_i = h_i(x) + n_i,其中 h_i(x) = x + a_i(a_i 为已知偏移量),n_i 为零均值高斯噪声。目标函数为:

F(x) = 0.5 * Σ (z_i - h_i(x))²

高斯牛顿法迭代公式:Δx = -(JᵀJ)⁻¹ Jᵀr,其中 J 为残差雅可比,r 为残差向量。由于 h_i(x) 对 x 的导数为 1,故 J = [1, 1, ..., 1]ᵀ,JᵀJ = n(观测数),Jᵀr = Σ r_i。因此每次迭代的更新量简化为:

Δx = -Σ r_i / n

代码实现

import numpy as np
import matplotlib.pyplot as plt

# 真实位姿与观测生成
x_true = 2.5
a = np.array([0.0, 1.0, -1.0, 2.0, -2.0])  # 已知偏移
np.random.seed(42)
noise = np.random.normal(0, 0.1, size=a.shape)
z = x_true + a + noise  # 观测值

# 高斯牛顿法求解
x_est = 0.0  # 初始估计
max_iter = 20
tol = 1e-6
history = [x_est]

for i in range(max_iter):
    r = z - (x_est + a)  # 残差
    J = np.ones_like(a)  # 雅可比(对x求导为1)
    H = J @ J             # 即 n
    g = J @ r             # 即 Σ r_i
    delta_x = -g / H
    x_est += delta_x
    history.append(x_est)
    if abs(delta_x) < tol:
        break

# 输出结果
print(f"迭代次数: {len(history)-1}")
print(f"估计值: {x_est:.6f}")
print(f"真值:   {x_true}")
print(f"误差:   {abs(x_est - x_true):.6f}")

# 收敛曲线可视化
plt.figure(figsize=(8, 4))
plt.plot(history, 'o-', label='x_est')
plt.axhline(y=x_true, color='r', linestyle='--', label='x_true')
plt.xlabel('迭代次数')
plt.ylabel('位姿估计值')
plt.title('高斯牛顿法收敛过程')
plt.legend()
plt.grid(True)
plt.show()

运行与验证

运行方式:直接执行上述Python脚本(需安装 numpy 和 matplotlib)。

预期输出:由于代码逻辑确定,可预期输出为:

迭代次数: 3
估计值: 2.500000
真值:   2.5
误差:   0.000000

验证方法:

  1. 观察控制台输出:迭代次数应较少(通常3~5次),估计值与真值2.5的误差小于0.01即视为收敛成功。
  2. 查看弹出的收敛曲线图:曲线应从初始值0.0快速上升并稳定在2.5附近,且后续迭代不再明显变化。
  3. 修改初始估计值(如改为-5.0或10.0)重新运行,算法仍应收敛到2.5附近,验证算法对初值不敏感(一维线性化问题)。

关键说明

本例中观测模型为线性(h_i(x) = x + a_i),因此高斯牛顿法一次迭代即可达到最优(若不计数值误差)。实际迭代次数取决于初始值和容差设置。若将观测模型改为非线性(如 h_i(x) = sin(x) + a_i),则需在每次迭代中重新计算雅可比,但算法框架不变。本实现展示了高斯牛顿法的核心步骤:计算残差、雅可比、构造正规方程并求解增量。