C++ Ceres解算器成本函数继承错误:模板可能不是虚拟的
我已经使用了很长一段时间,这是一个了不起的工具。到目前为止,我的使用并不是基于可重用代码,我正在努力改进这一点。Ceres使用具有特定模板方法的特定结构作为其接口。在我试图解决的问题中,继承是有意义的,因为我需要的不同代价函数彼此非常相似。我已经创建了一个类似的示例(但这毫无意义,抱歉)。假设我们希望能够找到具有给定面积的多边形。在我的示例中,多边形可以是三角形或矩形。考虑到这一点,有一个实现一切的基类和实现每个特定多边形的面积计算的特定类是有意义的: ShapeCostFunctionC++ Ceres解算器成本函数继承错误:模板可能不是虚拟的,c++,templates,inheritance,ceres-solver,c++14,C++,Templates,Inheritance,Ceres Solver,C++14,我已经使用了很长一段时间,这是一个了不起的工具。到目前为止,我的使用并不是基于可重用代码,我正在努力改进这一点。Ceres使用具有特定模板方法的特定结构作为其接口。在我试图解决的问题中,继承是有意义的,因为我需要的不同代价函数彼此非常相似。我已经创建了一个类似的示例(但这毫无意义,抱歉)。假设我们希望能够找到具有给定面积的多边形。在我的示例中,多边形可以是三角形或矩形。考虑到这一点,有一个实现一切的基类和实现每个特定多边形的面积计算的特定类是有意义的: ShapeCostFunction cla
class shapeAreaCostFunction
{
public:
shapeAreaCostFunction(double desired_area): desired_area_(desired_area){}
template<typename T>
bool operator()(const T* shape, T* residual) const{
residual[0] = T(desired_area_) - area(shape);
return true;
}
template<typename T>
virtual T area(const T* shape) const = 0;
protected:
double desired_area_;
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class rectangleAreaCostFunction : public shapeAreaCostFunction
{
public:
rectangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return rectangleArea(triangle);
}
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class triangleAreaCostFunction : public shapeAreaCostFunction
{
public:
triangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return triangleArea(triangle);
}
};
#include <ceres/ceres.h>
#include <iostream>
#include "rectangleAreaCostFunction.h"
#include "triangleAreaCostFunction.h"
#include "areaLibrary.h"
int main(int argc, char** argv){
// Initialize glogging
//google::InitGoogleLogging(argv[0]);
// Get values
/// Get total area
double total_area;
std::cout<<"Enter the desired area: ";
std::cin>>total_area;
/// Get initial rectangle
double rect[2];
std::cout<<"Enter initial rectangle base: ";
std::cin>>rect[0];
std::cout<<"Enter initial rectangle height: ";
std::cin>>rect[1];
/// Get initial triagnle
double tri[2];
std::cout<<"Enter initial triangle base: ";
std::cin>>tri[0];
std::cout<<"Enter initial triangle height: ";
std::cin>>tri[1];
// Copy initial values
double rect_ini[] = {rect[0],rect[1]};
double tri_ini[] = {tri[0],tri[1]};
// Create problem
ceres::Problem problem;
ceres::CostFunction* cost_function_rectangle = new ceres::AutoDiffCostFunction<rectangleAreaCostFunction, 1, 2>(
new rectangleAreaCostFunction(total_area));
ceres::CostFunction* cost_function_triangle = new ceres::AutoDiffCostFunction<triangleAreaCostFunction, 1, 2>(
new triangleAreaCostFunction(total_area));
problem.AddResidualBlock(cost_function_rectangle, NULL, rect);
problem.AddResidualBlock(cost_function_triangle, NULL, tri);
// Solve
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
options.max_num_iterations = 10;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
// Compute final areas
double rect_area = rectangleArea(rect);
double tri_area = triangleArea(tri);
// Display results
std::cout << summary.FullReport() << std::endl;
std::cout<<"Rectangle: ("<<rect_ini[0]<<","<<rect_ini[1]<<") -> ("<<rect[0]<<","<<rect[1]<<") total area: "<<rect_area<<"("<< rect_area - total_area<<")"<<std::endl;
std::cout<<"Triangle: ("<<tri_ini[0]<<","<<tri_ini[1]<<") -> ("<<tri[0]<<","<<tri[1]<<") total area: "<<tri_area<<"("<< tri_area - total_area<<")"<<std::endl;
// Exit
return 0;
}
类shapeAreaCostFunction
{
公众:
shapeAreaCostFunction(双期望面积):期望面积(期望面积){
模板
布尔运算符()(常数T*形状,T*残差)常数{
剩余[0]=T(所需面积)-面积(形状);
返回true;
}
模板
虚拟T面积(常数T*形状)常数=0;
受保护的:
双所需面积;
};
矩形成本函数
class shapeAreaCostFunction
{
public:
shapeAreaCostFunction(double desired_area): desired_area_(desired_area){}
template<typename T>
bool operator()(const T* shape, T* residual) const{
residual[0] = T(desired_area_) - area(shape);
return true;
}
template<typename T>
virtual T area(const T* shape) const = 0;
protected:
double desired_area_;
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class rectangleAreaCostFunction : public shapeAreaCostFunction
{
public:
rectangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return rectangleArea(triangle);
}
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class triangleAreaCostFunction : public shapeAreaCostFunction
{
public:
triangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return triangleArea(triangle);
}
};
#include <ceres/ceres.h>
#include <iostream>
#include "rectangleAreaCostFunction.h"
#include "triangleAreaCostFunction.h"
#include "areaLibrary.h"
int main(int argc, char** argv){
// Initialize glogging
//google::InitGoogleLogging(argv[0]);
// Get values
/// Get total area
double total_area;
std::cout<<"Enter the desired area: ";
std::cin>>total_area;
/// Get initial rectangle
double rect[2];
std::cout<<"Enter initial rectangle base: ";
std::cin>>rect[0];
std::cout<<"Enter initial rectangle height: ";
std::cin>>rect[1];
/// Get initial triagnle
double tri[2];
std::cout<<"Enter initial triangle base: ";
std::cin>>tri[0];
std::cout<<"Enter initial triangle height: ";
std::cin>>tri[1];
// Copy initial values
double rect_ini[] = {rect[0],rect[1]};
double tri_ini[] = {tri[0],tri[1]};
// Create problem
ceres::Problem problem;
ceres::CostFunction* cost_function_rectangle = new ceres::AutoDiffCostFunction<rectangleAreaCostFunction, 1, 2>(
new rectangleAreaCostFunction(total_area));
ceres::CostFunction* cost_function_triangle = new ceres::AutoDiffCostFunction<triangleAreaCostFunction, 1, 2>(
new triangleAreaCostFunction(total_area));
problem.AddResidualBlock(cost_function_rectangle, NULL, rect);
problem.AddResidualBlock(cost_function_triangle, NULL, tri);
// Solve
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
options.max_num_iterations = 10;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
// Compute final areas
double rect_area = rectangleArea(rect);
double tri_area = triangleArea(tri);
// Display results
std::cout << summary.FullReport() << std::endl;
std::cout<<"Rectangle: ("<<rect_ini[0]<<","<<rect_ini[1]<<") -> ("<<rect[0]<<","<<rect[1]<<") total area: "<<rect_area<<"("<< rect_area - total_area<<")"<<std::endl;
std::cout<<"Triangle: ("<<tri_ini[0]<<","<<tri_ini[1]<<") -> ("<<tri[0]<<","<<tri[1]<<") total area: "<<tri_area<<"("<< tri_area - total_area<<")"<<std::endl;
// Exit
return 0;
}
#包括“shapeAreaCostFunction.h”
#包括“areaLibrary.h”
类rectangleAreaCostFunction:public shapeAreaCostFunction
{
公众:
矩形区域CostFunction(双所需_区域):shapeAreaCostFunction(所需_区域){}
模板
T面积(常数T*三角形)常数
{
返回矩形区域(三角形);
}
};
TriangeleCostFunction
class shapeAreaCostFunction
{
public:
shapeAreaCostFunction(double desired_area): desired_area_(desired_area){}
template<typename T>
bool operator()(const T* shape, T* residual) const{
residual[0] = T(desired_area_) - area(shape);
return true;
}
template<typename T>
virtual T area(const T* shape) const = 0;
protected:
double desired_area_;
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class rectangleAreaCostFunction : public shapeAreaCostFunction
{
public:
rectangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return rectangleArea(triangle);
}
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class triangleAreaCostFunction : public shapeAreaCostFunction
{
public:
triangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return triangleArea(triangle);
}
};
#include <ceres/ceres.h>
#include <iostream>
#include "rectangleAreaCostFunction.h"
#include "triangleAreaCostFunction.h"
#include "areaLibrary.h"
int main(int argc, char** argv){
// Initialize glogging
//google::InitGoogleLogging(argv[0]);
// Get values
/// Get total area
double total_area;
std::cout<<"Enter the desired area: ";
std::cin>>total_area;
/// Get initial rectangle
double rect[2];
std::cout<<"Enter initial rectangle base: ";
std::cin>>rect[0];
std::cout<<"Enter initial rectangle height: ";
std::cin>>rect[1];
/// Get initial triagnle
double tri[2];
std::cout<<"Enter initial triangle base: ";
std::cin>>tri[0];
std::cout<<"Enter initial triangle height: ";
std::cin>>tri[1];
// Copy initial values
double rect_ini[] = {rect[0],rect[1]};
double tri_ini[] = {tri[0],tri[1]};
// Create problem
ceres::Problem problem;
ceres::CostFunction* cost_function_rectangle = new ceres::AutoDiffCostFunction<rectangleAreaCostFunction, 1, 2>(
new rectangleAreaCostFunction(total_area));
ceres::CostFunction* cost_function_triangle = new ceres::AutoDiffCostFunction<triangleAreaCostFunction, 1, 2>(
new triangleAreaCostFunction(total_area));
problem.AddResidualBlock(cost_function_rectangle, NULL, rect);
problem.AddResidualBlock(cost_function_triangle, NULL, tri);
// Solve
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
options.max_num_iterations = 10;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
// Compute final areas
double rect_area = rectangleArea(rect);
double tri_area = triangleArea(tri);
// Display results
std::cout << summary.FullReport() << std::endl;
std::cout<<"Rectangle: ("<<rect_ini[0]<<","<<rect_ini[1]<<") -> ("<<rect[0]<<","<<rect[1]<<") total area: "<<rect_area<<"("<< rect_area - total_area<<")"<<std::endl;
std::cout<<"Triangle: ("<<tri_ini[0]<<","<<tri_ini[1]<<") -> ("<<tri[0]<<","<<tri[1]<<") total area: "<<tri_area<<"("<< tri_area - total_area<<")"<<std::endl;
// Exit
return 0;
}
#包括“shapeAreaCostFunction.h”
#包括“areaLibrary.h”
类triangleAreaCostFunction:public shapeAreaCostFunction
{
公众:
triangleAreaCostFunction(双所需_区域):shapeAreaCostFunction(所需_区域){}
模板
T面积(常数T*三角形)常数
{
返回三角形a(三角形);
}
};
区域库
template<typename T>
T rectangleArea(const T* rectangle)
{
return rectangle[0]*rectangle[1];
}
template<typename T>
T triangleArea(const T* triangle)
{
return rectangleArea(triangle)/T(2);
}
模板
T矩形区域(常数T*矩形)
{
返回矩形[0]*矩形[1];
}
模板
T三角形A(常数T*三角形)
{
返回矩形区域(三角形)/T(2);
}
Main
class shapeAreaCostFunction
{
public:
shapeAreaCostFunction(double desired_area): desired_area_(desired_area){}
template<typename T>
bool operator()(const T* shape, T* residual) const{
residual[0] = T(desired_area_) - area(shape);
return true;
}
template<typename T>
virtual T area(const T* shape) const = 0;
protected:
double desired_area_;
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class rectangleAreaCostFunction : public shapeAreaCostFunction
{
public:
rectangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return rectangleArea(triangle);
}
};
#include "shapeAreaCostFunction.h"
#include "areaLibrary.h"
class triangleAreaCostFunction : public shapeAreaCostFunction
{
public:
triangleAreaCostFunction(double desired_area): shapeAreaCostFunction(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return triangleArea(triangle);
}
};
#include <ceres/ceres.h>
#include <iostream>
#include "rectangleAreaCostFunction.h"
#include "triangleAreaCostFunction.h"
#include "areaLibrary.h"
int main(int argc, char** argv){
// Initialize glogging
//google::InitGoogleLogging(argv[0]);
// Get values
/// Get total area
double total_area;
std::cout<<"Enter the desired area: ";
std::cin>>total_area;
/// Get initial rectangle
double rect[2];
std::cout<<"Enter initial rectangle base: ";
std::cin>>rect[0];
std::cout<<"Enter initial rectangle height: ";
std::cin>>rect[1];
/// Get initial triagnle
double tri[2];
std::cout<<"Enter initial triangle base: ";
std::cin>>tri[0];
std::cout<<"Enter initial triangle height: ";
std::cin>>tri[1];
// Copy initial values
double rect_ini[] = {rect[0],rect[1]};
double tri_ini[] = {tri[0],tri[1]};
// Create problem
ceres::Problem problem;
ceres::CostFunction* cost_function_rectangle = new ceres::AutoDiffCostFunction<rectangleAreaCostFunction, 1, 2>(
new rectangleAreaCostFunction(total_area));
ceres::CostFunction* cost_function_triangle = new ceres::AutoDiffCostFunction<triangleAreaCostFunction, 1, 2>(
new triangleAreaCostFunction(total_area));
problem.AddResidualBlock(cost_function_rectangle, NULL, rect);
problem.AddResidualBlock(cost_function_triangle, NULL, tri);
// Solve
ceres::Solver::Options options;
options.linear_solver_type = ceres::DENSE_QR;
options.minimizer_progress_to_stdout = true;
options.max_num_iterations = 10;
ceres::Solver::Summary summary;
ceres::Solve(options, &problem, &summary);
// Compute final areas
double rect_area = rectangleArea(rect);
double tri_area = triangleArea(tri);
// Display results
std::cout << summary.FullReport() << std::endl;
std::cout<<"Rectangle: ("<<rect_ini[0]<<","<<rect_ini[1]<<") -> ("<<rect[0]<<","<<rect[1]<<") total area: "<<rect_area<<"("<< rect_area - total_area<<")"<<std::endl;
std::cout<<"Triangle: ("<<tri_ini[0]<<","<<tri_ini[1]<<") -> ("<<tri[0]<<","<<tri[1]<<") total area: "<<tri_area<<"("<< tri_area - total_area<<")"<<std::endl;
// Exit
return 0;
}
#包括
#包括
#包括“矩形区域costfunction.h”
#包括“triangleAreaCostFunction.h”
#包括“areaLibrary.h”
int main(int argc,字符**argv){
//初始化格洛格
//google::InitGoogleLogging(argv[0]);
//获取价值
///获取总面积
总面积加倍;
标准::库托塔卢地区;
///获取初始矩形
双矩形[2];
std::coutrect[0];
std::coutrect[1];
///获得初始测试
双三[2];
std::couttri[0];
std::couttri[1];
//复制初始值
双rect_ini[]={rect[0],rect[1]};
双tri_ini[]={tri[0],tri[1]};
//制造问题
谷神星:问题;
ceres::CostFunction*成本函数\矩形=新ceres::AutoDiffCostFunction(
新的矩形区域CostFunction(总面积);
ceres::CostFunction*成本函数\三角形=新ceres::AutoDiffCostFunction(
新的triangleAreaCostFunction(总面积);
问题.AddResidualBlock(代价函数矩形,NULL,rect);
问题.AddResidualBlock(代价函数三角,NULL,tri);
//解决
ceres::解算器::选项;
options.linear\u solver\u type=ceres::densite\u QR;
options.minimizer\u progress\u to\u stdout=true;
options.max_num_iterations=10;
ceres::Solver::Summary;
ceres::解决(选项、问题和总结);
//计算最终面积
双矩形面积=矩形面积(矩形);
双tri_面积=三角形面积a(tri);
//显示结果
我可以想出两种方法
首先,编写lambdas。其次,使用CRTP
撰写兰博达斯
这是最好的方法
要获取类型,decltype(tri\u cost)
因此:
auto tri_cost=cost_函数(三角形,3.14159);
ceres::CostFunction*成本函数\三角形=新ceres::AutoDiffCostFunction(
新的decltype(tri_成本)(tri_成本));
您可以在没有lambdas的情况下使用类似的合成技术,但它更繁琐。您还可以将一些赤裸裸的新功能包装到帮助器函数中
CRTP
模板
类shapeAreaCostFunction{
公众:
shapeAreaCostFunction(双期望面积):期望面积(期望面积){
模板
布尔运算符()(常数T*形状,T*残差)常数{
残余[0]=T(所需面积)-静态铸造(本)->面积(形状);
返回true;
}
受保护的:
双所需面积;
};
修改派生类型,如下所示:
class triangleAreaCostFunction :
public shapeAreaCostFunction<triangleAreaCostFunction>
{
using base=shapeAreaCostFunction<triangleAreaCostFunction>;
public:
triangleAreaCostFunction(double desired_area): base(desired_area){}
template<typename T>
T area(const T* triangle) const
{
return triangleArea(triangle);
}
};
class triangleAreaCostFunction:
公共shapeAreaCostFunction
{
使用base=shapeAreaCostFunction;
公众:
triangleAreaCostFunction(双所需_区域):基(所需_区域){}
模板
T面积(常数T*三角形)常数
{
返回三角形a(三角形);
}
};
这就是使用CRTP来实现静态多态性。
我喜欢这种CRTP方法来移除一个虚拟调用。谢谢@ YAKK,CRTP解决方案通过复制粘贴完美地工作。LAMNDA解决方案有点超出了我理解复杂C++代码的能力。