C++ Ceres Solver C++;:分段错误:11
我试图用谷歌的Ceres解算器来解一个非线性系统。以下示例来自本页: 我首先创建一个名为C++ Ceres Solver C++;:分段错误:11,c++,optimization,google-analytics,mathematical-optimization,ceres-solver,C++,Optimization,Google Analytics,Mathematical Optimization,Ceres Solver,我试图用谷歌的Ceres解算器来解一个非线性系统。以下示例来自本页: 我首先创建一个名为MatlabExample的类,在这里我计算残差和雅可比数: class MatlabExample : public SizedCostFunction<2,2> { public: virtual ~MatlabExample() {} virtual bool Evaluate(double const* const* parameters, doub
MatlabExample
的类,在这里我计算残差
和雅可比数
:
class MatlabExample
: public SizedCostFunction<2,2> {
public:
virtual ~MatlabExample() {}
virtual bool Evaluate(double const* const* parameters,
double* residuals,
double** jacobians) const {
double x1 = parameters[0][0];
double x2 = parameters[0][1];
residuals[0] = 2*x1+x1*x2-2;
residuals[1] = 2*x2-x1*pow(x2,2)-2 ;
if (jacobians != NULL && jacobians[0] != NULL) {
jacobians[0][0] = 2+x2;
jacobians[0][1] = x1;
jacobians[1][0] = -pow(x2,2);
jacobians[1][1] = 2-2*x1*x2;
}
return true;
}
};
类MatlabExample
:公共大小的成本函数{
公众:
虚拟~MatlabExample(){}
虚拟布尔求值(双常数*常数*参数,
双*残差,
双**雅可比数)常数{
双x1=参数[0][0];
双x2=参数[0][1];
残差[0]=2*x1+x1*x2-2;
残差[1]=2*x2-x1*pow(x2,2)-2;
if(雅可比数!=NULL&&jacobians[0]!=NULL){
雅可比[0][0]=2+x2;
雅可比[0][1]=x1;
雅可比[1][0]=-pow(x2,2);
雅可比[1][1]=2-2*x1*x2;
}
返回true;
}
};
主要文件如下:
int main(int argc, char** argv) {
google::InitGoogleLogging(argv[0]);
double x[] = { 0.0,0.0 };
Problem problem;
CostFunction* cost_function = new MatlabExample;
problem.AddResidualBlock(cost_function, NULL, &x);
Solver::Options options;
options.minimizer_progress_to_stdout = true;
Solver::Summary summary;
Solve(options, &problem, &summary);
std::cout << summary.BriefReport() << "\n";
return 0;
}
int main(int argc,char**argv){
google::InitGoogleLogging(argv[0]);
双x[]={0.0,0.0};
问题;
成本函数*成本函数=新MatlabExample;
问题.AddResidualBlock(cost_函数,NULL,&x);
解算器::选项;
options.minimizer\u progress\u to\u stdout=true;
解算器:总结;
解决(选项、问题和总结);
std::cout您访问雅可比数组时出错。原因如下
当您添加残差块时,您告诉Ceres,成本函数仅取决于一个大小为2的参数块,并生成大小为2的残差
jacobians数组是一个行主jacobians数组。每个参数块一个。因此,在本例中,它的大小为1,并包含一个指向大小为4的数组的指针,该数组应包含行主jacobians
您的雅可比填充代码应该改为
if (jacobians != NULL && jacobians[0] != NULL) {
jacobians[0][0] = 2+x2;
jacobians[0][1] = x1;
jacobians[0][2] = -pow(x2,2);
jacobians[0][3] = 2-2*x1*x2;
}
double const*const*parameters
-哇。你为什么要这样做?为什么不直接传递一个std::array
或std::vector
(可能通过const引用)?吹毛求疵:宁愿nullptr
而不是NULL
。我们不再生活在C++98中。因为抽象类“SizedCostFunction”以这种方式定义了虚拟函数“Evaluate”。我没有办法改变这一点,因为它来自CERESolver。我扩展了这个文件:对雅可比人
的空检查是可行的毫无价值。这并不能充分确定jacobians
是否适用于您如何使用它。谢谢。因此,这样做意味着jacobians[0][0]=df1/x1
,jacobians[0][1]=df1/x2
,jacobians[0][2]=df2/x1
,以及jacobians[0][3]=d f2/x2
。我们确定这个顺序吗?是的,Ceres中的雅可比矩阵是行主矩阵。很遗憾,Ceres包装器的作者没有将double**
包装在一个类中,因此至少可以使用size()
或类似的函数来验证维度大小。