Visual Servoing
ビジュアルサーボは、カメラ画像を使用してロボットの動きを制御し、目標に向けて視覚的な補正を継続的に行うフィードバック制御方式です。
ビジュアルサーボは、カメラ画像を使ってロボットの動きを継続的に調整し、目標の位置や視点に近づけるフィードバック制御技術です。ロボットは視覚特徴を観測し、目標構成との差を測定して、新しい画像が届くたびに動きを修正します。画像を解釈するコンピュータービジョンと、測定値を物理的な動作に変換するロボティクスをつなぐ技術です。ビジュアルサーボ制御も同義語です。J. HillとW. T. Parkは1979年に、移動カメラを用いたロボットのリアルタイム制御でこの用語を導入しました。
ビジュアルサーボの仕組み#
ビジュアルサーボシステムは、現在の観測結果を目標画像または相対姿勢と比較します。特徴抽出によって、キーポイント、線の位置、物体の輪郭などの測定値を取得します。コントローラーは、その誤差を動作指令に変換します。動くとカメラの観測内容が変化し、フィードバックループが閉じるため、ロボットが目標に近づく間、繰り返し修正できます。
インタラクション行列(画像ヤコビアンとも呼ばれます)は、カメラの動きによって視覚測定値がどのように変化するかを表します。その擬似逆行列は特徴量の誤差を補正速度に変換し、コントローラーのゲインは補正の強さを設定します。カメラの取り付け方によって、一般的な構成が2つあります。アイ・イン・ハンドではカメラを動くツールに取り付け、アイ・トゥ・ハンドでは外部カメラで作業空間を観測します。
Ultralytics YOLOは、このループに必要な認識測定値を提供します。YOLO26は物体検出によってバウンディングボックスを生成し、そのROS連携は、カメラ由来の検出結果と深度情報をロボットソフトウェアの各コンポーネント間で受け渡します。後段のコントローラーは、これらの測定値を使って動きを計算します。
画像ベースと位置ベースのビジュアルサーボ#
主な手法は、制御誤差の表現方法が異なります。
- 画像ベースのビジュアルサーボ(IBVS):点の座標など、現在の画像特徴と目標画像特徴との差を最小化します。点特徴を用いるコントローラーは、カメラの幾何情報と深度推定を使って、画像上の動きを物理的な動きに関連付けます。
- 位置ベースのビジュアルサーボ(PBVS):姿勢推定によって3次元の位置と向きを復元し、目標姿勢との差を小さくします。カメラのキャリブレーションと幾何学的な再構成が精度に影響します。
- ハイブリッドビジュアルサーボ:画像空間の測定値と3次元の測定値を組み合わせます。確立された2.5Dビジュアルサーボ手法では、画像特徴と部分的な姿勢情報を組み合わせます。
物体追跡では、フレーム間で特徴または物体の対応関係を維持します。ビジュアルサーボは、これらの観測結果を使って動きを制御します。ビジュアルSLAMはカメラの動きを推定し、マップを作成します。これらの認識機能は、ロボットのナビゲーションシステムと制御システムの異なる部分を支えます。
用途と実用上の制約#
- ロボットの把持:近距離での把持中、RGB-Dカメラは最小深度検出距離を超えてしまい、有効な距離測定値を取得できなくなる場合があります。閉ループの視覚把持ではIBVSを使用し、物体が動いている場合も含め、RGB特徴の測定値に基づいて最終接近動作を引き続き補正します。
- 移動ロボットの位置決め:ViSPのPioneerデモでは、カメラを搭載したPioneer P3-DXロボットを視覚ターゲットに対して制御します。ターゲットの観測結果に基づき、位置ベースのコントローラーを通じてロボットの動きを補正します。
タイミングと視認性は制御に直接影響します。画像処理の遅延は追跡の遅れを招き、ループを不安定にする可能性があります。そのため、リアルタイム推論では検出精度とともに推論レイテンシも重要です。オクルージョンは特徴の対応関係を途切れさせ、条件の悪い特徴の幾何配置は速度推定を画像ノイズの影響を受けやすくします。センサーフュージョンでは、視覚測定値と関節エンコーダーなどの情報を組み合わせ、動作中に有用な状態推定を維持します。
最小限のIBVSシミュレーション#
このPythonシミュレーションでは、標準的な擬似逆行列制御則を適用し、静止した1点を観測しながら横方向に移動するカメラをシミュレートします。pip install numpyでNumPyをインストールしてください。
import numpy as np
point = np.array([0.0, 0.0, 2.0])
camera = np.array([-0.4, 0.2, 0.0])
desired = np.zeros(2)
gain, dt, focal_pixels = 1.0, 0.05, 800.0
initial_error = np.linalg.norm((point - camera)[:2] / point[2])
for _ in range(200):
relative = point - camera
observed = relative[:2] / relative[2]
error = observed - desired
# Interaction matrix for sideways camera translation.
interaction = -np.eye(2) / relative[2]
velocity = -gain * np.linalg.pinv(interaction) @ error
camera[:2] += velocity * dt
final_error = np.linalg.norm((point - camera)[:2] / point[2])
print(f"Pixel error: {initial_error * focal_pixels:.2f} -> {final_error * focal_pixels:.2f}")繰り返し補正して点を中央に合わせると、画像誤差は約178.89ピクセルから0.01ピクセルに減少します。点特徴の場合、並進方向のインタラクション項は深度に反比例します。点までの深度が2倍になると、同じ横方向のカメラ移動によって生じる画像上の変位は半分になります。










