You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Ceres Solver中正确建模优化问题以解决编译断言错误?

编译错误原因与修复方案

错误根源分析

编译断言错误的核心原因是Ceres Solver动态维度模板参数的构造方式错误:当使用Eigen::Dynamic作为残差数或参数块维度时,必须显式传入具体数值,否则Ceres无法推导有效维度,导致内部断言失败。

具体问题点

  1. 动态残差/参数维度未显式指定
    在创建AutoDiffCostFunction时,若模板参数使用Eigen::Dynamic,必须通过构造函数的额外参数传入残差数量和参数块维度,否则Ceres会将维度默认设为-1,触发"Invalid parameter block dimension"断言。

  2. 目标函数的动态构造缺失维度参数
    TorqueObjective输出32个残差,参数块是32维,但原代码未在AutoDiffCostFunction构造时传入这两个数值,导致Ceres无法识别有效维度。

  3. 约束函数的动态参数维度未指定
    QuadraticConstraint和LinearConstraint的参数块维度是32维,但原代码仅指定了残差数为1,未传入参数块维度,同样触发维度断言错误。

修复后的关键代码

1. 修正目标函数创建逻辑

ceres::CostFunction* CeresOptimization::createTorqueObjective() {
    const int dim = 32;
    return new ceres::AutoDiffCostFunction<TorqueObjective, Eigen::Dynamic, Eigen::Dynamic>(
        new TorqueObjective(Eigen::VectorXd::Constant(dim, 0.6)),
        dim,  // 残差数量:对应32维输出
        dim); // 参数块维度:T是32维向量
}

2. 修正二次约束创建逻辑

ceres::CostFunction* CeresOptimization::createQuadraticConstraint(const DataConstraint* data) {
    const int param_dim = data->Bi.cols();
    return new ceres::AutoDiffCostFunction<QuadraticConstraint, 1, Eigen::Dynamic>(
        new QuadraticConstraint(data->Bi),
        1,          // 残差数量:单残差对应二次约束值
        param_dim); // 参数块维度:从输入矩阵推导
}

3. 修正线性约束创建逻辑

ceres::CostFunction* CeresOptimization::createLinearConstraint(const DataConstraint* data) {
    const int param_dim = data->J.cols();
    return new ceres::AutoDiffCostFunction<LinearConstraint, 1, Eigen::Dynamic>(
        new LinearConstraint(data->G, data->J, data->Ext),
        1,          // 残差数量:单残差对应范数平方
        param_dim); // 参数块维度:从输入矩阵推导
}

额外优化建议

  1. 不等式约束的正确处理
    原代码将TᵀB T <=0作为普通残差块添加,Ceres默认会将其当作等式约束处理。若要实现不等式约束,需添加损失函数将其转化为惩罚项,例如使用SoftPlusLoss(平滑的max(0, f(x))):

    problem.AddResidualBlock(quadratic_constraint, new ceres::SoftPlusLoss(1.0), T);
    
  2. 无穷范数目标的简化实现
    最小化||T/tmax||∞无需自定义目标函数,可直接使用Ceres内置的InfinityNormCostFunction,更高效且不易出错:

    Eigen::VectorXd tmax = Eigen::VectorXd::Constant(32, 0.6);
    ceres::CostFunction* torque_objective = 
        new ceres::InfinityNormCostFunction(tmax.data(), 32);
    

内容的提问来源于stack exchange,提问作者Abiud Rds

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 00:59:53