1. はじめに / この記事のゴール
本記事は、「Pika+G1でピッキング」シリーズの第2回です。
本シリーズでは、Unitree G1にAgileX RoboticsのPika Gripperを搭載し、スポンジのピッキングに取り組んでいます。
このデモを実現するために、ハードウェアのセットアップ、人手によるデータ収集、モデルの学習、G1へのデプロイ、スポンジのピッキングという一連のパイプラインを構築し、タスクの学習を進めてきました。
第1回では、Pika+G1でピッキング(ハード編)として、Pikaの構成、Pika SenseとPika Stationのセットアップ、Pika GripperをG1へ接続する方法を紹介しました。
本記事では、次の内容を扱います。
- ROS NoeticとDockerを用いたソフトウェア環境の構築
- Pika SenseとPika Stationのキャリブレーション
- フットペダルを用いたデータ保存トリガーの準備
- スポンジ仕分けタスクの手順とデータ収集ルールの定義
- ARマーカーを基準とした座標系の共有
- 収集データの保存形式とデータ規模
全体ワークフロー
スポンジのピッキングに至るまでの全体像は次のとおりです。本記事は、(1)データ収集のパートにあたります。
(0)ハードウェアの準備
Pika Stationの設置 / Pika Senseの接続 / Pika GripperのG1への接続
│
▼
(1)データ収集 ← 本記事
人がPika Senseを操作してスポンジの仕分けを実演し、
カメラ画像 / 深度画像 / グリッパー情報 / 6D姿勢を記録します。
│
▼
(2)モデル学習
収集データを学習モデル用の形式に変換し、モデルを学習します。
│
▼
(3)G1へのデプロイ
学習済みモデルをG1の実行環境へ組み込みます。
│
▼
(4)スポンジのピッキング
G1とPika Gripperを用いてスポンジを仕分けます。
2. ソフトウェア環境構築
まずは、Pikaからデータを受信するためのソフトウェア環境構築を行います。Pikaでは、ROS接続用のコードとSDKがオープンソースとして公開されています。手順書もそろっています。であれば、書かれた順に並べていけば動くはずです。しかし、実際に手を動かしてみると時間を取られたのは手順そのものではなく、その周りの依存関係でした。
2-1. ROS環境の構築
Pika SenseはROSを用いることで容易に通信を行うことが可能です。公式手順に従って環境を構築します。環境はROS Noeticになります。
2-2. 関連ソフトウェアの準備
ROS環境を構築したら、次に依存する他のソフトウェアをインストールします。
必要な作業は3つです。
- pika_rosリポジトリの取得
- サブモジュールの初期化
- 依存パッケージのインストール
次のコマンドで、まとめて実行します。
git clone https://github.com/agilexrobotics/pika_ros.git
cd pika_ros
git submodule update --init --recursive
sudo apt-get update && sudo apt install libjsoncpp-dev ros-noetic-ddynamic-reconfigure libpcap-dev ros-noetic-serial ros-noetic-ros-numpy ros-noetic-librealsense2 python3-pcl libqt5serialport5-dev build-essential zlib1g-dev libx11-dev libusb-1.0-0-dev freeglut3-dev liblapacke-dev libopenblas-dev libatlas-base-dev cmake git libssl-dev pkg-config libgtk-3-dev libglfw3-dev libgl1-mesa-dev libglu1-mesa-dev g++ python3-pip libopenvr-dev
もう1つ、ar_track_alvarを導入します。これはARマーカーのトラッキングに使うパッケージで、後段の学習で利用する座標を検出するために必要になります。
本記事ではDockerで環境を構築しており、次に示すDockerfile内でリポジトリを取得しています。
2-2-1. Docker化
ローカル環境へ直接変更を加えずに済み、同じ環境をあとから作り直せる。この2点を理由に、Docker上へ環境を構築しました。使用したDockerfileは次のとおりです。
# syntax=docker/dockerfile:1.4
FROM osrf/ros:noetic-desktop-full
SHELL ["/bin/bash", "-c"]
ENV PIKA_WS=/home/agilex/pika_ros PIKA_SDK=/home/agilex/pika_sdk \
DEBIAN_FRONTEND=noninteractive QT_X11_NO_MITSHM=1 \
LD_LIBRARY_PATH=/usr/local/lib:${LD_LIBRARY_PATH}
# ビルド・USB/カメラ・ROS 関連の依存(実際は約 40 パッケージ)
RUN apt-get update && apt-get install -y --no-install-recommends \
build-essential cmake git git-lfs unzip libusb-1.0-0-dev libgtk-3-dev \
libopenvr-dev python3-pip ros-noetic-cv-bridge ros-noetic-pcl-ros ... \
&& rm -rf /var/lib/apt/lists/*
# ROS 同梱版と衝突するため PyYAML は明示的に入れ直す
RUN pip3 install --no-cache-dir --ignore-installed "PyYAML>=5.4.1,<7" \
&& pip3 install --no-cache-dir opencv-python h5py scipy pyzmq "open3d==0.18.0"
# pika_ros 本体(同梱ソース類は Git LFS 管理)
RUN git clone --depth 1 https://github.com/agilexrobotics/pika_ros.git "${PIKA_WS}" \
&& cd "${PIKA_WS}" && git submodule update --init --recursive \
&& git lfs install --local && git lfs pull
# librealsense はソースビルド。2.50 を要求するバイナリ向けに互換リンクを張る
WORKDIR ${PIKA_WS}/source
RUN unzip -q librealsense-2.55.1.zip && tar -xzf curl-7.75.0.tar.gz \
&& cd librealsense-* && bash install.bash \
&& ln -sf /usr/local/lib/librealsense2.so.2.55 /usr/local/lib/librealsense2.so.2.50 \
&& ldconfig
# SDK は editable インストールで入れる
RUN git clone --depth 1 https://github.com/agilexrobotics/pika_sdk.git "${PIKA_SDK}" \
&& pip3 install --no-cache-dir -r "${PIKA_SDK}/requirements.txt" \
&& pip3 install --no-cache-dir --no-deps -e "${PIKA_SDK}"
# 配布済みビルド成果物を展開し、Vive トラッカー用 udev ルールを配置
RUN unzip -q -o "${PIKA_WS}/sourcecha/install.zip" -d "${PIKA_WS}" \
&& cp "${PIKA_WS}/scripts/81-vive.rules" /etc/udev/rules.d/ && mkdir -p /bags
# 自作ノードと RealSense / AR マーカー系は overlay ワークスペースでビルド
COPY src/ /tmp/src/
RUN source /opt/ros/noetic/setup.bash && source "${PIKA_WS}/install/setup.bash" \
&& catkin_make install -DCMAKE_BUILD_TYPE=Release # 実体は symlink で src を構成
ENTRYPOINT ["/ros_entrypoint.sh"] # ROS → pika_ros → overlay を順に source
CMD ["pika_with_rosbag.sh", "single"]
2-3. デバイスの登録
Pika Senseは両手で2台使用するためには、シリアル番号とカメラ番号を確認して記録し、実行用コードへ左右それぞれの対象デバイスを設定する必要があります。接続後のデバイス番号も、あわせて確認し、左右の対応関係が入れ替わることを防ぎます。
3. タスク環境のセットアップ
3-1. Pika Senseのキャリブレーション
Pika Senseの位置と姿勢は、Pika Stationを基準として計測します。つまり、記録される値はすべて、Stationの置き方に紐づきます。
置き方には条件があります。Pika Stationを床面から2m以上の高さに設置し、作業領域を見下ろせるように俯角を25〜35度程度に設定すると精度良く検出が行えます。本環境では、俯角30度を目安としました。
2台のPika Stationは、作業領域を中心として約90度の角度をつけて配置します。片方から見えなくなっても、もう一方が捉えていれば追跡は続きます。異なる方向から作業領域を捉えることで、オクルージョンの影響を抑え、Pika Senseを追跡しやすくなります。

配置が決まったら、キャリブレーションを実行します。
cd "$HOME/pika_ros/install/lib"
./survive-cli --force-calibrate
コマンドを実行すると、最初に2台のPika Stationとの通信が確認され、その後、Pika Senseのトラッキング確認が始まります。Pika Senseをゆっくり動かし、実際の作業領域で想定される動きを繰り返してデータを収集します。対応するポイントが1つ作成されたことを確認したら、Ctrl+Cでキャリブレーションを終了できます。
3-2. データ取得の準備
次にデータを取得し、保存を行うためのトリガーを準備します。
pika_rosには、すでに保存のための仕組みが用意されていて、Pika Senseを素早く2回開閉すると、保存トリガーが起動します。手だけで完結するので、準備は少ないですが、手先の開閉の記録が残ってしまいます。本来のタスクとは関係のない手の動きが、データに混ざるのはできる限り避けたいです。
そこで今回は、フットペダルに保存用のキーを割り当て、足でペダルを踏むことでデータを保存する構成にしました。これにより、手は静止したままタスクに必要な動作のみを収集できました。

4. データ取得
今回は、黄色と青色の2種類のスポンジを、それぞれ対応する色の箱へ片付ける仕分けタスクをヒューマノイドに実行させるためデータを収集しました。
4-1. タスクの明確化
手順を決めず、自由に動かして集めたほうが多様なデータになりますが、動作のバリエーションが必要以上に増え、学習に必要なデータ量と収集時間も増えてしまいます。
今回はデモタスクであることを踏まえ、タスクを実行する順序とルールを明確に定義しました。タスクの初期条件は
- 黄色と青色のスポンジが2つ置かれている場合
- 黄色のスポンジが1つ置かれている場合
- 青色のスポンジが1つ置かれている場合
の3種類の条件を用意しました。
黄色と青色のスポンジが2つ置かれている場合
手順
- 正面を向いた初期姿勢から、両手を物体の観測姿勢へ遷移。
- 左手で黄色のスポンジを把持し、左手を初期姿勢へ遷移。
- 右手で青色のスポンジを把持し、右手を初期姿勢へ遷移。
- 左手で黄色のスポンジを黄色の箱へ入れ、左手を初期姿勢へ遷移。
- 右手で青色のスポンジを青色の箱へ入れ、右手を初期姿勢へ遷移。
スポンジが1つ置かれている場合
- 正面を向いた初期姿勢から、スポンジの色に対応する手を物体の観測姿勢へ遷移。黄色には左手を、青色には右手を使用。
- 対応する手でスポンジを把持し、初期姿勢へ遷移。
- 対応する手でスポンジを同じ色の箱へ入れ、初期姿勢へ遷移。
また、すべてのデータ収集を次のルールに従って実施します。
- データ取得の開始時は、作業領域内の同じ位置と姿勢から始める。
- 各手順は、1秒ごとの同じテンポで実行する。
- グリッパーの開閉状態は、完全に開いた状態または完全に閉じた状態の2通りになるように意識する。
同じ動作が毎回同じ形で記録されるようにするためのルールになります。
4-2. マーカーによる座標の共有
Pika Senseによって取得される座標はPika Stationを基準とした座標軸で出力されます。そのため、Stationが動けば、軸も一緒に動いてしまい、収集データの座標値に一貫性がなくなる可能性があります。
そこで、データ取得前に卓上へ設置したARマーカーの座標を取得し、マーカー座標系を基準として動作軌道を扱います。基準が卓上に移れば、Stationがどこにあっても、軌道の値は同じ意味を保ちます。
利点は、今回のデータの中だけにとどまりません。マーカー座標系を共通の基準にすることで、収集データを別のロボットへ転移する場合も、Pikaとロボットの間で共通の座標軸を利用でき、座標変換を計算しやすくなります。

4-3. 収集データの形式
収集したデータは以下の形式で保存されます。
episodeN/
├── instructions.json # タスク指示文(例: "Pick up the cube, put in the bowl, and serve.")
├── statistic.txt # 各トピックのフレーム数・周波数(Hz)の統計、収録時間14.004秒
├── camera/
│ ├── color/
│ │ ├── pikaDepthCamera_l/ <timestamp>.jpg + config.json(camera parameter)
│ │ ├── pikaDepthCamera_r/ <timestamp>.jpg + config.json(camera parameter)
│ │ ├── pikaFisheyeCamera_l/ <timestamp>.jpg + config.json(camera parameter)
│ │ └── pikaFisheyeCamera_r/ <timestamp>.jpg + config.json(camera parameter)
│ ├── depth/
│ │ ├── pikaDepthCamera_l/ <timestamp>.png + config.json(camera parameter)
│ │ └── pikaDepthCamera_r/ <timestamp>.png + config.json(camera parameter)
├── gripper/
│ └── encoder/
│ ├── pika_l/ <timestamp>.json(motor angle & finger distance)
│ └── pika_r/ <timestamp>.json(motor angle & finger distance)
└── localization/
└── pose/
└── raw/
├── pika_l/ <timestamp>.json(6dpose xyz+rpy)
└── pika_r/ <timestamp>.json(6dpose xyz+rpy)
1エピソードの中に、タスク指示文、統計情報、カラー画像、深度画像、グリッパーのエンコーダ値、6D姿勢が並びます。学習に使うときは、これを各学習モデルのデータ形式に変換します。
4-4. 収集データ規模
最後にタスク学習のためのデータを収集します。
ここでは、1セット100エピソードとして6セット、合計600エピソードのデータを収集しました。セット内の内訳は、物体の配置位置を変えて成功した動作を60エピソード、物体を取り落としたがもう一度把持し直して復帰した動作を40エピソード取得しました。
成功した動作だけを集めたほうが、きれいに学習できそうに見えますが、失敗後の復帰動作を学習しなければ、何らかの要因で失敗した時に復帰できなくなってしまいます。
また、セットごとに背景を固定化しませんでした。デモ実行環境がデータ取得環境と異なることが確定していたため、学習において背景情報に依存させないために、家具配置、データ取得場所、照明条件を変更し6セット、合計600エピソードのデータを学習のために取得しました。
5. まとめ
本記事ではパイプラインの(1)データ収集をまとめました。
DockerベースのROS環境構築、Pika Senseのキャリブレーション、タスク手順の定義、ARマーカーによる座標系の共有を経て、スポンジ仕分けタスクの実演データを合計600エピソード収集しました。
次回以降は、今回収集したデータでのモデル学習、G1へのデプロイ、そしてスポンジピッキングの実行まで、パイプラインの続きを順に書いていく予定です。
6. 採用についてお知らせ
GMOインターネットグループ株式会社 グループ研究開発本部 AI研究開発室では,フィジカルAI・ロボティクスのリサーチエンジニア・リサーチサイエンティストを募集しています。ヒューマノイドの全身制御やその他の要素技術,社会実装にご興味を持って頂ける方がいらっしゃいましたら、ぜひ募集職種一覧からご応募をお願いします。皆さんのご応募をお待ちしています。