コンテンツにスキップ

チュートリアル用メディアの撮影手順

docs/images/ に置いているスクリーンショット・動画(GIF)を、toio_gazeboシミュレーションから撮り直す/追加する手順。すべてホストのX11ディスプレイ上でGazebo・RVizを動かし、画面を取り込む。以下のコマンドは docs/ ディレクトリで実行する前提で、出力先を images/ 相対で書いている。

前提ツール

sudo apt-get install -y ffmpeg imagemagick scrot xdotool wmctrl fonts-noto-cjk
  • ffmpeg … 画面録画(x11grab)とGIF変換
  • import(imagemagick)… ウィンドウ単位のスクリーンショット
  • xdotool / wmctrl … ウィンドウの前面化・座標取得
  • fonts-noto-cjk … 端末風PNG(05_bidding_log.png)の日本語描画

sim起動(録画対象)

source /opt/ros/jazzy/setup.bash
source ~/dev_ws/install/setup.bash
ros2 launch toio_rmf_bringup toio_rmf.launch.py mat:=a3 run_sim:=true use_sim_time:=true

RVizの表示がマット向けに正しく出るにはrmf_visualization のsmall-mapsパッチが必要(未適用だとfootprint/vicinityの巨大な円柱がnavグラフを覆う)。手順はdocs/SETUP.mdの「rmf_visualizationパッチ」を参照。

ウィンドウ単位のスクリーンショット

export DISPLAY=:1
# 対象ウィンドウIDを調べる(RViz / Gazebo Sim)
wmctrl -lG | grep -iE 'rviz|gazebo'
# 前面化して取り込む
WID=0xXXXXXXXX
xdotool windowactivate $WID; xdotool windowraise $WID; sleep 0.5
import -window $WID images/00_setup_rviz.png

画面録画 → GIF

ffmpeg のx11grabで対象ウィンドウの矩形を録画する。幅・高さは偶数にすること(libx264は奇数サイズを拒否する。RViz既定1853x1025 → 1852x1024)。

# 位置とサイズ: xdotool getwindowgeometry <WID> で確認
ffmpeg -y -f x11grab -framerate 15 -video_size 1852x1024 -i :1.0+81,118 \
  -t 16 -pix_fmt yuv420p /tmp/clip.mp4
# mp4 -> GIF(パレット生成で発色を良く。横幅は 926 程度に縮小)
ffmpeg -y -i /tmp/clip.mp4 -vf "fps=10,scale=926:-2:flags=lanczos,palettegen" /tmp/pal.png
ffmpeg -y -i /tmp/clip.mp4 -i /tmp/pal.png \
  -lavfi "fps=10,scale=926:-2:flags=lanczos[x];[x][1:v]paletteuse" images/04_patrol.gif

動きを確実に写すには「タスク投入 → 数秒待って走り出してから録画開始」。タスク完了後に撮ると静止画になる(GIFがほとんど変化せず数KBほどのファイルになっていたら、これが原因)。

合成GIF(左RViz / 右Gazebo)

04_patrol.gif / 06_traffic.gif はRVizとGazeboを左右に並べた合成GIF。「スケジュール(RViz)」と「実際のキューブの動き(Gazebo)」を同時に見せるため。同一走行からRVizとGazeboの両ウィンドウを毎フレーム同時にグラブするので、左右のパネルはフレーム単位で同期する。ffmpeg が使えない環境向けに、Pythonだけで撮影・合成する手順も用意した。

pip install --user mss imageio python-xlib   # 画面グラブ / GIF / ウィンドウ操作

前提: RVizをマットスケールで綺麗に写すため、rmf_visualization のsmall-mapsパッチを適用しておく(docs/SETUP.md)。未適用だとfootprint/vicinityの巨大マーカーがnavグラフを覆う。

  1. simをGUI付きで起動(toio_rmf.launch.py を rmf_headless を付けずに実行 →Gazebo GUIとRMF可視化RVizが両方 :1 に出る)。実GPU付きのX(:1)ならヘッドレス寄りの環境でもGUIは描画される。
  2. 2つのウィンドウを重ならないように左右へ配置(python-xlib の _NET_MOVERESIZE_WINDOW / _NET_ACTIVE_WINDOW)。
  3. タスクを投入し、走り出すまで数秒(交通調停なら約5秒)待ってから録画を始める。毎フレームRVizとGazeboの両矩形を mss でグラブし、描画部分をcropして連番PNGのペアで保存する(10fps × 180フレーム=18秒)。traffic は片道で終わると後半が静止するので、2台を逆向きに周回(例: patrol_B patrol_C と patrol_C patrol_B)させて全編クロスし続ける画にする。
  4. RVizを左、Gazeboを右に置いて横並び合成し、ラベル(RViz2 / Gazebo)を焼き込む(Pillow)。両パネルは同じフレーム番号=同時刻なので同期する。
  5. GIF軽量化のコツ: 静止部の微小レンダノイズで色indexがブレるとフレーム間圧縮が効かず数MBに膨れる。ImageOps.posterize(5) でノイズを丸め、共有パレット・ディザ無効・disposal=1(前フレームに差分だけ上書き)で保存すると、180フレームでも1〜2MBに収まる。

RVizのカメラ(フィット/センタリング)

rviz/toio_rmf.rviz の Views > Current(TopDownOrtho)で決まる:

キー 値 意味
Scale 2200 px/m相当。大きいほど拡大。A3マットが画面に収まる値
X / Y 0.2 / -0.15 注視点(マット中央)

A4マットで撮るときは Scale を上げ気味に、X/Y をA4の中央へ合わせる。

既知の注意点

  • タスク開始直後にnavグラフ/床面図が一度消えることがある。navgraph visualizerが起動直後にDELETEALLを送り、RVizがそれを受けてクリアするため(publisher側のlatchデータは生きている)。撮影前にRVizを一度リロードしておくと、再購読でnavグラフが復活し、以後はタスク中も残って安定する。
  • Gazeboウィンドウはマップを見失わないので、「実行中の様子」を確実に撮るにはGazebo側が手堅い。

各メディアの撮り方(対応表)

ファイル 対象 撮り方
00_setup_gazebo.png Gazebo 起動直後、2台がチャージャー上の全景
00_setup_rviz.png RViz 同上のnavグラフ全景(idle)
03_go_to_place.gif RViz+Gazebo(合成) dispatch_go_to_place -p patrol_B -R toio1 で対角に移動する様子を左RViz/右Gazeboで同時グラブ(上記「合成GIF」参照)
04_patrol_rviz.png RViz patrol投入後、スケジュール経路帯が出た瞬間
04_patrol.gif RViz+Gazebo(合成) patrol走行を左RViz/右Gazeboで並べた合成GIF(上記「合成GIF」参照)
05_bidding_log.png 端末風PNG dispatch_patrol の -R有/無 の実出力を並べて描画(scripts外の生成物)
06_traffic_rviz.png RViz 2台に別タスクを投入、経路帯が交錯した瞬間
06_traffic.gif RViz+Gazebo(合成) 2台の交差を左RViz/右Gazeboで並べた合成GIF(上記「合成GIF」参照)
07_battery_charge.gif RViz+Gazebo(合成) publish_battery:=true(放電を速めた例)でpatrol → 残量低下 → チャージャーで充電 → 復帰。左RViz/右Gazeboを同時グラブし、左下にtoio1の残量バー(/fleet_states の battery_percent)を焼き込む(上記「合成GIF」参照)
08_delivery.gif RViz+Gazebo(合成) deliveryを投入し、pickup→dropoffの移動と各地点の保持を左RViz/右Gazeboで同時グラブ(上記「合成GIF」参照)
09_fleet_action.gif RViz+Gazebo(合成) dispatch_action を複数投入し、pickup(緑)/dropoff(青)のLED点灯と移動を左RViz/右Gazeboで同時グラブ(上記「合成GIF」参照)
10_footprint_vicinity.png RViz ScheduleMarkers の participant location 0/1 を表示に切り替え、稼働中の円が出た状態
10_dashboard_robots.png ブラウザ rmf-webのRobotsタブ。別途コンテナ起動が要る(docs/DASHBOARD.md)

07_battery_charge.gif は残量バーを焼き込むため、フレームごとに /fleet_states の battery_percent を記録しながら両ウィンドウをグラブし、合成時にバー(緑/黄/赤 + CHARGING 表示)を描く。放電が速すぎると0%まで落ちてから充電に入るので、battery_discharge_rate は0%に達する前に帰還・充電が見える程度(例0.03)に抑える。残量の既定は10%刻みなので、滑らかなバーにするには battery_quantize_steps:=0 を付ける。

図版(SVG)の原本

images/navgraph_a3.svg / navgraph_a4.svg / initial_placement_a4.svg は撮影物ではなく手描きのSVGで、原本はtoio_rmf_bringupのdocs/images/にある(bringup側のREADME・SETUP.md・TASKS.mdからも参照されるため)。変更するときはbringup側を更新し、このリポジトリへコピーして同期する。