2021年2月22日月曜日

Jetson (JetPack 4.5) でOpen3D + Open3D-MLをビルドする

目的


前回のブログではJetson Nano (Jetpack 4.5) でOpen3DをUSE_SYSTEM_LIBREALSENSE(インストール済みライブラリをリンク)でビルドした。

今回は、Open3D-MLも含めてビルドする。


リファレンス




準備


Pythonの仮想環境のインストール


Open3D-MLを含めてビルド後、Python パッケージをインストールすると、システムでインストール済みのpyyamlを競合してしまう。
このため、Pythonの仮想環境にインストールする。

好みでvirtualenv virtualenvwrapperを選択。
$ sudo pip3 install virtualenv virtualenvwrapper

# Add to .bashrc
# virtualenv and virtualenvwrapper
export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_VIRTUALENV=/usr/local/bin/virtualenv
export VIRTUALENVWRAPPER_PYTHON=/usr/bin/python3
source /usr/local/bin/virtualenvwrapper.sh
export VIRTUALENVWRAPPER_ENV_BIN_DIR=bin

$ source .bashrc
$ mkvirtualenv --python=python3 open3d
$ workon open3d


TensorFlowのインストール


リファレンスを参考にインストール。
(open3d) $ sudo apt-get update
(open3d) $ sudo apt-get install libhdf5-serial-dev hdf5-tools libhdf5-dev zlib1g-dev zip libjpeg8-dev liblapack-dev libblas-dev gfortran

(open3d) $ pip3 install numpy==1.16.1 future==0.18.2 mock==3.0.5 h5py==2.10.0 keras_preprocessing==1.1.1 keras_applications==1.0.8 gast==0.2.2 futures protobuf pybind11
(open3d) $ pip3 install --pre --extra-index-url https://developer.download.nvidia.com/compute/redist/jp/v45 tensorflow


PyTorchのインストル


こちらもフォーラムにあるとおりにインストール。
(open3d) $ wget https://nvidia.box.com/shared/static/cs3xn3td6sfgtene6jdvsxlr366m2dhq.whl -O torch-1.7.0-cp36-cp36m-linux_aarch64.whl
(open3d) $ sudo apt-get install python3-pip libopenblas-base libopenmpi-dev
(open3d) $ pip3 install Cython
(open3d) $ pip3 install numpy torch-1.7.0-cp36-cp36m-linux_aarch64.whl


Open3Dのビルド


まずは、TensorFlow、PyTorchのCXX ABIの確認。
Open3Dのドキュメントにもあるとおり、TensorFlow、PyTorch、Open3Dで異なる CXX ABIであると問題が発生する。
(open3d) $ python -c "import torch; print(torch._C._GLIBCXX_USE_CXX11_ABI)"
True
(open3d) $ python -c "import tensorflow; print(tensorflow.__cxx11_abi_flag__)"
2021-02-22 18:53:09.238147: I tensorflow/stream_executor/platform/default/dso_loader.cc:49] Successfully opened dynamic library libcudart.so.10.2
1

CXX ABIはすべてCXX11 ABIであることが確認できた。

事前にInstall dependenciesにあるソフトウェアをインストール。

メモリを確保するため、CUIモードで作業。
(open3d) $ sudo systemctl set-default multi-user.target
(open3d) $ sudo reboot

あとは、ビルドするだけ。
CMakeのオプションで注意する点は以下。
  • BUILD_CUDA_MODULEをON
  • GLIBCXX_USE_CXX11_ABIをON
  • BUNDLE_OPEN3D_MLをONにして、OPEN3D_ML_ROOTにOpen3D-MLのパスを指定
  • BUILD_TENSORFLOW_OPS、BUILD_PYTORCH_OPSをON
  • make pip-packageする前にyapfパッケージをpipでインストールする
    (なぜかmakeで失敗する。たぶん、requirements.txtに必要?)
$ workon open3d
(open3d) $ git clone --recursive https://github.com/intel-isl/Open3D
(open3d) $ git clone https://github.com/intel-isl/Open3D-ML.git
(open3d) $ cd Open3D/
(open3d) $ mkdir build && cd build
(open3d) $ cmake \
    -DPYTHON_EXECUTABLE=$(which python3) \
    -DBUILD_SHARED_LIBS=ON \
    -DBUILD_BENCHMARKS=ON \
    -DBUILD_CUDA_MODULE=ON \
    -DBUILD_CACHED_CUDA_MANAGER=ON \
    -DBUILD_GUI=ON \
    -DGLIBCXX_USE_CXX11_ABI=ON \
    -DBUILD_RPC_INTERFACE=ON \
    -DBUILD_TENSORFLOW_OPS=ON \
    -DBUILD_PYTORCH_OPS=ON \
    -DBUNDLE_OPEN3D_ML=ON \
    -DOPEN3D_ML_ROOT=../../Open3D-ML \
    -DCMAKE_BUILD_TYPE=Release \
    ..
(open3d) $ make -j 3 
(open3d) $ sudo make install
(open3d) $ pip install yapf
(open3d) $ sudo make pip-package
(open3d) $ pip install /home/jetson/Open3D/build/lib/python_package/pip_package/open3d-0.12.0+408d9d0a-cp36-cp36m-linux_aarch64.whl


確認


GUIモードに戻して、Window managerをLXDEに変更する(使えるメモリを増やすため)。
$ sudo systemctl set-default graphical.target
$ sudo reboot

その後、Open3D-MLのサンプルを動作させてみる。

ただ、Jetson Nanoのメモリ(4GB)では不足しているので
  • モデルはKPConvのみをロード
  • データも1種類(000700)だけロード
するように変更して実行する。



表示まで1、2分待ってなんとか動いた〜😅
(サンプルはPyTorchのモデルを実行するみたい。TensorFlowはどうだろうか?)

Jetson AGX XavierやJetson Xavier NXとかだとフルで動かせるのかな?

Open3DをUSE_SYSTEM_LIBREALSENSE(インストール済みライブラリをリンク)でビルドする

 目的


Open3DはRealSense SDK(librealsense)が組み込まれている。

ソースビルドした際、デフォルトではlibrealsenseをローカルでビルドし、静的リンクしている。Open3DのビルドオプションはFORCE_RSUSB_BACKEND=ONであったりするため、できればpre-install済みのバイナリを使いたい場合もある。

ビルド時に「USE_SYSTEM_LIBREALSENSE」を指定すればpre-install済みのバイナリをリンクするはずなのだが、実際には動作していないことがわかった。

このため、CMakeを修正し、「USE_SYSTEM_LIBREALSENSE」でpre-install済みのlibrealsenseをリンクするように対応する。


動機


前回のブログ「Jetson Nano(JetPack 4.5)でlibrealsenseをソースビルドする」でRealSense SDKをソースビルドしてインストールした。

このlibrealsenseを使ってOpen3DのRealSense IFを使ってみたかった。


リファレンス




手順


Open3Dに出したPull requestはマージされたのでcommit 41fcfdc 以降でビルドすればOK。

前回のブログのJetson Nano(librealsenseをソースビルドしてインストール)でビルドした(x86のUbuntuでも確認済み)。

Jetson Nanoの場合は、ARM supportの手順に従ってビルドする。
cmakeの際に
  • 「BUILD_LIBREALSENSE」と「USE_SYSTEM_LIBREALSENSE」をONにする。
  • 「GLIBCXX_USE_CXX11_ABI」をONにする。
    フラグをOFFにするとOpen3DとlibrealsenseのC++ ABIの違いで#2985の問題が発生する。
    このため、GLIBCXX_USE_CXX11_ABI=OFFを指定するとUSE_SYSTEM_LIBREALSENSEはOFFにしている。

$ git clone --recursive https://github.com/intel-isl/Open3D
$ cd Open3D
$ mkdir build && cd build
$ cmake \
    -DCMAKE_BUILD_TYPE=Release \
    -DBUILD_SHARED_LIBS=ON \
    -DBUILD_CUDA_MODULE=OFF \
    -DBUILD_GUI=ON \
    -DPYTHON_EXECUTABLE=$(which python3) \
    -DBUILD_LIBREALSENSE=ON \
    -DUSE_SYSTEM_LIBREALSENSE=ON \
    -DGLIBCXX_USE_CXX11_ABI=ON
    ..
$ make -j3
$ sudo make install
$ sudo make install-pip-package


動作確認


Jetson Nanoで確認。

Pythonで接続したRealSense(L515)を認識していること。
$ python
Python 3.6.9 (default, Oct  8 2020, 12:12:24) 
[GCC 8.4.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import open3d as o3d
>>> o3d.t.io.RealSenseSensor.list_devices()
[Open3D INFO] [0] Intel RealSense L515: f0220613
[Open3D INFO] 	depth_resolution: [320,240]
[Open3D INFO] 	depth_format: [RS2_FORMAT_Z16]
[Open3D INFO] 	visual_preset: [RS2_L500_VISUAL_PRESET_CUSTOM | RS2_L500_VISUAL_PRESET_DEFAULT | RS2_L500_VISUAL_PRESET_LOW_AMBIENT | RS2_L500_VISUAL_PRESET_MAX_RANGE | RS2_L500_VISUAL_PRESET_NO_AMBIENT | RS2_L500_VISUAL_PRESET_SHORT_RANGE]
[Open3D INFO] 	color_fps: [15 | 30 | 6]
[Open3D INFO] 	depth_fps: [30]
[Open3D INFO] 	color_resolution: [640,480]
[Open3D INFO] 	color_format: [RS2_FORMAT_BGR8 | RS2_FORMAT_BGRA8 | RS2_FORMAT_RGB8 | RS2_FORMAT_RGBA8 | RS2_FORMAT_Y16 | RS2_FORMAT_YUYV]
[Open3D INFO] Open3D only supports synchronized color and depth capture (color_fps = depth_fps).
True
>>> 

RealSenseRecorderのサンプルが動作すること。

やった〜!
PRもマージされて、Open3DのContributorになったぞ〜!!

2021年2月21日日曜日

Jetson Nano(JetPack 4.5)でlibrealsenseをソースビルドする

目的


NVIDIA Jetson NanoでIntel RealSenseをソースビルド(Native Backend)する。

RealSenseのSDK(librealsense)でNative Backendを使うには、カーネルにパッチを当てたうえでソースビルドが必要。
しかし、librealsenseのJetson用のパッチはJetPack 4.3用のため、JetPack4.5ではパッチがエラーとなってしまう。
このため、パッチをJetPack 4.5に対応してビルドする。


注意事項


2021.2.21時点
  • 公式のリポジトリ(librealsense)が対応した場合、この内容は古くなってしまうため、必ず最新情報を確認すること。
  • パッチの内容について誤りがある可能性があること(公式の対応でないため)。


リファレンス



リポジトリ


librealsenseをforkしたリポジトリを用意した。



手順


カーネルのパッチ適用&ビルド


JetPack 4.5を書き込んだJetson Nanoを用意する。
あとは公式の「Building from Source using Native Backend」と同じ手順で問題ない。
途中でCloneしたカーネルソースのtag を求められるので「tegra-l4t-r32.5」を入力する。

$ sudo apt update
$ sudo apt upgrade

$ git clone -b jetson_l4t-r32.5-4.9 https://github.com/NobuoTsukamoto/librealsense.git
$ cd librealsense
$ ./scripts/patch-realsense-ubuntu-L4T.sh

~~~~~~~~~~
Create the sandbox - NVidia L4T source tree(s)
Downloading default kernel/kernel-4.9 source...
Cloning into '/home/jetson/librealsense/Tegra/sources/kernel/kernel-4.9'...
remote: Enumerating objects: 5207472, done.
remote: Counting objects: 100% (5207472/5207472), done.
remote: Compressing objects: 100% (833434/833434), done.
remote: Total 5207472 (delta 4367040), reused 5173766 (delta 4333423)
Receiving objects: 100% (5207472/5207472), 943.55 MiB | 1.03 MiB/s, done.
Resolving deltas: 100% (4367040/4367040), done.
The default kernel/kernel-4.9 source is downloaded in: /home/jetson/librealsense/Tegra/sources/kernel/kernel-4.9
Please enter a tag to sync /home/jetson/librealsense/Tegra/sources/kernel/kernel-4.9 source to
(enter nothing to skip): 

ここで、「tegra-l4t-r32.5」入力してEner。あとはビルドが終わるのを待つ。

~~~~~~~~~~
Copying the patched modules to (~/)
~/librealsense
Move the modified modules into the modules tree
Insert the modified kernel modules
Replacing uvcvideo  -
        Applying the patched module ...  succeeded
Replacing hid_sensor_accel_3d  -
        Applying the patched module ...  succeeded
Replacing hid_sensor_gyro_3d  -
        Applying the patched module ...  succeeded
Replacing hid_sensor_trigger  -
        Applying the patched module ...  succeeded
Replacing hid_sensor_iio_common  -
        Module hid_sensor_iio_common  is used by hid_sensor_trigger
        Unloading dependency hid_sensor_trigger
        Module is resident, unloading ...  succeeded.
        Applying the patched module ...  succeeded      Reloading dependent kernel module hid_sensor_trigger ...  succeeded.


Script has completed. Please consult the installation guide for further instruction.


librealsenseのビルド


あとはlibrealsenseのビルドを行う。
念のため再起動してcloneしたlibrealsenseディレクトリに移動。

$ mkdir build && cd build
$ export PATH=${PATH}:/usr/local/cuda/bin
$ cmake \
  -DBUILD_WITH_CUDA=ON \
  -DBUILD_WITH_OPENMP=ON \
  -DBUILD_PYTHON_BINDINGS=ON \
  -DCMAKE_BUILD_TYPE=Release \
  ..
$ make -j$(($(nproc)-1))
$ sudo make install

Pythonラッパーを使う場合は、/usr/lib/python3/dist-packages/pyrealsense2/にパスを通しておく。

$ export PYTHONPATH=$PYTHONPATH:/usr/lib/python3/dist-packages/pyrealsense2/


確認


realsense-viewerを起動してFrame Metadataが正しそうなことを確認する。


できたー!

2021年2月7日日曜日

Raspberry Pi 4の64bit OSでlibrealsenseをビルドする

(2021.2.9 Pythonラッパー(pyrealsense2)を使うを追記)

 目的


Raspberry Pi で RealSense (L515)を扱いたい。
できるならmatadata, 加速度・ジャイロセンサーも使いたい(UVC Backendでなくて)。
このため、Raspberry Piのkernelにpatchを適用・ビルドし、RealSenseが動作する(realsense-viewerが実行できる)ところまでを確認した。

このブログでは、ビルド手順以外でつまったところ、補足的な内容を残す。


リファレンス


以下を参考にした。
1.はRaspberry Piのインストールガイドであるが、UVC_BACKENDでの手順。

2, 4, 5.はRaspberry Pi のkernelにpatchを適用するものだが、当時のkernel バージョンは4.x系で、現在のバージョン(5.x系)ではうまくいかない。


ビルド


ビルド手順については、Githubのリポジトリにアップしたのでそちらを参照。




つまったこと


とくにつまったことを記載する。


kernel pathの作成


librealsenseにあるpatchは以下だが、そのままRaspberry Piのkernel(5.10.13)には適用できなかった。
おそらく、最新のkernel ソースの変更に伴うものであると推測。
このため、上記のpatchをもとにRaspberry Piのkernelに適用できるpatchを作成した。


Raspberry Pi OS 64 bitのkernel ビルド


最初、Raspberry Pi上でのkernelのソースビルドを実行しようとした。
以下は公式ドキュメントの手順。
しかし、いざビルドを行うとエラーとなって実行できない。。。
どうやら、Raspberry Pi OS 64 bitでのkernel ビルドはできないとのこと。
(公式ドキュメントもよく読むとクロスコンパイルの手順はあるけど、64 bitのRaspberry Pi上でのビルド手順はない。。。)
このため、Host PCでのクロスコンパイルを行うこととした。


WSL(Windows Subsystem for Linux)でビルドするとSDカードに書き込みできない...


Raspberry PiのkernelはWSLのUbuntu上でクロスコンパイルが可能(実際できた)。
しかしながら、SDカードへ書き込む際に問題が発生する。
rootsf(ext4)への書き込みが必要だが、Windowsが認識できないためマウントできず書き込めない。。。
結局、Fedora 33(のvirt-managerで動かしているUbuntu)から書き込みを行った。

ただ、WSL2ではext4もマウントできるようなので、上記は私の認識不足かもしれない。。。


librealsenseのビルド


依存関係のあるライブラリの一つにlibapriltag(オプション)がある。
これをインストールしてlibrealsenseをビルドするとビルドエラーとなる。このため、インストールせずにビルドした。
/usr/bin/ld: CMakeFiles/rs-pose-apriltag.dir/rs-pose-apriltag.cpp.o: in function `apriltag_manager::apriltag_pose_destroy(apriltag_pose_t*)':
/home/pi/librealsense-2.41.0/examples/pose-apriltag/rs-pose-apriltag.cpp:106: undefined reference to `matd_destroy'
/usr/bin/ld: /home/pi/librealsense-2.41.0/examples/pose-apriltag/rs-pose-apriltag.cpp:106: undefined reference to `matd_destroy'
/usr/bin/ld: CMakeFiles/rs-pose-apriltag.dir/rs-pose-apriltag.cpp.o: in function `main':
/home/pi/librealsense-2.41.0/examples/pose-apriltag/rs-pose-apriltag.cpp:76: undefined reference to `tag36h11_create()'
/usr/bin/ld: /home/pi/librealsense-2.41.0/examples/pose-apriltag/rs-pose-apriltag.cpp:92: undefined reference to `tag36h11_destroy(apriltag_family*)'
/usr/bin/ld: CMakeFiles/rs-pose-apriltag.dir/rs-pose-apriltag.cpp.o: in function `apriltag_manager::detect(unsigned char*, rs2_pose const*) const':
/home/pi/librealsense-2.41.0/examples/pose-apriltag/rs-pose-apriltag.cpp:123: undefined reference to `estimate_pose_for_tag_homography(apriltag_detection_info_t*, apriltag_pose_t*)'
/usr/bin/ld: /home/pi/librealsense-2.41.0/examples/pose-apriltag/rs-pose-apriltag.cpp:161: undefined reference to `matd_create'
collect2: error: ld returned 1 exit status
make[2]: *** [examples/pose-apriltag/CMakeFiles/rs-pose-apriltag.dir/build.make:92: examples/pose-apriltag/rs-pose-apriltag] エラー 1
make[1]: *** [CMakeFiles/Makefile2:1919: examples/pose-apriltag/CMakeFiles/rs-pose-apriltag.dir/all] エラー 2
make[1]: *** 未完了のジョブを待っています....


32 bit版(Raspberry Pi OS)は?


おそらく、kernelビルドもうまくいくはずだが、試していない。
余力があれば試してみる。


Pythonラッパー(pyrealsense2)を使う(2021.2.9追記)


Pythonでpyrealsense2はimportできるのだが、いざAPIを呼び出すとエラーになることが分かった。


$ python3
Python 3.7.3 (default, Jul 25 2020, 13:03:44)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
<<< import pyrealsense2 as rs
<<< pipeline = rs.pipeline()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'pyrealsense2' has no attribute 'pipeline'
<<< quit()

原因はライブラリへのPathが通っていないと推測。
/usr/lib/python3/dist-packages/pyrealsense2/配下にある
  • pybackend2.cpython-37m-aarch64-linux-gnu.so
  • pyrealsense2.cpython-37m-aarch64-linux-gnu.so
が、Pathが通っていないためと推測。

このため、.bashrcにPYTHONPATHを追加することで無事呼び出せることが確認できた。
export PYTHONPATH=$PYTHONPATH:/usr/lib/python3/dist-packages/pyrealsense2/