1. cmake 프로젝트 구성
- 다음과 같은 구조의 프로젝트를 구성한다
2. 모듈 구성
1. 라이브러리 빌드
- thirdparty 폴더에서 라이브러리를 빌드한다
Eigen
git clone https://gitlab.com/libeigen/eigen.git mkdir build/ mkdir install/ cd build cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install ../eigen make -j"$(nproc)" sudo make install
Pangolin
git clone --recursive https://github.com/stevenlovegrove/Pangolin.git mkdir build/ mkdir install/ cd Pangolin ./scripts/install_prerequisites.sh recommended # ubuntu ./scripts/install_prerequisites.sh -m brew all # mac cd ../build/ cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=../install ../Pangolin make -j"$(nproc)" sudo make install
2. cpp, hpp 구성
modules/module2/include/module2/ClassEigenMat.hpp
#ifndef HELLO_CMAKE_CLASSEIGENMAT_HPP #define HELLO_CMAKE_CLASSEIGENMAT_HPP #include "Eigen/Core" // using namespace Eigen; class ClassEigenMat { public: ClassEigenMat() = default; }; #endif // HELLO_CMAKE_CLASSEIGENMAT_HPP
modules/module2/src/ClassEigenMat.cpp
#include "module2/ClassEigenMat.hpp"
modules/module3/include/module3/ClassPangolinMat.hpp
#ifndef HELLO_CMAKE_CLASSPANGOLINMAT_HPP #define HELLO_CMAKE_CLASSPANGOLINMAT_HPP #include "pangolin/pangolin.h" class ClassPangolinMat { public: ClassPangolinMat() = default; }; #endif
modules/module3/src/ClassPangolinMat.cpp
#include "module3/ClassPangolinMat.hpp"
3. CMakeLists.txt 구성
module2의 CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0) project(module2 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(MODULE2_SOURCE_FILES src/ClassEigenMat.cpp ) add_library(module2 ${MODULE2_SOURCE_FILES} ) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_MODULE_PATH}) find_package(Eigen3 REQUIRED HINTS ${CMAKE_SOURCE_DIR}/thirdparty/Eigen3/install/share/eigen3/cmake) if (Eigen3_FOUND) message(STATUS "Eigen3 Found! - ${Eigen3_DIR}") set(Eigen3_LIBS Eigen3::Eigen) endif() target_include_directories(module2 PUBLIC include ${Eigen3_INCLUDE_DIRS} ) target_link_libraries(module2 PUBLIC ${Eigen3_LIBS} )
module3의 CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0) project(module3 LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) set(MODULE3_SOURCE_FILES src/ClassPangolinMat.cpp ) add_library(module3 ${MODULE3_SOURCE_FILES} ) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_MODULE_PATH}) find_package(Pangolin REQUIRED HINTS ${CMAKE_SOURCE_DIR}/thirdparty/PangolineLib/install/lib/cmake/Pangolin) if (Pangolin_FOUND) message(STATUS "Pangolin Found! - ${Pangolin_DIR}") endif() target_include_directories(module3 PUBLIC include ${Pangolin_INCLUDE_DIRS} ) target_link_libraries(module3 PUBLIC ${Pangolin_LIBRARIES} )
modules의 CMakeLists.txt
add_subdirectory(module2) add_subdirectory(module3)
CMakeLists.txt
cmake_minimum_required(VERSION 3.0.0) project(coordinate_transformation LANGUAGES CXX) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) add_subdirectory(modules) add_executable(coordinate_transformation main.cpp) add_executable(plot_trajectory examples/plot_trajectory.cpp) target_include_directories(plot_trajectory PRIVATE include ) target_link_libraries(plot_trajectory PRIVATE module2 module3)
4. 코드 구성
main.cpp
#include <iostream> int main(int, char**) { std::cout << "Hello, world!\n"; }
include/plot_trajectory.hpp
#include <fstream> #include <iostream> #include <unistd.h> int width = 1024; int height = 768; std::string trajectory_file = "../examples/trajectory.txt"; void DrawTrajectory(std::vector<Eigen::Isometry3d, Eigen::aligned_allocator<Eigen::Isometry3d>>);
examples/plot_trajectory.cpp
#include "module2/ClassEigenMat.hpp" #include "module3/ClassPangolinMat.hpp" #include "plot_trajectory.hpp" int main() { // trajectory.txt 파일 불러온다 std::vector<Eigen::Isometry3d, Eigen::aligned_allocator<Eigen::Isometry3d>> poses; std::ifstream fin(trajectory_file); if (!fin) { std::cout << "cannot find trajectory file at " << trajectory_file << std::endl; return 1; } // trajectory.txt 파일의 내용을 읽어서 자료형에 저장한다 while (!fin.eof()) { double time, tx, ty, tz, qx, qy, qz, qw; fin >> time >> tx >> ty >> tz >> qx >> qy >> qz >> qw; Eigen::Isometry3d Twr(Eigen::Quaterniond(qw, qx, qy, qz)); Twr.pretranslate(Eigen::Vector3d(tx, ty, tz)); poses.push_back(Twr); } std::cout << "read total " << poses.size() << " pose entries" << std::endl; // pangolin 라이브러리로 궤도를 그린다 DrawTrajectory(poses); return 0; } /*******************************************************************************************/ void DrawTrajectory(std::vector<Eigen::Isometry3d, Eigen::aligned_allocator<Eigen::Isometry3d>> poses) { // pangolin 윈도우를 생성하는 등의 초기화 작업을 진행한다 pangolin::CreateWindowAndBind("Trajectory Viewer", width, height); glEnable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); // pangolin 디스플레이를 정의한다 pangolin::OpenGlRenderState s_cam ( pangolin::ProjectionMatrix(width, height, 500, 500, 512, 389, 0.1, 1000), pangolin::ModelViewLookAt(0, -0.1, -1.8, 0, 0, 0, 0.0, -1.0, 0.0) ); pangolin::View &d_cam = pangolin::CreateDisplay() .SetBounds(0.0, 1.0, 0.0, 1.0, -1 * (float)width / (float)height) .SetHandler(new pangolin::Handler3D(s_cam)); // 저장한 자료형에 따라서 궤도를 그린다 while (pangolin::ShouldQuit() == false) { // 기존에 그린 선을 초기화한다 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); d_cam.Activate(s_cam); glClearColor(1.0f, 1.0f, 1.0f, 1.0f); glLineWidth(2); for (size_t i = 0; i < poses.size(); i++) { // X, Y, Z 좌표축을 그린다 Eigen::Vector3d Ow = poses[i].translation(); Eigen::Vector3d Xw = poses[i] * (0.1 * Eigen::Vector3d(1, 0, 0)); Eigen::Vector3d Yw = poses[i] * (0.1 * Eigen::Vector3d(0, 1, 0)); Eigen::Vector3d Zw = poses[i] * (0.1 * Eigen::Vector3d(0, 0, 1)); glBegin(GL_LINES); // X 좌표를 표현한다 glColor3f(1.0, 0.0, 0.0); glVertex3d(Ow[0], Ow[1], Ow[2]); glVertex3d(Xw[0], Xw[1], Xw[2]); // Y 좌표를 표현한다 glColor3f(0.0, 1.0, 0.0); glVertex3d(Ow[0], Ow[1], Ow[2]); glVertex3d(Yw[0], Yw[1], Yw[2]); // Z 좌표를 표현한다 glColor3f(0.0, 0.0, 1.0); glVertex3d(Ow[0], Ow[1], Ow[2]); glVertex3d(Zw[0], Zw[1], Zw[2]); glEnd(); } // 궤도의 선을 그린다 for (size_t i = 0; i < poses.size(); i++) { glColor3f(0.0, 0.0, 0.0); glBegin(GL_LINES); auto p1 = poses[i], p2 = poses[i + 1]; glVertex3d(p1.translation()[0], p1.translation()[1], p1.translation()[2]); glVertex3d(p2.translation()[0], p2.translation()[1], p2.translation()[2]); glEnd(); } pangolin::FinishFrame(); usleep(5000); // sleep 5 ms } std::cout << "Success!!" << std::endl; }
5. 예제 실행
- plot_trajectory 실행하면 다음과 같은 화면이 보인다
- so 파일 에러가 없다면 환경변수에 등록한다
export LD_LIBRARY_PATH=/home/ubuntu/Documents/dev/programmers_slam/week16-1/coordinate_transformation/thirdparty/PangolineLib/install/lib:$LD_LIBRARY_PATH
source ~/.zshrc