Thursday, February 28, 2019

find_package가 지원되는 CMake module 만들기

Reference : https://cmake.org/cmake/help/v3.4/module/CMakePackageConfigHelpers.html#example-generating-package-files

여기서 예시된 cmake 프로젝트의 이름은 Foo 이다.
configure_file을 직접 쓸수도 있으나, 그보다는
include(CMakePackageConfigHelpers) 호출후 사용할 수 있는 명령어
configure_package_config_file 를 권장한다.
아래는 CMakeLists.txt의 예시로, 취소선은 version 선언을 생략한 것이다.

# foo/CMakeLists.txt
project(Foo)

set(INCLUDE_DIR ${CMAKE_SOURCE_DIR}/include/)     # find_package 로 알려줄 header file path
set(LIB_DIR ${CMAKE_LIBRARY_OUTPUT_DIRECTORY})    # library 가 생성될 path 

...

add_library(foo src/foo.cpp)
target_link_libraries(foo some_lib_a some_lib_b some_lib_c)
...


include(CMakePackageConfigHelpers)                  # 명령어 추가. 
configure_package_config_file(cmake_modules/FooConfig.cmake.in  # <Input>
  ${PROJECT_NAME}Config.cmake                                   # <Output> 
  INSTALL_DESTINATION ${CMAKE_CURRENT_BINARY_DIR}               # <Desntination> of output. Both Absolute,relative
  PATH_VARS INCLUDE_DIR LIB_DIR)                                # <PATH_VARS> are the variables which contain install destinations

write_basic_package_version_file(
  ${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake
  VERSION 1.2.3
  COMPATIBILITY SameMajorVersion )

install(FILES ${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake
              ${CMAKE_CURRENT_BINARY_DIR}/FooConfigVersion.cmake  # Version information 생략
        DESTINATION lib/${PROJECT_NAME}/cmake ) # /usr/local/lib/Foo/cmake/에 FooConfig.cmake 설치

# foo library 에 dependent한 module이 some_lib_[a/b/c] 를 자동으로 링크할 수 있도록 export.
export(TARGETS foo some_lib_a some_lib_b some_lib_c
 FILE "${CMAKE_BINARY_DIR}/fooTargets.cmake" )
export(PACKAGE ${PROJECT_NAME} ) 


이상의 cmake lists의 명령어가 cmake_modules/FooConfig.cmake.in 파일을 참고하여, FooConfig.cmake를 binary directory (예를 들면 build) 에 생성한다.

추가적으로 필요한 FooConfig.cmake.in 는 다음과 같다.

# foo/cmake_modules/FooConfig.cmake.in
set(FOO_VERSION x.y.z)
@PACKAGE_INIT@ 

# configure_package_config_file 함수가 호출하는 .cmake.in 에서는 set 대신 set_and_check를 권장.
set_and_check(FOO_INCLUDE_DIR "@PACKAGE_INCLUDE_DIR@"
set_and_check(FOO_LIB_DIR "@PACKAGE_LIB_DIR@")
set_and_check(FOO_SRC_DIR "@PROJECT_SOURCE_DIR@") # ${} 대신 @ 연산자로 foo module의 변수를 넘겨줌.

include("@CMAKE_BINARY_DIR@/fooTargets.cmake")  # CMakeLists.txt에서 export한 target들을 포함.
check_required_components(Foo) # component를 선언했을때만 필요


Bar project에서 foo package를 찾아보자.

# bar/CMakeLists.txt
...

find_package(Foo REQUIRED)
include_directories(${FOO_INCLUDE_DIR})  # FooConfig.cmake.in 에서 선언한 경로를 확인할 수 있음

add_executable(bar src/main.cpp)
target_link_libraries(bar foo) # libfoo.so 를 링크



...


TODO
export(PACKAGE ) 의 역할.
https://stackoverflow.com/questions/48661265/what-does-export-package-mean

P.S
cmake 를 실행하고 나면, build directory에 CMakeCache.txt가 생성된다. 다음은 find_package(OpenCV)의 결과, CMakeCache.txt에 추가된 message이다.

//The directory containing a CMake configuration file for OpenCV. OpenCV_DIR:PATH=/~~~~~/OpenCV-3.3.1-dev

이를통해 find_package는 /~~~~ 에 설치된 opencv의 configuration file, "OpenCVConfig.cmake" 를 선택했음을 알 수 있다. 해당 config.cmake

파일을 보면, find_package를 실행함으로써 주어진 정보들에 대해 알 수 있다.



Friday, February 15, 2019

git merge tool

$ sudo apt-get install meld
$ git config -global merge.tool meld
$ git merge [Other branch to merge]
$ git mergetool

Sunday, November 25, 2018

c++ / vtk trackball camera style

https://www.vtk.org/Wiki/VTK/Examples/Cxx/Interaction/TrackballCamera

vtk 만으로 style을 수정하려면 위 링크처럼 하면된다.

단, Qt를 사용할경우, QVTKWidget은 기본 스타일이 트랙볼카메라 이므로 속편하게 그냥 쓰면 된다.
$ sudo apt-get install libvtk6-qt-dev  # QVTKWidget이 제공되는 vtk 설치

CMakeLists.txt --------------------------------------------------------
find_package(VTK 6 REQUIRED)
include(${VTK_USE_FILE}) # Not include_directories

find_package(Qt5Widgets REQUIRED)
include_directories( ${Qt5Widgets_INCLUDE_DIRS})
QT5_WRAP_CPP(moc_src viewer.h)

add_executable(${PROJECT_NAME} 
main.cpp
${moc_src}
)

target_link_libraries(${PROJECT_NAME}
${VTK_LIBRARIES}
${QT_LIBRARIES}
)

main.cpp ------------------------------------------------
#include <stdio.h>
#include <QVTKWidget.h>
#include <QWidget>
#include <QApplication>
#include <QVBoxLayout>
#include <vtkSphereSource.h>
#include <vtkActor.h>
#include <vtkSphere.h>
#include <vtkSphereSource.h>
#include <vtkCone.h>
#include <vtkConeSource.h>
#include <vtkPolyDataMapper.h>
#include <vtkSmartPointer.h>
#include <vtkRenderer.h>
#include <vtkRenderWindow.h>
#include <QKeyEvent>
#include <vtkInteractorStyleTrackballCamera.h>
#include <vtkCamera.h>

class MyWidget : public QWidget {
public:
  MyWidget()
    :qvtk_widget_(new QVTKWidget(this))
  {
    QVBoxLayout* layout = new QVBoxLayout;
    setLayout(layout);
    layout->addWidget(qvtk_widget_);
    qvtk_widget_->setFixedSize(640,480);
    renderer_ = vtkSmartPointer<vtkRenderer>::New();
    renderer_->SetBackground(1.0, 1.0, 1.0);
    render_window_ = vtkSmartPointer<vtkRenderWindow>::New();
    render_window_->AddRenderer(renderer_);
    qvtk_widget_->SetRenderWindow(render_window_);

    qvtk_widget_->installEventFilter((QWidget*)this);

    tarckball_style = vtkSmartPointer<vtkInteractorStyleTrackballCamera>::New();
    auto qvtk_interactor = vtkSmartPointer<QVTKInteractor>::New();
    // Make sure that don't auto adjust camera clipping range, because of zoom in/out.
    // AutoAdjust will cause glitch because of wrong adjustment.
    tarckball_style->SetAutoAdjustCameraClippingRange(false);
    qvtk_interactor->SetInteractorStyle(tarckball_style);
    qvtk_interactor->SetRenderWindow(render_window_);

    Initialize();
  }

  vtkSmartPointer<vtkInteractorStyleTrackballCamera> tarckball_style;

  void Initialize(){
    auto sphereSource = vtkSmartPointer<vtkSphereSource>::New();
    sphereSource->SetCenter(1.0, 0.0, 0.0);
    sphereSource->Update();
    auto sphereMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    sphereMapper->SetInputConnection(sphereSource->GetOutputPort());
    auto sphereActor = vtkSmartPointer<vtkActor>::New();
    sphereActor->SetMapper(sphereMapper);
    auto coneSource = vtkSmartPointer<vtkConeSource>::New();
    auto coneMapper = vtkSmartPointer<vtkPolyDataMapper>::New();
    coneMapper->SetInputConnection(coneSource->GetOutputPort());
    vtkSmartPointer<vtkActor> coneActor = vtkSmartPointer<vtkActor>::New();
    coneActor->SetMapper(coneMapper);
    renderer_->AddActor(sphereActor);
    renderer_->AddActor(coneActor);
    ResetCamera();
    return;
  }

  void ResetCamera(){
    renderer_->ResetCamera();
    // Don't forget reset clipiing range after Reset camera.
    vtkCamera* camera = renderer_->GetActiveCamera();
    camera->SetClippingRange(0.001, 1e+8);
    render_window_->Render();
    return;
  }

  bool eventFilter(QObject *obj, QEvent *ev){
    if (ev->type() == QEvent::KeyPress ) {
      QKeyEvent* keyevent = dynamic_cast<QKeyEvent*>(ev);
      if(keyevent->key() == Qt::Key_Q){
        close();
        // eventFilter intercepts the event.
        return true;
      }
      else if(keyevent->key() == Qt::Key_R){
        ResetCamera();
        return true;
      }
      else{
        vtkCamera* camera = renderer_->GetActiveCamera();
        std::cout << tarckball_style->GetAutoAdjustCameraClippingRange()
          << " : " << camera->GetClippingRange()[0]
          << " : " << camera->GetClippingRange()[1] << std::endl;
      }
    }
    // eventFilter doesn't intercept the event.
    return false;
  }

private:
  QVTKWidget*const qvtk_widget_;
  vtkSmartPointer<vtkRenderer> renderer_;
  vtkSmartPointer<vtkRenderWindow> render_window_;
};

int main(int argc, char**argv){
  QApplication app(argc, argv);
  MyWidget mywidget;
  mywidget.show();
  app.exec();
  return 1;
}
------------------------------------------------------------

Friday, November 2, 2018

Logging

1) glog를 이용한 logging 예시
-------------------------------------------------------------------------------------------

int f3(){
  print_stacktrace();
  printf("hello f3\n");
  LOG(INFO) << "Hello" << std::endl;
  std::vector<int> vec = {1, 2, 3, 4};
  int j = vec.at(20);
  return j;
}
void f2(){
  f3();
  return;
}

void f1(){
  f2();
  return;
}

void WriteToStderr(const char* data, int size) {
  //LOG(ERROR) << __pretty_function__ << ":Error..." << std::string(data,size);
  LOG(ERROR) << __func__ << ":Error..." << std::string(data,size);
}

int main(int argc, char** argv){
  std::string log_destination = "/home/geonuk/atlas/ws/test/output/log";
  google::InstallFailureSignalHandler();
  google::InstallFailureWriter(WriteToStderr);
  google::InitGoogleLogging(argv[0]);
  google::SetLogDestination(google::GLOG_INFO, log_destination.c_str() );
  f3();
  return 0;
}

-------------------------------------------------------------------------------------------
2) subtrace를 얻는법 예시

void print_trace(void) {
  void *array[10];
  char **strings;
  size_t size = backtrace(array, 10);
  backtrace_symbols_fd(array, size, STDERR_FILENO);
}
-------------------------------------------------------------------------------------------


Monday, October 22, 2018

vrep study, memo

1) 우선 model browser에서 Bill on path.ttm 불러와, scene에 추가. bill on path의 script를 참고해서, camera motion을 구현하려고함.
미리 만든 환경에 bill on path.ttm model 추가.
이름(Bill#0) 옆의 script (문서모양 아이콘)을 클릭하면 예시로 참고할 Non-threaded child script가 표시된다.

2) bill on path 를 모방해서 path를 추종하는 camera를 만든다.

그림과 같이 root Dummy를 Cam이라 명명하고, 그 밑에 path, dummy 추가. dumyy의 자식에 vision_sensor를 더 추가.

vision_sensor가 보는 화면을 확인하기 위해서, floating view를 추가한다.
scene viewer에서 마우스 우클릭 - Add - Floating view

새로 추가된 Floating view (empty) 우클릭 - View - view selector - Vision_sensor 선택
default parameter는 resolution이 매우 안좋다.  속성을 바꾸기 위해서 Scene hierarchy의vision_sensor의 아이콘 클릭.
Resolution X/Y를 최소 640/480 픽셀 이상으로, 적절하게 지정.
Near/far clipping도 최소값/최대값으로 지정해서 자연스러운 카메라 화면이 나오게 한다.

이번에는 bill on path의 script를 참고해서 path 를 추종하도록 함.
path의 편집은 path edit mode에서 add point를 통해 수행.
http://www.coppeliarobotics.com/helpFiles/en/pathEditMode.htm

Scene hierarchy - root Dummy (Cam) 우클릭 - Add - associated child script - non threaded




Wednesday, October 17, 2018

언리얼

1.우분투
github 계정 / epicgames 계정 필요 (가입)
epicgames 계정에 github 계정 연결 필요. 자세한 내용은 아래링크 참고
https://www.unrealengine.com/en-US/ue4-on-github
https://wiki.unrealengine.com/Building_On_Linux
$ git clone https://github.com/EpicGames/UnrealEngine.git
$ cd UnrealEngine
$ ./Setup.sh
$ ./GenerateProjectFiles.sh 

퀵스타트 와 엔진내 튜토리얼(학사모 모양 아이콘) 을 조회하면 대략적인 사용법을 익힐 수 있다.
특히 actor와 blue print 개념이 중요해 보임.

2. 윈도우
마켓플레이스의 asset donwload는 기본적으로 윈도우에서만 된다.
https://www.reddit.com/r/unrealengine/comments/5lqub5/unreal_asset_installation_linux/

대부분의 asset을 마켓플레이스에서 구해야하므로, 리눅스에서 개발여부와는 상관없이 윈도우 버전도 설치해두는게 편리.
http://api.unrealengine.com/KOR/GettingStarted/Installation/
윈도우에서 설치는 install guide에 따라 unreal launcher 설치 -> launcher 내에서 engine 설치.


* 필요한 mesh가 없으면 freeCAD나, blender를 이용해서 구현. 유튜브의 튜토리얼 참고.