はじめに
研究でG-ICPの実装ができれば良いなと思い、現在ライブラリを見て実装の勉強をしています。 日々のコードとのにらめっこにも飽きてきたので、気分転換にライブラリのテストコードでも動かしてみることにしました。 その際にいくつか躓いたことがあったので、メモとして記しておこうと思います。
そもそもG-ICPとは
(この説明はまだ上手くできません...勉強中です。) 現時点でわかっているのは、 ICPがユークリッド距離の最小化を目指すのに対し、G-ICPはマハラノビス距離の最小化を目指す、ということくらいです。
ライブラリ詳細などはこちら
今回試したのはこちらのライブラリです。 https://github.com/avsegal/gicp
起動するのは test_gicp.cpp になります。
起動コマンド
まずはリポジトリをダウンロードします。
git clone https://github.com/avsegal/gicp.git
次に、依存ライブラリであるANNライブラリをコンパイルします。
cd gicp/ann_1.1.1/
make linux-g++
(ここで後述するエラーが発生しました)
[エラー対処後] ANNライブラリの準備ができたら、G-ICP本体をコンパイルします。
お次はG-ICP本体のコンパイル
cd ../
make
[エラー対処後] コンパイルが成功したら、お好きなサンプルデータを指定して実行します。
./test_gicp "data/hall/hall0[300x541].ascii" "data/hall/hall1[300x541].ascii"
これで完了です。(実行結果はテキスト表示のみなので、面白みはあまりないかもしれません...)
遭遇したエラーと対処法
以下は、私が遭遇したエラーとその対処の記録です。
gicp本体の make でのエラー
$ make
g++ `pkg-config --cflags gsl` -O3 -I./ann_1.1.1/include/ANN -c gicp.cpp -o gicp.o
g++ `pkg-config --cflags gsl` -O3 -I./ann_1.1.1/include/ANN -c optimize.cpp -o optimize.o
g++ `pkg-config --cflags gsl` -O3 -I./ann_1.1.1/include/ANN -c bfgs_funcs.cpp -o bfgs_funcs.o
g++ `pkg-config --cflags gsl` -O3 -I./ann_1.1.1/include/ANN -c transform.cpp -o transform.o
g++ `pkg-config --cflags gsl` -O3 -I./ann_1.1.1/include/ANN -c scan.cpp -o scan.o
scan.cpp: In member function ‘int dgc_scan_t::load(const char*)’:
scan.cpp:80:8: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result [-Wunused-result]
80 | fread(&n, sizeof(int), 1, f);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~
scan.cpp:81:8: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result [-Wunused-result]
81 | fread(&pose, sizeof(dgc_pose_t), 1, f);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
scan.cpp:85:10: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result [-Wunused-result]
85 | fread(&pt, sizeof(dgc_vector3d_c_t), 1, f);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
scan.cpp:89:8: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result [-Wunused-result]
89 | fread(&m, sizeof(int), 1, f);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~
scan.cpp:92:10: warning: ignoring return value of ‘size_t fread(void*, size_t, size_t, FILE*)’, declared with attribute warn_unused_result [-Wunused-result]
92 | fread(&nu, sizeof(dgc_vector3d_c_t), 1, f);
| ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
ar rvs libgicp.a gicp.o optimize.o bfgs_funcs.o transform.o scan.o
ar: creating libgicp.a
a - gicp.o
a - optimize.o
a - bfgs_funcs.o
a - transform.o
a - scan.o
g++ `pkg-config --cflags gsl` -O3 -I./ann_1.1.1/include/ANN -c test_gicp.cpp -o test_gicp.o
g++ -o test_gicp test_gicp.o gicp.o optimize.o bfgs_funcs.o transform.o `pkg-config --libs gsl` -L. -lgicp -Lann_1.1.1/lib -lANN -lgsl -lgslcblas -lboost_program_options -lboost_system -lstdc++
/usr/bin/ld: cannot find -lANN
collect2: error: ld returned 1 exit status
make: *** [Makefile:34: test_gicp] Error 1
どうやら、libANN.aというライブラリがないみたいです。(知るかよ)
/usr/bin/ld: cannot find -lANN とあるので、リンカが libANN.a というライブラリを見つけられていないようです。 これは、ANNライブラリのコンパイルが正しく完了していないためだと推測しました。
私はここでもう一度、最初と同じようにコンパイルのコマンドを打ちました。
cd gicp/ann_1.1.1/
make linux-g++
//cd ../
//make clean
//make
ですが、
~/gicp/ann_1.1.1$ make linux-g++
cd src ; make linux-g++
make[1]: Entering directory '/home/ryosuke/gicp/ann_1.1.1/src'
make targets \
"ANNLIB = libANN.a" \
"C++ = g++" \
"CFLAGS = -O3" \
"MAKELIB = ar ruv" \
"RANLIB = true"
make[2]: Entering directory '/home/ryosuke/gicp/ann_1.1.1/src'
ar ruv libANN.a ANN.o brute.o kd_tree.o kd_util.o kd_split.o kd_dump.o kd_search.o kd_pr_search.o kd_fix_rad_search.o bd_tree.o bd_search.o bd_pr_search.o bd_fix_rad_search.o perf.o
ar: `u' modifier ignored since `D' is the default (see `U')
ar: creating libANN.a
a - ANN.o
a - brute.o
a - kd_tree.o
a - kd_util.o
a - kd_split.o
a - kd_dump.o
a - kd_search.o
a - kd_pr_search.o
a - kd_fix_rad_search.o
a - bd_tree.o
a - bd_search.o
a - bd_pr_search.o
a - bd_fix_rad_search.o
a - perf.o
true libANN.a
mv libANN.a ../lib
make[2]: Leaving directory '/home/ryosuke/gicp/ann_1.1.1/src'
make[1]: Leaving directory '/home/ryosuke/gicp/ann_1.1.1/src'
cd test ; make linux-g++
make[1]: Entering directory '/home/ryosuke/gicp/ann_1.1.1/test'
make targets \
"ANNLIB = libANN.a" \
"C++ = g++" \
"CFLAGS = -O3" \
"MAKELIB = ar ruv" \
"RANLIB = true"
make[2]: Entering directory '/home/ryosuke/gicp/ann_1.1.1/test'
make[2]: *** No rule to make target '../lib/libANN.a', needed by '../bin/ann_test'. Stop.
make[2]: Leaving directory '/home/ryosuke/gicp/ann_1.1.1/test'
make[1]: *** [../Make-config:72: linux-g++] Error 2
make[1]: Leaving directory '/home/ryosuke/gicp/ann_1.1.1/test'
make: *** [Makefile:61: linux-g++] Error 2
よくわかりませんが、libファイルにエラーがあるみたいです。
:~/gicp/ann_1.1.1$ ls lib/
ls: cannot access 'lib/': Not a directory
そもそもlibファイルがないらしい。よーわからん。
:~/gicp/ann_1.1.1$ rm lib #念の為消します。
mkdir lib bin #作り直して
make linux-g++ #再びコンパイル
これで私はANNのコンパイルが通りました。
お次はG-ICPのコンパイルを通します。
cd ../
make clean
make
コンパイル後
./test_gicp "data/hall/hall0[300x541].ascii" "data/hall/hall1[300x541].ascii"
これを実行すれば、できました。
あんまり面白くないですね...