ceres-solver / ceres-solver

A large scale non-linear optimization library

Home Page:http://ceres-solver.org/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Upgrading CERES v1.14.0 to v2.0.0 - Error when linking CERES v2.0.0 in a C++ project

esaumar opened this issue · comments

Development description:
OS: Ubuntu 18.04
Main project dependencies: OpenMVG v1.2 and CERES v2.0.0
CMake version: 3.10.2

Hi folks!

I'm trying to upgrade the version of CERES Solver in my project from v1.14.0 to v2.0.0 but I'm getting some errors during the compilation. With v1.14.0 it is compiling and working correctly but when I try to compile with v2.0.0 I got the next error:

Scanning dependencies of target test_transforms
[ 78%] Building CXX object tests/CMakeFiles/test_transforms.dir/test_transforms.cpp.o
[ 79%] Linking CXX executable test_transforms
../myproject/transforms/libmyproject_transforms.so: undefined reference to `ceres::Problem::AddResidualBlock(ceres::CostFunction*, ceres::LossFunction*, double* const*, int)'
collect2: error: ld returned 1 exit status
tests/CMakeFiles/test_transforms.dir/build.make:173: recipe for target 'tests/test_transforms' failed
make[2]: *** [tests/test_transforms] Error 1
CMakeFiles/Makefile2:2832: recipe for target 'tests/CMakeFiles/test_transforms.dir/all' failed
make[1]: *** [tests/CMakeFiles/test_transforms.dir/all] Error 2
Makefile:140: recipe for target 'all' failed
make: *** [all] Error 2

It seems that it is a linking issue:

../libmyproject/transforms/libmyproject_transforms.so: undefined reference to `ceres::Problem::AddResidualBlock(ceres::CostFunction*, ceres::LossFunction*, double* const*, int)'

This is the way I'm defining the CMakeLists.txt for the module where I use CERES solver

cmake_minimum_required(VERSION 3.5)
project(myproject_transforms)
add_definitions(-std=c++14)

# Eigen used for SVD and others
find_package(Eigen REQUIRED)
include_directories(${EIGEN_INCLUDE_DIRS})

# OpenMVG for RANSAC related
add_definitions(${OPENMVG_DEFINITIONS})

# Ceres for bundle adjustment
find_package(Ceres REQUIRED)
target_link_libraries(${PROJECT_NAME} ceres)
include_directories(${CERES_INCLUDE_DIRS})

# Myproject common definitions and libraries
target_link_libraries(${PROJECT_NAME} ${MYPROJECT_THIRD_PARTY_LIBS})
add_definitions(${MYPROJECT_DEFINITIONS})

install(TARGETS ${PROJECT_NAME} DESTINATION lib EXPORT MYPROJECT_EXPORTS)

Can you give a hint about how to solve it?

Btw, I'm not sure if it is related but I disabled the miniglog included into OpenMVG repo because I was getting some issues during the compilation of my project. Instead I installed glog and gflags before compiling OpenMVG and CERES solver. One more note, the order I'm following for the compilation is:

  1. gflags
  2. glog
  3. OpenMVG 1.2
  4. CERES Solver 2.0.0
  5. Myproject

This looks like a linker problem when linking myproject_transforms. It does not have anything to do with ceres solver. I suspect it has to do with the order of libraries sent to the linker. I think it is worth looking at the actual command being executed when "[ 79%] Linking CXX executable test_transforms" is being done. So if you run your build process more verbosely you will be able to see that.

Thanks for your response.

You are right, it was a linker problem with the project. It was pointing to an older libceres.a library (probably installed by OpenMVG). I made a workaround by adding the correct library libceres.so.2.0.0 manually and now it worked. My CMakeListst.txt now looks something like this:

cmake_minimum_required(VERSION 3.5)
project(myproject_transforms)
add_definitions(-std=c++14)

# Eigen used for SVD and others
find_package(Eigen REQUIRED)
include_directories(${EIGEN_INCLUDE_DIRS})

# OpenMVG for RANSAC related
add_definitions(${OPENMVG_DEFINITIONS})

# Ceres for bundle adjustment
find_package(Ceres REQUIRED)
target_link_libraries(${PROJECT_NAME} /usr/local/lib/libceres.so.2.0.0) #<------whole path to lib
include_directories(${CERES_INCLUDE_DIRS})

# Myproject common definitions and libraries
target_link_libraries(${PROJECT_NAME} ${MYPROJECT_THIRD_PARTY_LIBS})
add_definitions(${MYPROJECT_DEFINITIONS})

install(TARGETS ${PROJECT_NAME} DESTINATION lib EXPORT MYPROJECT_EXPORTS)

Hi @sandwichmaker! I reopen the issue for another question. This might not be related to a linking problem but it is something I found when trying to upgrade to CERES v2.0.0.

I have a file functors_definition.cpp where I'm defining the cost functions as a class template follows

template
class ceres::AutoDiffCostFunction<PinholeCameraFunctor, 2, 3, 4, 3, 3>;

In another file functors_pinhole.cpp I have the definition of PinholeCameraFunctor as follows

template<typename T>
  bool operator()(const T *const cam_K,                 // 3 params
                  const T *const cam_R,                 // 4 params
                  const T *const cam_t,                 // 3 params
                  const T *const landmark,             // 3 params
                  T *residuals) const {                // 2 residuals

    // Apply external parameters (Pose)
    T x_u, y_u;
    ToCameraCoordinates(cam_R, cam_t, landmark, x_u, y_u);

    // Apply intrinsic parameters
    T projected_x, projected_y;
    ApplyIntrinsics(cam_K, x_u, y_u, projected_x, projected_y);

    // Compute error
    residuals[0] = projected_x - T(m_observation[0]);
    residuals[1] = projected_y - T(m_observation[1]);

    return true;
  }

This code was working correctly with CERES v1.14.0 but when I tried to upgrade to CERES v2.0.0 I got this error during the compilation

/usr/local/include/ceres/autodiff_cost_function.h: In instantiation of 'ceres::AutoDiffCostFunction<CostFunctor, kNumResiduals, Ns>::AutoDiffCostFunction(CostFunctor*, int, ceres::Ownership) [with CostFunctor = myproject::PinholeCameraFunctor; int kNumResiduals = 2; int ...Ns = {3, 4, 3, 3}]':
/home/Repos/myproject/functors_definition.cpp:10:14:   required from here
/usr/local/include/ceres/autodiff_cost_function.h:175:5: error: static assertion failed: Can't run the dynamic-size constructor if the number of residuals is not ceres::DYNAMIC.
     static_assert(kNumResiduals == DYNAMIC,
     ^~~~~~~~~~~~~

I saw that the definition of autodiff_cost_function.h changed a bit from v1.14.0 to v2.0.0 in terms of the Number of parameters in each parameter block but I can't see if my code needs some modifications. I think it should work as my number of residuals is not DYNAMIC.

v1.14.0

int N0, // Number of parameters in block 0.

v2.0.0

int... Ns> // Number of parameters in each parameter block.

Btw, I'm compiling using C++11, not sure if it has relation with the error. Can you give me a hint about the issue? Thanks!

Thank you for your response. Yeah, the functors_definition.cpp file is a explicit instantiation of template to improve build time but it was not necessary to be instantiated that way. I removed that instantiation and now it compiled correctly.