Hello,
I am following this sample (with Ceres Solver version 1.10.0 on Linux):
but instead of fitting the exp function I would like to fit the Bessel functions of the first kind with integer order equal to 1.
My first tentative was to just replace 'exp' with 'j1' but I got the following compiler error:
/home/ag/projects/ceres-hello-world/curve_fitting.cc: In instantiation of ‘bool MyResidual::operator()(const T*, const T*, T*) const [with T = ceres::Jet<double, 2>]’:
/usr/local/include/ceres/internal/variadic_evaluate.h:167:26: required from ‘static bool ceres::internal::VariadicEvaluate<Functor, T, N0, N1, 0, 0, 0, 0, 0, 0, 0, 0>::Call(const Functor&, const T* const*, T*) [with Functor = MyResidual; T = ceres::Jet<double, 2>; int N0 = 1; int N1 = 1]’
/usr/local/include/ceres/internal/autodiff.h:283:45: required from ‘static bool ceres::internal::AutoDiff<Functor, T, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Differentiate(const Functor&, const T* const*, int, T*, T**) [with Functor = MyResidual; T = double; int N0 = 1; int N1 = 1; int N2 = 0; int N3 = 0; int N4 = 0; int N5 = 0; int N6 = 0; int N7 = 0; int N8 = 0; int N9 = 0]’
/usr/local/include/ceres/autodiff_cost_function.h:218:25: required from ‘bool ceres::AutoDiffCostFunction<CostFunctor, kNumResiduals, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Evaluate(const double* const*, double*, double**) const [with CostFunctor = MyResidual; int kNumResiduals = 1; int N0 = 1; int N1 = 1; int N2 = 0; int N3 = 0; int N4 = 0; int N5 = 0; int N6 = 0; int N7 = 0; int N8 = 0; int N9 = 0]’
/home/ag/projects/ceres-hello-world/curve_fitting.cc:146:1: required from here
/home/ag/projects/ceres-hello-world/curve_fitting.cc:111:49: error: cannot convert ‘ceres::Jet<double, 2>’ to ‘double’ for argument ‘1’ to ‘double j1(double)’
residual[0] = T(y_) - j1(m[0] * T(x_) + c[0]);
^
make[2]: *** [CMakeFiles/curve_fitting.dir/curve_fitting.cc.o] Error 1
make[1]: *** [CMakeFiles/curve_fitting.dir/all] Error 2
make: *** [all] Error 2
I then debug the original sample (with 'exp' and I realized that 'exp' is not the C++ library function but it is defined inside the namespace ceres in this file:
/home/ag/projects/ceres-solver-1.10.0/include/ceres/jet.h
And, as you know, 'exp' is defined as:
// exp(a + h) ~= exp(a) + exp(a) h
template <typename T, int N> inline
Jet<T, N> exp(const Jet<T, N>& f) {
const T tmp = exp(f.a);
return Jet<T, N>(tmp, tmp * f.v);
}
So I tried to add in my code a similar definition for j1:
namespace ceres {
// j0 is the Bessel functions of the first kind with integer order equal to 0
// j1 is the Bessel functions of the first kind with integer order equal to 1
// jn is the Bessel functions of the first kind with integer order equal to n
// In general, f(a + h) ~= f(a) + f'(a) h, via the chain rule.
// j1(a + h) ~= j1(a) + 0.5 ( j0(a) - j2(a) ) h
template <typename T, int N> inline
Jet<T, N> j1(const Jet<T, N>& f) {
return Jet<T, N>(j1(f.a), T(0.5) * ( j0(f.a)-jn(2,f.a) ) * f.v);
}
}
and now I have the following compiler error (see attached code):
/home/ag/projects/ceres-hello-world/curve_fitting.cc: In instantiation of ‘ceres::Jet<T, N> ceres::j1(const ceres::Jet<T, N>&) [with T = double; int N = 2]’:
/home/ag/projects/ceres-hello-world/curve_fitting.cc:111:49: required from ‘bool MyResidual::operator()(const T*, const T*, T*) const [with T = ceres::Jet<double, 2>]’
/usr/local/include/ceres/internal/variadic_evaluate.h:167:26: required from ‘static bool ceres::internal::VariadicEvaluate<Functor, T, N0, N1, 0, 0, 0, 0, 0, 0, 0, 0>::Call(const Functor&, const T* const*, T*) [with Functor = MyResidual; T = ceres::Jet<double, 2>; int N0 = 1; int N1 = 1]’
/usr/local/include/ceres/internal/autodiff.h:283:45: required from ‘static bool ceres::internal::AutoDiff<Functor, T, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Differentiate(const Functor&, const T* const*, int, T*, T**) [with Functor = MyResidual; T = double; int N0 = 1; int N1 = 1; int N2 = 0; int N3 = 0; int N4 = 0; int N5 = 0; int N6 = 0; int N7 = 0; int N8 = 0; int N9 = 0]’
/usr/local/include/ceres/autodiff_cost_function.h:218:25: required from ‘bool ceres::AutoDiffCostFunction<CostFunctor, kNumResiduals, N0, N1, N2, N3, N4, N5, N6, N7, N8, N9>::Evaluate(const double* const*, double*, double**) const [with CostFunctor = MyResidual; int kNumResiduals = 1; int N0 = 1; int N1 = 1; int N2 = 0; int N3 = 0; int N4 = 0; int N5 = 0; int N6 = 0; int N7 = 0; int N8 = 0; int N9 = 0]’
/home/ag/projects/ceres-hello-world/curve_fitting.cc:146:1: required from here
/home/ag/projects/ceres-hello-world/curve_fitting.cc:101:26: error: no matching function for call to ‘j1(const double&)’
return Jet<T, N>(j1(f.a), T(0.5) * ( j0(f.a)-jn(2,f.a) ) * f.v);
^
/home/ag/projects/ceres-hello-world/curve_fitting.cc:101:26: note: candidate is:
/home/ag/projects/ceres-hello-world/curve_fitting.cc:100:11: note: template<class T, int N> ceres::Jet<T, N> ceres::j1(const ceres::Jet<T, N>&)
Jet<T, N> j1(const Jet<T, N>& f) {
^
/home/ag/projects/ceres-hello-world/curve_fitting.cc:100:11: note: template argument deduction/substitution failed:
/home/ag/projects/ceres-hello-world/curve_fitting.cc:101:26: note: mismatched types ‘const ceres::Jet<T, N>’ and ‘const double’
return Jet<T, N>(j1(f.a), T(0.5) * ( j0(f.a)-jn(2,f.a) ) * f.v);
^
make[2]: *** [CMakeFiles/curve_fitting.dir/curve_fitting.cc.o] Error 1
make[1]: *** [CMakeFiles/curve_fitting.dir/all] Error 2
make: *** [all] Error 2
What am I missing?
Thank you very much.
Best regards,
Alessandro Gentilini