【问题标题】:Ceres Solver C++: Segmentation fault: 11Ceres Solver C++:分段错误:11
【发布时间】:2019-10-20 09:38:34
【问题描述】:

我正在尝试使用 Google 的 Ceres Solver 求解非线性系统。下面的例子来自这个页面:http://terpconnect.umd.edu/~petersd/460/html/newtonex1z.html

我首先创建了一个名为MatlabExample 的类,我在其中计算residualsjacobians

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;
}
};

主文件如下:

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;
}

编译时出现Segmentation fault: 11 错误。有什么想法吗?

【问题讨论】:

  • double const* const* parameters - 哇。为什么要这么做?为什么不直接传递 std::arraystd::vector(可能通过 const 引用)?
  • 吹毛求疵:更喜欢nullptr 而不是NULL。我们不再生活在 C++98 的土地上。
  • 因为抽象类'SizedCostFunction'以这种方式定义了虚函数'Evaluate'。我无法改变它,因为它来自 Ceres Solver。
  • jacobians 的空检查实际上毫无价值。这并不能充分确定 jacobians 对您的使用方式是否有效。

标签: c++ optimization google-analytics mathematical-optimization ceres-solver


【解决方案1】:

您正在访问错误的 jacobians 数组。这就是原因。

当您添加残差块时,您告诉 Ceres 成本函数仅取决于一个大小为 2 的参数块,并产生大小为 2 的残差。

雅可比数组是行主要雅可比数组。每个参数块一个。因此,在这种情况下,它的大小为 1,并包含一个指向大小为 4 的数组的指针,该数组应包含行主要雅可比行列式。

你的雅可比填充代码应该改为

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;
}

【讨论】:

  • 谢谢。因此,这样做意味着jacobians[0][0]=d f1/x1jacobians[0][1]=d f1/x2jacobians[0][2]=d f2/x1jacobians[0][3]=d f2/x2。我们确定这个订单吗?
  • 是的,谷神星中的雅可比矩阵是行主矩阵。
  • Ceres 包装器的作者没有将double** 包装在一个类中,这太糟糕了,所以至少可以使用size() 或类似的函数来验证尺寸大小.
猜你喜欢
  • 2014-04-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-22
  • 1970-01-01
相关资源
最近更新 更多