2021年1月30日土曜日

Vitis 2020.2でvector additionサンプルをコマンドラインからライブラリとしてビルドできるようにしてデバッグ方法を確認した

vector additionサンプルをコマンドラインからライブラリとしてビルドできるようにしてデバッグ方法を確認した話。

環境

  • ubuntu:20.04
  • vitis:2020.2
  • yocto:zeus(https://github.com/akira-nishiyama/petalinux-ros2-manifests feature-v2020.2ブランチ)
  • board:ultra96v2(https://github.com/akira-nishiyama/ultra96v2_4z.git feature-v2020.2ブランチ)

ビルド方法

githubにvadd_lib_sampleリポジトリを用意するので、 xsaとboot componentを用意してsdカードのパスを確認して以下の通り実行すればok。なお、サンプルはVitis-Tutorialsを参考にさせてもらっている。

git clone https://github.com/akira-nishiyama/vitis_library_compilation_sample.git
cd vitis_library_compilation_sample

platform設定は用意したxsaとboot componentに合わせて修正が必要。 guiでプラットフォーム作るときと同じようにパスを指定すれば良い。

  • platform/platform.tcl
platform create -name {ultra96v2_platform}\
-hw {/home/akira/work/ultra96v2/xsa_dir/ultra96v2_4z/ultra96v2_4z.xsa}\
-proc {psu_cortexa53} -os {linux} -arch {64-bit} -no-boot-bsp -fsbl-target {psu_cortexa53_0} -out {.}

platform write
platform active {ultra96v2_platform}
domain config -bif {/home/akira/work/ultra96v2/vitis_args/linux.bif}
platform write
domain config -boot {/home/akira/work/ultra96v2/boot}
platform write
domain config -image {/home/akira/work/ultra96v2/boot}
platform write
domain config -rootfs {/home/akira/work/ultra96v2/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.ext4}
platform write
domain config -sysroot {/home/akira/work/ultra96v2/sdk/sysroots/aarch64-xilinx-linux}
platform write
domain config -qemu-data {/home/akira/work/ultra96v2/vitis_args}
platform write
domain config -qemu-data {/home/akira/work/ultra96v2/boot}
platform write
domain config -qemu-args {/home/akira/work/ultra96v2/vitis_args/qemu_args.txt}
platform write
domain config -pmuqemu-args {/opt/Xilinx/Vitis/2020.2/data/emulation/platforms/zynqmp/sw/a53_linux/qemu/pmu_args.txt}
platform write
domain config -pmuqemu-args {/home/akira/work/ultra96v2/vitis_args/pmu_args.txt}
platform write
domain config -qemu-data {/home/akira/work/ultra96v2/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp}
platform write
platform generate

<sd-device>,<sd-device-root>は環境に合わせて指定すること。

source <vitis-installation-path>/settings.sh
source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export PATH_TO_SD=<path-to-sd>
mkdir build
cd build
cmake .. -DBUILD_TARGET=hw
sudo dd if=hw_link/package_hw/sd_card.img of=<sd-device>
mkdir rootfs
sudo mount <sd-device-root> rootfs
sudo cp host/test_vecadd rootfs/home/root
sudo cp hw_link/binary_container_2_hw.xclbin rootfs/home/root
sudo cp host/libvecadd.so rootfs/usr/lib

sdをultra96v2に挿して起動後、次のコマンドを実行するとTEST PASSEDの文字が確認できる。

# ./vecadd_test binary_container_2_hw.xclbin 
Loading: 'binary_container_2_hw.xclbin'
TEST PASSED

また、BUILD_TARGETをsw_emu,hw_emuとするとbuild配下のhw_link/package_sw_emuやhw_link/package_hw_emuにエミュレーション用のファイル出来上がるので、それぞれのフォルダでterminalを2つ用意し、次の通り実行するとデバッグ可能。(https://japan.xilinx.com/html_docs/xilinx2020_1/vitis_doc/debugappproj.html#rme1587072841352)

なお、実行に際してはxrt.iniを自分で用意する必要がある。(https://www.xilinx.com/html_docs/xilinx2020_2/vitis_doc/obl1532064985142.html)

[Debug] 
profile=true
timeline_trace=true
trace_buffer_size=1M

ライブラリのパスをどうやって解決しているのかはよくわからない。

sw_emu

build/package_sw_emuに移動して次のコマンドを実行する。

  • terminal1
./launch_sw_emu.sh -pid-file emulation.pid -no-reboot -forward-port 1440 1534

ログインプロンプトが表示されたら次のコマンドを実行する。 デバッグしないなら/mnt/sd-mmcblk0p1においてあるテストプログラムを実行すれば結果が得られる。 ただし、export XCL_EMULATION_MODE=sw_emuの実行(xrt.iniに書いても可かも)と、libvecadd.soを/usr/libにコピーする必要がある。

  • terminal2
vitis -debug -flow embedded_accel -target sw_emu -exe ../../host/vecadd_test -program-args binary_container_2_sw_emu.xclbin -kernels vadd

実行後、vitisが立ち上がるので、vaddにブレークポイントを設定する。


 

メニューからFile->Open fileしてline break pointを指定しても良い。


 

実行するとbreak pointにひっかかる。


 

無事に終了。


 

profileデータなどはbuild/package_sw_emu/reportに保存されるのでvitis_analyzerで開けば確認できる。

vitis_analyzer reports



hw_emu

build/package_hw_emuに移動して次のコマンドを実行する。 -sim-guiは波形でバッグしない場合は不要。

  • terminal1
./launch_hw_emu.sh -pid-file emulation.pid -sim-gui -no-reboot -forward-port 1440 1534

ログインプロンプトが表示されたら次のコマンドを実行する。 デバッグしないなら/mnt/sd-mmcblk0p1においてあるテストプログラムを実行すれば結果が得られる。

  • terminal2
vitis -debug -flow embedded_accel -target hw_emu -exe ../../host/vecadd_test -program-args binary_container_2_hw_emu.xclbin -kernels vadd

メニューからFile->Open fileしてline break pointを指定できる。 HWカーネルはCソースレベルではブレークできないようだが、 vivado_simと同じ使い方でブレークさせることは可能そう。


 

構成

まず、vitisのembedded accelerationはplatform部と、host部と、hw_kernel部と、hw_link部に分けることができる。

platformは必要なファイルを集めて固定のshell部分を作っている。

host部はクロスコンパイラを使用してxilinxopencl,pthread,rt,stdc++,gmp,xrt_coreとリンクすれば良い。インクルードディレクトリはsdkの環境セットアップすれば解決される。通常のC++などと同じに扱えるのでライブラリはそれで作成可能。 (https://japan.xilinx.com/html_docs/xilinx2020_1/vitis_doc/debugappproj.html#rme1587072841352)

hw_kernel部はv++ -cを動作させて.xoを作成している。

hw_link部ではv++ -lで.xoを必要な個数接続している。また、パッケージ化もついでに行っている。

2021年1月19日火曜日

ros2 eloquent + orb_slam2_rosをクロスコンパイルして動かした話

ultra96v2とros2 eloquentでorb_slam2を動かした際のメモ。 能力不足なのか、マッピングが動かなかった。

vitisで性能改善させるのにsdkでのクロスコンパイル環境必要かと思ったので整えた。

レシピはここのfeature-v2020.2ブランチから一式取得できる。 もしくはここのfeature-v2020.2ブランチにレシピ類がまとめてある。

レシピの変更

クロスコンパイル用のパッケージにはnativesdkをBBCLASSEXTENDに追加する必要がある。 そのため、/sources/meta-ros/meta-ros-common/classes/ros_superflore_generated.bbclassを変更する。

# BBCLASSEXTEND_append = "${@bb.utils.contains('ROS_SUPERFLORE_GENERATED_BUILDTOOLS', '${BPN}-native', ' native', '', d)}"
BBCLASSEXTEND_append = "${@bb.utils.contains('ROS_SUPERFLORE_GENERATED_BUILDTOOLS', '${BPN}-native', ' native nativesdk', '', d)}"

次のファイルはFILES_${PN} += "*"を追加する。 そのままだとament-cmake向けファイル等がインストールされない模様。
recipes-ros2/ament-index-python/ament-index-python_%.bbappend
recipes-ros2/ament-package/ament-package_%.bbappend
recipes-ros2/domain-coordinator/domain-coordinator_%.bbappend

python3-lark-parserはBsuperfloreのBUILDTOOL登録されていないため、nativesdk化されない。 なのでbbappendでBBCLASSEXTEND_appendにnativesdkを追加する。 recipes-ros2/python3-lark-parser/python3-lark-parser_%.bbappend

rviz-ogre-vendorがmesaに依存しているけど、 zynqではmesa-glを使用するので、mesaを削除してmesa-glを追加する。
recipes-ros2/rviz/rviz-ogre-vendor_%.bbappend

ROS_BUILD_DEPENDS_remove = "mesa"
ROS_BUILD_DEPENDS_append = " mesa-gl"
ROS_EXPORT_DEPENDS_remove = "mesa"
ROS_EXPORT_DEPENDS_append = " mesa-gl"
ROS_EXEC_DEPENDS_remove = "mesa"
ROS_EXEC_DEPENDS_append = " mesa-gl"

あとはpackage.xmlを参考にopencv-camとros2-sharedのレシピを作成する。
recipes-ros2/opencv-cam/opencv-cam_git.bb
recipes-ros2/ros2-shared/ros2-shared_git.bb

あとはSDKのためにTOOLCHAIN_TARGET_TASK_appendとTOOLCHAIN_HOST_TASK_appendを recipes-core/images/petalinux-image-minimal-ultra96v2ros2.bbに追加していく。
yoctoは自動的に依存関係収集してくれないようなので、クロスコンパイルしたい対象の依存関係を手動で解決していく。
*-nativeに依存している場合はnativesdk-*をTOOLCHAIN_HOST_TASK_appendに追加する。
無印の場合にはTOOLCHAIN_TARGET_TASK_appendに該当パッケージを追加する。
クロスコンパイル実行時にライブラリが不足などのメッセージが出た場合には-staticdevや-devなどをTOOLCHAIN_TARGET_TASK_appendに追加する。
(で合ってるはず。自信は無い。)

ビルド

MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2
MACHINE=ultra96v2-zynqmp bitbake petalinux-image-minimal-ultra96v2ros2 -c do_populate_sdk

orb-slam2-rosの実行

まずはカメラ画像の確認。 USBのHOSTにwebカメラを接続する。 使用するのはlogicoolのc270n。 ついでにCPU使用率を確認する。

ssh 192.168.2.1 -l root
root@ultra96v2-zynqmp:~# source ros_setup.sh
root@ultra96v2-zynqmp:~# ros2 run opencv_cam opencv_cam_main --ros-args --param index:=0 --param camera_info_path:=camera-info-logicool-c270n.ini &
root@ultra96v2-zynqmp:~# top

topで動作を確認。

top - 23:11:54 up 11:33,  2 users,  load average: 0.86, 1.13, 1.63
Tasks: 103 total,   3 running, 100 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.2 us,  2.3 sy,  0.0 ni, 97.5 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1974.4 total,   1682.3 free,    124.8 used,    167.3 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1780.4 avail Mem 

大したことはなさそう。

orb-slam2-rosを動かす。

root@ultra96v2-zynqmp:~# ros2 run orb_slam2_ros orb_slam2_ros_mono --ros-args --remap /camera/image_raw:=/image_raw --remap /camera/camera_info:=/camera_info --param params_file:=/usr/share/orb_slam2_ros/ros/config/params_d435_mono.yaml --param voc_file:=/usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt &

同じくtopで確認。1オプションでCPU毎の負荷も確認しておく。

top - 23:50:13 up 12:11,  2 users,  load average: 3.71, 3.16, 2.74
Tasks: 108 total,   2 running, 106 sleeping,   0 stopped,   0 zombie
%Cpu0  : 85.9 us,  2.0 sy,  0.0 ni, 11.8 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu1  : 21.5 us,  5.0 sy,  0.0 ni, 73.2 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
%Cpu2  : 48.1 us,  6.5 sy,  0.0 ni, 45.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
%Cpu3  :  3.2 us, 26.4 sy,  0.0 ni, 70.4 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
MiB Mem :   1974.4 total,   1089.0 free,    665.8 used,    219.6 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1239.2 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                 
 1628 root      20   0 1790424 505660  21916 R 121.2  25.0  26:20.67 orb_slam2_ros_m                                                                         
 1277 root      20   0  516600  47812  23240 S  47.4   2.4  12:44.68 opencv_cam_main                                                                         
 4034 root       0 -20       0      0      0 I  31.8   0.0   3:38.79 kworker/u9:2-uvcvideo                                                                   
 1258 root      20   0  415052  37020  15196 S   1.0   1.8   0:24.32 python3                                                                                 
 6384 root      20   0    3320   2024   1564 R   0.7   0.1   0:02.39 top                                                                                     

CPUごとに見ると1つのCPUの負荷が高く、orb_slam2_rosプロセスの負荷が高い。 load averageも高めで能力足りてないと見ればいいかな。

クロスコンパイル

sdkをインストールしたあと

/sysroots/x86_64-petalinux-linux/usr/share/cmake/OEToolchainConfig.cmake を次のように編集する。 $ENV{OECORE_NATIVE_SYSROOT}が無いとnativeツールが発見できないため

set( CMAKE_FIND_ROOT_PATH "\$ENV{OECORE_TARGET_SYSROOT};\$ENV{OECORE_NATIVE_SYSROOT}" )

sysroots/aarch64-xilinx-linux/usr/share/fastrtps/cmake/fastrtps-targets.cmakeの検索パスが間違っているので修正。 レシピから修正したほうがいいだろうけど、とりあえずなんとかなるから後回し。

#set_target_properties(fastrtps PROPERTIES
#  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
#  INTERFACE_LINK_LIBRARIES "fastcdr;foonathan_memory;-lpthread;dl;/home/akira/work/ultra96v2/petalinux/build/tmp/work/aarch64-xilinx-linux/fastrtps/1.9.3-2-r0/recipe-sysroot/usr/lib/libtinyxml2.so;\$<\$<BOOL:1>:OpenSSL::SSL\$<SEMICOLON>OpenSSL::Crypto>;\$<\$<BOOL:>:iphlpapi\$<SEMICOLON>Shlwapi>"
#)
set_target_properties(fastrtps PROPERTIES
  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include"
  INTERFACE_LINK_LIBRARIES "fastcdr;foonathan_memory;-lpthread;dl;$ENV{OECORE_TARGET_SYSROOT}/usr/lib/libtinyxml2.so;\$<\$<BOOL:1>:OpenSSL::SSL\$<SEMICOLON>OpenSSL::Crypto>;\$<\$<BOOL:>:iphlpapi\$<SEMICOLON>Shlwapi>"
)

buildの実行。インストールパスはsd-cardのrootをマウントした場所を指定する。

source <sdk-installation-path>/environment-setup-aarch64-xilinx-linux
export AMENT_PREFIX_PATH=$OECORE_NATIVE_SYSROOT/usr:$OECORE_TARGET_SYSROOT/usr
export PYTHONPATH=$OECORE_NATIVE_SYSROOT/usr/lib/python3.7/site-packages:$OECORE_TARGET_SYSROOT/usr/lib/python3.7/site-packages
cd <path-to-orb_slam2_ros-repository>
mkdir build
cd build
cmake .. -DCMAKE_INSTALL_SO_NO_EXE=0 -DBUILD_TESTING=OFF -DCMAKE_NO_SYSTEM_FROM_IMPORTED=1 -GNinja -DCMAKE_INSTALL_PREFIX=<sd-card-root>
cmake --build
sudo ninja install

同じようにtopを実行してみると似た結果が得られている。

top - 00:12:13 up 12 min,  2 users,  load average: 3.12, 1.92, 0.98
Tasks: 109 total,   4 running, 105 sleeping,   0 stopped,   0 zombie
%Cpu(s): 45.3 us, 14.8 sy,  0.0 ni, 39.5 id,  0.0 wa,  0.0 hi,  0.3 si,  0.0 st
MiB Mem :   1974.4 total,   1059.6 free,    636.4 used,    278.5 buff/cache
MiB Swap:      0.0 total,      0.0 free,      0.0 used.   1249.7 avail Mem 

  PID USER      PR  NI    VIRT    RES    SHR S  %CPU  %MEM     TIME+ COMMAND                                                                                 
 1212 root      20   0 1785152 499480  21788 R 125.2  24.7   0:15.17 orb_slam2_ros_m                                                                         
  812 root      20   0  516588  47672  22840 S  67.5   2.4   1:58.91 opencv_cam_main                                                                         
  133 root       0 -20       0      0      0 R  46.4   0.0   0:50.66 kworker/u9:0+uvcvideo                                                                   
 1211 root      20   0    3320   2064   1616 R   0.7   0.1   0:00.10 top                         

また、rviz2でdebug_imageを確認するとorb_slam2_rosから出力されているのでクロスコンパイル版もしっかり動作している模様。

2021年1月12日火曜日

ubuntu 20.04+ros2 foxyでorab_slam2_rosを動作させてみた

ubuntu 20.04とros2 foxyでカメラを動作させてorb_slam2_rosを試してみた際のメモ。 カメラで試したのはros2_v4l2_cameraopencv_cam。 ほぼリンク先の通り実行しただけ。

opencvの準備

ubuntu 20.04標準のopencvではバージョン起因と思われるエラーが出たので、 v4.5.0をソースからビルドした。 特別問題なくビルドできた。

cd <path-to-opencv-download-dir>
unzip opencv-4.5.0.zip
cd opencv-4.5.0
mkdir build
cd build
cmake .. -GNinja -DCMAKE_INSTALL_PREFIX=<opencv-installation-path>/local
ninja -j4
ninja install

私の環境では既にopencv3.4.12が入っているので、v4.5.0が先に見つかるように環境変数を設定する。 colcon実行前に以下のコマンドが必要。

export PATH=<opencv-installation-path>/local/bin:$PATH
export LD_LIBRARY_PATH=<opencv-installation-path>/local/lib:$LD_LIBRARY_PATH
export PYTHONPATH=<opencv-installation-path>/local/lib/python3.8/dist-packages:$PYTHONPATH

ros2_v4l2_cameraの準備

こちらは記載の通りに実行して特に問題なかった。 ~/ros_work/srcにリポジトリをクローンする。

使用したhashは以下の通り

ros2_v4l2_camera:65b072565f8e4520d166b725d91d5f31acd97610
image_common:4c5053ecf703a58c25a712d1d4a80012f5076a1f
image_transport_plugins:0565f23dc955fa2d56cffcfebc63de5a97cd005f
vision_opencv:2026f6d66833e0830f9ce69004d43c9abd1e5fa4

opencv_camの準備

ここを参考にしてビルドした。 image_pipelineのビルドはros2ブランチのhash:b4fbbae6463fb3baaa4b36a0a7517d0b0395e837を使用する。 foxyっぽいブランチを使用すると2021/1/12時点ではcalibrationを実行する際にros-argsを指定すると実行できない問題がある模様。 (https://github.com/ros-perception/image_pipeline/pull/597) image_commonはros2_v4ls_cameraと同じ。 ~/ros_work/srcにリポジトリをクローンする。

使用したhashは以下の通り。

opencv_cam:f4487b0de651a4323a535f8e8d0e86b147cc81c2
ros2_shared:02433ef4f873876c3dd3ab2925987cf04d224660
image_common:4c5053ecf703a58c25a712d1d4a80012f5076a1f
image_pipeline:b4fbbae6463fb3baaa4b36a0a7517d0b0395e837

ビルド

パスの設定をしてビルドする。

cd ~/ros_work
export PATH=<opencv-installation-path>/local/bin:$PATH
export LD_LIBRARY_PATH=<opencv-installation-path>/local/lib:$LD_LIBRARY_PATH
export PYTHONPATH=<opencv-installation-path>/local/lib/python3.8/dist-packages:$PYTHONPATH
colcon build --symlink-install

videoの出力

cam2imageを試す場合は以下。 /dev/video0のみが出力できる。

source ~/ros_work/install/setup.sh
ros2 run image_tools cam2image

v4l2_cameraを試す場合は以下。 video_deviceのパラメータで指定可能。 videoデバイスが複数合ってどれを使えばいいかわからない場合は、 videoデバイスの情報の調べ方を使って調べられる。 USBなら挿して増えたものでいいとは思う。 eloquent以前のビルドはできそうになかったので、 ultra96v2への採用は見送った。

source ~/ros_work/install/setup.sh
ros2 run v4l2_camera v4l2_camera_node --ros-args -p video_device:=/dev/video14

opencv_camを試す場合は以下。 indexでvideoデバイスファイルの番号を指定できる。

source ~/ros_work/install/setup.sh
ros2 run opencv_cam opencv_cam_main --ros-args --param index:=14

videoデバイスの情報の調べ方

v4l2-ctlを使用する。 ない場合にはv4l-utilsをインストールすると使用できる。

sudo apt install v4l-utils

logicoolのc270nに試してみた結果は以下の通り。

# v4l2-ctl -d /dev/video14 --all
driver Info:
    Driver name      : uvcvideo
    Card type        : UVC Camera (046d:0825)
    Bus info         : usb-0000:00:14.0-1.1
    Driver version   : 5.8.18
    Capabilities     : 0x84a00001
        Video Capture
        Metadata Capture
        Streaming
        Extended Pix Format
        Device Capabilities
    Device Caps      : 0x04200001
        Video Capture
        Streaming
        Extended Pix Format
Media Driver Info:
    Driver name      : uvcvideo
    Model            : UVC Camera (046d:0825)
    Serial           : 98251310
    Bus info         : usb-0000:00:14.0-1.1
    Media version    : 5.8.18
    Hardware revision: 0x00000012 (18)
    Driver version   : 5.8.18
Interface Info:
    ID               : 0x03000002
    Type             : V4L Video
Entity Info:
    ID               : 0x00000001 (1)
    Name             : UVC Camera (046d:0825)
    Function         : V4L2 I/O
    Flags         : default
    Pad 0x01000007   : 0: Sink
      Link 0x02000019: from remote pad 0x100000a of entity 'Extension 4': Data, Enabled, Immutable
Priority: 2
Video input : 0 (Camera 1: ok)
Format Video Capture:
    Width/Height      : 640/480
    Pixel Format      : 'YUYV' (YUYV 4:2:2)
    Field             : None
    Bytes per Line    : 1280
    Size Image        : 614400
    Colorspace        : sRGB
    Transfer Function : Default (maps to sRGB)
    YCbCr/HSV Encoding: Default (maps to ITU-R 601)
    Quantization      : Default (maps to Limited Range)
    Flags             : 
Crop Capability Video Capture:
    Bounds      : Left 0, Top 0, Width 640, Height 480
    Default     : Left 0, Top 0, Width 640, Height 480
    Pixel Aspect: 1/1
Selection Video Capture: crop_default, Left 0, Top 0, Width 640, Height 480, Flags: 
Selection Video Capture: crop_bounds, Left 0, Top 0, Width 640, Height 480, Flags: 
Streaming Parameters Video Capture:
    Capabilities     : timeperframe
    Frames per second: 30.000 (30/1)
    Read buffers     : 0
                     brightness 0x00980900 (int)    : min=0 max=255 step=1 default=128 value=128
                       contrast 0x00980901 (int)    : min=0 max=255 step=1 default=32 value=32
                     saturation 0x00980902 (int)    : min=0 max=255 step=1 default=32 value=32
 white_balance_temperature_auto 0x0098090c (bool)   : default=1 value=1
                           gain 0x00980913 (int)    : min=0 max=255 step=1 default=64 value=64
           power_line_frequency 0x00980918 (menu)   : min=0 max=2 default=2 value=2
                0: Disabled
                1: 50 Hz
                2: 60 Hz
      white_balance_temperature 0x0098091a (int)    : min=0 max=10000 step=10 default=4000 value=4000 flags=inactive
                      sharpness 0x0098091b (int)    : min=0 max=255 step=1 default=24 value=24
         backlight_compensation 0x0098091c (int)    : min=0 max=1 step=1 default=0 value=0
                  exposure_auto 0x009a0901 (menu)   : min=0 max=3 default=3 value=3
                1: Manual Mode
                3: Aperture Priority Mode
              exposure_absolute 0x009a0902 (int)    : min=1 max=10000 step=1 default=166 value=166 flags=inactive
         exposure_auto_priority 0x009a0903 (bool)   : default=0 value=1

videoの確認

上記でvideoの出力したものはrqt_image_viewで確認できる。 rviz2だとカメラ画像はうまく表示されなかった。(camera_infoの出力が必要とのこと)

ros2 run rqt_image_view rqt_image_view

 

calibration

カメラのキャリブレーションしないとopencv_camを実行した際にcamera_infoのtopicを出力できない旨のエラーメッセージが出力される。

[ERROR] [1610449586.191007718] [camera_calibration_parsers]: Failed to detect content in .ini file
[ERROR] [1610449586.191095947] [opencv_cam]: cannot get camera info, will not publish

キャリブレーション方法はこちらに記載の内容に従って行った。 途中でフリーズしてCalibrateボタンが押せないことが何度かあったが、頑張ってプログラムを完了させた。

#ros2 run camera_calibration cameracalibrator \
  --size=8x6 \
  --square=0.063 \
  --approximate=0.3 \
  --no-service-check \
  --ros-args --remap /image:=/image_raw
*** Added sample 1, p_x = 0.479, p_y = 0.527, p_size = 0.602, skew = 0.051
*** Added sample 2, p_x = 0.790, p_y = 0.645, p_size = 0.634, skew = 0.083
*** Added sample 3, p_x = 0.758, p_y = 0.556, p_size = 0.634, skew = 0.164
*** Added sample 4, p_x = 0.599, p_y = 0.417, p_size = 0.627, skew = 0.155
*** Added sample 5, p_x = 0.529, p_y = 0.281, p_size = 0.622, skew = 0.103
*** Added sample 6, p_x = 0.435, p_y = 0.000, p_size = 0.627, skew = 0.128
*** Added sample 7, p_x = 0.463, p_y = 0.776, p_size = 0.621, skew = 0.057
*** Added sample 8, p_x = 0.630, p_y = 0.905, p_size = 0.627, skew = 0.056
*** Added sample 9, p_x = 0.465, p_y = 0.997, p_size = 0.629, skew = 0.101
*** Added sample 10, p_x = 0.787, p_y = 0.888, p_size = 0.667, skew = 0.104
*** Added sample 11, p_x = 0.336, p_y = 0.914, p_size = 0.647, skew = 0.025
*** Added sample 12, p_x = 0.355, p_y = 0.735, p_size = 0.666, skew = 0.005
*** Added sample 13, p_x = 0.460, p_y = 0.585, p_size = 0.688, skew = 0.012
*** Added sample 14, p_x = 0.255, p_y = 0.577, p_size = 0.683, skew = 0.032
*** Added sample 15, p_x = 0.371, p_y = 0.504, p_size = 0.706, skew = 0.054
*** Added sample 16, p_x = 0.640, p_y = 0.781, p_size = 0.737, skew = 0.073
*** Added sample 17, p_x = 0.402, p_y = 0.322, p_size = 0.719, skew = 0.036
*** Added sample 18, p_x = 0.534, p_y = 0.101, p_size = 0.747, skew = 0.069
*** Added sample 19, p_x = 0.689, p_y = 0.225, p_size = 0.764, skew = 0.129
*** Added sample 20, p_x = 0.632, p_y = 0.539, p_size = 0.733, skew = 0.140
*** Added sample 21, p_x = 0.527, p_y = 0.628, p_size = 0.711, skew = 0.133
*** Added sample 22, p_x = 0.241, p_y = 0.822, p_size = 0.620, skew = 0.040
*** Added sample 23, p_x = 0.524, p_y = 0.801, p_size = 0.745, skew = 0.015
*** Added sample 24, p_x = 0.603, p_y = 0.734, p_size = 0.669, skew = 0.157
*** Added sample 25, p_x = 0.404, p_y = 0.131, p_size = 0.690, skew = 0.103
*** Added sample 26, p_x = 0.301, p_y = 0.048, p_size = 0.690, skew = 0.082
*** Added sample 27, p_x = 0.743, p_y = 0.106, p_size = 0.692, skew = 0.131
*** Added sample 28, p_x = 0.788, p_y = 0.305, p_size = 0.689, skew = 0.128
*** Added sample 29, p_x = 0.423, p_y = 0.621, p_size = 0.631, skew = 0.084
*** Added sample 30, p_x = 0.638, p_y = 0.191, p_size = 0.651, skew = 0.117
*** Added sample 31, p_x = 0.410, p_y = 0.404, p_size = 0.629, skew = 0.059
*** Added sample 32, p_x = 0.700, p_y = 0.411, p_size = 0.678, skew = 0.244
*** Added sample 33, p_x = 0.577, p_y = 0.321, p_size = 0.674, skew = 0.193
*** Added sample 34, p_x = 0.416, p_y = 0.468, p_size = 0.664, skew = 0.171
*** Added sample 35, p_x = 0.348, p_y = 0.709, p_size = 0.778, skew = 0.065
*** Added sample 36, p_x = 0.546, p_y = 0.666, p_size = 0.784, skew = 0.035
*** Added sample 37, p_x = 0.545, p_y = 0.369, p_size = 0.769, skew = 0.006
*** Added sample 38, p_x = 0.640, p_y = 0.493, p_size = 0.598, skew = 0.063
*** Added sample 39, p_x = 0.814, p_y = 0.795, p_size = 0.610, skew = 0.071
*** Added sample 40, p_x = 0.730, p_y = 0.839, p_size = 0.600, skew = 0.166
*** Added sample 41, p_x = 0.587, p_y = 0.679, p_size = 0.570, skew = 0.052
D =  [0.45527714279447146, 0.29663576559913546, -0.023494638427063057, -0.03623143280219075, 0.0]
K =  [1594.715058900246, 0.0, 214.64225194625027, 0.0, 1535.171197718767, 174.6268394034711, 0.0, 0.0, 1.0]
R =  [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
P =  [1628.6416015625, 0.0, 210.49766367948905, 0.0, 0.0, 1574.3720703125, 171.79825469629577, 0.0, 0.0, 0.0, 1.0, 0.0]
None
# oST version 5.0 parameters


[image]

width
640

height
480

[narrow_stereo]

camera matrix
1594.715059 0.000000 214.642252
0.000000 1535.171198 174.626839
0.000000 0.000000 1.000000

distortion
0.455277 0.296636 -0.023495 -0.036231 0.000000

rectification
1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 1.000000

projection
1628.641602 0.000000 210.497664 0.000000
0.000000 1574.372070 171.798255 0.000000
0.000000 0.000000 1.000000 0.000000


D =  [0.45527714279447146, 0.29663576559913546, -0.023494638427063057, -0.03623143280219075, 0.0]
K =  [1594.715058900246, 0.0, 214.64225194625027, 0.0, 1535.171197718767, 174.6268394034711, 0.0, 0.0, 1.0]
R =  [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
P =  [1628.6416015625, 0.0, 210.49766367948905, 0.0, 0.0, 1574.3720703125, 171.79825469629577, 0.0, 0.0, 0.0, 1.0, 0.0]
None
# oST version 5.0 parameters


[image]

width
640

height
480

[narrow_stereo]

camera matrix
1594.715059 0.000000 214.642252
0.000000 1535.171198 174.626839
0.000000 0.000000 1.000000

distortion
0.455277 0.296636 -0.023495 -0.036231 0.000000

rectification
1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 1.000000

projection
1628.641602 0.000000 210.497664 0.000000
0.000000 1574.372070 171.798255 0.000000
0.000000 0.000000 1.000000 0.000000


('Wrote calibration data to', '/tmp/calibrationdata.tar.gz')
D =  [0.45527714279447146, 0.29663576559913546, -0.023494638427063057, -0.03623143280219075, 0.0]
K =  [1594.715058900246, 0.0, 214.64225194625027, 0.0, 1535.171197718767, 174.6268394034711, 0.0, 0.0, 1.0]
R =  [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0]
P =  [1628.6416015625, 0.0, 210.49766367948905, 0.0, 0.0, 1574.3720703125, 171.79825469629577, 0.0, 0.0, 0.0, 1.0, 0.0]
# oST version 5.0 parameters


[image]

width
640

height
480

[narrow_stereo]

camera matrix
1594.715059 0.000000 214.642252
0.000000 1535.171198 174.626839
0.000000 0.000000 1.000000

distortion
0.455277 0.296636 -0.023495 -0.036231 0.000000

rectification
1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 1.000000

projection
1628.641602 0.000000 210.497664 0.000000
0.000000 1574.372070 171.798255 0.000000
0.000000 0.000000 1.000000 0.000000

/tmp/calibrationdata.tar.gzに保存されたものを使用する。 解凍すると、ost.txtがあり、これがiniファイルとして使用できる。(コンソールの結果も同じ) なので、camera-info-logicool-c270n.iniとして保存した。 使うときには以下の通り。 ただし、rviz2では表示されなかった。あと何がいるんだ?

ros2 run opencv_cam opencv_cam_main --ros-args --param index:=14 --param camera_info_path:=camera-info-logicool-c270n.ini

orb_slam2実行

以下のコマンドでorb_slam2_rosを実行する。

ros2 run orb_slam2_ros orb_slam2_ros_mono --ros-args --remap /camera/image_raw:=/image_raw --remap /camera/camera_info:=/camera_info --param params_file:=install/orb_slam2_ros/share/orb_slam2_ros/ros/config/params_d435_mono.yaml --param voc_file:=install/orb_slam2_ros/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt 

ultra96v2で実行する場合は以下。機能の実装方法は次回。

ros2 run orb_slam2_ros orb_slam2_ros_mono --ros-args --remap /camera/image_raw:=/image_raw --remap /camera/camera_info:=/camera_info --param params_file:=/usr/share/orb_slam2_ros/ros/config/params_d435_mono.yaml --param voc_file:=/usr/share/orb_slam2_ros/orb_slam2/Vocabulary/ORBvoc.txt 

以下のような結果が得られた。 なんだか微妙な感じだけどキャリブレーションうまくいってないのか?


 

参考

http://joe.ash.jp/program/ros/tutorial/tutorial_camera.htm
https://medium.com/swlh/raspberry-pi-ros-2-camera-eef8f8b94304
https://jeffzzq.medium.com/ros2-image-pipeline-tutorial-3b18903e7329

2020年12月31日木曜日

ultra96v2+ros2 eloquentでorb_slam2を動かしてみた話

ultra96v2向けにORB_SLAM2をビルドした話。 ORB_SLAM2のビルドにはPangolinとimage_commonが必要だったので、レシピを作成する。
上記以外の必要なものはmeta-rosに含まれていたものでOKだった。

準備

環境は前に作成したものと同じ。以下に示すレシピもmeta-ultra96v2に追加済なのでそのままビルドすれば実行できる。

Pangolinのビルド

recipetoolを使用してPangolinのレシピを作成してビルドしてみる。

{class="prettyprint lang-sh} recipetool create -o pangolin_git.bb https://github.com/stevenlovegrove/Pangolin.git mv pangolin_git.bb ../sources/meta-ultra96v2/recipes-graphics/pangolin MACHINE=ultra96v2-zynqmp bitbake pangolin

そのままのビルドではエラーが出た。 内容はdo_package_qa: QA Issue: pangolin-dev package contains non-symlink .so ここを参考にして、 パッケージするファイルを選択すると解消する。合ってるかどうかはいまいち自信がない。

あと、ライセンスも修正しておく。

レシピは以下の通り。

LICENSE = "MIT & BSD-3-Clause"
LIC_FILES_CHKSUM = "file://LICENCE;md5=37611e574d0acc5cc68f827d28a9ce8a \
                    file://include/pangolin/utils/xml/license.txt;md5=d63ab70ba21ca0544b03284958324301 \
                    file://external/pybind11/LICENSE;md5=beb87117af69fd10fbf9fb14c22a2e62 \
                    file://external/pybind11/tools/clang/LICENSE.TXT;md5=dfabea443c6c16b6321441a8c8c19705"

SRC_URI = "gitsm://github.com/stevenlovegrove/Pangolin.git;protocol=https"

# Modify these as desired
PV = "1.0+git${SRCPV}"
SRCREV = "86eb4975fc4fc8b5d92148c2e370045ae9bf9f5d"

S = "${WORKDIR}/git"


# NOTE: unable to map the following CMake package dependencies: Pangolin Eigen
inherit cmake
inherit python3native

DEPENDS = "libeigen glew virtual/libgl"

FILES_SOLIBSDEV = ""

FILES_${PN} += " ${libdir}/libpangolin.so"
FILES_${PN} += " ${bindir}/*"
FILES_${PN}-dev += " ${includedir}/*"


# Specify any options you want to pass to cmake using EXTRA_OECMAKE:
EXTRA_OECMAKE = ""

image-commonのビルド

recipetoolを使うとエラーが出てしまったので他のrosレシピを参考に手動で作成。 inherit ros_distro_eloquentと、inherit ros_superflore_generated、 ROS_BUILD_TYPE = “ament_cmake”、inherit ros_${ROS_BUILD_TYPE}を設定すれば良い。 ROS_CNはパッケージ名、ROS_BPNにはイメージ名を記載する。 buld_dependsなどはpackage.xmlに記載された設定と同じにする。 image-commonのパッケージからは4つイメージをビルドする必要があるので、 camera-calibration-parsers,camera-info-manager,image-common,image-transportの4つのレシピを作成する。 次はimage-commonの場合。レシピ名はimage-common_git.bbとしている。

LICENSE = "BSD"
#LIC_FILES_CHKSUM = "file://"

SRC_URI = "git://github.com/ros-perception/image_common.git;protocol=https;branch=ros2"

# Modify these as desired
PV = "1.0+git${SRCPV}"
SRCREV = "4c5053ecf703a58c25a712d1d4a80012f5076a1f"

S = "${WORKDIR}/git"

inherit ros_distro_eloquent
inherit ros_superflore_generated

DESCRIPTION = ""
AUTHOR = "Patrick Mihelich and James Bowman"
ROS_AUTHOR = ""
HOMEPAGE = "https://wiki.ros.org/image_common"
SECTION = "devel"

ROS_CN = "image-common"
ROS_BPN = "image-common"

ROS_BUILD_DEPENDS = ""

ROS_BUILDTOOL_DEPENDS = " \
    ament-cmake-native \
"

ROS_EXPORT_DEPENDS = ""

ROS_BUILDTOOL_EXPORT_DEPENDS = ""

ROS_EXEC_DEPENDS = " \
    camera-calibration-parsers \
    camera-info-manager \
    image-transport \
"

# Currently informational only -- see http://www.ros.org/reps/rep-0149.html#dependency-tags.
ROS_TEST_DEPENDS = " \
    ament-lint-auto \
    ament-lint-common \
"

DEPENDS = "${ROS_BUILD_DEPENDS} ${ROS_BUILDTOOL_DEPENDS}"
# Bitbake doesn't support the "export" concept, so build them as if we needed them to build this package (even though we actually
# don't) so that they're guaranteed to have been staged should this package appear in another's DEPENDS.
DEPENDS += "${ROS_EXPORT_DEPENDS} ${ROS_BUILDTOOL_EXPORT_DEPENDS}"

RDEPENDS_${PN} += "${ROS_EXEC_DEPENDS}"

ROS_BUILD_TYPE = "ament_cmake"

inherit ros_${ROS_BUILD_TYPE}

orb-slam2のビルド

pangolinとcamera-calibration-parsers,camera-info-manager,image-common,image-transportが必要。 これは準備したので、レシピを作成する。

recipetoolを使用してPangolinのレシピを作成してビルドしてみる。 が、meta-ros向けのレシピはうまく作ってくれないので手作業。 package.xmlから以下の通り生成する。 superfloreなんかを使うとこの辺はうまくやってくれるのだと思う。

レシピ名はorb-slam2_git.bbとした。

LICENSE = "GPLv3 & BSD-3-Clause"
LIC_FILES_CHKSUM = "file://License-gpl.txt;md5=d32239bcb673463ab874e80d47fae504 \
                    file://LICENSE.txt;md5=9f7421fb91aef33332dbdfab7e243c01 \
                    file://orb_slam2/Thirdparty/DBoW2/LICENSE.txt;md5=b91b90de616800c44c9ebba46c143a70 \
                    file://orb_slam2/Thirdparty/g2o/license-bsd.txt;md5=9c0c0561478261cb090e64115139d923"

SRC_URI = "git://github.com/appliedAI-Initiative/orb_slam_2_ros.git;protocol=https;branch=ros2"

# Modify these as desired
PV = "1.0+git${SRCPV}"
SRCREV = "0f964c618a2e0b7715c1c6fc49e6b70b2ba2c904"

S = "${WORKDIR}/git"

inherit ros_distro_eloquent
inherit ros_superflore_generated

DESCRIPTION = ""
AUTHOR = "Raul Mur-Artal, Juan D. Tardos, J. M. M. Montiel and Dorian Galvez-Lopez (DBoW2)."
ROS_AUTHOR = ""
HOMEPAGE = ""
SECTION = "devel"

ROS_CN = "orb-slam2"
ROS_BPN = "orb-slam2"

ROS_BUILD_DEPENDS = " \
    rclcpp \
    std-msgs \
    geometry-msgs \
    tf2-geometry-msgs \
    cv-bridge \
    image-common \
    image-transport \
    tf2-ros \
    sensor-msgs \
    rosidl-default-generators \
"

ROS_BUILDTOOL_DEPENDS = " \
    ament-cmake-native \
    rosidl-default-generators-native \
"

ROS_EXPORT_DEPENDS = " \
    boost \
    cairo \
    ceres-solver \
    gflags \
    glog \
    libeigen \
    lua \
    protobuf \
"

ROS_BUILDTOOL_EXPORT_DEPENDS = ""

ROS_EXEC_DEPENDS = " \
    rclcpp \
    std-msgs \
    geometry-msgs \
    cv-bridge \
    image-transport \
    tf2-ros \
    sensor-msgs \
    rosidl-default-runtime \
"

# Currently informational only -- see http://www.ros.org/reps/rep-0149.html#dependency-tags.
ROS_TEST_DEPENDS = " \
    ament-lint-auto \
    ament-lint-common \
"

DEPENDS = "${ROS_BUILD_DEPENDS} ${ROS_BUILDTOOL_DEPENDS}"
# Bitbake doesn't support the "export" concept, so build them as if we needed them to build this package (even though we actually
# don't) so that they're guaranteed to have been staged should this package appear in another's DEPENDS.
DEPENDS += "${ROS_EXPORT_DEPENDS} ${ROS_BUILDTOOL_EXPORT_DEPENDS}"

RDEPENDS_${PN} += "${ROS_EXEC_DEPENDS}"

FILES_${PN} += "*"

ROS_BUILD_TYPE = "ament_cmake"

inherit ros_${ROS_BUILD_TYPE}

動作確認

hostでrviz2を起動し、point_cloudをAddする。 debug_imageは追加してもカクカクなので見ない。

  • window1
source /opt/ros/foxy/setup.sh
rviz2

テスト用にTUM1のbagファイルを再生する。

  • window2
source /opt/ros/noetic/setup.sh
source /opt/ros/foxy/setup.sh
ros2 bag play -s rosbag_v2 rgbd_dataset_freiburg1_xyz.bag --read-ahead-queue-size 1000000

bagファイルの再生には時間がかかるので、 その間にultra96v2にsshでログインしてorb_slam2を起動させる。

  • window3
root@ultra96v2-zynqmp:~# source ros_setup.sh
root@ultra96v2-zynqmp:~# ros2 launch orb_slam2_ros TUM1_mono_launch.py
[INFO] [launch]: All log files can be found below /home/root/.ros/log/2020-12-28-21-11-00-749497-ultra96v2-zynqmp-1140
[INFO] [launch]: Default logging verbosity is set to INFO
[INFO] [orb_slam2_ros_mono-1]: process started with pid [1149]
[orb_slam2_ros_mono-1] [INFO] [orb_slam2_mono]: Camera info received.
[orb_slam2_ros_mono-1]
[orb_slam2_ros_mono-1] ORB-SLAM2 Copyright (C) 2014-2016 Raul Mur-Artal, University of Zaragoza.
[orb_slam2_ros_mono-1] This program comes with ABSOLUTELY NO WARRANTY;
[orb_slam2_ros_mono-1] This is free software, and you are welcome to redistribute it
[orb_slam2_ros_mono-1] under certain conditions. See LICENSE.txt.
[orb_slam2_ros_mono-1]
[orb_slam2_ros_mono-1] OpenCV version : 3.4.3
[orb_slam2_ros_mono-1] Major version : 3
[orb_slam2_ros_mono-1] Minor version : 4
[orb_slam2_ros_mono-1] Subminor version : 3
[orb_slam2_ros_mono-1] Input sensor was set to: Monocular
[orb_slam2_ros_mono-1]
[orb_slam2_ros_mono-1] Loading ORB Vocabulary.
[orb_slam2_ros_mono-1] Vocabulary loaded!
[orb_slam2_ros_mono-1]
[orb_slam2_ros_mono-1]
[orb_slam2_ros_mono-1] Camera Parameters:
[orb_slam2_ros_mono-1] - fx: 525
[orb_slam2_ros_mono-1] - fy: 525
[orb_slam2_ros_mono-1] - cx: 319.5
[orb_slam2_ros_mono-1] - cy: 239.5
[orb_slam2_ros_mono-1] - k1: 0
[orb_slam2_ros_mono-1] - k2: 0
[orb_slam2_ros_mono-1] - p1: 0
[orb_slam2_ros_mono-1] - p2: 0
[orb_slam2_ros_mono-1] - fps: 30
[orb_slam2_ros_mono-1] - bf: 0
[orb_slam2_ros_mono-1] - color order: RGB (ignored if grayscale)
[orb_slam2_ros_mono-1]
[orb_slam2_ros_mono-1] ORB Extractor Parameters:
[orb_slam2_ros_mono-1] - Number of Features: 2000
[orb_slam2_ros_mono-1] - Scale Levels: 8
[orb_slam2_ros_mono-1] - Scale Factor: 1.2
[orb_slam2_ros_mono-1] - Initial Fast Threshold: 20
[orb_slam2_ros_mono-1] - Minimum Fast Threshold: 7
[orb_slam2_ros_mono-1] [WARN] [orb_slam2_mono]: Map point vector is empty!
[orb_slam2_ros_mono-1] [WARN] [orb_slam2_mono]: Map point vector is empty!
[orb_slam2_ros_mono-1] [WARN] [orb_slam2_mono]: Map point vector is empty!
[orb_slam2_ros_mono-1] [WARN] [orb_slam2_mono]: Map point vector is empty!
[orb_slam2_ros_mono-1] [WARN] [orb_slam2_mono]: Map point vector is empty!
[orb_slam2_ros_mono-1] [WARN] [orb_slam2_mono]: Map point vector is empty!
[orb_slam2_ros_mono-1] [WARN] [orb_slam2_mono]: Map point vector is empty!
[orb_slam2_ros_mono-1] New Map created with 237 points
[ 1284.850620] NOHZ: local_softirq_pending 08

2020年12月26日土曜日

Ubuntu 20.04 + ros2 foxyでORB_SLAM2を使ってみた

Ubuntu 20.04 + ros2 foxyでORB_SLAM2を使ってみた話。

環境

Ubuntu 20.04
ros2 foxy ros noetic(rosbag2によるデータセット再生用)

ros2はソースビルドをした場合にrosbag2_bag_v2をビルドするのがうまくできなかったので、 パッケージ版を使用する。 今回はros1で保存されているbagファイルを再生させるためにrosbag2_bag_v2プラグインを使用したいので、 noeticの環境をセットアップした後にfoxyとrosbag2の環境を準備した。

まずはnoeticのセットアップを行う。 公式ページにしたがって環境セットアップだけする。 必要なパッケージは後でインストールされるのでここでは不要。

sudo apt update && sudo apt install curl gnupg2 lsb-release
sudo sh -c 'echo "deb http://packages.ros.org/ros/ubuntu $(lsb_release -sc) main" > /etc/apt/sources.list.d/ros-latest.list'
sudo apt-key adv --keyserver 'hkp://keyserver.ubuntu.com:80' --recv-key C1CF6E31E6BADE8868B172B4F42ED6FBAB17C654

次はros2側のセットアップを行う。foxyを使用し、rosbag2とbag_v2プラグインをセットアップする。 インストールするのはros-foxy-ros2bagとros-foxy-rosbag2*なので注意。 公式ページにしたがって以下のように準備。

curl -s https://raw.githubusercontent.com/ros/rosdistro/master/ros.asc | sudo apt-key add -
sudo sh -c 'echo "deb [arch=$(dpkg --print-architecture)] http://packages.ros.org/ros2/ubuntu $(lsb_release -cs) main" > /etc/apt/sources.list.d/ros2-latest.list'
sudo apt update
sudo apt install ros-foxy-base
sudo apt update && apt-get install -y ros-foxy-ros2bag ros-foxy-rosbag2*

ORB_SLAM2のビルド

必要なソースを取得してきてビルドを行う。

cd <work-dir>
mkdir src
cd src
git clone https://github.com/ros-perception/vision_opencv.git -b ros2
git clone https://github.com/ros-perception/image_common.git -b ros2
git clone https://github.com/appliedAI-Initiative/orb_slam_2_ros.git -b ros2

今回試した際のHash値は次の通りだった。 image_common:4c5053ecf703a58c25a712d1d4a80012f5076a1f
vision_opencv:2026f6d66833e0830f9ce69004d43c9abd1e5fa4 orb_slam_2_ros:0f964c618a2e0b7715c1c6fc49e6b70b2ba2c904

orb_slam_2_rosのLaunchファイルを作成する。 なぜかは分からないけど、コマンドラインからのRemapオプションが受け付けられないので。

今回は動かすだけなので、params_fileはデフォルトのparams_d435_mono.yamlを使用する。 オリジナルのTUM1.yamlを使用しても良い。

import os
from launch import LaunchDescription
from launch.actions import DeclareLaunchArgument
from launch.substitutions import LaunchConfiguration
from launch_ros.actions import Node
from ament_index_python.packages import get_package_share_directory


def generate_launch_description():

    use_sim_time = LaunchConfiguration('use_sim_time')
    params_file = LaunchConfiguration('params_file')
    voc_file = LaunchConfiguration('voc_file')

    remappings = [
        ('/camera/image_raw', '/camera/rgb/image_color'),
        ('/camera/camera_info', '/camera/rgb/camera_info'),
    ]

    return LaunchDescription([
        DeclareLaunchArgument(
            'use_sim_time',
            default_value='false',
            description='Use simulation (Gazebo) clock if true'),

        DeclareLaunchArgument(
            'params_file',
            default_value=os.path.join(
                get_package_share_directory("orb_slam2_ros"),
                'ros', 'config', 'params_d435_mono.yaml'),
            description='Full path to the ROS2 parameters file to use for all launched nodes'),

        DeclareLaunchArgument(
            'voc_file',
            default_value=os.path.join(
                get_package_share_directory("orb_slam2_ros"),
                'orb_slam2', 'Vocabulary', 'ORBvoc.txt'),
            description='Full path to vocabulary file to use'),

        Node(
            parameters=[
              params_file,
              {"voc_file": voc_file,
               "use_sim_time": use_sim_time},
            ],
            package='orb_slam2_ros',
            node_executable='orb_slam2_ros_mono',
            node_name='orb_slam2_mono',
            output='screen',
            remappings=remappings
        )
    ])

あとは依存関係正しく無いと思われるので、orb_slam_2_rosのpackage.xmlを修正する。
image_commonを足しておく。

cd <work-dir>
source /opt/ros/foxy/setup.sh
colcon build --symlink-install

ORB_SLAM2の動作確認

  • window1
source install/setup.sh
ros2 launch orb_slam2_ros TUM1_mono_launch.py
  • window2
source /opt/ros/foxy/setup.sh
rviz2

debug_imageと、point_cloudをAddする。


bagファイルをここから取得する。 テストにはrgbd_dataset_freiburg1_xyzを使用した。

  • window3
source /opt/ros/noetic/setup.sh
source /opt/ros/foxy/setup.sh
ros2 bag play -s rosbag_v2 rgbd_dataset_freiburg1_xyz.bag --read-ahead-queue-size 1000000

以下の通りの結果が得られた。


 

2020年12月9日水曜日

ultra96v2でVitis_AIを試してみた(2020.2)

ultra96v2でVitis_AIを試してみた話。

参考ページ

sdイメージの作成はここ

MNISTの実行はここ

日本語ならここ

環境

Ubuntu 20.04
Vitis 2020.2
Vivado 2020.2
Petalinux 2020.2

準備

ここに書いてあるplatformを準備する。 petalinuxのイメージは記事から変更している。(Vitis-AI関連とparted関連) vitis-ai-devパッケージは念の為入れといたけど動かす分には不要そう。(試して無いのでリポジトリはそのまま)

Platformの作成

VItis-AIにあるDPU-TRDをultra96v2向けに設定する。

cd <path-to-work-dir>
git clone https://github.com/Xilinx/Vitis-AI.git -b v1.2.1
cd DPU-TRD/prj/Vitis

そのままだと合成できなかったので以下3つのファイルを変更した。

  • DPU-TRD/prj/Vitis/Makefile そのままの設定だとultra96v2に乗らないので、Configを変更する。 また、pre-builtの環境を使用しないので指定できるように変更する。

hwhファイルのパスが変更となっているのか、取得できなかったので合わせて修正している。

-XOCC_OPTS = -t ${TARGET} --platform ${SDX_PLATFORM} --save-temps --config ${DIR_PRJ}/config_file/prj_config_102_3dpu_LPD --xp param:compiler.userPostSysLinkOverlayTcl=${DIR_PRJ}/syslink/strip_interconnects.tcl 
+XOCC_OPTS = -t ${TARGET} --platform ${SDX_PLATFORM} --save-temps --config ${DIR_PRJ}/config_file/prj_config --xp param:compiler.userPostSysLinkOverlayTcl=${DIR_PRJ}/syslink/strip_interconnects.tcl

-   v++ -t ${TARGET} --platform ${SDX_PLATFORM} -p binary_container_1/dpu.xclbin --package.out_dir binary_container_1 --package.rootfs $(EDGE_COMMON_SW)/rootfs.ext4 --package.sd_file $(EDGE_COMMON_SW)/Image 
-   cp ./binary_*/link/vivado/vpl/prj/prj.srcs/sources_1/bd/*/hw_handoff/*.hwh ./binary_*/sd_card
+   v++ -t ${TARGET} --platform ${SDX_PLATFORM} -p binary_container_1/dpu.xclbin --package.out_dir binary_container_1 --package.rootfs $(ROOTFS) --package.sd_file $(IMAGE)
+   cp ./binary_*/link/vivado/vpl/prj/*/sources_1/bd/*/hw_handoff/*.hwh ./binary_*/sd_card
  • DPU-TRD/prj/Vitis/config_file/prj_config DPUを1個に設定する。
-freqHz=300000000:DPUCZDX8G_2.aclk
-freqHz=600000000:DPUCZDX8G_2.ap_clk_2
+#freqHz=300000000:DPUCZDX8G_2.aclk
+#freqHz=600000000:DPUCZDX8G_2.ap_clk_2

-sp=DPUCZDX8G_2.M_AXI_GP0:HPC0
-sp=DPUCZDX8G_2.M_AXI_HP0:HP2
-sp=DPUCZDX8G_2.M_AXI_HP2:HP3
+#sp=DPUCZDX8G_2.M_AXI_GP0:HPC0
+#sp=DPUCZDX8G_2.M_AXI_HP0:HP2
+#sp=DPUCZDX8G_2.M_AXI_HP2:HP3

-nk=DPUCZDX8G:2
+nk=DPUCZDX8G:1
  • DPU-TRD/prj/Vitis/dpu_conf.vh b/DPU-TRD/prj/Vitis/dpu_conf.vh DPUの型式を変更する。
-`define B4096 
+`define B512

修正したらmakeする。

source <vitis_install_path>/2020.2/settings.sh
make KERNEL=DPU_SM DEVICE=ultra96v2 SDX_PLATFORM=<path-to-platform>/ultra96v2-platform.xpfm ROOTFS=<path-to-rootfs>/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.ext4 IMAGE=<path-to-image>/Image

ビルドが終了したらsdカードを作成する。

dd if=binary_container_1/sd_card.img of=/dev/sdX

MNIST実行ファイルの作成

Vitis-AI-Tutorialを利用する。 dockerのsetupは必要。 理由は不明だが、vitis-ai-cpu:latestはdletがうまく動作しなかったので、 xilinx/vitis-ai:latestを使用。2020.2を使用しているからか?

cd <path-to-work-dir>
git clone https://github.com/Xilinx/Vitis-AI-Tutorials.git -b MNIST=Classification-TensorFlow
    cd Vitis-AI-Tutorials/files
cp <path-to-work-dir>/Vitis-AI/DPU-TRD/prj/Vitis/binary_container_1/sd_card/ultra96v2_4z.hwh .
wget https://www.fpga.co.jp/u96v2_vitisai_2020.1/u96v2.json
./docker_run xilinx/vitis-ai:latest

vitis-aiが起動したらTutorialに従い以下の通り実行する。 6_compileと7_make_targetはultra96v2向けに変更が必要。

source 0_setenv.sh
dlet -f ultra96v2_4z.hwh
export COMPILE_u96v2=${BUILD}/compile_u96v2
export TARGET_u96v2=${BUILD}/target_u96v2
source 1_train.sh
source 2_freeze.sh
source 3_eval_frozen_graph.sh
source 4_quant.sh
source 5_eval_quant_graph.sh

#source 6_compile_u96v2.sh
rm -rf ${COMPILE_u96v2}
mkdir -p ${COMPILE_u96v2}
vai_c_tensorflow --frozen_pb  ${QUANT}/deploy_model.pb --arch ./u96v2.json --output_dir ${COMPILE_u96v2} --net_name ${NET_NAME}

#source 7_make_target_u96v2.sh
# remove previous results
rm -rf ${TARGET_u96v2}
mkdir -p ${TARGET_u96v2}/model_dir

# copy application to target folder
cp ${APP}/*.py ${TARGET_u96v2}
echo "  Copied application to target folder"

# copy elf to target folder
cp ${COMPILE_u96v2}/*.elf ${TARGET_u96v2}/model_dir/.
echo "  Copied elf file(s) to target folder"

# create image files and copy to target folder
mkdir -p ${TARGET_u96v2}/images

python generate_images.py  \
    --dataset=mnist \
    --image_dir=${TARGET_u96v2}/images \
    --image_format=jpg \
    --max_images=10000

ultra96v2の電源を投入し、ログインしてSDのパーティションを広げる。 wifiを有効にしているので、wifi経由でアクセスする場合にはネットワーク接続したあと以下の通り実行する。

ssh 192.168.2.1 -l root
parted
resizepart
2
Yes
100%
quit
resize2fs /dev/mmcblk0p2

このあと、ホストから必要なファイルを転送してチュートリアルを実行する。

cd <path-to-work-dir>/Vitis-AI-Tutorials/files
tar cvfz target_u96v2.tar.gz build/target_u96v2
scp target_u96v2.tar.gz root@192.168.2.1:~/

ターゲット側で以下の通り実行して動作確認する。 2スレッド実行時は-t 2を指定する。

tar xzvf target_u96v2.tar.gz
cd build/target_u96v2
python3 app_mt.py -m model_dir/dpu_customcnn.elf

実行結果

root@ultra96v2-zynqmp:~/build/target_u96v2# python3 app_mt.py -m model_dir/dpu_customcnn.elf 
Command line options:
 --image_dir :  images
 --threads   :  1
 --model     :  model_dir/dpu_customcnn.elf
Pre-processing 10000 images...
Starting 1 threads...
FPS=2679.56, total frames = 10000 , time=3.7320 seconds
Correct: 980 Wrong: 9020 Accuracy: 0.098

root@ultra96v2-zynqmp:~/build/target_u96v2# python3 app_mt.py -m model_dir/dpu_customcnn.elf -t 2
Command line options:
 --image_dir :  images
 --threads   :  2
 --model     :  model_dir/dpu_customcnn.elf
Pre-processing 10000 images...
Starting 2 threads...
FPS=3346.35, total frames = 10000 , time=2.9883 seconds
Correct: 980 Wrong: 9020 Accuracy: 0.098

2020年12月4日金曜日

ultra96v2のembedded acceleration platformをvitis2020.2で作成してみた話その2

ultra96v2のembedded platformをvitis 2020.2で作成した話。 VitisのVecaddを動かすまで。 前回の続き。

準備

vitisで使用するlinux_bifとqemu_args.txtとpmu_args.txtを準備する。

cd <work-dir-path>
mkdir vitis_args

vitis_argsにlinux.bifとqemu_args.txtとpmu_args.txtを保存する。内容は以下の通り。

  • linux.bif
/* linux */
the_ROM_image:
{
    [fsbl_config] a53_x64
    [bootloader] <fsbl-ultra96v2-zynqmp.elf>
    [destination_device=pl] <bitstream>
    [pmufw_image] <pmu-firmware-ultra96v2-zynqmp.elf>
    [destination_cpu=a53-0, exception_level=el-3, trustzone] <arm-trusted-firmware.elf>
    [load=0x100000] <system.dtb>
    [destination_cpu=a53-0, exception_level=el-2] <u-boot.elf>
}
  • qemu_args.txt
    system.dtbは2020.1からBOOT.binで書き込むようにしている模様。
    ##work-dir-path##は環境に合わせて置き換えてください。
-M arm-generic-fdt
-net nic -net nic -net nic
-serial /dev/null -serial mon:stdio
-display none
-device loader,file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/arm-trusted-firmware.elf,cpu-num=0
-device loader,file=<u-boot.elf>
-device loader,file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/system.dtb,addr=0x100000
-drive file=##work-dir-path##/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.wic.qemu-sd,if=sd,id=sd0,format=raw,index=0
-boot mode=3
-global xlnx,zynqmp-boot.cpu-num=0
-global xlnx,zynqmp-boot.use-pmufw=true
-m 4G
  • pmu_args.txt
    ##work-dir-path##は環境に合わせて置き換えてください。
-M microblaze-fdt
-serial /dev/null -serial /dev/null
-display none
-device loader,file=##work-dir-path##/build/tmp/deploy/images/ultra96v2-zynqmp/pmu-ultra96v2-zynqmp.elf
-device loader,addr=0xfd1a0074,data=0x1011003,data-len=4
-device loader,addr=0xfd1a007C,data=0x1010f03,data-len=4

Platformの作成

ここを参考にplatformを作成していく。 日本語ならこちら

export LIBRARY_PATH=/usr/lib/x86_64-linux-gnu
source <path-to-vitis-installation>/2020.2/settings64.sh
cd <work-dir-path>
mkdir vitis_pfm
cd vitis_pfm
mkdir wksp1
vitis -workspace wksp1

create platformを行い、platform名はultra96v2-platform、xsaは/xsa_dir/ultra96v2_4z/ultra96v2_4z.xsaを指定する。

linux domainの設定を以下のように行う。

Bif File: <work-dir-path>/vitis_args/linux.bif
Boot Components Directory:<work-dir-path>/boot
Linux Image Directory:<work-dir-path>/boot
Linux Rootfs:<work-dir-path>/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp/petalinux-image-minimal-ultra96v2ros2-ultra96v2-zynqmp.ext4
Bootmode:SD
Sysroot Directory:<work-dir-path>/sdk/sysroots/aarch64-xilinx-linux
QEMU Data:<work-dir-path>/petalinux/build/tmp/deploy/images/ultra96v2-zynqmp
QEMU Arguments:<work-dir-path>/vitis_args/qemu_args.txt
PMU QEMU Arguments:<work-dir-path>vitis_args/pmu_args.txt

platformをbuildする。Application projectを作成するところまでは同じだが、その後のUIが少し変わっている。


 

vecadd_systemを開いてActive Build Configurationを変更してAssistant上でBuildする。

また、最初にリソースファイルを作成するようになったためか、buildボタンを押してしばらく反応が無かったりする。ビルドが始まるまで気長に待つ必要があった。 ビルドの際にkernelとhw_linkとhostプログラムを分けてビルドしてくれるようになったり、変更後のビルドで影響ある部分だけビルドしてくれたりと少し賢くなったけど、初動は遅くなったイメージを持った。

Platformのテスト

ここを参考にplatformのテストを行う。 日本語ならこちら

application project nameはvecaddとした。 途中、Kernel Imageが空欄となっているので、/boot/Imageを指定しておく。

Emulation-SW

まずはvecadd_systemを開いてActive Build ConfigurationをEmulation-SWに変更してBuildする。 Launch on Emulatorを試す。 RunかDebugのボタンを押し、Launch SW Emulatorを選択する。 Application Timelineはデフォルトで有効になっていないので、有効にする場合はRun ConfigurationsからXilinx Runtime ProfilingのConfigurationをEditして、OpenCL detailed profile summary and timeline traceを選択する。


 
 

結果は以前と変化ないので省略。

また、2020.2ではEmulation-SWのLaunch on Hardwareに相当する操作はできなくなっていた。 アクセラレーション前の実行時間を計測するのに便利そうと思っていたのに。 直接動かしたり、コマンドラインからのデバッグ実行ならばいけるかもしれないので、後で試す。 (または、Emulatorが起動したとしてもTCFの接続先を実機にしておけば目的は達成されるかも)

Emulation-HW

vecadd_systemを開いてActive Build ConfigurationをEmulation-HWに変更してBuildする。 Launch Emulator in GUI modeを選択するとvivado simulatorが立ち上がるのが見える。


 

GUI modeの場合は手動で実行されるまでQEMUは実行を待機している模様。必要な信号線をaddした後にrun allすることを想定しているのかな。


 

今回Emulation-HWの動作が期待通りとなることを確認したけど、v2020.1でEmulation-HW(Launch on Hardware)は何をやっていたことになるのか謎。 Timelineあったけど、普通にHardwareの動作していただけ?

Hardware

vecadd_systemを開いてActive Build ConfigurationをHardwareに変更してBuildする。 SDの準備はv2020.1と同じ。sd_card.imgをddすれば良い。

また、これもv2020.1の時と同じであるが、Lunch Target Connectionで実機に接続できるように設定を行う。Emulation-SWのLaunch Target Connectionを参照。

実行結果はTEST PASSEDが出るだけで特別言うことも無いので省略。

Vitis Analyzer 

それぞれの実行結果を記載する。
Emulation-HWの結果がエラい長いけどこんな感じでいいのか?

Emulation-SW



 

Emulation-HW

 


Hardware