2025.09.30
Jetson × RealSense で物体検知: ROS 2 / DeepStream の導入
はじめに
こんにちは。グループ研究開発本部、AI研究開発室のY.Tです。
エッジGPU、良い響きですね。
この記事は、Jetson への DeepStream 7.1 を導入と、Intel RealSense の接続方法について備忘録的にまとめたものです。とりあえず何か画面に見えるまで1からやるとそれなりに手間がかかったので、一旦まとめておこうという書いています。
今回の目的
- 前提: Jetson (Orin Nano Super, JetPack 6.x 相当)・RealSense D435i・ROS 2 Humble
- 今回の目的: RealSense RGB →
deepstream-app
→ 人/車/標識/二輪の4クラス検出 → 画面表示
環境
- JetPack 6.x (Ubuntu 22.04 aarch64)
- DeepStream 7.1 (Jetson 版)
- Intel RealSense D435i
- ROS 2 Humble
1) 前提のインストール
ROS 2 Humble
こちらを参考にインストールします。
ROS 2 Documentation: Humble Installation Ubuntu (deb packages)
自分の手順は以下のような形です。
sudo apt install -y locales software-properties-common curl sudo locale-gen en_US en_US.UTF-8 && sudo update-locale LC_ALL=en_US.UTF-8 LANG=en_US.UTF-8 source /etc/default/locale || true # ROS 2 APTソース指定 export ROS_APT_SOURCE_VERSION=$(curl -s https://api.github.com/repos/ros-infrastructure/ros-apt-source/releases/latest | grep -F "tag_name" | awk -F\" '{print $4}') curl -L -o /tmp/ros2-apt-source.deb "https://github.com/ros-infrastructure/ros-apt-source/releases/download/${ROS_APT_SOURCE_VERSION}/ros2-apt-source_${ROS_APT_SOURCE_VERSION}.$(. /etc/os-release && echo $VERSION_CODENAME)_all.deb" sudo dpkg -i /tmp/ros2-apt-source.deb sudo apt update sudo apt install -y ros-humble-desktop python3-rosdep source /opt/ros/humble/setup.bash # ワークスペースを作成しておく mkdir -p ~/ros2_ws/src cd ~/ros2_ws rosdep init || true rosdep update
DeepStream 7.1
SDK Manager で導入済みなら本章はスキップ可。 ここでは アーカイブ版(tbz2) の手動導入を記載します。
# パッケージを展開(例:Downloads に置いた tbz2 を /opt へ) sudo mkdir -p /opt/nvidia/deepstream cd ~/Downloads sudo tar -xvf deepstream_sdk_v7.1.0_jetson.tbz2 -C /opt/nvidia/deepstream/ # インストーラ実行 cd /opt/nvidia/deepstream/deepstream-7.1 sudo ./install.sh sudo ldconfig # 環境変数を設定しておく echo 'export GST_PLUGIN_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib/gst-plugins:$GST_PLUGIN_PATH' | sudo tee -a /etc/environment echo 'export LD_LIBRARY_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib:$LD_LIBRARY_PATH' | sudo tee -a /etc/environment source /etc/environment export GST_PLUGIN_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib/gst-plugins:$GST_PLUGIN_PATH export LD_LIBRARY_PATH=/opt/nvidia/deepstream/deepstream-7.1/lib:$LD_LIBRARY_PATH
2) RealSense(librealsense)
realsense-viewerを使えるようにしておく。ターミナルからrealsense-viewerを叩くとGUIが起動し、GUIを操作することでリアルタイムにカメラの映像が流れるようになる。今回は使わないがDepthも出せる。
sudo apt update && sudo apt install -y git cmake build-essential libssl-dev \ libusb-1.0-0-dev pkg-config libgtk-3-dev libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev udev git clone --depth=1 https://github.com/IntelRealSense/librealsense.git cd librealsense && mkdir build && cd build cmake .. -DFORCE_RSUSB_BACKEND=ON -DBUILD_WITH_CUDA=ON -DBUILD_EXAMPLES=OFF -DCMAKE_BUILD_TYPE=Release make -j$(nproc) sudo make install sudo cp ../config/99-realsense-libusb.rules /etc/udev/rules.d/ sudo udevadm control --reload-rules && sudo udevadm trigger realsense-viewer # GUIが起動する。RGB が映ればOK
3)DeepStreamのサンプル実行
サンプルconfigをユーザ領域へ複製して編集すると扱いやすい。(設定ファイル内のファイルの参照は相対パスなのでそこは注意。)今回はsource2_1080p_dec_infer-resnet_demux_int8.txtというファイル名のconfigで動かす。サンプル動画もパッケージに含まれている。
mkdir -p ~/ds_cfg cd /opt/nvidia/deepstream/deepstream-7.1/samples/configs/deepstream-app cp source2_1080p_dec_infer-resnet_demux_int8.txt ~/ds_cfg/ cp -a ../../models/Primary_Detector ~/ds_cfg/ # 参照しやすい場所に置く(任意) # 表示を有効化(sink0=EGL)と mux バッチを 2 に統一、URI を絶対化 APP=~/ds_cfg/source2_1080p_dec_infer-resnet_demux_int8.txt xhost +local: 2>/dev/null || true export DISPLAY=${DISPLAY:-:0} sed -i '/^\[sink0\]/,/^\[/{s/^type=.*/type=2/; s/^enable=.*/enable=1/; s/^sync=.*/sync=0/}' "$APP" sed -i '/^\[sink1\]/,/^\[/{s/^enable=.*/enable=0/}' "$APP" sed -i '/^\[sink2\]/,/^\[/{s/^enable=.*/enable=0/}' "$APP" sed -i '/^\[streammux\]/,/^\[/{s/^batch-size=.*/batch-size=2/}' "$APP" sed -i 's#uri=file://\./\./streams/#uri=file:///opt/nvidia/deepstream/deepstream-7.1/samples/streams/#g' "$APP"
3-1) TensorRT エンジン作成
アプリケーションの初回実行時に作成されてキャッシュに保存され、次回以降はキャッシュを参照して高速に起動する。。。はずではあるが、うまくキャッシュを保存できない、読めない、という状況なら明示的に作ってしまうのが早いです。
mkdir -p ~/.cache/ds_engines /usr/src/tensorrt/bin/trtexec \ --onnx=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx \ --int8 --calib=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/cal_trt.bin \ --minShapes='input_1:0':1x3x544x960 --optShapes='input_1:0':2x3x544x960 --maxShapes='input_1:0':2x3x544x960 \ --memPoolSize=workspace:2048M \ --saveEngine=$HOME/.cache/ds_engines/primary_b2_gpu0_int8.engine
3-2) P‑GIEのconfigを編集
~/ds_cfg/config_infer_primary.txt
を新規作成し、シンプルに必要な項目だけ書く。
[property] gpu-id=0 net-scale-factor=0.0039215697906911373 offsets=123.0;117.0;104.0 model-engine-file=%HOME%/.cache/ds_engines/primary_b2_gpu0_int8.engine onnx-file=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/resnet18_trafficcamnet_pruned.onnx labelfile-path=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/labels.txt int8-calib-file=/opt/nvidia/deepstream/deepstream-7.1/samples/models/Primary_Detector/cal_trt.bin network-mode=1 batch-size=2 custom-lib-path=/opt/nvidia/deepstream/deepstream-7.1/lib/libnvds_infercustomparser.so parse-bbox-func-name=NvDsInferParseCustomResnet output-blob-names=output_cov/Sigmoid;output_bbox/BiasAdd num-detected-classes=4 gie-unique-id=1 [class-attrs-all] pre-cluster-threshold=0.20 nms-iou-threshold=0.5 cluster-mode=2 topk=200
注意:model-engine-file
の参照はよく確認すること
sed -i 's#^model-engine-file=.*#model-engine-file='"$HOME"'/.cache/ds_engines/primary_b2_gpu0_int8.engine#' ~/ds_cfg/config_infer_primary.txt
アプリ側config($APP
)で P‑GIE をこのファイルに差し替える。
sed -i "s#^config-file=./dstest1_pgie_config.txt#config-file=$HOME/ds_cfg/config_infer_primary.txt#" "$APP"
3-3) 実行
engineファイルを作成済みなので高速に起動するはず。起動に数分以上かかるようならTensorRTエンジンを再作成しているはずで、cacheを参照できていない。単純にパスが違うケースもあるが、設定ファイルの記述の不整合の場合もある。以下に動画のように検知ボックスが出てこないケースでは、モデルが違うか、config_infer_primary.txtの閾値の問題の場合もあります。
/opt/nvidia/deepstream/deepstream-7.1/bin/deepstream-app -c "$APP"
4) ROS 2 でRealSenseを動かす(任意)
RealSense の ROS 2 ノードで軽量に RGB を配信しつつ可視化する例。自分は十分なFPSを得るためにROS2を導入しました。
ちなみに、GUIが起動したら、GUI上で見たいトピックを選択しないと画面は真っ黒です。そんな事で困る人はあまりいないかもしれませんが念の為(一敗)。
ROS_DISTRO=humble source /opt/ros/$ROS_DISTRO/setup.bash . ~/ros2_ws/install/setup.bash ros2 run realsense2_camera realsense2_camera_node --ros-args \ -p enable_color:=true -p enable_depth:=false -p enable_infra1:=false -p enable_infra2:=false \ -p enable_gyro:=false -p enable_accel:=false \ -p rgb_camera.color_profile:="424x240x15" \ -p rgb_camera.frames_queue_size:=2 -p color_qos:=SENSOR_DATA -p initial_reset:=true # 可視化(GUIが起動。) ros2 run rqt_image_view rqt_image_view
5) 今回のハマりどころ
DeepStream が「動いてるっぽいのに出ない」とき、結局よくハマるのはこのあたりです。参考になれば。
エンジン(.engine)の置き場所
思ったファイルを参照できていないのはよくやらかしますね。例えば、既定で /opt/...
に吐こうとして 書き込めない パターンなど、、、
ユーザ領域のわかりやすいところに自分でディレクトリを作ってちゃんと設定するのが安定ですね。(例:~/.cache/ds_engines/primary_b2_gpu0_int8.engine
)。何参照してるかわからないならば、いったん消して作り直すのが手っ取り早いです。
TensorRT の世代が合ってない
別環境から持ち込んだ .engine をそのまま使ったときに起きがちですね。TensorRT のバージョン違いでロード直後に落ちたり、推論が始まらないなど。
解決策はシンプル、現環境で再生成です。再ビルドしてコーヒーでも飲んでいましょう。
batch が噛み合ってない
streammux
のbatch-size
と P-GIE のbatch-size
が同じか確認。- エンジンは他のbatch設定で使えないので、値を変えたらエンジンも作り直し。
パーサと出力名がモデルに合ってない
推論は回ってるのに検出ゼロ、のケースでよくあリマス。
parse-bbox-func-name=NvDsInferParseCustomResnet output-blob-names=output_cov/Sigmoid;output_bbox/BiasAdd
ResNet10(dstest1 系)は上記で確認。BatchedNMS/TLT 系を混ぜると出力数が合わなくて沈黙します。
実は OSD / sink で消してる
ログでは検出カウントが増えてるのに画面は無、という時はこの辺りを疑いましょう。
[osd]
がenable=1 display-bbox=1 display-text=1
になってる?[sink0]
がnveglglessink
など表示系になってる?(fakesink
は見えません)
閾値が高すぎる
一時的に思い切って下げて実行してみるとわかります。暗い/小さい被写体は特に注意
sed -i 's/^pre-cluster-threshold=.*/pre-cluster-threshold=0.15/' ~/ds_cfg/config_infer_primary.txt
まとめ
以上、とりあえず環境構築でした。次はカメラ映像での検知モデル実行の予定です。
宣伝
グループ研究開発本部 AI研究開発室では、データサイエンティスト/機械学習エンジニアを募集しています。ビッグデータの解析業務などAI研究開発室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。皆さんのご応募をお待ちしています。
グループ研究開発本部の最新情報をTwitterで配信中です。ぜひフォローください。
Follow @GMO_RD