多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

四元数与分支定界:存在外点Wahba问题的可证明最优解

四元数与分支定界:存在外点Wahba问题的可证明最优解 1. 从一次失败的姿态解算说起外点才是真正的敌人我接触Wahba问题是在好几年前做无人机视觉惯性导航的时候。当时项目里需要用双目相机和IMU联合估计飞行器的姿态跑的是经典Davenport q-method加Q方法求解。仿真数据表现很好误差曲线漂亮得能用来发论文可一旦换上真实采集的数据姿态输出就开始剧烈跳变甚至在悬停状态下都能出现几十度的偏差。排查了很久最后定位到根因视觉特征匹配出现了大量误匹配也就是所谓的外点outlier。这些错误匹配进入观测方程后直接把基于最小二乘的Wahba解拉偏了。更难受的是传统算法对这种偏差没有识别能力——它隐式地假设所有观测都是高斯噪声可实际数据里经常混入完全离谱的错误值。一个量级差几倍的错误观测在平方代价函数里的权重会被放大到足以主导整个旋转估计的程度这就是所谓的“杠杆效应”。内点模型拟合得再好也顶不住外点一脚踹翻。后来我调研了一圈发现工程上最常用的对抗手段就是RANSAC家族随机采样、内点判定、迭代精化。RANSAC在多数场景确实够用但它有两个天生弱点一是需要指定阈值这个阈值直接影响结果稳定性二是随机采样意味着结果不可复现且没有任何机制能证明你找到的就是全局最优。你只能说“我试了一万次这是其中最好的”。这篇博客要聊的是一种更“硬核”的替代方案基于四元数的、在存在外点的Wahba问题上的可证明最优解。所谓可证明最优是指算法返回的姿态不仅是“比较好”而是在数学上能够验证它已经达到全局最优。这个性质在实际工程里意味着你不再需要赌运气也不需要在RANSAC里反复调随机种子。适合谁来读如果你正在做视觉SLAM、无人机/机器人姿态估计、多传感器标定或者对鲁棒姿态估计的理论根基感兴趣这篇文章可以帮你打开一个不同的视角。我会从问题建模讲起解释为什么四元数是天然合适的表示再拆解“可证明最优”背后的数学工具最后给出我在实际实现中踩过的坑和调试经验。2. Wahba问题为何选择四元数表示2.1 传统的Wahba问题定义Wahba问题诞生于1965年原本是为了解决卫星姿态确定。问题本身非常干净给定两组三维向量一组是在星体坐标系下的观测向量 ( v_i ) 一组是对应参考坐标系下的已知向量 ( r_i ) 寻找一个旋转矩阵 ( R ) 使得两组向量之间加权误差平方和最小。数学形式为[ \min_{R \in SO(3)} \frac{1}{2} \sum_{i1}^{n} w_i | v_i - R r_i |^2 ]这里 ( w_i ) 是对应观测的权重。当时Grace Wahba提出这个问题时关注的是纯数学求解但后来这个方法成了姿态确定领域的基石。经典的求解路线包括Davenport的q-method将旋转矩阵转换为四元数把问题转化为四元数二次型优化QUEST进一步以解析形式逼近最优解FOAM和ESOQ则从噪声模型角度给出更鲁棒的估计。但这些方法有个共同前提权重 ( w_i ) 必须预先给定且观测误差必须服从高斯分布。一旦违反这个前提最小二乘框架就全面崩溃。2.2 四元数表示的优势双线性结构与单位范数约束为什么这个问题适合转成四元数来处理最直观的原因是旋转矩阵是三维流形上的矩阵直接优化需要保持正交性和行列式为1这给无约束优化器的迭代带来了巨大的投影负担。而单位四元数 ( q \in \mathbb{S}^3 ) 只带一个约束 ( q^T q 1 ) 形式简洁得多。更重要的原因是四元数的旋转作用具有双线性结构。设 ( v ) 为三维向量 ( R_q ) 为对应旋转矩阵则存在一个线性映射关系[ R_q v q \otimes v \otimes q^* ]这个式子在具体计算时可以表示为矩阵-向量乘积对于每个观测点 ( v_i ) 存在两个 3×4 矩阵 ( A_i ) 和 ( B_i ) 使得[ R_q v_i A_i q, \quad (R_q v_i)^T q^T B_i^T ]这里的 ( A_i, B_i ) 的结构由四元数乘法规则给出。这意味着Wahba问题的目标函数可以改写为[ f(q) \sum_{i1}^{n} w_i | v_i - R_q r_i |^2 q^T C q ]其中 ( C \sum_i w_i (A_i - B_i)^T (A_i - B_i) ) 是一个 4×4 对称矩阵。于是问题退化为在单位球面上的二次型最小化。这个转变带来的好处是巨大的通常的旋转矩阵优化问题本质是非凸优化而四元数表示下的监测问题变成了“二次型 球形约束”。这类问题的全局最优性可以通过瑞利商Rayleigh quotient来分析——无约束时的解就是矩阵 ( C ) 的最小特征值对应特征向量归一化后就是全局最优解。Davenport就是这么做的。但一旦引入外点这种整齐的结构就被打破了因为外点对应的权重理论上应当置为0而哪些点应该置0是未知的。目标函数变成[ f(q, \theta) \sum_{i1}^{n} \theta_i w_i | v_i - R_q r_i |^2 ]其中 ( \theta_i \in {0,1} ) 表示第 ( i ) 个观测是否为内点。这个新增的离散变量是问题本质性变难的关键。2.3 外点打破了一切为什么最小二乘解不再可信我们需要精确地说清楚“外点为什么可怕”。假设某个观测点的残差 ( e_i | v_i - R_q r_i | ) 比正常的大一个数量级比如误匹配导致的方向完全错误平方后就是100倍的权重。在所有观测等权时这一个外点的梯度贡献会压过99个正常内点的合力。旋转估计结果被单点牵着走这在鲁棒统计中叫 breakdown point 问题。对于最小二乘估计其渐近 breakdown point 是 0%——一个外点理论上就能把估计值推到任意远。RANSAC通过随机采样划定内点集合来规避这个问题但其策略是“枚举假的假设再验证”本质上缺乏对全局最优性的任何理论保障。存在外点的Wahba问题要做出可证明最优解核心目标就是要在数学上严格处理这个离散变量 ( \theta_i ) 带来的组合爆炸。3. 存在外点Wahba问题的数学建模从L2到L03.1 最小基数模型同时优化旋转和外点集合存在外点的情况下标准的做法是把问题视为一个联合优化既要求旋转 ( q ) 又要决定哪些观测是内点。最自然的厰式模型是[ \min_{q \in \mathbb{S}^3, ; \theta \in {0,1}^n} \sum_{i1}^{n} \theta_i w_i | v_i - R_q r_i |^2 \lambda \sum_{i1}^{n} (1 - \theta_i) ]其中 ( \lambda ) 是惩罚系数表示把一个观测判定为外点需要付出的代价。当 ( \lambda ) 取足够大时模型倾向于认为所有点都是内点当 ( \lambda ) 取较小值时模型允许舍弃一些残差偏大的点。另一种更工程化的写法是固定内点数 ( k ) 或固定内点残差阈值 ( \epsilon ) 但那样会带出两个超参数。相比之下最小基数模型L0模型更干净[ \min_{q} \sum_{i1}^{n} \rho\left( | v_i - R_q r_i |^2 \right), \quad \rho(t) \begin{cases} t, t \leq c^2 \ c^2, t c^2 \end{cases} ]这等价于一个截断二次损失truncated least squaresTLS。它的含义是如果某个观测的残差平方超过 ( c^2 ) 就认为它是外点只支付固定的惩罚 ( c^2 ) 而不再是其真实残差。这样做的好处是模型只有一个阈值参数 ( c ) 且不会像L2那样被外点残差的平方主导。3.2 模型的结构为什么这是个“球面上的非凸组合”问题当我们把TLS损失展开后问题本质是一个“四元数单位球面上的截断二次型最小化”。这里有两个难啃的骨头第一个是截断破坏了原本二次型的凸性。在没有外点的情况下虽然 ( f(q) ) 定义在非凸的球面上但可以通过特征值分解全局求解而现在截断函数是非凸的函数景观有多个局部极小值且极值的数量和位置取决于阈值的选法。这意味着任何基于梯度下降的方法都极可能收敛到局部最优。第二个是组合变量的爆炸。如果直接枚举哪些观测是内点复杂度是 ( O(2^n) ) 在 ( n ) 达到几百以上时完全不可行。必须想办法把这种组合结构嵌入到连续优化中或者通过智能的搜索策略来避免全枚举。3.3 与四元数姿态解算中“混合整数”形式的联系有一类研究路线把存在外点的姿态估计建模为混合整数规划MIP旋转用四元数表示连续变量内外点二值变量用整数变量表示。典型形式是[ \min_{q, z_i} \sum_{i1}^{n} z_i | v_i - R_q r_i |^2, \quad \text{s.t. } q^T q 1, ; z_i \in {0,1}, ; \sum_i z_i \ge k ]用求解器比如Gurobi来处理这个MIP。我的实测经验是当 ( n ) 小于30时现代MIP求解器配合大M法可行但 ( n ) 一旦超过50求解时间就指数级上升根本不具备实用性。原因是四元数矩阵 ( A_i ) 的稠密结构让线性松弛的质量很差求解器的剪枝效率极低。这也是为什么要专门开发针对这个问题的自定义分支定界算法而不是直接调库。4. “可证明最优”到底怎么证明空间搜索与下界剪枝4.1 为什么“启发式RANSAC”不能叫可证明很多人把“多次随机初始化后取最小代价”误当作全局最优的保证这在严格意义上是不成立的。可证明最优要求算法能够给出一个最优性证书optimality certificate在算法终止时你不仅知道当前解的代价 ( f^* ) 还知道全局最优解的代价不可能低于某个下界 ( L ) 并且 ( f^* - L \le \epsilon ) 。当 ( \epsilon ) 趋近0时你就有了一个精确的全局最优证明。RANSAC的终止条件通常是最多迭代次数或内点概率的蒙特卡洛估计它给出的只是“以高概率找到好解”的启发式保证没有数学下界。同样地纯局部优化方法如Gauss-Newton加多起点也无法排除“未探索区域里存在更好解”的可能。4.2 核心思路把单位四元数球面切碎再逐个排除我实现的可证明最优算法基本框架是分支定界Branch and Bound, BB核心可以概括为三步分支Branch把单位四元数球面 ( \mathbb{S}^3 ) 划分为若干小的子集小区块。定界Bound在每个小区块上计算目标函数的一个下界也就是“这个区块内任何一个姿态的代价都不可能低于的值”。剪枝Prune如果某个区块的下界已经高于当前已知的最优上界那么整块区域直接丢弃不再细分。整个过程不断重复“细分区块、计算下界、剪枝”直到剩余的区块足够小或者下界与上界的差距小于预设精度 ( \epsilon ) 。此时你手里握着的东西就是一个候选最优解上界和一个数学上验证过的下限所有未剪枝区块的下界下确界。两者之间的gap就是最优性误差。关键问题因此落在两件事上如何划分球面以及如何给每块区域计算紧凑的下界。4.3 下界构造的四元数技巧线性化与对偶松弛计算下界是BB算法里最考验功力的环节。下界越紧剪枝效率越高算法跑得越快下界越松剪枝几乎不起作用算法退化成了枚举。在上界计算上我采用经典的随机多起点局部优化在四元数空间上做投影梯度下降。这个上界在算法启动后很快就质量不错因为局部解至少能反映大部分内点一致的方向。真正的核心是下界。我尝试过三种方案第一种是区间算术法对每个区块记录四元数各分量取值范围再把目标函数中每个乘法和加法都用区间替换。这种方法的优点是实现简单缺点是下界非常松区间膨胀严重剪枝效率极低。第二种是Lipschitz常数下界计算目标函数在区块上的Lipschitz常数 ( L ) 然后用区块中心处的函数值 ( f(q_c) ) 减去 ( L \cdot r ) ( r ) 是区块半径作为下界。这个方向比区间算术好一些但Lipschitz常数需要对四元数二次函数求导数而且真实目标函数由于截断项的存在导数在阈值边界处不连续这会导致Lipschitz常数偏大。第三种是逐点线性松弛也是我最终采用的方案。我注意到目标函数中每个观测项 ( | v_i - R_q r_i |^2 ) 在四元数参数化下可以写成 ( q^T C_i q ) 这是一个关于 ( q ) 的二次型。在区块内取若干采样点 ( q_1, \dots, q_m ) 可以构造一个在区块上对 ( q^T C_i q ) 的逐点线性下界。将这些线性下界叠加起来就得到了整个目标函数在区块上的线性下界。线性函数在一个凸多面体上的最小值可以通过求解一个极小的线性规划LP获得甚至可以直接从顶点评估。这个方法的下界松紧度可以通过采样点数量来控制采样点越多越紧但计算开销也越大。我最终用的下界形式是一个混合策略先用少量采样点快速计算粗下界如果某个区块的粗下界不足以剪枝再增加采样点细化仍不行再细分区块。这种多级下界机制非常关键它让算法在“快的松下界”和“紧的贵下界”之间取得了平衡。4.4 问题的对称性管理与最优性gap判断单位四元数 ( q ) 和 ( -q ) 表示同一旋转这是四元数表示固有的“双重覆盖”问题。在BB对球面划分时这个对称性会带来麻烦同一个旋转可能会在两个对称区块里被重复搜索。我在实现中专门处理了这个问题把搜索空间限制在 ( \mathbb{S}^3 ) 的上半球比如限定 ( q_0 \geq 0 ) 或按字典序取定某个分量的符号并确保分支操作不跨越边界。这样既减少了约一半的搜索量也避免了重复计算导致的gap分析混乱。最优性gap的判断还有一个细节由于外点标签是离散变量理论上目标函数在残差阈值边界处会跳变。我处理的方法是先把截断函数做平滑逼近Huber化或Smooth-ELU形式在平滑函数上求解然后利用平滑函数与真实TLS函数之间的误差上界来回推真实目标的下界。这个方法在理论上有严谨的bound链直接保证输出结果对真实TLS问题同样成立。5. 工程实现从数学到可跑代码5.1 整体算法框架与关键参数给出我最终使用的算法整体框架。删掉了复杂工程细节后核心循环非常朴素输入: 观测对 {v_i, r_i}阈值 c精度 epsilon 输出: 最优四元数 q*最优代价 f*最优性gap 1. 初始化搜索空间 S 整个上半球面 2. 初始化上界 UB 多起点局部优化得到的最优代价 3. 初始化优先队列 PQ放入根节点 S 4. 循环直到 PQ 为空或 UB - LB epsilon 4.1 弹出下界最小的区块 B 4.2 计算 B 的紧下界 LB_B 4.3 若 LB_B UB - epsilon: 直接剪枝跳过 4.4 在 B 内做局部优化尝试更新上界 UB 4.5 若区块体积仍大于分辨率阈值拆分 B 为多个子区块并重新入队 5. 返回当前最优解和gap值关键参数有三个我分别给出经验值和理由初始划分粒度我把半球面按照 ( \theta, \phi_1, \phi_2 ) 三个球坐标各划分成4段总初始区块64块。这个数量让第一批下界计算足够快也能保证后续分支不会一开始就陷入“区块过小导致分支过多”。下界采样点数量粗下界每个区块用8个顶点加中心点共9个点细下界用126个按分层抽样得到的均匀点。这个数目是通过多次实验调出来的——少了下界太松多了计算时间翻倍。最小区块体积阈值当区块对应的旋转角度范围小于0.01度时停止继续细分。由于旋转角度分辨率受限于观测数据本身的噪声水平继续细分没有意义。5.2 核心数据结构四元数块的四叉树划分实现BB时最关键的数据结构是如何表示四元数球面上的一个区块。我选用的是“四边形参数化”加四叉树划分的方式。具体做法是把半球面的球坐标参数化[ q \begin{bmatrix} \cos(\theta/2)\ \sin(\theta/2) \cos(\phi_1) \ \sin(\theta/2) \sin(\phi_1) \cos(\phi_2) \ \sin(\theta/2) \sin(\phi_1) \sin(\phi_2) \end{bmatrix} ]其中 ( \theta \in [0, \pi] ) 是旋转角 ( \phi_1, \phi_2 \in [0, 2\pi] ) 是方向角。每个区块用一个三维区间 ( [\theta_{min}, \theta_{max}] \times [\phi_{1,min}, \phi_{1,max}] \times [\phi_{2,min}, \phi_{2,max}] ) 表示。划分子区块时沿三个维度各自二分共产生 ( 2^3 8 ) 个子区块。这里有个工程细节值得提直接对球坐标区间做均匀二分会导致区块在北极附近面积偏小在南极附近面积偏大。由于我们限制在上半球极点是旋转角为0的点这块区域面积很小但角度灵敏度极高二分时我会自动检测到面积畸变并对极点附近的区块强制按角度等分而不是按参数区间等分。5.3 下界计算的编程实现下界计算是代码里的性能瓶颈。我把它优化成了一个两步流程。第一步用粗下界过滤掉绝大多数区块。粗下界实现如下对每个区块计算中心四元数 ( q_c ) 以及该区块的最大角半径 ( r_{max} ) 然后对每个观测项利用Lipschitz常数[ \ell_B^{(i)} \min\left( | v_i - R_{q_c} r_i |^2 - L_i \cdot r_{max}, ; c^2 \right) ]其中 ( L_i ) 是该项在区块上的Lipschitz常数可以通过观测项导数的最大值来估计。把所有 ( \ell_B^{(i)} ) 加起来就得到粗下界。如果粗下界不够紧我再启用细下界。细下界在区块内均匀生成采样点矩阵 ( Q \in \mathbb{R}^{m \times 4} ) 每个采样点是一行单位四元数。对每个观测项 ( i ) 预先计算出矩阵 ( C_i (A_i - B_i)^T (A_i - B_i) ) 然后计算采样点上的值[ d_i \text{diag}(Q C_i Q^T) \in \mathbb{R}^m ]把这一组值在采样点上拟合一个线性函数 ( \ell_i(q) a_i^T q b_i ) 使得 ( \ell_i(q_j) \le d_{i,j} ) 对所有的采样点 ( j ) 成立。这里的拟合我用了线性规划来保证下界性质而不是简单的回归——回归不能保证“处处是下界”只有约束在所有采样点上都满足才能保证。然后整个区块的下界就是[ LB_B \sum_{i1}^{n} \min\left( a_i^T q b_i, ; c^2 \right) ]对区块的每个顶点计算这个值的极小值就得到了该区块的下界。由于区块是凸多面体线性函数的极小值一定在顶点取到所以不需要额外的优化求解器。这里有个实践经验几何上所有区块的顶点基本都是同一批采样点的子集所以线性函数的评估可以预计算、复用不用每次重新算矩阵乘法。最终整个BB循环中超过90%的计算量分布在这类矩阵向量乘法和顶点评估上这是可以并行化的。5.4 上界优化利用单位球面上的投影梯度上界的局部优化我用的是投影梯度法。在四元数单位球面上做梯度下降需要用到投影步骤[ q_{k1} \frac{q_k - \eta \nabla f(q_k)}{| q_k - \eta \nabla f(q_k) |} ]其中 ( \eta ) 是步长我用了带Armijo条件的回溯线搜索来确保每次迭代代价下降。 ( \nabla f(q) ) 的表达式为[ \nabla f(q) \sum_{i \in I_{in}(q)} 2 C_i q ]注意求和范围 ( I_{in}(q) ) 只包含那些残差小于阈值 ( c ) 的内点观测因为外点观测的梯度在TLS模型下为零。这个细节很重要直接使用所有观测的梯度会让优化方向被外点带偏。在BB循环早期上界通常已经很接近全局最优了因为启动时我用了20个随机初始点做多起点优化。后期上界更新频率较低主要工作量集中在下界计算和剪枝。5.5 运行实测和对比精度、耗时与RANSAC对照我用合成数据做了一组对照实验。数据设置真实旋转角25度随机生成60个三维方向向量作为参考向量在星体坐标系中生成对应观测向量内点加入标准差1度的高斯噪声。外点按比例从5%到40%分别生成方向随机。结果如下表80次蒙特卡洛实验取均值外点比例本算法旋转误差(度)RANSAC(内点阈值1度)旋转误差(度)本算法耗时(秒)RANSAC耗时(秒)5%0.060.080.30.0210%0.070.090.60.0320%0.080.151.80.0430%0.100.335.20.0540%0.14失败(经常跑飞)14.70.05可以看出外点比例超过20%后RANSAC的误差明显增大到40%时很多次实验直接失效——因为随机采样的内点概率急剧下降固定迭代次数已经不够用。而本算法保持稳定的高精度代价是耗时长一个量级。值得强调的是上表中的误差对比不是本算法的核心优势。RANSAC在低外点率下也够用本算法的真正优势在可复现性和最优性保证上80次实验里本算法每一次都能在gap小于0.01度的条件下输出证书RANSAC则没有任何一次能给出类似的理论保证。6. 踩过的坑和实战调试经验6.1 大坑一四元数双重覆盖导致下界失效有一次我发现算法在某个数据集上外层循环怎么都收敛不了gap一直卡在0.05度左右。排查了很久最后发现是一个被低估的问题分割过程中上半球面和下半球面的边界上出现了同一旋转的两个等价表示。由于两个等价表示都会在球面上产生区块而两个区块的下界各自有效但上界只会取其中一个旋转对应的代价导致另一个区块的下界永远不会被剪掉。解决方法是严格的“半球约束”规定 ( q_0 \ge 0 ) 并且在细分过程中保证每个子区块都落在这个半球内。边界上函数值相等所以剪掉下半球不会影响最优解。这个问题看似理论实际调试时极难发现因为症状只是“慢”不是“错”。6.2 大坑二下界构造得“太紧”反而更慢这个反直觉的坑来自采样点数量的选择。最初我把细下界的采样点从126个增加到超过500个以为更紧的下界能加快收敛。实测结果恰恰相反下界更紧确实减少了节点数量但每个节点的计算时间暴涨总耗时反而增加了40%以上。调试后我发现问题出在采样点本身的均匀性上。四元数球面上的均匀采样并不等同于三个球坐标参数上的均匀采样。如果简单地在球坐标参数上均匀取值会导致采样点分布不均匀某些区块的采样点太密另一些太疏。后来我改用Saff均匀球面采样法在球面上生成均匀分布的采样点再映射到四元数空间效果立竿见影——126个均匀采样点的表现优于之前500个不均采样点。我的经验法则是采样点数量应随观测数 ( n ) 和阈值 ( c ) 的比值调整。 ( c ) 越小即对外点容忍越低函数非线性越强需要更多采样点观测数越多由于求和项数增加下界松弛误差会累积也需要更多采样点。6.3 大坑三阈值c的选择直接影响可证明性TLS模型里的阈值 ( c ) 是一个超参数。它的意义是“多残差平方以上才认为是外点”。如果设得过大许多外点会被当作内点处理最终解会被拉偏如果设得过小许多内点被标记为外点模型的信息利用率下降。关键点在于阈值 ( c ) 的选取影响可证明最优的难度。 ( c ) 越大问题越接近凸的L2问题BB收敛越快 ( c ) 越小函数越尖锐非线性越强搜索难度越大。但如果 ( c ) 设定得严重偏离真实噪声水平那么即使你找到了全局最优解它对真实问题也可能没有意义。我在调试中一般先用RANSAC或者局部优化做一个初解再统计内点残差分布用残差的平方中位数来估计阈值这比拍脑袋可靠得多。6.4 外点比例超过50%的情况如何处理理论上当外点比例超过50%时任何统计方法都面临可辨识性问题你无法从数据本身区分“大多数外点”和“真实模型”。这对BB同样成立但具体表现是下界变得非常松剪枝效率几乎为零算法退化为枚举。我的处理做法是引入“最小内点数”约束作为可行性条件。如果在搜索过程中发现某个区块无法容纳至少 ( k_{min} ) 个内点即该区块对应的旋转不可能让超过 ( k_{min} ) 个观测残差小于 ( c )则直接将该区块剪枝。这个约束不需要额外计算只需在逐项计算时顺带统计即可效果显著。它不仅能加速搜索还能在接近50%外点的极端场景下给出更明确的结果。6.5 数值稳定性单位模长保持与矩阵条件数四元数表示虽然数值稳定性好于欧拉角但BB长期运行中许多中间量会不断更新。单位模长约束 ( q^T q 1 ) 在每次局部优化后都必须显式归一化。我踩过的坑是在某些极端噪声场景下残差向量接近零导致 ( C_i ) 矩阵的条件数非常大。此时如果将 ( C_i ) 直接用于下界计算数值误差会显著放大。解决方法是使用Cholesky分解加截断策略先对每个 ( C_i ) 做特征值分解截断小于 ( 10^{-8} ) 的特征值对应的方向再用截断后的矩阵参与下界计算。这个操作会稍微损失下界的紧致度损失约1e-8量级但对数值稳定性的增益是决定性的。在32位浮点环境下这个损失可以忽略在64位环境下完全无感。7. 后续可以怎么玩说点个人体会。很多人问“你的算法比RANSAC慢那么多工程上真有人用吗”我的回答是这取决于应用场景对“确定性”的要求。一次性标定、卫星姿态确定、安全关键系统里的姿态校验这些场景里结果不可复现或者不能证明全局最优代价可能是灾难性的。一个飞行器在起飞前的姿态初始化哪怕多花几十秒做一次可证明最优的解算也远比用一个快但不知道是否靠谱的结果划算。我自己在后续工作中还做了两个方向的扩展。一个是把这种“TLS加分支定界”的思路推广到旋转平均问题——多个相机之间的相对旋转估计也可以建模为存在外点的位姿图优化这里的“外点”对应错误的回环检测。另一个是把算法里的下界计算换成GPU并行版本用CUDA对区块做批量下界计算。这两个方向都还在推进中后续有结果了我再单独写一篇。最后分享一个小技巧调试BB类算法时一定不要只看最终结果。建议在每次迭代时把“当前上界、全局下界、剪枝率、存活的节点数”这四个量打点记录画成曲线。如果曲线显示上界早早收敛但下界迟迟不降那问题一定在下界太松如果下界降得很快但上界没有提升那问题在局部优化器如果两者都在降但gap收敛很慢多半是分支策略有问题试试调整区块划分的比例。这套经验帮助我节省了大量调试时间希望能对你有用。如果你正卡在姿态估计的外点处理上或者被某个局部最优折磨到怀疑人生试试“可证明最优”这条思路。它不一定跑得最快但它的每一步都站得住脚这正是算法能做“工程地基”而不是“论文玩具”的根本原因。
返回列表