物理シミュレータChronoをC++で用いるためのサンプルプログラム。 ビルドシステムにはCMakeを使用する。
執筆時点(2023/11/28)でのインストール方法を示す。 今回はProject Chrono公式が提供しているDockerイメージuwsbel/projectchronoを用いる。
以下はローカル環境ではなく、Dockerイメージとして構築した環境条件である。
- OS: Ubuntu 22.04
- Chrono: 8.0.0
- CMake: 3.22.1
まずはじめに、ChronoのDockerイメージをダウンロードする。 [重要] Dockerのlatest版はGitHub上のmainブランチでも8.0.0タグでもないバージョンである(結局どのバージョンに該当するのかは未確認)。デモプログラムに関しても、公式HPチュートリアルに乗っているプログラムと若干異なっているので注意。
docker pull uwsbel/projectchrono:latest続いてDockerコンテナを生成する。ちなみに今回使用しているローカル環境はNvidia GPUを使用していないため、nvidia-dockerは不要である(逆に言えば、Nvidia GPU搭載PCを用いる場合はnvidia-dockerをインストールしておく)。
ただし、シミュレータなどのGUI表示を行う必要があるので、いくつか特殊な設定をする必要がある。
具体的には、今回は以下のコマンドを実行した。
docker run -it \
--net=host \
--env=DISPLAY=$DISPLAY \
--env=QT_X11_NO_MITSHM=1 \
--volume="/home/$USER:/home/$USER" \
--volume="$HOME/.Xauthority:/root/.Xauthority" \
--volume="/tmp/.X11-unix:/tmp/.X11-unix:rw" \
--name chrono_env00 \
uwsbel/projectchrono:latest \
bash問題なくコンテナが生成できたら、続いて必要なソフトウェアをインストールしておく。
apt update
apt upgrade
apt install gedit cmake-curses-gui git続いてChronoライブラリのビルドを行う。
基本的には公式ビルド手順に従えば問題ないが、Eigen LibraryとIrrlicht Libraryのダウンロードに関してはあらかじめDockerコンテナに含まれているのでスキップしてよい。
chrono_buildというディレクトリを作成し、そこでビルドファイルを生成する。
cd ~/Desktop
mkdir chrono_build
cd chrono_build
ccmake ../chrono/各種設定値が下図のようになっていればOK。[c]Configureを押した際のログがConfigure Doneになっていて、エラーも出ていなさそうであれば[g]Generateを入力してMakeFileを生成する。
問題なく生成されていれば、chrono_buildディレクトリ内にMakeFileなどが生成されるはずである。
最後に以下コマンドを入力してビルドを開始する(今回使用している端末はCPUが48コア(!)もあるので、並列計算させるとすごく早く終わる)。
make -j48独自プログラムでChronoを使用したい場合は、各種ライブラリをインクルードすればよい。 詳細な手順はBuilding a project that uses Chronoに記載があるが、この通りに実行してもビルドエラーが発生して非常に辛かった。 以降ではその原因についても簡単に触れておく。
ここでは例として、リポジトリのdemoディレクトリ内にあるbuild_systemというデモプログラムを参考に、ビルド手順を示す。他のデモについても同様の手順でビルドすることができる。
まずはソースコードまで移動し、buildディレクトリを作成する。
その後、事前に用意してあるCMakeLists.txtを使ってMakeFile生成を開始する。
cd demos/build_system
mkdir build
cd build
ccmake ../このとき、以下のような画面表示になるはず。[c]Configureを入力する。
続いて下図の画面に遷移するはず。ログ表示の通り、Chrono_DIRという変数が定義されていないためにChrono関連ライブラリが見つからないと言われている。[e]Exitを入力して一旦Configure処理を停止する。
変数一覧画面に戻ると、Chrono_DIRが設定できるようになっている(Not Foundという表示になっている)。ここではChronoのcmake変数が格納されたコンフィグファイルchrono-config.cmakeのフルパスを指定してあげる必要がある。このコンフィグファイルは先程ビルドしたchrono_buildディレクトリ内に入っている。具体的には下図のように設定し(ユーザ名は適宜変更すること)、再度[c]Configureを入力する。
ログ出力画面を見てみると、前回とは違い適切にパラメータが設定されていることが確認できる。
問題なさそうであれば[e]Exitを入力して変数一覧画面に戻り、[g]Generateを入力する。
最後に以下コマンドでビルドを実行する。
ビルドが成功した場合は、buildディレクトリ内にdemo_CH_buildsystemという実行ファイルが生成されるはずである。
makebuildsystemデモプログラムのCMakeLists.txtの中身は以下のようになっている。
cmake_minimum_required(VERSION 3.10)
set(PROGRAM demo_CH_buildsystem)
project(${PROGRAM})
LIST(APPEND CMAKE_PREFIX_PATH "/usr/local/lib")
find_package(Chrono
COMPONENTS Irrlicht
OPTIONAL_COMPONENTS PardisoMKL
CONFIG)
if (NOT Chrono_FOUND)
message("Could not find Chrono or one of its required modules")
return()
endif()
set(CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD ${CHRONO_CXX_STANDARD})
# Important!: なぜか公式Tutorialに従ってライブラリをビルドしても、CHRONO_LIBRARIESに静的ライブラリが含まれなかったため、手動でリンクを追加。
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoEngine.so")
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoEngine_vehicle.so")
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoModels_robot.so")
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoModels_vehicle.so")
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoEngine_vehicle_cosim.so")
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoEngine_irrlicht.so")
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoEngine_postprocess.so")
LIST(APPEND CHRONO_LIBRARIES "/sbel/Desktop/chrono_build/lib/libChronoEngine_vehicle_irrlicht.so")
include_directories(${CHRONO_INCLUDE_DIRS})
add_executable(${PROGRAM} ${PROGRAM}.cpp)
target_compile_definitions(${PROGRAM} PUBLIC "CHRONO_DATA_DIR=\"${CHRONO_DATA_DIR}\"")
target_compile_options(${PROGRAM} PUBLIC ${CHRONO_CXX_FLAGS})
target_link_options(${PROGRAM} PUBLIC ${CHRONO_LINKER_FLAGS})
target_link_libraries(${PROGRAM} ${CHRONO_LIBRARIES})ここで、公式サイトの手順で紹介されているCMakeLists.txtと大きく異なるのは、CHRONO_LIBRARIESの設定値である。
なぜかわからないが、デフォルトのCHRONO_LIBRARIESは以下2つのPATHしか含まれていない。
- /usr/lib/gcc/x86_64-linux-gnu/11/libgomp.so
- /usr/lib/x86_64-linux-gnu/libpthread.a
名前からわかるように、Chrono関連のライブラリが含まれていないのである。
この状態でビルドを行うと、Chronoライブラリ関連の関数が軒並みUndefined reference to <chrono::関数名>というエラーがでる。
Qiita: リンクエラーの話にも記載があるとおりこれはリンクエラーであり、Chrono関連ライブラリが正しくリンクされなかったことが原因である。
(リンクエラーは本当にデバッグが大変なのでやめてほしい。。。)
CMakeLists.txt中にある大量のLISTコマンドは、CHRONO_LIBRARIESに必要な静的ライブラリを登録している。







