如何在Ceres Solver中正确建模优化问题以解决编译断言错误?
编译错误原因与修复方案
错误根源分析
编译断言错误的核心原因是Ceres Solver动态维度模板参数的构造方式错误:当使用Eigen::Dynamic作为残差数或参数块维度时,必须显式传入具体数值,否则Ceres无法推导有效维度,导致内部断言失败。
具体问题点
动态残差/参数维度未显式指定
在创建AutoDiffCostFunction时,若模板参数使用Eigen::Dynamic,必须通过构造函数的额外参数传入残差数量和参数块维度,否则Ceres会将维度默认设为-1,触发"Invalid parameter block dimension"断言。目标函数的动态构造缺失维度参数
TorqueObjective输出32个残差,参数块是32维,但原代码未在AutoDiffCostFunction构造时传入这两个数值,导致Ceres无法识别有效维度。约束函数的动态参数维度未指定
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); // 参数块维度:从输入矩阵推导 }
额外优化建议
不等式约束的正确处理
原代码将TᵀB T <=0作为普通残差块添加,Ceres默认会将其当作等式约束处理。若要实现不等式约束,需添加损失函数将其转化为惩罚项,例如使用SoftPlusLoss(平滑的max(0, f(x))):problem.AddResidualBlock(quadratic_constraint, new ceres::SoftPlusLoss(1.0), T);无穷范数目标的简化实现
最小化||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
相关产品推荐
相关产品推荐

