インピーダンス制御の理論と実装 — 力と位置を統合するロボット制御

宇宙空間に漂う故障衛星を、ロボットアームで捕獲するシーンを想像してみてください。アームが目標に近づき、グリッパが衛星表面に触れた瞬間 — もしアームが「何が何でも目標位置に行く」という硬い位置制御をしていたら、どうなるでしょうか? 衛星が予想と少しでも違う位置にあれば、接触時に巨大な力が発生し、衛星を弾き飛ばしたり、最悪の場合はロボット自身や衛星を破壊してしまいます。

これは地上のロボットでも同じです。産業用ロボットが部品を組み立てる、研磨する、人間と協働する — こうした環境との物理的接触を伴うタスクでは、位置だけを制御するのでは不十分です。接触時に生じる力を「適切に」扱う制御法が必要になります。

インピーダンス制御(impedance control)は、この問題に対するエレガントな解決策です。ロボットの手先が外力を受けたとき、あたかも「バネとダンパが付いているかのように」振る舞わせることで、力と位置の関係を自然に調整します。硬い壁に触れても衝撃を吸収し、柔らかい対象物にはしっかりと力を加える — そのような「やわらかさ」をプログラムで実現するのがインピーダンス制御です。

インピーダンス制御を理解すると、以下のような応用が可能になります。

  • 宇宙デブリ捕獲・衛星サービシング: 協力的でない(非協調な)対象物を安全に把持する
  • ロボット組立作業: ペグ・イン・ホール(穴にピンを挿入する作業)など、接触を伴う精密組立
  • 人間協働ロボット: 人間と物理的に接触しても安全に動作するコボット制御
  • 惑星探査ローバー: 未知の地形との接触力を適切に管理した移動・掘削

本記事の内容

  • 機械インピーダンスの概念 — バネ・ダンパ・質量モデルによる力と運動の関係
  • インピーダンス制御の目標動力学とその意味
  • 制御則の導出(位置ベースと力ベース)
  • アドミタンス制御との双対関係
  • インピーダンスパラメータの設計指針
  • 宇宙環境での接触制御の特有の課題
  • Pythonによる壁面接触シミュレーション — インピーダンス制御と位置制御の比較

前提知識

この記事を読む前に、以下の記事を読んでおくと理解が深まります。

また、以下の基礎的な制御工学の知識があると理解がスムーズです。

機械インピーダンスとは

電気回路のアナロジーから理解する

「インピーダンス」という言葉を聞くと、多くの方は電気回路を思い浮かべるでしょう。交流回路において、インピーダンス $Z$ は電圧 $V$ と電流 $I$ の関係を規定するものでした。

$$ V = Z \cdot I $$

電圧は「力」のようなもの(電荷を押す力)、電流は「流れ」のようなもの(電荷の運動)です。つまり、インピーダンスとは「力」と「運動」の関係を表す量なのです。この考え方は、機械系にもそのまま適用できます。

機械インピーダンスの定義

機械系では、「力」は文字通りの力 $f$ であり、「運動」は速度 $v$ です。機械インピーダンス(mechanical impedance)とは、力と速度の関係を規定する量です。

$$ f = Z_m \cdot v $$

ここで $Z_m$ が機械インピーダンスです。直感的には、インピーダンスが大きいとは「動かそうとしても大きな力が必要=硬い」ということであり、インピーダンスが小さいとは「小さな力で動く=柔らかい」ということです。

最も馴染み深い機械インピーダンスの例は、バネ-ダンパ-質量系です。この系では、外力 $f$ と変位 $x$ の関係が次のように書けます。

$$ f = m\ddot{x} + d\dot{x} + kx $$

ここで $m$ は質量(慣性)、$d$ は粘性減衰係数(ダンパ)、$k$ はバネ定数です。この式は、ラプラス変換($s$ を微分演算子とする)を用いると次のようになります。

$$ F(s) = (ms^2 + ds + k) X(s) = (ms + d + k/s) V(s) $$

つまり、機械インピーダンスは周波数領域で $Z_m(s) = ms + d + k/s$ と表されます。

3つの要素の物理的意味

バネ・ダンパ・質量はそれぞれ異なる物理的役割を持っています。

質量(慣性)$m$: 加速度に比例した力を生じます。急に動かそうとすると大きな力が必要ですが、ゆっくり動かすのには力がほとんど要りません。高周波の運動を妨げる効果があります。

ダンパ(粘性)$d$: 速度に比例した力を生じます。エネルギーを散逸させる役割を持ち、振動を減衰させます。水中で手を動かすときに感じる抵抗がこれに近いです。

バネ(剛性)$k$: 変位に比例した力を生じます。平衡位置からのずれに対する復元力です。輪ゴムを引っ張ると戻ろうとする力がまさにバネの効果です。

この3つの要素を組み合わせることで、あらゆる「やわらかさ」を表現できます。硬いバネ(大きな $k$)は位置を保持する力が強く、強いダンパ(大きな $d$)は振動を素早く抑制し、大きな質量(大きな $m$)は急激な加速を防ぎます。

ロボット制御において重要なのは、このバネ・ダンパ・質量の特性を物理的に実現する必要はないということです。モータのトルクを適切に制御することで、あたかもバネやダンパが取り付けられているかのような振る舞いをプログラムで実現できます。これがインピーダンス制御の核心です。

ここまでで機械インピーダンスの概念を理解しました。次に、この概念をロボット制御にどう適用するか — つまり、ロボットの手先にどのようなインピーダンス特性を持たせるかを定式化していきます。

インピーダンス制御の目標動力学

ロボットに「望ましい柔らかさ」を与える

インピーダンス制御の基本的なアイデアは、ロボットの手先(エンドエフェクタ)が外力を受けたとき、あらかじめ設計者が指定したバネ-ダンパ-質量系として振る舞うようにすることです。

これを目標インピーダンス(target impedance)と呼びます。設計者は、ロボットが「どの程度の柔らかさで」「どの程度の速さで振動を収束させるか」を自由に指定できます。物理的にバネを取り付けるのとは異なり、パラメータをリアルタイムに変更することも可能です。

目標動力学の式

ロボットの手先位置を $\bm{x} \in \mathbb{R}^n$、目標位置(平衡位置)を $\bm{x}_d \in \mathbb{R}^n$、手先にかかる外力を $\bm{f}_{ext} \in \mathbb{R}^n$ とします。インピーダンス制御の目標動力学は、次の2階微分方程式で記述されます。

$$ \bm{M}_d(\ddot{\bm{x}} – \ddot{\bm{x}}_d) + \bm{D}_d(\dot{\bm{x}} – \dot{\bm{x}}_d) + \bm{K}_d(\bm{x} – \bm{x}_d) = \bm{f}_{ext} $$

ここで各パラメータの意味は次の通りです。

パラメータ サイズ 意味
$\bm{M}_d$ $n \times n$ 望ましい慣性行列(見かけの質量)
$\bm{D}_d$ $n \times n$ 望ましい粘性行列(見かけのダンパ)
$\bm{K}_d$ $n \times n$ 望ましい剛性行列(見かけのバネ)
$\bm{x}_d$ $n \times 1$ 目標位置(平衡位置)
$\bm{f}_{ext}$ $n \times 1$ 環境から手先にかかる外力

これらの行列は通常、正定値対称行列として設計します。$n$ は作業空間の次元(平面なら2、3次元空間なら6 — 並進3 + 回転3)です。

式の物理的な読み方

この式を理解するために、1自由度(スカラー)の場合に簡略化してみましょう。

$$ M_d(\ddot{x} – \ddot{x}_d) + D_d(\dot{x} – \dot{x}_d) + K_d(x – x_d) = f_{ext} $$

位置の誤差を $e = x – x_d$ とすると、$\dot{e} = \dot{x} – \dot{x}_d$、$\ddot{e} = \ddot{x} – \ddot{x}_d$ なので、次のように書けます。

$$ M_d \ddot{e} + D_d \dot{e} + K_d e = f_{ext} $$

これは質量 $M_d$、ダンパ $D_d$、バネ $K_d$ の1自由度振動系に外力 $f_{ext}$ が加わった系の運動方程式そのものです。

外力がゼロ($f_{ext} = 0$)の場合: 目標位置 $x_d$ に向かって減衰振動しながら収束します。つまり、通常の位置制御と同様に目標位置を追従します。

外力がかかった場合($f_{ext} \neq 0$): 目標位置からのずれは $e = f_{ext}/K_d$(定常状態)となります。バネ定数 $K_d$ が大きいほど、外力に対して位置ずれが小さくなります(硬い制御)。逆に $K_d$ が小さいと、外力に対して柔軟に位置が変わります(やわらかい制御)。

力制御と位置制御の統合としての理解

インピーダンス制御の美しさは、力制御と位置制御を連続的なスペクトルとして統一的に扱える点にあります。

$K_d \to \infty$ の極限: $e \to 0$(外力に関係なく目標位置を保持)。これは理想的な位置制御に対応します。

$K_d \to 0$ の極限: 位置の誤差に関係なく力の関係だけが成り立ちます。これは力制御に近づきます。

つまり、インピーダンスパラメータ $\bm{M}_d$、$\bm{D}_d$、$\bm{K}_d$ を調整することで、位置制御と力制御の「中間」を自由に設定できるのです。デブリ捕獲の接近フェーズでは硬め(高い $K_d$)で正確に位置追従し、接触の瞬間には柔らかめ(低い $K_d$)に切り替える — こうした制御の柔軟性がインピーダンス制御の強みです。

この目標動力学が定まったところで、次はこの振る舞いを実際のロボットで実現するための制御則を導出していきましょう。

制御則の導出

ロボットの運動方程式

まず、ロボットマニピュレータの運動方程式を確認します。$n$ 自由度のロボットの関節座標 $\bm{q} \in \mathbb{R}^n$ における運動方程式は次の通りです。

$$ \bm{H}(\bm{q})\ddot{\bm{q}} + \bm{C}(\bm{q}, \dot{\bm{q}})\dot{\bm{q}} + \bm{g}(\bm{q}) = \bm{\tau} + \bm{J}^T(\bm{q})\bm{f}_{ext} $$

ここで、各項の意味は以下の通りです。

  • $\bm{H}(\bm{q})$: 慣性行列($n \times n$、正定値対称)
  • $\bm{C}(\bm{q}, \dot{\bm{q}})$: コリオリ・遠心力行列
  • $\bm{g}(\bm{q})$: 重力項
  • $\bm{\tau}$: 関節トルク(制御入力)
  • $\bm{J}(\bm{q})$: ヤコビ行列
  • $\bm{f}_{ext}$: 手先にかかる外力

一方、手先の位置 $\bm{x}$ と関節角度 $\bm{q}$ の関係は順運動学で結ばれています。

$$ \bm{x} = \bm{f}_{kin}(\bm{q}) $$

この関係を微分すると、手先の速度と加速度が得られます。

$$ \dot{\bm{x}} = \bm{J}(\bm{q})\dot{\bm{q}} $$

$$ \ddot{\bm{x}} = \bm{J}(\bm{q})\ddot{\bm{q}} + \dot{\bm{J}}(\bm{q})\dot{\bm{q}} $$

作業空間での運動方程式

制御則を導くために、関節空間の運動方程式を作業空間(手先座標系)に変換します。関節空間の加速度 $\ddot{\bm{q}}$ をヤコビ行列の逆行列を使って表すと(正方かつ非特異と仮定)、次のようになります。

$$ \ddot{\bm{q}} = \bm{J}^{-1}(\ddot{\bm{x}} – \dot{\bm{J}}\dot{\bm{q}}) $$

これをロボットの運動方程式に代入します。

$$ \bm{H}\bm{J}^{-1}(\ddot{\bm{x}} – \dot{\bm{J}}\dot{\bm{q}}) + \bm{C}\dot{\bm{q}} + \bm{g} = \bm{\tau} + \bm{J}^T\bm{f}_{ext} $$

両辺に左から $\bm{J}^{-T}$($\bm{J}^{-1}$ の転置)を掛けて整理すると、作業空間での運動方程式が得られます。

$$ \bm{\Lambda}(\bm{q})\ddot{\bm{x}} + \bm{\mu}(\bm{q}, \dot{\bm{q}})\dot{\bm{x}} + \bm{p}(\bm{q}) = \bm{F} + \bm{f}_{ext} $$

ここで、各項は次のように定義されます。

作業空間の慣性行列:

$$ \bm{\Lambda}(\bm{q}) = \bm{J}^{-T}\bm{H}(\bm{q})\bm{J}^{-1} $$

作業空間のコリオリ・遠心力項:

$$ \bm{\mu}(\bm{q}, \dot{\bm{q}}) = \bm{J}^{-T}\bm{C}\bm{J}^{-1} – \bm{\Lambda}\dot{\bm{J}}\bm{J}^{-1} $$

作業空間の重力項:

$$ \bm{p}(\bm{q}) = \bm{J}^{-T}\bm{g}(\bm{q}) $$

作業空間での制御力:

$$ \bm{F} = \bm{J}^{-T}\bm{\tau} $$

制御則の設計

目標は、作業空間の運動方程式の振る舞いを目標インピーダンスに一致させることです。すなわち、次の関係を実現したいのです。

$$ \bm{M}_d(\ddot{\bm{x}} – \ddot{\bm{x}}_d) + \bm{D}_d(\dot{\bm{x}} – \dot{\bm{x}}_d) + \bm{K}_d(\bm{x} – \bm{x}_d) = \bm{f}_{ext} $$

この目標動力学から $\ddot{\bm{x}}$ を解くと、手先の望ましい加速度が求まります。

$$ \ddot{\bm{x}} = \ddot{\bm{x}}_d + \bm{M}_d^{-1}\left[\bm{f}_{ext} – \bm{D}_d(\dot{\bm{x}} – \dot{\bm{x}}_d) – \bm{K}_d(\bm{x} – \bm{x}_d)\right] $$

この望ましい加速度を作業空間の運動方程式に代入することで、必要な制御力 $\bm{F}$ が得られます。

$$ \bm{F} = \bm{\Lambda}\ddot{\bm{x}} + \bm{\mu}\dot{\bm{x}} + \bm{p} – \bm{f}_{ext} $$

上式に望ましい加速度を代入すると、次の制御力が得られます。

$$ \bm{F} = \bm{\Lambda}\left[\ddot{\bm{x}}_d + \bm{M}_d^{-1}\left(\bm{f}_{ext} – \bm{D}_d\dot{\bm{e}} – \bm{K}_d\bm{e}\right)\right] + \bm{\mu}\dot{\bm{x}} + \bm{p} – \bm{f}_{ext} $$

ここで $\bm{e} = \bm{x} – \bm{x}_d$ は位置誤差です。最後に、関節トルクに変換すると制御則が完成します。

$$ \bm{\tau} = \bm{J}^T \bm{F} $$

簡略化: $\bm{M}_d = \bm{\Lambda}$ の場合

実用上、望ましい慣性 $\bm{M}_d$ をロボット自身の慣性 $\bm{\Lambda}$ と等しく設定するケースが多くあります。この場合、制御則は大幅に簡略化されます。

目標動力学の式に $\bm{M}_d = \bm{\Lambda}$ を代入して整理すると、次のようになります。

$$ \bm{\Lambda}(\ddot{\bm{x}} – \ddot{\bm{x}}_d) + \bm{D}_d(\dot{\bm{x}} – \dot{\bm{x}}_d) + \bm{K}_d(\bm{x} – \bm{x}_d) = \bm{f}_{ext} $$

作業空間の運動方程式 $\bm{\Lambda}\ddot{\bm{x}} + \bm{\mu}\dot{\bm{x}} + \bm{p} = \bm{F} + \bm{f}_{ext}$ と比較すると、次の制御力が必要だとわかります。

$$ \bm{F} = \bm{\Lambda}\ddot{\bm{x}}_d + \bm{\mu}\dot{\bm{x}} + \bm{p} – \bm{D}_d\dot{\bm{e}} – \bm{K}_d\bm{e} $$

これは計算トルク法(computed torque method)にインピーダンス項を追加したものと解釈できます。$\bm{\Lambda}\ddot{\bm{x}}_d + \bm{\mu}\dot{\bm{x}} + \bm{p}$ がフィードフォワード補償(ロボットの非線形動力学のキャンセル)を行い、$-\bm{D}_d\dot{\bm{e}} – \bm{K}_d\bm{e}$ がインピーダンス特性を付与します。

この簡略化では見かけの慣性を変更できないという制約がありますが、慣性の変更はロボットの動力学の完全なキャンセルを必要とするため、モデル誤差に対して敏感になるという実用上の問題があります。多くの場合、$\bm{M}_d = \bm{\Lambda}$ とする方がロバストです。

ここまでで制御則の導出が完了しました。しかし、この制御則を実装するにはいくつかの方式があります。外力の計測手段やロボットのアクチュエータ特性によって、最適な実装方式が異なります。次に、代表的な2つの実装方式を比較します。

位置ベースインピーダンス制御 vs 力ベースインピーダンス制御

実装方式の違い

インピーダンス制御の実現方法は、ロボットの内部制御ループの構造によって大きく2つに分類されます。

力ベースインピーダンス制御(torque-based impedance control)は、前節で導出した制御則を直接適用する方式です。関節トルクを直接制御できるロボット(トルク制御型)に適しています。

位置ベースインピーダンス制御(position-based impedance control)は、目標インピーダンスの式から「修正された目標位置」を計算し、内部の位置制御ループに渡す方式です。位置制御型のロボット(多くの産業用ロボット)に適しています。

力ベースインピーダンス制御

力ベースの方式では、先ほど導出した制御トルクを直接アクチュエータに印加します。

$$ \bm{\tau} = \bm{H}\bm{J}^{-1}(\ddot{\bm{x}}_{cmd} – \dot{\bm{J}}\dot{\bm{q}}) + \bm{C}\dot{\bm{q}} + \bm{g} – \bm{J}^T\bm{f}_{ext} $$

ここで $\ddot{\bm{x}}_{cmd}$ は目標インピーダンスから計算された手先の加速度指令です。

$$ \ddot{\bm{x}}_{cmd} = \ddot{\bm{x}}_d + \bm{M}_d^{-1}\left[\bm{f}_{ext} – \bm{D}_d(\dot{\bm{x}} – \dot{\bm{x}}_d) – \bm{K}_d(\bm{x} – \bm{x}_d)\right] $$

利点: – インピーダンスパラメータを正確に実現できる – 見かけの慣性 $\bm{M}_d$ も自由に変更可能 – 応答が速い

欠点: – ロボットの動力学モデル($\bm{H}$, $\bm{C}$, $\bm{g}$)が必要 – トルク制御可能なアクチュエータが必要 – モデル誤差の影響を受けやすい

位置ベースインピーダンス制御

位置ベースの方式では、外力の情報から目標インピーダンスの関係を使って「位置の修正量」を計算します。

目標インピーダンスの式を変形して、位置の修正量 $\Delta\bm{x}$ を求めます。定常状態(加速度・速度がゼロ)では次のようになります。

$$ \bm{K}_d \Delta\bm{x} = \bm{f}_{ext} $$

$$ \Delta\bm{x} = \bm{K}_d^{-1}\bm{f}_{ext} $$

動的な場合は、目標インピーダンスの式を $\Delta\bm{x} = \bm{x} – \bm{x}_d$ について解くことになります。

$$ \bm{M}_d \Delta\ddot{\bm{x}} + \bm{D}_d \Delta\dot{\bm{x}} + \bm{K}_d \Delta\bm{x} = \bm{f}_{ext} $$

この微分方程式を数値的に解いて $\Delta\bm{x}$ を求め、修正された目標位置 $\bm{x}_{ref} = \bm{x}_d + \Delta\bm{x}$ を内部の位置制御ループに渡します。

利点: – ロボットの動力学モデルが不要(位置制御ループが内部で処理) – 既存の位置制御型ロボットにそのまま適用可能 – 実装がシンプル

欠点: – 位置制御ループの帯域幅に制限される(応答が遅い) – 見かけの慣性の変更が困難 – 低インピーダンス(非常に柔らかい制御)の実現が難しい

使い分けの指針

条件 推奨方式
トルク制御型ロボット(研究用ロボットなど) 力ベース
位置制御型ロボット(産業用ロボットなど) 位置ベース
高い応答性が必要(高速接触タスク) 力ベース
モデルの不確かさが大きい 位置ベース
非常に柔らかい制御が必要 力ベース

宇宙ロボットの場合、多くは力/トルクセンサを搭載しつつも、関節はモータ+減速機の構成であることが多いため、位置ベースと力ベースのハイブリッドが用いられることもあります。

ここまでで2つの実装方式を見てきましたが、実はインピーダンス制御と双対な関係にある「アドミタンス制御」という概念もあります。次にこの関係を整理しましょう。

アドミタンス制御との関係

双対問題としての理解

インピーダンス制御とアドミタンス制御は、力と運動の因果関係が逆になった双対(dual)の関係にあります。

インピーダンス制御: 運動(変位)を入力として、力を出力とする関係を規定します。

$$ \bm{f}_{ext} = \bm{M}_d\ddot{\bm{e}} + \bm{D}_d\dot{\bm{e}} + \bm{K}_d\bm{e} $$

「変位が与えられたとき、どれだけの力が生じるか」を決めるのがインピーダンスです。

アドミタンス制御: 力を入力として、運動(変位)を出力とする関係を規定します。

$$ \ddot{\bm{e}} = \bm{M}_d^{-1}\left[\bm{f}_{ext} – \bm{D}_d\dot{\bm{e}} – \bm{K}_d\bm{e}\right] $$

「力が加わったとき、どれだけ動くか」を決めるのがアドミタンスです。

電気回路のアナロジーでは、インピーダンスが $Z = V/I$ なら、アドミタンスは $Y = I/V = 1/Z$ です。機械系でも同様に、機械アドミタンスは機械インピーダンスの逆です。

数学的には同じ、実装は異なる

目標動力学の式自体は同じ $\bm{M}_d\ddot{\bm{e}} + \bm{D}_d\dot{\bm{e}} + \bm{K}_d\bm{e} = \bm{f}_{ext}$ です。しかし、制御系の実装構造が異なります。

インピーダンス制御の実装: 1. 手先の位置・速度を計測する 2. 位置の偏差から目標インピーダンスに基づいて力/トルクを計算する 3. その力/トルクをアクチュエータに指令する

つまり、「位置を計測 → 力を出力」の構造です。これはロボット自体が力を制御できる(バックドライバブルな)アクチュエータを持つ場合に適しています。

アドミタンス制御の実装: 1. 力/トルクセンサで外力を計測する 2. 外力から目標アドミタンスに基づいて位置の修正量を計算する 3. 修正された位置指令を位置制御ループに渡す

つまり、「力を計測 → 位置を出力」の構造です。これは位置制御ループが強固な(高ゲインの)ロボットに適しています。

環境のインピーダンスとの相補性

ロボットと環境の相互作用を安定に保つためには、ロボットと環境のインピーダンス/アドミタンスが相補的であることが望ましいとされています。

Hogan(1985)の原則: 安定な接触制御のためには、環境がインピーダンスを示すなら(環境が硬い)ロボットはアドミタンスを示す(柔らかく動く)べきであり、逆に環境がアドミタンスを示すなら(環境が柔らかい)ロボットはインピーダンスを示す(硬く力を加える)べきです。

直感的には、硬い壁(高インピーダンス環境)に対して硬いロボット(高インピーダンスロボット)を押し付けると、わずかな位置誤差で巨大な力が生じて不安定になります。一方、硬い壁に対して柔らかいロボット(低インピーダンス=高アドミタンス)で接触すれば、力は穏やかに制御されます。

環境の特性 ロボットの制御方式 理由
硬い(高インピーダンス) アドミタンス制御 柔らかく受け止める
柔らかい(低インピーダンス) インピーダンス制御 確実に力を加える

実用上の選択

実際のロボットシステムでは、以下のように選択されることが多いです。

  • 研究用の軽量ロボットアーム(例: KUKA iiwa, Franka Emika): トルクセンサ内蔵でバックドライバブル → インピーダンス制御が自然
  • 産業用ロボットアーム(例: ABB, FANUC): 高減速比で高剛性 → アドミタンス制御(外部力センサ + 位置指令修正)が実用的
  • 宇宙ロボットアーム(例: JEMRMS, Canadarm2): 位置制御ベースだが力覚センサ搭載 → アドミタンス制御ベースが多い

インピーダンス/アドミタンスの選択は、制御システムの安定性に直結します。では、どちらの方式を選んだとしても重要になるのが、インピーダンスパラメータ $\bm{M}_d$, $\bm{D}_d$, $\bm{K}_d$ の具体的な値をどう決めるかです。次節でパラメータ設計の考え方を見ていきましょう。

インピーダンスパラメータの設計

パラメータ設計の基本方針

インピーダンス制御の性能は、$\bm{M}_d$, $\bm{D}_d$, $\bm{K}_d$ の値に大きく依存します。これらのパラメータは、タスクの要求に応じて設計する必要があります。ここでは1自由度の場合を考えて基本的な設計指針を説明します。

固有振動数と減衰比

1自由度の目標インピーダンスの特性方程式は次の通りです。

$$ M_d s^2 + D_d s + K_d = 0 $$

これを標準的な2次系の形に書き直すと、次のようになります。

$$ s^2 + 2\zeta\omega_n s + \omega_n^2 = 0 $$

$M_d$ で両辺を割ることで、固有角振動数 $\omega_n$ と減衰比 $\zeta$ が得られます。

$$ \omega_n = \sqrt{\frac{K_d}{M_d}}, \quad \zeta = \frac{D_d}{2\sqrt{K_d M_d}} $$

これらの2つのパラメータが、インピーダンス制御の動的な特性を決定します。

固有振動数 $\omega_n$: 外力が加わったときに目標位置に戻ろうとする速さを決めます。$\omega_n$ が大きいほど応答が速くなりますが、制御帯域幅の上限やセンサのノイズに制約されます。

減衰比 $\zeta$: 振動の減衰の仕方を決めます。

  • $\zeta < 1$(不足減衰): 振動しながら収束する。$\zeta = 0$ で永久に振動
  • $\zeta = 1$(臨界減衰): 振動せずに最も速く収束する
  • $\zeta > 1$(過減衰): 振動しないが収束が遅い

剛性 $K_d$ の設計

剛性 $K_d$ は最も重要なパラメータで、外力に対する位置のずれ量を直接決定します。

定常状態で外力 $f_0$ が加わったときの位置ずれは次の通りです。

$$ \Delta x_{ss} = \frac{f_0}{K_d} $$

したがって、許容される位置ずれ $\Delta x_{max}$ と想定される最大外力 $f_{max}$ から、必要な剛性が決まります。

$$ K_d \geq \frac{f_{max}}{\Delta x_{max}} $$

ただし、$K_d$ を大きくしすぎると硬い位置制御に近づき、接触時の衝撃が大きくなります。タスクの性質に応じたバランスが必要です。

接触タスク別の剛性の目安:

タスク $K_d$ の目安 理由
デブリ捕獲・衛星把持 50〜500 N/m 衝撃を避けるため柔らかく
ペグ挿入(組立作業) 500〜5,000 N/m ある程度の力は必要
研磨・研削 1,000〜10,000 N/m 一定の押し付け力が必要
自由空間での位置追従 10,000〜100,000 N/m 高精度な位置追従

粘性 $D_d$ の設計

粘性 $D_d$ は振動の減衰速度を決定します。臨界減衰($\zeta = 1$)を基準として設計するのが一般的です。

$$ D_d = 2\zeta\sqrt{K_d M_d} $$

接触タスクでは、振動(バウンシング)を避けるために $\zeta \geq 1$(臨界減衰以上)が推奨されます。特にデブリ捕獲のような一発勝負のタスクでは、$\zeta = 1.0 \sim 1.5$ 程度の過減衰が安全です。

逆に、人間との協働作業では $\zeta = 0.7 \sim 1.0$ 程度として、ある程度の応答性を確保しつつ振動を抑えるのが一般的です。

慣性 $M_d$ の設計

慣性 $M_d$ は見かけの質量であり、加速度に対する抵抗を決めます。

$M_d$ を小さくすると、外力に対して素早く動く(機敏な応答)になりますが、ノイズに対しても敏感になります。$M_d$ を大きくすると、安定ですが応答が鈍くなります。

実用上の設計指針として、以下のアプローチがよく使われます。

方法1 — ロボット自身の慣性を使う: $M_d = \Lambda$(作業空間の慣性行列)とすると、慣性の変更が不要になり、制御則が簡略化されます。多くの実装でこの方法が採用されています。

方法2 — 固有振動数から逆算する: 望ましい $K_d$ と $\omega_n$ から $M_d = K_d / \omega_n^2$ で求めます。タスクの応答速度の要求から設計できます。

多自由度への拡張

多自由度の場合、$\bm{K}_d$, $\bm{D}_d$, $\bm{M}_d$ は行列になりますが、対角行列として設計すれば各軸独立に1自由度の設計を適用できます。

$$ \bm{K}_d = \text{diag}(K_{d,x}, K_{d,y}, K_{d,z}), \quad \bm{D}_d = \text{diag}(D_{d,x}, D_{d,y}, D_{d,z}) $$

タスクの方向によって異なる剛性を設定できるのがインピーダンス制御の利点です。例えば、壁面に対して垂直方向は柔らかく(低い $K_d$)、壁面に平行な方向は硬く(高い $K_d$)と設定すれば、壁に押し付けながら滑らかに移動するような動作を実現できます。

パラメータの設計方法がわかったところで、次は宇宙環境特有の課題について考えます。地上のロボットとは異なる条件が、インピーダンス制御の設計にどのような影響を与えるかを見ていきましょう。

宇宙環境での接触制御の課題

微小重力環境の影響

地上のロボットでは、重力補償 $\bm{g}(\bm{q})$ が大きな割合を占めます。宇宙では微小重力なので重力項はほぼゼロになりますが、それは必ずしも制御が簡単になることを意味しません。

反力の問題: 地上では、ロボットのベース(台座)は地面に固定されているため、アームが力を発揮してもベースは動きません。しかし宇宙では、ロボットのベースは人工衛星そのものであり、自由浮遊しています。アームが対象物を押すと、反作用でベース衛星が逆方向に動いてしまいます。

これはニュートンの第3法則(作用・反作用の法則)の直接的な帰結です。外力がかかっていない系(宇宙空間のロボット+ベース衛星)では運動量が保存されるため、ロボットアームが動くとベース衛星は必ず反対方向に移動します。

$$ \bm{p}_{total} = m_{base}\dot{\bm{x}}_{base} + \sum_i m_i \dot{\bm{x}}_i = \text{const.} $$

この効果により、ロボットの手先の実効的なインピーダンスはベース衛星の質量にも依存します。ベース衛星が軽い(小型衛星の場合)と、この影響が顕著になり、設計したインピーダンスパラメータが想定通りに実現されなくなります。

フリーフライングロボットの動力学

宇宙ロボットはフリーフライングマニピュレータ(free-flying manipulator)として扱う必要があります。ベースが固定されていないため、通常のロボット動力学に加えて、ベース衛星の並進・回転の運動方程式も考慮しなければなりません。

フリーフライングロボットの一般化された運動方程式は次のように拡張されます。

$$ \begin{bmatrix} \bm{H}_{bb} & \bm{H}_{bm} \\ \bm{H}_{mb} & \bm{H}_{mm} \end{bmatrix} \begin{bmatrix} \ddot{\bm{x}}_b \\ \ddot{\bm{q}} \end{bmatrix} + \begin{bmatrix} \bm{c}_b \\ \bm{c}_m \end{bmatrix} = \begin{bmatrix} \bm{F}_b \\ \bm{\tau} \end{bmatrix} + \begin{bmatrix} \bm{J}_b^T \\ \bm{J}_m^T \end{bmatrix} \bm{f}_{ext} $$

ここで添字 $b$ はベース衛星、$m$ はマニピュレータを表します。$\bm{H}_{bm}$ は連成慣性行列であり、アームの運動がベースに、ベースの運動がアームに影響を及ぼすことを表しています。

ベース衛星への影響と対策

接触時にアームが受ける外力は、ベース衛星の姿勢と位置を乱します。これは以下の問題を引き起こします。

姿勢外乱: 太陽電池パネルやアンテナの指向が狂い、電力供給や通信が途絶する可能性があります。

軌道外乱: 大きな力が加わると、ベース衛星の軌道が変化し、軌道維持のための追加の推進剤が必要になります。

これらの問題に対する対策として、以下のアプローチが研究されています。

リアクションナルスペース制御: アームの関節運動のうち、ベースの姿勢に影響を与えない成分(リアクションナルスペース)のみを使って制御する手法です。ベースへの外乱をゼロにできますが、アームの可動範囲が制限されます。

ベースの姿勢制御との協調: リアクションホイールやスラスタを使ってベースの姿勢を安定させながら、アームの制御を行います。ただし、推進剤の消費量とのトレードオフがあります。

一般化ヤコビ行列: ベースの動きも含めた手先の運動学を記述するために、通常のヤコビ行列を拡張した一般化ヤコビ行列 $\bm{J}_g$ を用います。

$$ \dot{\bm{x}} = \bm{J}_g \dot{\bm{q}} $$

ここで $\bm{J}_g$ はベース衛星の運動も考慮した実効的なヤコビ行列です。インピーダンス制御の設計では、通常のヤコビ行列 $\bm{J}$ の代わりにこの一般化ヤコビ行列を使用します。

通信遅延の問題

宇宙ロボットの多くは地上からのテレオペレーション(遠隔操作)で運用されます。地球-月間で約1.3秒、地球-火星間で数分〜数十分の通信遅延があります。

通信遅延がある場合、オペレータの指令と実際のロボット状態の間にタイムラグが生じます。このラグが制御ループに入ると、系が不安定になりやすくなります。

インピーダンス制御は、この問題に対して有利な側面を持っています。ロボット側で自律的にインピーダンス特性を維持するため、接触時の局所的な安定性は通信遅延の影響を受けません。ただし、インピーダンスパラメータの変更指令が遅延する点には注意が必要です。

力センサの課題

宇宙環境では、力/トルクセンサに以下の特有の課題があります。

温度変動: 宇宙空間では太陽光の当たる面と影の面で100度以上の温度差が生じることがあります。ひずみゲージ式の力センサはこの温度変動でドリフトしやすく、校正が困難です。

放射線: 半導体ベースのセンサは放射線による劣化(性能低下)のリスクがあります。

打ち上げ環境: ロケット打ち上げ時の振動・衝撃に耐える頑健性が必要です。

これらの課題から、宇宙ロボットでは力センサに頼りすぎない制御手法(例えば、モータ電流からのトルク推定)も重要視されています。

以上の宇宙特有の課題を踏まえた上で、次はPythonを使って、インピーダンス制御の効果を具体的にシミュレーションしてみましょう。壁面への接触タスクを通じて、インピーダンス制御と位置制御の振る舞いの違いを定量的に確認します。

Pythonによる壁面接触シミュレーション

シミュレーションの設定

ここでは、1自由度のロボットが壁面に接触するタスクをシミュレーションします。理論の本質を抽出するために、問題を単純化して考えます。

シナリオ: 質量 $m$ のエンドエフェクタが、位置 $x_{wall}$ にある壁に向かって移動します。目標位置 $x_d$ は壁の向こう側($x_d > x_{wall}$)に設定されています。位置制御では壁にぶつかったときに大きな力が生じますが、インピーダンス制御では「やわらかく」接触できることを確認します。

まず、壁のモデルとシミュレーションの基本パラメータを設定しましょう。

import numpy as np
import matplotlib.pyplot as plt

# シミュレーションパラメータ
dt = 0.001          # 時間刻み [s]
t_end = 3.0         # シミュレーション時間 [s]
t = np.arange(0, t_end, dt)
N = len(t)

# ロボット(1自由度エンドエフェクタ)のパラメータ
m_robot = 5.0       # 手先の等価質量 [kg]

# 壁のパラメータ(バネモデル)
x_wall = 0.3        # 壁の位置 [m]
k_wall = 50000.0    # 壁の剛性 [N/m](硬い壁)
d_wall = 100.0      # 壁の粘性 [Ns/m]

# 目標位置(壁の向こう側)
x_desired = 0.35    # 目標位置 [m]

# 初期条件
x0 = 0.0            # 初期位置 [m]
v0 = 0.0            # 初期速度 [m/s]

def wall_force(x, v):
    """壁との接触力を計算する(壁はバネ-ダンパモデル)"""
    if x > x_wall:
        penetration = x - x_wall
        f = -k_wall * penetration - d_wall * v
        return f
    else:
        return 0.0

壁はバネ-ダンパモデルで表現しています。ロボットが壁の位置 $x_{wall}$ を超えると、侵入量に比例した反力が生じます。壁の剛性 $k_{wall} = 50000$ N/m は金属面のような硬い壁を想定しています。

位置制御(PD制御)のシミュレーション

最初に、単純なPD位置制御での振る舞いを見てみましょう。制御則は次の通りです。

$$ f_{ctrl} = K_p(x_d – x) + K_v(\dot{x}_d – \dot{x}) $$

ここで $K_p$, $K_v$ は位置ゲインと速度ゲインです。高い位置追従性を得るために大きなゲインを設定します。

# PD位置制御のパラメータ
Kp_pd = 10000.0     # 位置ゲイン [N/m]
Kv_pd = 500.0       # 速度ゲイン [Ns/m]

# PD位置制御のシミュレーション
x_pd = np.zeros(N)
v_pd = np.zeros(N)
f_contact_pd = np.zeros(N)
f_ctrl_pd = np.zeros(N)

x_pd[0] = x0
v_pd[0] = v0

for i in range(N - 1):
    # 壁との接触力
    f_ext = wall_force(x_pd[i], v_pd[i])
    f_contact_pd[i] = -f_ext  # 壁が受ける力(正が押し込み方向)

    # PD位置制御
    f_ctrl = Kp_pd * (x_desired - x_pd[i]) + Kv_pd * (0.0 - v_pd[i])
    f_ctrl_pd[i] = f_ctrl

    # 運動方程式: m * a = f_ctrl + f_ext
    a = (f_ctrl + f_ext) / m_robot
    v_pd[i + 1] = v_pd[i] + a * dt
    x_pd[i + 1] = x_pd[i] + v_pd[i + 1] * dt

f_contact_pd[-1] = f_contact_pd[-2]
f_ctrl_pd[-1] = f_ctrl_pd[-2]

インピーダンス制御のシミュレーション

次に、インピーダンス制御を適用したケースです。ここでは力ベースのインピーダンス制御を使用します。制御則は次の通りです。

$$ f_{ctrl} = M_d \ddot{x}_d + D_d(\dot{x}_d – \dot{x}) + K_d(x_d – x) + \left(1 – \frac{M_d}{m_{robot}}\right)f_{ext} $$

$M_d = m_{robot}$(ロボット自身の慣性と等しく)とすると、制御則は次のように簡略化されます。

$$ f_{ctrl} = D_d(\dot{x}_d – \dot{x}) + K_d(x_d – x) $$

このとき、閉ループ系は目標インピーダンスに一致します。

$$ m_{robot}\ddot{e} + D_d\dot{e} + K_d e = f_{ext} $$

# インピーダンス制御のパラメータ
Md_imp = m_robot     # 望ましい慣性 = ロボットの慣性 [kg]
Kd_imp = 200.0       # 望ましい剛性 [N/m](柔らかく設定)
zeta = 1.0           # 臨界減衰
Dd_imp = 2.0 * zeta * np.sqrt(Kd_imp * Md_imp)  # 望ましい粘性

print(f"インピーダンス制御パラメータ:")
print(f"  Md = {Md_imp:.1f} kg")
print(f"  Dd = {Dd_imp:.1f} Ns/m")
print(f"  Kd = {Kd_imp:.1f} N/m")
print(f"  固有振動数: {np.sqrt(Kd_imp/Md_imp):.2f} rad/s")
print(f"  減衰比: {zeta:.2f}")

# インピーダンス制御のシミュレーション
x_imp = np.zeros(N)
v_imp = np.zeros(N)
f_contact_imp = np.zeros(N)
f_ctrl_imp = np.zeros(N)

x_imp[0] = x0
v_imp[0] = v0

for i in range(N - 1):
    # 壁との接触力
    f_ext = wall_force(x_imp[i], v_imp[i])
    f_contact_imp[i] = -f_ext

    # インピーダンス制御(Md = m_robot の場合の簡略化版)
    e = x_imp[i] - x_desired     # 位置誤差
    de = v_imp[i] - 0.0          # 速度誤差
    f_ctrl = -Kd_imp * e - Dd_imp * de
    f_ctrl_imp[i] = f_ctrl

    # 運動方程式
    a = (f_ctrl + f_ext) / m_robot
    v_imp[i + 1] = v_imp[i] + a * dt
    x_imp[i + 1] = x_imp[i] + v_imp[i + 1] * dt

f_contact_imp[-1] = f_contact_imp[-2]
f_ctrl_imp[-1] = f_ctrl_imp[-2]

結果の可視化

位置制御とインピーダンス制御の結果を並べて比較しましょう。

fig, axes = plt.subplots(3, 1, figsize=(10, 10), sharex=True)

# 位置の比較
axes[0].plot(t, x_pd, 'r-', linewidth=2, label='PD position control')
axes[0].plot(t, x_imp, 'b-', linewidth=2, label='Impedance control')
axes[0].axhline(y=x_wall, color='k', linestyle='--', linewidth=1,
                label=f'Wall position ({x_wall} m)')
axes[0].axhline(y=x_desired, color='gray', linestyle=':', linewidth=1,
                label=f'Desired position ({x_desired} m)')
axes[0].set_ylabel('Position [m]')
axes[0].set_title('Comparison: PD Position Control vs Impedance Control')
axes[0].legend(loc='lower right')
axes[0].grid(True, alpha=0.3)

# 接触力の比較
axes[1].plot(t, f_contact_pd, 'r-', linewidth=2, label='PD position control')
axes[1].plot(t, f_contact_imp, 'b-', linewidth=2, label='Impedance control')
axes[1].set_ylabel('Contact Force [N]')
axes[1].legend(loc='upper right')
axes[1].grid(True, alpha=0.3)

# 制御力の比較
axes[2].plot(t, f_ctrl_pd, 'r-', linewidth=2, label='PD position control')
axes[2].plot(t, f_ctrl_imp, 'b-', linewidth=2, label='Impedance control')
axes[2].set_xlabel('Time [s]')
axes[2].set_ylabel('Control Force [N]')
axes[2].legend(loc='upper right')
axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('impedance_vs_position_control.png', dpi=150, bbox_inches='tight')
plt.show()

このシミュレーション結果から、位置制御とインピーダンス制御の決定的な違いが読み取れます。

位置(上段): PD位置制御では、ロボットは壁を大きく押し込もうとします。高ゲインの位置制御は「目標位置 $x_d = 0.35$ m に行け」という指令を忠実に実行しようとするため、壁が邪魔をしても強引に押し込みます。一方、インピーダンス制御では壁に触れた後、壁際で穏やかに停止します。これは $K_d = 200$ N/m という柔らかいバネの効果で、「壁から押し返されたら引き下がる」という賢い振る舞いを示しています。

接触力(中段): 最も重要な違いがここに現れます。位置制御では接触の瞬間に非常に大きなピーク力が発生し、その後も壁に対して大きな力を加え続けます。インピーダンス制御では接触力のピークが大幅に低減され、穏やかに力が増加して定常値に収束します。宇宙デブリ捕獲のシナリオでは、このピーク力の差が対象物を破壊するか安全に把持できるかの分かれ目になります。

制御力(下段): 位置制御では壁に押し込むために大きな制御力を発揮し続けます。インピーダンス制御では必要最小限の制御力で穏やかに動作します。宇宙ロボットではアクチュエータのトルク容量が限られているため、制御力が小さく抑えられることは大きな利点です。

剛性パラメータの影響

次に、インピーダンスパラメータの剛性 $K_d$ を変えたときの接触力の変化を観察しましょう。

# 異なる剛性でのシミュレーション
Kd_values = [50.0, 200.0, 1000.0, 5000.0]
colors = ['#2196F3', '#4CAF50', '#FF9800', '#F44336']
labels = [f'$K_d$ = {Kd} N/m' for Kd in Kd_values]

fig, axes = plt.subplots(2, 1, figsize=(10, 8), sharex=True)

for Kd, color, label in zip(Kd_values, colors, labels):
    Dd = 2.0 * 1.0 * np.sqrt(Kd * m_robot)  # 臨界減衰

    x_sim = np.zeros(N)
    v_sim = np.zeros(N)
    f_contact_sim = np.zeros(N)

    for i in range(N - 1):
        f_ext = wall_force(x_sim[i], v_sim[i])
        f_contact_sim[i] = -f_ext

        e = x_sim[i] - x_desired
        de = v_sim[i] - 0.0
        f_ctrl = -Kd * e - Dd * de

        a = (f_ctrl + f_ext) / m_robot
        v_sim[i + 1] = v_sim[i] + a * dt
        x_sim[i + 1] = x_sim[i] + v_sim[i + 1] * dt

    f_contact_sim[-1] = f_contact_sim[-2]

    axes[0].plot(t, x_sim, color=color, linewidth=2, label=label)
    axes[1].plot(t, f_contact_sim, color=color, linewidth=2, label=label)

axes[0].axhline(y=x_wall, color='k', linestyle='--', linewidth=1, label='Wall')
axes[0].axhline(y=x_desired, color='gray', linestyle=':', linewidth=1, label='Desired')
axes[0].set_ylabel('Position [m]')
axes[0].set_title('Effect of Stiffness $K_d$ on Impedance Control')
axes[0].legend(loc='lower right', fontsize=9)
axes[0].grid(True, alpha=0.3)

axes[1].set_xlabel('Time [s]')
axes[1].set_ylabel('Contact Force [N]')
axes[1].legend(loc='upper right', fontsize=9)
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('impedance_stiffness_comparison.png', dpi=150, bbox_inches='tight')
plt.show()

この結果から、剛性 $K_d$ がインピーダンス制御の振る舞いに与える影響が明確に見えます。

$K_d = 50$ N/m(非常に柔らかい)の場合、壁との接触力は非常に小さく、ロボットは壁の手前でほぼ停止します。接触時の衝撃は最小限ですが、目標位置からの偏差が大きくなります。定常的な接触力は $f_{ss} = K_d(x_d – x_{wall}) = 50 \times 0.05 = 2.5$ N 程度です。

$K_d = 5000$ N/m(硬い)の場合、壁を強く押し込む傾向があり、接触力のピークも大きくなります。位置追従性は高いですが、衝撃力も大きくなるため、繊細な対象物の把持には不向きです。

このように、$K_d$ の選択はタスクの要求(位置精度 vs 力の安全性)に応じたトレードオフになります。

減衰比の影響

最後に、減衰比 $\zeta$ を変えた場合の振る舞いを確認しましょう。

# 異なる減衰比でのシミュレーション
Kd_fixed = 500.0
zeta_values = [0.3, 0.7, 1.0, 2.0]
colors_zeta = ['#E91E63', '#9C27B0', '#2196F3', '#009688']
labels_zeta = [f'$\\zeta$ = {z}' for z in zeta_values]

fig, axes = plt.subplots(2, 1, figsize=(10, 8), sharex=True)

for z, color, label in zip(zeta_values, colors_zeta, labels_zeta):
    Dd = 2.0 * z * np.sqrt(Kd_fixed * m_robot)

    x_sim = np.zeros(N)
    v_sim = np.zeros(N)
    f_contact_sim = np.zeros(N)

    for i in range(N - 1):
        f_ext = wall_force(x_sim[i], v_sim[i])
        f_contact_sim[i] = -f_ext

        e = x_sim[i] - x_desired
        de = v_sim[i] - 0.0
        f_ctrl = -Kd_fixed * e - Dd * de

        a = (f_ctrl + f_ext) / m_robot
        v_sim[i + 1] = v_sim[i] + a * dt
        x_sim[i + 1] = x_sim[i] + v_sim[i + 1] * dt

    f_contact_sim[-1] = f_contact_sim[-2]

    axes[0].plot(t, x_sim, color=color, linewidth=2, label=label)
    axes[1].plot(t, f_contact_sim, color=color, linewidth=2, label=label)

axes[0].axhline(y=x_wall, color='k', linestyle='--', linewidth=1, label='Wall')
axes[0].set_ylabel('Position [m]')
axes[0].set_title(f'Effect of Damping Ratio $\\zeta$ ($K_d$ = {Kd_fixed} N/m)')
axes[0].legend(loc='lower right', fontsize=9)
axes[0].grid(True, alpha=0.3)

axes[1].set_xlabel('Time [s]')
axes[1].set_ylabel('Contact Force [N]')
axes[1].legend(loc='upper right', fontsize=9)
axes[1].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('impedance_damping_comparison.png', dpi=150, bbox_inches='tight')
plt.show()

減衰比の影響は接触後の過渡応答に如実に現れます。

$\zeta = 0.3$(不足減衰)の場合、壁に接触した後にバウンシング(跳ね返り)が発生しています。接触力が振動的に変化し、一時的に接触が離れる瞬間もあります。デブリ捕獲のようなタスクでは、一度把持した対象物を跳ね返してしまう危険があるため、この設定は不適切です。

$\zeta = 1.0$(臨界減衰)の場合、振動なく最も速く定常状態に収束します。接触力のピークも適度に抑えられており、多くのタスクで良い出発点となります。

$\zeta = 2.0$(過減衰)の場合、振動は完全に抑えられますが、定常状態への収束が遅くなります。安全性が最優先のタスク(宇宙でのデブリ捕獲など)では、この設定が適している場合があります。

宇宙デブリ捕獲を想定したシミュレーション

最後に、宇宙環境でのデブリ捕獲シナリオをシミュレーションしましょう。デブリ(対象物)は浮遊しているため、接触すると動き出すことを考慮します。

# 宇宙デブリ捕獲シミュレーション
# デブリは自由浮遊(壁ではなく、質量を持つ物体)

m_debris = 50.0      # デブリの質量 [kg]
x_debris_0 = 0.3     # デブリの初期位置 [m]

# 接触のバネ-ダンパモデル(グリッパとデブリ間)
k_contact = 10000.0  # 接触剛性 [N/m]
d_contact = 200.0    # 接触粘性 [Ns/m]

# 接触力モデル(デブリが浮遊している場合)
def contact_force_debris(x_robot, v_robot, x_debris, v_debris):
    """ロボットとデブリの接触力"""
    gap = x_robot - x_debris
    if gap > 0:
        rel_v = v_robot - v_debris
        f = -k_contact * gap - d_contact * rel_v
        return f
    else:
        return 0.0

# --- 位置制御でのデブリ捕獲 ---
x_pd2 = np.zeros(N)
v_pd2 = np.zeros(N)
x_deb_pd = np.zeros(N)
v_deb_pd = np.zeros(N)
f_contact_pd2 = np.zeros(N)

x_deb_pd[0] = x_debris_0
x_desired2 = 0.35

for i in range(N - 1):
    f_ext = contact_force_debris(x_pd2[i], v_pd2[i],
                                  x_deb_pd[i], v_deb_pd[i])
    f_contact_pd2[i] = -f_ext

    # PD制御
    f_ctrl = Kp_pd * (x_desired2 - x_pd2[i]) + Kv_pd * (0.0 - v_pd2[i])

    # ロボットの運動
    a_robot = (f_ctrl + f_ext) / m_robot
    v_pd2[i + 1] = v_pd2[i] + a_robot * dt
    x_pd2[i + 1] = x_pd2[i] + v_pd2[i + 1] * dt

    # デブリの運動(接触力の反作用を受ける)
    a_debris = (-f_ext) / m_debris
    v_deb_pd[i + 1] = v_deb_pd[i] + a_debris * dt
    x_deb_pd[i + 1] = x_deb_pd[i] + v_deb_pd[i + 1] * dt

f_contact_pd2[-1] = f_contact_pd2[-2]

# --- インピーダンス制御でのデブリ捕獲 ---
Kd_space = 100.0     # 宇宙用: 柔らかめの剛性
zeta_space = 1.2     # やや過減衰
Dd_space = 2.0 * zeta_space * np.sqrt(Kd_space * m_robot)

x_imp2 = np.zeros(N)
v_imp2 = np.zeros(N)
x_deb_imp = np.zeros(N)
v_deb_imp = np.zeros(N)
f_contact_imp2 = np.zeros(N)

x_deb_imp[0] = x_debris_0

for i in range(N - 1):
    f_ext = contact_force_debris(x_imp2[i], v_imp2[i],
                                  x_deb_imp[i], v_deb_imp[i])
    f_contact_imp2[i] = -f_ext

    # インピーダンス制御
    e = x_imp2[i] - x_desired2
    de = v_imp2[i] - 0.0
    f_ctrl = -Kd_space * e - Dd_space * de

    # ロボットの運動
    a_robot = (f_ctrl + f_ext) / m_robot
    v_imp2[i + 1] = v_imp2[i] + a_robot * dt
    x_imp2[i + 1] = x_imp2[i] + v_imp2[i + 1] * dt

    # デブリの運動
    a_debris = (-f_ext) / m_debris
    v_deb_imp[i + 1] = v_deb_imp[i] + a_debris * dt
    x_deb_imp[i + 1] = x_deb_imp[i] + v_deb_imp[i + 1] * dt

f_contact_imp2[-1] = f_contact_imp2[-2]

結果を可視化します。

fig, axes = plt.subplots(3, 1, figsize=(10, 10), sharex=True)

# 位置の比較
axes[0].plot(t, x_pd2, 'r-', linewidth=2, label='Robot (PD control)')
axes[0].plot(t, x_deb_pd, 'r--', linewidth=1.5, label='Debris (PD control)')
axes[0].plot(t, x_imp2, 'b-', linewidth=2, label='Robot (Impedance)')
axes[0].plot(t, x_deb_imp, 'b--', linewidth=1.5, label='Debris (Impedance)')
axes[0].axhline(y=x_desired2, color='gray', linestyle=':', linewidth=1,
                label='Desired position')
axes[0].set_ylabel('Position [m]')
axes[0].set_title('Space Debris Capture: PD Control vs Impedance Control')
axes[0].legend(loc='lower right', fontsize=9)
axes[0].grid(True, alpha=0.3)

# 接触力の比較
axes[1].plot(t, f_contact_pd2, 'r-', linewidth=2, label='PD control')
axes[1].plot(t, f_contact_imp2, 'b-', linewidth=2, label='Impedance control')
axes[1].set_ylabel('Contact Force [N]')
axes[1].legend(loc='upper right')
axes[1].grid(True, alpha=0.3)

# デブリの速度の比較
axes[2].plot(t, v_deb_pd * 100, 'r-', linewidth=2, label='PD control')
axes[2].plot(t, v_deb_imp * 100, 'b-', linewidth=2, label='Impedance control')
axes[2].set_xlabel('Time [s]')
axes[2].set_ylabel('Debris Velocity [cm/s]')
axes[2].legend(loc='upper right')
axes[2].grid(True, alpha=0.3)

plt.tight_layout()
plt.savefig('debris_capture_comparison.png', dpi=150, bbox_inches='tight')
plt.show()

# 定量的な比較
print("\n===== 定量的比較 =====")
print(f"PD制御:")
print(f"  接触力ピーク: {np.max(f_contact_pd2):.1f} N")
print(f"  デブリ最大速度: {np.max(np.abs(v_deb_pd))*100:.2f} cm/s")
print(f"インピーダンス制御:")
print(f"  接触力ピーク: {np.max(f_contact_imp2):.1f} N")
print(f"  デブリ最大速度: {np.max(np.abs(v_deb_imp))*100:.2f} cm/s")
print(f"ピーク力の比: {np.max(f_contact_pd2)/max(np.max(f_contact_imp2), 1e-10):.1f}倍")

このデブリ捕獲シミュレーションの結果は、宇宙ロボティクスにおけるインピーダンス制御の必要性を明確に示しています。

位置の比較(上段): PD位置制御ではロボットがデブリに「衝突」し、デブリを大きく弾き飛ばしています。接触後もロボットは目標位置を追い続けるため、デブリとの間で衝突と分離を繰り返す可能性があります。インピーダンス制御では、ロボットがデブリに穏やかに接触し、両者がほぼ一体となってゆっくりと移動します。これが「やわらかい」捕獲です。

接触力(中段): PD制御での接触力ピークはインピーダンス制御の数倍に達しています。脆弱な太陽電池パネルやアンテナを持つ衛星に対してこの力が加わると、対象物を破壊するリスクがあります。インピーダンス制御では力のピークが大幅に低減されており、対象物に優しい接触を実現しています。

デブリの速度(下段): PD制御ではデブリが大きな速度を得ており、弾き飛ばされていることがわかります。インピーダンス制御ではデブリの速度変化が緩やかで、制御された状態での接触が実現されています。宇宙空間では一度弾き飛ばしたデブリの回収は極めて困難であるため、この差は任務の成否に直結します。

まとめ

本記事では、インピーダンス制御の理論と実装について、基礎概念から宇宙応用まで一貫して解説しました。

  • 機械インピーダンスはバネ・ダンパ・質量のモデルで力と運動の関係を表す概念であり、ロボットの「やわらかさ」を定量的に設計する枠組みを提供します
  • 目標動力学 $\bm{M}_d\ddot{\bm{e}} + \bm{D}_d\dot{\bm{e}} + \bm{K}_d\bm{e} = \bm{f}_{ext}$ により、位置制御と力制御を連続的なスペクトルとして統一的に扱えます
  • 実装方式として、トルク制御型ロボット向けの力ベース方式と、位置制御型ロボット向けの位置ベース方式があり、タスクとハードウェアに応じて選択します
  • アドミタンス制御はインピーダンス制御の双対であり、環境の特性に応じた適切な選択が安定性の鍵です
  • パラメータ設計では、固有振動数と減衰比の観点から、タスクに応じた剛性・粘性・慣性を設計します
  • 宇宙環境では、ベース衛星の反力、通信遅延、センサの課題など、地上にはない特有の問題に対処する必要があります
  • Pythonシミュレーションにより、位置制御との比較でインピーダンス制御が接触力を大幅に低減することを定量的に確認しました

インピーダンス制御は「力と位置のどちらか一方」ではなく「力と位置の関係」を制御するという点で、ロボット制御の基本パラダイムの一つです。しかし、実際の接触タスクでは「ある方向は力を制御し、別の方向は位置を制御する」という使い分けが必要な場合もあります。

次のステップとして、以下の記事も参考にしてください。