gadomski / cpd

C++ implementation of the Coherent Point Drift point set registration algorithm.
http://www.gadom.ski/cpd
GNU General Public License v2.0
385 stars 122 forks source link

cpd seems incompatible with PCL #163

Closed jiangzhiwei2018 closed 8 months ago

jiangzhiwei2018 commented 9 months ago

Here are more details.

First, I clone the cpd repo.

git clone https://github.com/gadomski/cpd.git

Secondly, build and install

cd cpd
mkdir build
cd build
cmake -DJSONCPP_WITH_CMAKE_PACKAGE=ON -DBUILD_SHARED_LIBS=ON ..
make
sudo make install

Thirdly, compile and run

I compiled the examples/random.cpp with my own CMakeList.txt,

cmake_minimum_required(VERSION 2.8.12)
project(random)

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -O3")
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_BUILD_TYPE Release)

find_package(Cpd REQUIRED jsoncpp REQUIRED)

find_package(OpenMP)
set(OpenMPDep)
if(OpenMP_CXX_FOUND)
    set(OpenMPDep OpenMP::OpenMP_CXX)
    add_definitions(-DOpenGR_USE_OPENMP)
    message(STATUS "Parallelization enabled using OpenMP")
endif()

find_package(PCL REQUIRED)
add_definitions(${PCL_DEFINITIONS})

list(APPEND INCLUDE_DIRS
        ${PCL_INCLUDE_DIRS}
        )
list(APPEND ALL_LIBS_DIR
        ${PCL_LIBRARY_DIRS}
        )

list(APPEND ALL_LIBS
        ${PCL_LIBRARIES}
        ${OpenMPDep}
        Cpd::Library-C++ Cpd::Jsoncpp
        )   
FILE(GLOB_RECURSE SRC_FILES random.cpp)

add_executable(${PROJECT_NAME} ${SRC_FILES})

target_include_directories(${PROJECT_NAME} PUBLIC ${INCLUDE_DIRS})
target_link_directories(${PROJECT_NAME} PUBLIC ${ALL_LIBS_DIR})
target_link_libraries(${PROJECT_NAME} PUBLIC ${ALL_LIBS})

the examples/random.cpp:

// cpd - Coherent Point Drift

#include <iostream>
#include <string>

#include <cpd/nonrigid.hpp>
#include <cpd/rigid.hpp>

int main(int argc, char** argv) {
    if (argc != 4) {
        std::cout << "Invalid usage: cpd-random <method> <rows> <cols>"
                  << std::endl;
        return 1;
    }
    std::string method = argv[1];
    size_t rows = std::stoi(argv[2]);
    size_t cols = std::stoi(argv[3]);
    cpd::Matrix fixed = cpd::Matrix::Random(rows, cols);
    cpd::Matrix moving = cpd::Matrix::Random(rows, cols);

    if (method == "rigid") {
        //std::cout << "started rigid: " << method << std::endl;
        cpd::rigid(fixed, moving);
    } else if (method == "nonrigid") {
        cpd::nonrigid(fixed, moving);
    } else {
        std::cout << "Invalid method: " << method << std::endl;
        return 1;
    }
    std::cout << "Registration completed OK" << std::endl;
    return 0;
}

run wtih:

./random rigid 100 3

Then I got

Segmentation fault (core dumped)

What I had tried:

1、Deleted PCL in CMakeList.txt

...
list(APPEND ALL_LIBS
        #${PCL_LIBRARIES}   # Just change this line
        ${OpenMPDep}
        Cpd::Library-C++ Cpd::Jsoncpp
        )
...   

compiled and ran with same command. It worked well.

./random rigid 100 3 

Registration completed OK

2、Tried to keep PCL, changed CMAKE_BUILD_TYPE and -O3 flag in cmake

...
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")   # delete -O3 flag
set(CMAKE_CXX_STANDARD 11)
#set(CMAKE_BUILD_TYPE Release)  # delete this line
...

compiled and ran with same command. It worked well too.

./random rigid 100 3 

Registration completed OK

3、Tried to rebuild and reinstall cpd with CMAKE_BUILD_TYPE=Release.

mkdir build
cd build
cmake -DJSONCPP_WITH_CMAKE_PACKAGE=ON -DBUILD_SHARED_LIBS=ON -DCMAKE_BUILD_TYPE=Release ..
make
sudo make install

Then I ran with the same command, error occurred when I deleted PCLRelease type and -O3 flag in CMake.

./random rigid 100 3

double free or corruption (out)
Aborted (core dumped)

3、Tried to other flags like -O -O1 -O2. They didn't work either.

4、Tried to use GDB debug error occurred in Eigen lib

 /** \internal Frees memory allocated with handmade_aligned_malloc */
EIGEN_DEVICE_FUNC inline void handmade_aligned_free(void *ptr)
{
  if (ptr) {
    EIGEN_USING_STD(free)
    free(*(reinterpret_cast<void**>(ptr) - 1)); // error occurred at this line
  }
}

It finished the main rigid function but copy Result struct.

/// Our base matrix class.
typedef Eigen::MatrixXd Matrix;

/// Typedef for our specific type of vector.
typedef Eigen::VectorXd Vector;

/// Typedef for an index vector, used to index other matrices.
typedef Eigen::Matrix<Matrix::Index, Eigen::Dynamic, 1> IndexVector;

/// Typedef for our specific type of array.
typedef Eigen::ArrayXd Array;
/// The result of a generic transform run.
struct Result {
    /// The final moved points.
    Matrix points;
    /// The final sigma2 value.
    double sigma2;
    /// The correspondence vector.
    IndexVector correspondence;
    /// The runtime.
    std::chrono::microseconds runtime;
    /// The number of iterations.
    size_t iterations;

    /// De-normalize this result.
    ///
    /// Generally, this scales the points back, and sometimes adjust transforms
    /// or shifts or the like.
    virtual void denormalize(const Normalization& normalization);
};
struct RigidResult : public Result {
    /// The rotation component of the transformation.
    Matrix rotation;
    /// The translation component of the transformation.
    Vector translation;
    /// The scaling component of the transformation.
    double scale;

    /// Returns a single matrix that contains all the transformation
    /// information.
    Matrix matrix() const;

    void denormalize(const Normalization& normalization);
};

My envs:

OS:Ubuntu 20.04

gcc:9.4.0

PCL:1.13.1

Eigen:3.4.0

So I'm a bit confused about -O3flag or Release type which could make crash in two libraries. And do not make sure what cause the error.

EDIT

The program worked well after I changed Matrix typedef as below. set Matrix with Eigen::DontAlign

/// Our base matrix class.
typedef Eigen::Matrix<double, -1, -1, Eigen::DontAlign> Matrix;

/// Typedef for our specific type of vector.
typedef Eigen::Matrix<double, -1, 1, Eigen::DontAlign> Vector;

/// Typedef for an index vector, used to index other matrices.
typedef Eigen::Matrix<Matrix::Index, Eigen::Dynamic, 1> IndexVector;

/// Typedef for our specific type of array.
typedef Eigen::Array<double, -1, 1, Eigen::DontAlign> Array;

But it seems would cost more, any other solutions?

I had also tried to add EIGEN_MAKE_ALIGNED_OPERATOR_NEW, but it didn't work.

gadomski commented 8 months ago

Coud (sic) you fix it?

Unlikely. I'm not funded on this project and I'm not using it for active work. Pull requests welcome!