宇宙ロボットへの強化学習の適用 — Sim-to-Real転移で未知環境に挑む

宇宙空間で作業するロボットは、地上のロボットとはまったく異なる課題に直面します。微小重力環境では物体の動きが地上の直感に反し、通信遅延のためにリアルタイムの遠隔操作は困難です。さらに、デブリの回転状態や宇宙機の表面状態など、事前にすべてのシナリオをプログラムすることは不可能です。このような「未知の環境に自律的に適応する能力」が求められる場面で、強化学習(Reinforcement Learning, RL)は極めて有望なアプローチとなります。

強化学習を宇宙ロボットに適用できれば、以下のような革新的な応用が可能になります。

  1. デブリキャプチャ: 回転する宇宙デブリに自律的に接近し、安全に捕獲する
  2. 軌道上組立: 大型宇宙構造物のモジュールを自動的に組み立てる
  3. 自律ドッキング: 故障した衛星や協力しない対象への接近・接続を自律的に行う
  4. 惑星探査: 未知の地形を持つ天体表面で自律的に移動・サンプリングする

しかし、宇宙で直接試行錯誤を繰り返すことは許されません。打上げコストは莫大であり、失敗は取り返しがつかないからです。そこで鍵となるのが Sim-to-Real転移 — シミュレーション環境で学習した方策を実機に転移する技術です。

本記事の内容

  • 強化学習の基本フレームワーク(MDP、方策勾配、Actor-Critic)の復習
  • Sim-to-Real転移の基本戦略と理論的背景
  • ドメインランダマイゼーションによる頑健な方策獲得
  • 宇宙環境特有のSim-to-Realギャップとその対策
  • 適用例(デブリキャプチャ、軌道上組立、自律ドッキング)
  • Safe RL(安全な探索)の重要性
  • Pythonによる2Dデブリキャプチャ環境でのRL学習デモ

前提知識

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

なぜ強化学習が宇宙ロボットに有望なのか

従来手法の限界

宇宙ロボットの制御には、これまで主に2つのアプローチが使われてきました。

1. 事前計画型(Motion Planning): 事前にすべての動作シーケンスを計算しておく方法です。ISSのロボットアーム「カナダアーム2」の制御などに使われています。しかし、この方法は環境が既知であることが前提です。回転するデブリのように予測困難な対象には対応できません。

2. 古典的フィードバック制御(PID制御等): 偏差に基づいてリアルタイムに修正をかける方法です。安定性の保証が得やすい反面、複雑な非線形ダイナミクスや多自由度の協調動作には設計が困難です。

これらの手法は「既知の環境で、想定内の状況に対処する」場面では有効ですが、宇宙空間で遭遇する未知の状況 — 予想外のデブリの回転、想定と異なる表面摩擦、通信途絶 — には柔軟に対応できません。

強化学習がもたらす自律性

強化学習は、エージェントが環境との相互作用を通じて方策を自ら獲得する枠組みです。事前にすべてのシナリオを想定する必要がなく、報酬関数の設計さえ適切であれば、エージェントは試行錯誤の中から最適な振る舞いを見つけ出します。

宇宙ロボットにとっての強化学習の利点を整理すると、以下のようになります。

課題 従来手法 強化学習
未知の対象物 事前モデルが必要 試行錯誤で適応
非線形ダイナミクス 線形近似に頼る 非線形方策を直接学習
通信遅延 遠隔操作が困難 オンボードで自律判断
多自由度の協調 設計が複雑 End-to-Endで学習

ただし、宇宙空間で直接的な試行錯誤を行うことは許されません。1回の失敗が数億円の損失やミッションの終了につながるためです。この矛盾を解決するのが、次に解説するSim-to-Real転移です。

まず、Sim-to-Real転移の議論に入る前に、強化学習の基本的な数学的フレームワークを復習しておきましょう。

強化学習の基本フレームワーク復習

マルコフ決定過程(MDP)

強化学習の問題は、マルコフ決定過程(Markov Decision Process, MDP)として定式化されます。MDPは以下の5つ組で表されます。

$$ \mathcal{M} = (\mathcal{S}, \mathcal{A}, P, R, \gamma) $$

ここで各要素は次の意味を持ちます。

  • $\mathcal{S}$: 状態空間(例: ロボットの位置・姿勢・速度)
  • $\mathcal{A}$: 行動空間(例: 各関節に加えるトルク)
  • $P(s’ \mid s, a)$: 状態遷移確率(状態 $s$ で行動 $a$ をとったとき、次に状態 $s’$ に遷移する確率)
  • $R(s, a, s’)$: 報酬関数(その遷移で得られるスカラー報酬)
  • $\gamma \in [0, 1)$: 割引率(将来の報酬をどれだけ重視するか)

宇宙ロボットの文脈では、状態 $s$ にはロボットアームの関節角度・角速度、対象物の相対位置・姿勢・角速度などが含まれます。行動 $a$ は各関節のトルクやスラスタの噴射量です。

エージェントの目標は、累積割引報酬(リターン)の期待値を最大化する方策 $\pi^*$ を見つけることです。

$$ \pi^* = \arg\max_{\pi} \mathbb{E}_{\pi} \left[ \sum_{t=0}^{\infty} \gamma^t R(s_t, a_t, s_{t+1}) \right] $$

方策勾配法

連続行動空間の問題(トルク制御など)では、方策をパラメータ $\theta$ を持つニューラルネットワーク $\pi_\theta(a \mid s)$ で表現し、勾配法で最適化する方策勾配法が広く使われます。

目的関数 $J(\theta)$ は累積報酬の期待値です。

$$ J(\theta) = \mathbb{E}_{\pi_\theta} \left[ \sum_{t=0}^{\infty} \gamma^t r_t \right] $$

方策勾配定理により、この目的関数の勾配は次のように書けます。

$$ \nabla_\theta J(\theta) = \mathbb{E}_{\pi_\theta} \left[ \sum_{t=0}^{T} \nabla_\theta \log \pi_\theta(a_t \mid s_t) \cdot G_t \right] $$

ここで $G_t = \sum_{k=t}^{T} \gamma^{k-t} r_k$ はステップ $t$ 以降のリターンです。

直感的には、この勾配は「良い報酬が得られた行動の確率を上げ、悪い報酬の行動の確率を下げる」方向にパラメータを更新します。しかし、$G_t$ の分散が大きいと学習が不安定になります。

Actor-Critic法

方策勾配法の分散を低減するために、Actor-Critic法では2つのネットワークを併用します。

  • Actor(方策ネットワーク): 方策 $\pi_\theta(a \mid s)$ を出力
  • Critic(価値ネットワーク): 状態価値 $V_\phi(s)$ を推定

リターン $G_t$ の代わりにアドバンテージ関数 $A(s_t, a_t)$ を使うことで分散を低減します。

$$ A(s_t, a_t) = R(s_t, a_t) + \gamma V_\phi(s_{t+1}) – V_\phi(s_t) $$

アドバンテージ関数は「実際に得た報酬 + 次の状態の価値推定」と「現在の状態の価値推定」の差です。正のアドバンテージは「期待より良い行動」、負のアドバンテージは「期待より悪い行動」を意味します。

Actor の更新は次のようになります。

$$ \nabla_\theta J(\theta) = \mathbb{E} \left[ \nabla_\theta \log \pi_\theta(a_t \mid s_t) \cdot A(s_t, a_t) \right] $$

Critic の更新は、価値推定の誤差(TD誤差)を最小化します。

$$ L(\phi) = \mathbb{E} \left[ \left( R(s_t, a_t) + \gamma V_\phi(s_{t+1}) – V_\phi(s_t) \right)^2 \right] $$

代表的なActor-Criticアルゴリズムとしては、PPO(Proximal Policy Optimization)やSAC(Soft Actor-Critic)があり、宇宙ロボットの研究でも広く使われています。PPOは方策の更新幅を制限することで安定した学習を実現し、SACはエントロピー正則化により探索と活用のバランスを自動調整します。

ここまでで強化学習の基本的なフレームワークを確認しました。しかし、宇宙ロボットに強化学習を適用するには、シミュレーションで学習した方策を実機に転移するという大きな課題があります。次に、このSim-to-Real転移の戦略を見ていきましょう。

Sim-to-Real転移の基本戦略

Reality Gapとは何か

シミュレーションと実環境の間には避けられない差異が存在します。これを Reality Gap(現実ギャップ)と呼びます。シミュレーション上では完璧に動作する方策が、実環境では全く機能しないことは珍しくありません。

たとえば、シミュレーション上で学習したロボットアームの制御方策を実機に転移する場合、以下のような差異が問題になります。

  • 物理パラメータの差異: 摩擦係数、質量分布、関節の遊びなど
  • センサノイズ: シミュレーションでは完全な状態観測、実機ではノイズ入り
  • アクチュエータの特性: 応答遅延、飽和、ヒステリシスなど
  • モデル化されていない現象: 接触力学の簡略化、流体効果の無視など

数学的には、シミュレーション環境のMDPを $\mathcal{M}_{\text{sim}} = (\mathcal{S}, \mathcal{A}, P_{\text{sim}}, R, \gamma)$、実環境のMDPを $\mathcal{M}_{\text{real}} = (\mathcal{S}, \mathcal{A}, P_{\text{real}}, R, \gamma)$ とすると、Reality Gapは遷移確率の差 $\| P_{\text{sim}} – P_{\text{real}} \|$ として表現できます。Sim-to-Real転移の目標は、この差が存在しても性能が大きく劣化しない方策を獲得することです。

主要な転移戦略

Sim-to-Real転移には、大きく分けて3つの戦略があります。

戦略1: シミュレーションの高忠実度化(System Identification)

実環境の物理パラメータを精密に同定し、シミュレーションの忠実度を上げるアプローチです。ロボットの質量特性、摩擦係数、センサ特性などを実機で測定し、シミュレータに反映します。

利点は、同定が正確であればそのまま転移できることですが、すべてのパラメータを正確に同定するのは実際には困難であり、モデル化されていない現象には対応できません。

戦略2: ドメインランダマイゼーション

物理パラメータや観測にランダムなばらつきを加えてシミュレーションを行い、多様な環境で頑健に動作する方策を獲得するアプローチです。「実環境はランダム化の範囲のどこかにあるはず」という考え方に基づいています。次のセクションで詳しく解説します。

戦略3: ドメイン適応(Domain Adaptation)

シミュレーションと実環境の特徴量分布の差を縮小する手法です。敵対的学習などを使って、シミュレーション上の観測と実環境の観測を区別できないような特徴表現を学習します。

宇宙ロボットの文脈では、実環境のデータを大量に取得することが困難なため、戦略1と戦略2の組み合わせが最も実用的です。まずシステム同定で大まかなパラメータを決め、その周辺でドメインランダマイゼーションを行うという二段階アプローチが主流となっています。

それでは、宇宙ロボットのSim-to-Real転移で最も重要な手法であるドメインランダマイゼーションを詳しく見ていきましょう。

ドメインランダマイゼーション

基本的な考え方

ドメインランダマイゼーション(Domain Randomization, DR)は、「シミュレーション環境のパラメータをランダムに変動させることで、多様な環境に対して頑健な方策を獲得する」手法です。

日常的なアナロジーで説明しましょう。料理の初心者は、レシピ通りの分量と手順でないと上手く作れません。しかし熟練した料理人は、材料の分量が多少違っても、火加減が異なるコンロでも、美味しい料理を作れます。なぜなら、様々な条件で調理した経験があるからです。ドメインランダマイゼーションはまさにこれと同じ発想で、「様々な条件でシミュレーション学習する」ことで、実環境の条件が多少異なっても動作する頑健な方策を獲得します。

数学的定式化

ドメインランダマイゼーションを数学的に定式化すると、シミュレーション環境のパラメータベクトル $\bm{\xi}$ を確率分布 $p(\bm{\xi})$ からサンプリングし、期待性能を最大化する方策を求める問題になります。

パラメータ $\bm{\xi}$ を持つシミュレーション環境でのMDPを $\mathcal{M}_{\bm{\xi}}$ と書くと、ドメインランダマイゼーションの目的関数は次のように定義されます。

$$ J_{\text{DR}}(\theta) = \mathbb{E}_{\bm{\xi} \sim p(\bm{\xi})} \left[ \mathbb{E}_{\pi_\theta, \mathcal{M}_{\bm{\xi}}} \left[ \sum_{t=0}^{T} \gamma^t r_t \right] \right] $$

外側の期待値はパラメータのランダム化に関するもので、内側の期待値は方策と環境の確率的な相互作用に関するものです。

この目的関数を最大化することは、「平均的にどのような環境パラメータでも良い性能を発揮する方策」を探索することに対応します。

ランダム化するパラメータ

宇宙ロボットの文脈で典型的にランダム化されるパラメータを整理します。

動力学パラメータ: – 対象物の質量 $m$: 公称値の $\pm 30\%$ 程度 – 慣性モーメントテンソル $\bm{I}$: 各成分を $\pm 20\%$ – 接触時の摩擦係数 $\mu$: 0.1〜0.8 – 反発係数 $e$: 0.2〜0.9 – 関節のダンピング係数: $\pm 25\%$

観測パラメータ: – センサノイズ $\bm{\epsilon} \sim \mathcal{N}(\bm{0}, \sigma^2 \bm{I})$: $\sigma$ を変動 – 観測遅延: 0〜3 タイムステップ – カメラの内部パラメータ: 焦点距離、歪み係数を変動

環境パラメータ: – 残存大気抵抗(低軌道の場合): 密度を $\pm 50\%$ – 太陽放射圧: $\pm 30\%$ – 初期条件: 対象物の位置・速度・姿勢を分布からサンプリング

パラメータの分布 $p(\bm{\xi})$ は、一般に一様分布 $\xi_i \sim U[\xi_i^{\min}, \xi_i^{\max}]$ が使われますが、事前知識がある場合はガウス分布やベータ分布も有効です。

Automatic Domain Randomization(ADR)

ランダム化の範囲をどう設定するかは重要な設計判断です。範囲が狭すぎると実環境をカバーできず、広すぎると学習が困難になります。

この問題に対処するため、Automatic Domain Randomization(ADR) が提案されています。ADRでは、ランダム化の範囲を学習の進行に応じて自動的に拡大します。

基本的なアルゴリズムは次の通りです。

  1. 狭いランダム化範囲 $[\xi_i^{\min,0}, \xi_i^{\max,0}]$ から開始
  2. 現在の範囲で方策の性能が閾値 $\eta$ を超えたら範囲を拡大: $\xi_i^{\min} \leftarrow \xi_i^{\min} – \Delta$, $\xi_i^{\max} \leftarrow \xi_i^{\max} + \Delta$
  3. 性能が閾値を下回ったら範囲を縮小

ADRにより、方策の能力に応じた適切なランダム化範囲が自動的に決定されます。OpenAIのRubik’s Cube(ルービックキューブを解くロボットハンド)の研究では、このADRが成功の鍵となりました。

ドメインランダマイゼーションは強力な手法ですが、宇宙環境にはさらに地上とは異なる固有の課題があります。次に、宇宙特有のSim-to-Realギャップについて見ていきましょう。

宇宙環境特有のSim-to-Real課題

微小重力環境の特殊性

地上のロボットと宇宙ロボットの最大の違いは、重力環境です。微小重力下(マイクログラビティ)では、以下のような現象が生じます。

浮遊力学(Free-floating dynamics): 宇宙空間でロボットアームを動かすと、反作用で本体(ベース衛星)が動きます。地上では台座が地面に固定されているためこの問題は生じません。ベースが自由に動くロボットの運動方程式は次のようになります。

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

ここで $\bm{q}$ は一般化座標(ベースの位置・姿勢 + 関節角度)、$\bm{H}$ は慣性行列、$\bm{C}$ はコリオリ・遠心力項、$\bm{\tau}$ は関節トルク、$\bm{F}_{\text{ext}}$ は外力です。

重要なのは、この系では運動量とangular momentum(角運動量)が保存する点です。外力が作用しない場合、

$$ \bm{p} = \sum_{i} m_i \dot{\bm{r}}_i = \text{const} $$

$$ \bm{L} = \sum_{i} \bm{r}_i \times m_i \dot{\bm{r}}_i + \bm{I}_i \bm{\omega}_i = \text{const} $$

この保存則により、ロボットアームの動作がベースの姿勢に影響を与える動力学的カップリングが生じます。地上のシミュレーションでこのカップリングを正確に再現することがSim-to-Real転移の精度に直結します。

接触力学の変化: 微小重力下では物体を「置く」ことができません。接触すれば反発で離れてしまいます。グリッパーの把持力設計やインピーダンス制御のパラメータが地上とは大きく異なります。

放射線環境と計算資源制限

宇宙空間は地磁気の外側では高エネルギー粒子が飛び交う過酷な放射線環境です。この環境はニューラルネットワークの推論に影響します。

Single Event Upset(SEU): 高エネルギー粒子がチップに衝突するとビットが反転し、ニューラルネットワークの重みが一瞬で変化する可能性があります。宇宙用プロセッサは放射線耐性のために性能が制限されており(地上の最新GPUの数百分の一程度)、大規模なニューラルネットワークの実行は困難です。

これらの制約に対するRL方策の設計指針をまとめると、次のようになります。

制約 対策
計算資源の限界 小型ネットワーク(数百〜数千パラメータ)、量子化
SEUによるビット反転 冗長化、チェックポイント、誤り検出符号(ECC)
リアルタイム性 推論時間の上界保証、単純なアーキテクチャ
電力制約 低消費電力アクセラレータ(FPGAなど)

地上検証の困難さ

宇宙環境のシミュレーション忠実度を検証することも大きな課題です。微小重力を地上で長時間再現する方法は限られています。

  • 落下塔: 数秒間の微小重力(カプセルを自由落下させる)
  • 放物線飛行: 約20秒間の微小重力(航空機の放物線飛行)
  • 水中施設: 中性浮力で微小重力を模擬(ただし流体抵抗が残る)
  • エアベアリング: 2D平面上で摩擦のない運動を模擬

いずれも完全な再現ではなく、時間的・空間的な制約があります。このため、シミュレーションの信頼性はドメインランダマイゼーションで補完する必要があります。

通信遅延と自律性の要求

地球低軌道(LEO)の衛星でも、地上局との通信には数百ミリ秒〜数秒の遅延があります。静止軌道では片道約0.24秒、月では約1.3秒、火星では4〜24分の遅延が生じます。

この遅延のため、リアルタイムの遠隔操作は実質的に不可能であり、ロボットはオンボードで自律的に判断する必要があります。RL方策はオンボードプロセッサ上で推論可能なサイズでなければならず、これがネットワークアーキテクチャへの強い制約となります。

宇宙特有の課題が明らかになったところで、次にこれらの課題に強化学習がどのように適用されているか、具体的な応用例を見ていきましょう。

適用例

デブリキャプチャ

宇宙デブリの除去は、宇宙環境の持続可能性にとって喫緊の課題です。デブリは制御不能な回転をしていることが多く、その回転状態は事前に正確に予測できません。この不確実性に対応するため、強化学習が注目されています。

デブリキャプチャのRL定式化は以下のようになります。

状態空間: チェイサー衛星とデブリの相対位置 $\bm{r}_{\text{rel}}$、相対速度 $\dot{\bm{r}}_{\text{rel}}$、デブリの姿勢四元数 $\bm{q}_d$、角速度 $\bm{\omega}_d$、ロボットアームの関節角度 $\bm{\theta}_{\text{arm}}$

$$ \bm{s} = [\bm{r}_{\text{rel}}, \dot{\bm{r}}_{\text{rel}}, \bm{q}_d, \bm{\omega}_d, \bm{\theta}_{\text{arm}}, \dot{\bm{\theta}}_{\text{arm}}] $$

行動空間: スラスタ力 $\bm{F}$ とアーム関節トルク $\bm{\tau}_{\text{arm}}$

$$ \bm{a} = [\bm{F}, \bm{\tau}_{\text{arm}}] $$

報酬関数: 距離の縮小、安全な速度での接近、燃料消費のペナルティを組み合わせます。

$$ r(s, a) = -w_1 \|\bm{r}_{\text{rel}}\| – w_2 \|\bm{F}\|^2 + w_3 \cdot \mathbb{1}[\text{capture}] – w_4 \cdot \mathbb{1}[\text{collision}] $$

ここで $w_1, w_2, w_3, w_4$ は重み係数です。第1項は距離の縮小を促し、第2項は燃料消費を抑制し、第3項は捕獲成功に大きな正の報酬を、第4項は衝突に大きなペナルティを与えます。

軌道上組立

大型宇宙望遠鏡や宇宙太陽光発電所のような巨大構造物は、ロケットのフェアリングに収まりません。そこで、モジュール化された部品を軌道上で組み立てる必要があります。

軌道上組立でのRLの役割は、「どの順番で」「どのような動作で」部品を組み立てるかを学習することです。

部品の接続には精密な位置合わせ(ミリメートル精度)が必要であり、自由浮遊する部品の力学を考慮した力制御が求められます。RL方策は、力覚センサからのフィードバックに基づいて、インピーダンス制御のパラメータ(仮想剛性、仮想減衰)をリアルタイムに調整する形で実装されます。

自律ドッキング

故障した衛星への接近・ドッキングは、非協力的対象(cooperative でない対象)へのアプローチという難しい問題です。対象がビーコン信号を発していない場合、画像ベースの相対航法(ビジュアルサーボ)に頼る必要があります。

RL方策は、カメラ画像から直接スラスタの噴射指令を出力する End-to-End の学習が可能です。画像認識と制御を一体で学習することで、照明条件の変化や対象物の外見の違いに対する頑健性が向上します。

これらの応用に共通するのは、「失敗が許されない」という宇宙特有の制約です。次のセクションでは、この制約に対応するSafe RLの概念を解説します。

安全な探索(Safe RL)の重要性

なぜ安全性が必要か

標準的な強化学習アルゴリズムは、報酬を最大化するために「まず試してみて、悪ければ修正する」という探索戦略を取ります。しかし、宇宙ロボットでは一度の衝突が衛星の損傷や破壊につながるため、この無制約な探索は許されません。

Safe RL(安全な強化学習)は、制約条件を満たしながら報酬を最大化する枠組みです。数学的には 制約付きMDP(Constrained MDP, CMDP) として定式化されます。

制約付きMDPの定式化

CMDPは、標準のMDPにコスト関数 $C(s, a)$ と制約 $d$ を追加したものです。

$$ \max_{\pi} \quad \mathbb{E}_\pi \left[ \sum_{t=0}^{T} \gamma^t R(s_t, a_t) \right] $$

$$ \text{s.t.} \quad \mathbb{E}_\pi \left[ \sum_{t=0}^{T} \gamma^t C_i(s_t, a_t) \right] \leq d_i, \quad i = 1, \ldots, m $$

ここでコスト関数 $C_i$ は、安全に関わる指標です。宇宙ロボットの文脈では以下のようなものが典型的です。

  • 衝突回避コスト: $C_1(s, a) = \mathbb{1}[\|\bm{r}_{\text{rel}}\| < r_{\text{safe}}] \cdot v_{\text{approach}}$(安全距離内での接近速度)
  • 燃料消費コスト: $C_2(s, a) = \|\bm{F}\|$(推力の大きさ)
  • 関節トルク制限コスト: $C_3(s, a) = \max(0, \|\bm{\tau}\| – \tau_{\max})$(最大トルクの超過)

Lagrangian緩和法

CMDPを解く代表的な方法はLagrangian緩和法です。制約条件をラグランジュ乗数 $\lambda_i \geq 0$ でペナルティに変換し、次の最小最大問題を解きます。

$$ \min_{\lambda \geq 0} \max_{\pi} \quad \mathbb{E}_\pi \left[ \sum_{t=0}^{T} \gamma^t R(s_t, a_t) \right] – \sum_{i=1}^{m} \lambda_i \left( \mathbb{E}_\pi \left[ \sum_{t=0}^{T} \gamma^t C_i(s_t, a_t) \right] – d_i \right) $$

この式の意味を解説します。第1項は通常の累積報酬の最大化で、第2項が安全制約です。$\lambda_i$ が大きいほど制約違反のペナルティが大きくなります。

ラグランジュ乗数 $\lambda_i$ は方策 $\pi$ と交互に更新します。

方策の更新($\lambda$ 固定)では次のラグランジアンを最大化します。

$$ \mathcal{L}(\theta, \lambda) = J(\theta) – \sum_{i} \lambda_i (J_{C_i}(\theta) – d_i) $$

ラグランジュ乗数の更新($\pi$ 固定)では制約違反の度合いに応じて $\lambda$ を増減します。

$$ \lambda_i \leftarrow \max\left(0, \lambda_i + \alpha_\lambda (J_{C_i}(\theta) – d_i) \right) $$

ここで $\alpha_\lambda$ は乗数の学習率です。制約が守られていれば $J_{C_i}(\theta) – d_i < 0$ なので $\lambda_i$ は減少し、制約が破られていれば $\lambda_i$ は増加してペナルティを強化します。

シールドメカニズム

学習中にも安全を保証するために、安全シールド(Safety Shield) を方策の上に被せる手法もあります。RLエージェントが出力した行動が安全制約を満たすかをチェックし、違反する場合は最も近い安全な行動に修正します。

$$ a_{\text{safe}} = \arg\min_{a’ \in \mathcal{A}_{\text{safe}}} \|a’ – a_{\text{RL}}\|^2 $$

ここで $\mathcal{A}_{\text{safe}} = \{a \mid g(s, a) \leq 0\}$ は安全な行動の集合です。この射影操作により、学習中でも安全性が保証されます。

安全性の理論的枠組みを理解したところで、いよいよ実装に移りましょう。Pythonで簡単な2Dデブリキャプチャ環境を構築し、RLエージェントがデブリの捕獲を学習する様子を確認します。

Pythonで学ぶ: 2Dデブリキャプチャ環境でのRL学習

環境の設計

ここでは、2次元平面上でチェイサーが回転するデブリに接近・捕獲する問題を考えます。微小重力を模擬するため、重力は無視し、チェイサーはスラスタの噴射でのみ移動します。

環境の仕様は以下の通りです。

  • チェイサーは2次元推力($F_x$, $F_y$ 方向)を制御
  • デブリは一定の角速度で回転しつつ、ゆっくりドリフト
  • チェイサーがデブリの捕獲半径内に、十分低い相対速度で到達すれば成功
  • 衝突(高速接近)や燃料切れは失敗

まず、環境クラスを実装します。

import numpy as np
import matplotlib.pyplot as plt

class DebrisCaptureEnv:
    """2Dデブリキャプチャ環境(簡略版)"""

    def __init__(self, dt=0.1, max_steps=300, randomize=False):
        self.dt = dt
        self.max_steps = max_steps
        self.randomize = randomize  # ドメインランダマイゼーションフラグ

        # 公称パラメータ
        self.chaser_mass_nominal = 500.0    # チェイサー質量 [kg]
        self.max_thrust = 10.0              # 最大推力 [N]
        self.fuel_capacity = 50.0           # 燃料(推力積の上限)[N·s]
        self.capture_radius = 2.0           # 捕獲半径 [m]
        self.capture_max_speed = 0.5        # 捕獲許容相対速度 [m/s]
        self.collision_speed = 2.0          # 衝突判定速度 [m/s]

        # 状態次元: [rx, ry, vx, vy, debris_angle, fuel_remaining]
        self.obs_dim = 6
        self.act_dim = 2  # [Fx, Fy]

    def reset(self):
        # ドメインランダマイゼーション
        if self.randomize:
            self.chaser_mass = self.chaser_mass_nominal * np.random.uniform(0.7, 1.3)
            noise_std = np.random.uniform(0.0, 0.05)
        else:
            self.chaser_mass = self.chaser_mass_nominal
            noise_std = 0.0
        self.noise_std = noise_std

        # 初期状態: チェイサーとデブリの相対位置・速度
        self.rel_pos = np.array([
            np.random.uniform(15.0, 25.0),
            np.random.uniform(-10.0, 10.0)
        ])
        self.rel_vel = np.array([
            np.random.uniform(-0.5, 0.0),
            np.random.uniform(-0.3, 0.3)
        ])
        self.debris_angle = np.random.uniform(0, 2 * np.pi)
        self.debris_omega = np.random.uniform(0.1, 0.5)  # デブリ角速度 [rad/s]
        self.fuel = self.fuel_capacity
        self.step_count = 0
        self.trajectory = [self.rel_pos.copy()]

        return self._get_obs()

    def _get_obs(self):
        obs = np.array([
            self.rel_pos[0], self.rel_pos[1],
            self.rel_vel[0], self.rel_vel[1],
            np.cos(self.debris_angle),  # 角度を三角関数で表現
            self.fuel / self.fuel_capacity
        ])
        # センサノイズ
        obs += np.random.normal(0, self.noise_std, size=obs.shape)
        return obs

    def step(self, action):
        action = np.clip(action, -1.0, 1.0) * self.max_thrust
        thrust_mag = np.linalg.norm(action) * self.dt

        # 燃料消費
        self.fuel -= thrust_mag
        fuel_empty = self.fuel <= 0
        if fuel_empty:
            action = np.zeros(2)
            self.fuel = 0.0

        # 運動方程式(微小重力: 推力のみ)
        acc = action / self.chaser_mass
        self.rel_vel += acc * self.dt
        self.rel_pos -= self.rel_vel * self.dt  # 相対距離を縮める方向が正

        # デブリの回転更新
        self.debris_angle += self.debris_omega * self.dt

        self.step_count += 1
        self.trajectory.append(self.rel_pos.copy())

        # 判定
        dist = np.linalg.norm(self.rel_pos)
        speed = np.linalg.norm(self.rel_vel)

        done = False
        reward = -0.01  # 時間ペナルティ

        # 距離報酬(距離が縮むほど報酬)
        reward += -0.1 * dist / 25.0

        # 燃料効率
        reward += -0.05 * thrust_mag / (self.max_thrust * self.dt)

        # 捕獲成功
        if dist < self.capture_radius and speed < self.capture_max_speed:
            reward += 100.0
            done = True

        # 衝突(速すぎる接近)
        elif dist < self.capture_radius and speed >= self.collision_speed:
            reward += -50.0
            done = True

        # タイムアウトまたは燃料切れで遠すぎる
        if self.step_count >= self.max_steps:
            done = True

        return self._get_obs(), reward, done, {}

この環境クラスでは、randomize=True に設定するとドメインランダマイゼーションが有効になり、チェイサーの質量やセンサノイズがエピソードごとにランダムに変化します。これにより、特定のパラメータに過適合しない頑健な方策を学習できます。

次に、この環境を学習するための簡単なActor-Criticエージェントを実装します。

import numpy as np

class SimpleActorCritic:
    """簡易Actor-Criticエージェント(線形方策 + 線形価値関数)"""

    def __init__(self, obs_dim, act_dim, lr_actor=0.001, lr_critic=0.005, gamma=0.99):
        self.obs_dim = obs_dim
        self.act_dim = act_dim
        self.gamma = gamma
        self.lr_actor = lr_actor
        self.lr_critic = lr_critic

        # Actor: ガウス方策のパラメータ(平均を線形関数で近似)
        self.W_actor = np.random.randn(act_dim, obs_dim) * 0.01
        self.b_actor = np.zeros(act_dim)
        self.log_std = np.zeros(act_dim) - 0.5  # 初期標準偏差

        # Critic: 線形価値関数
        self.W_critic = np.random.randn(obs_dim) * 0.01
        self.b_critic = 0.0

    def get_action(self, obs):
        mean = self.W_actor @ obs + self.b_actor
        std = np.exp(self.log_std)
        action = mean + std * np.random.randn(self.act_dim)
        return np.clip(action, -1.0, 1.0), mean, std

    def get_value(self, obs):
        return self.W_critic @ obs + self.b_critic

    def update(self, obs, action, reward, next_obs, done):
        # TD誤差の計算
        v = self.get_value(obs)
        v_next = 0.0 if done else self.get_value(next_obs)
        td_error = reward + self.gamma * v_next - v

        # Critic更新(TD誤差の最小化)
        self.W_critic += self.lr_critic * td_error * obs
        self.b_critic += self.lr_critic * td_error

        # Actor更新(方策勾配)
        mean = self.W_actor @ obs + self.b_actor
        std = np.exp(self.log_std)

        # ガウス方策の対数尤度の勾配
        diff = (action - mean) / (std ** 2)
        grad_W = np.outer(diff, obs)
        grad_b = diff
        grad_log_std = (action - mean) ** 2 / (std ** 2) - 1.0

        # アドバンテージで重み付けして更新
        self.W_actor += self.lr_actor * td_error * grad_W
        self.b_actor += self.lr_actor * td_error * grad_b
        self.log_std += self.lr_actor * 0.1 * td_error * grad_log_std
        self.log_std = np.clip(self.log_std, -2.0, 0.5)

Actor-Criticエージェントは、ガウス方策(平均値を線形関数で近似、標準偏差はグローバルパラメータ)とTD学習による価値関数更新を行います。本来は深層ニューラルネットを使いますが、ここでは教育目的で線形近似を使い、学習の原理を明確にしています。

学習の実行と比較

ドメインランダマイゼーションの有無による学習性能の違いを比較します。

import numpy as np
import matplotlib.pyplot as plt

def train_agent(randomize, n_episodes=1500, seed=42):
    """エージェントを学習させ、エピソード報酬の推移を返す"""
    np.random.seed(seed)
    env = DebrisCaptureEnv(randomize=randomize)
    agent = SimpleActorCritic(obs_dim=env.obs_dim, act_dim=env.act_dim)

    episode_rewards = []

    for ep in range(n_episodes):
        obs = env.reset()
        total_reward = 0.0

        while True:
            action, _, _ = agent.get_action(obs)
            next_obs, reward, done, _ = env.step(action)
            agent.update(obs, action, reward, next_obs, done)

            obs = next_obs
            total_reward += reward

            if done:
                break

        episode_rewards.append(total_reward)

    return episode_rewards, agent

# 標準環境(ランダマイゼーションなし)で学習
rewards_standard, agent_standard = train_agent(randomize=False, seed=42)

# ドメインランダマイゼーションありで学習
rewards_dr, agent_dr = train_agent(randomize=True, seed=42)

# 学習曲線の可視化
window = 50
rewards_std_smooth = np.convolve(rewards_standard, np.ones(window)/window, mode='valid')
rewards_dr_smooth = np.convolve(rewards_dr, np.ones(window)/window, mode='valid')

plt.figure(figsize=(10, 5))
plt.plot(rewards_std_smooth, label='Standard (no randomization)', alpha=0.9)
plt.plot(rewards_dr_smooth, label='Domain Randomization', alpha=0.9)
plt.xlabel('Episode')
plt.ylabel('Episode Reward (moving average)')
plt.title('Training Curves: Standard vs Domain Randomization')
plt.legend()
plt.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()

上のグラフから、2つの重要な傾向が読み取れます。

  1. 標準環境での学習は初期に速く報酬が上昇する: ランダマイゼーションなしの環境は常に同じパラメータなので、エージェントはその特定の環境に素早く適応します。しかし、これは「過適合」であり、パラメータが変わると性能が大きく低下するリスクがあります。

  2. ドメインランダマイゼーション環境での学習は初期に遅いが安定する: 毎エピソードでパラメータが変わるため、初期の学習は遅くなります。しかし、多様な環境を経験することで、パラメータの変動に対して頑健な方策が獲得されます。長期的には安定した性能に収束していきます。

転移性能の評価

学習した方策を「未知の環境」(学習時と異なるパラメータ設定)でテストして、転移性能を評価します。

import numpy as np
import matplotlib.pyplot as plt

def evaluate_transfer(agent, n_eval=200, mass_ratio=1.4, noise_std=0.08, seed=123):
    """学習時と異なるパラメータ環境でエージェントを評価"""
    np.random.seed(seed)
    env = DebrisCaptureEnv(randomize=False)

    successes = 0
    collisions = 0
    timeouts = 0
    total_rewards = []

    for _ in range(n_eval):
        obs = env.reset()
        # 転移先の未知パラメータ
        env.chaser_mass = env.chaser_mass_nominal * mass_ratio
        env.noise_std = noise_std

        total_reward = 0.0
        while True:
            action, _, _ = agent.get_action(obs)
            # 評価時は決定的方策(平均値を使用)
            action = agent.W_actor @ obs + agent.b_actor
            action = np.clip(action, -1.0, 1.0)

            next_obs, reward, done, _ = env.step(action)
            obs = next_obs
            total_reward += reward

            if done:
                dist = np.linalg.norm(env.rel_pos)
                speed = np.linalg.norm(env.rel_vel)
                if dist < env.capture_radius and speed < env.capture_max_speed:
                    successes += 1
                elif dist < env.capture_radius and speed >= env.collision_speed:
                    collisions += 1
                else:
                    timeouts += 1
                break

        total_rewards.append(total_reward)

    return {
        'success_rate': successes / n_eval,
        'collision_rate': collisions / n_eval,
        'timeout_rate': timeouts / n_eval,
        'mean_reward': np.mean(total_rewards)
    }

# 標準エージェントの転移性能
results_std = evaluate_transfer(agent_standard, mass_ratio=1.4, noise_std=0.08)
# DRエージェントの転移性能
results_dr = evaluate_transfer(agent_dr, mass_ratio=1.4, noise_std=0.08)

# 結果の可視化
labels = ['Success Rate', 'Collision Rate', 'Timeout Rate']
std_vals = [results_std['success_rate'], results_std['collision_rate'], results_std['timeout_rate']]
dr_vals = [results_dr['success_rate'], results_dr['collision_rate'], results_dr['timeout_rate']]

x = np.arange(len(labels))
width = 0.35

fig, ax = plt.subplots(figsize=(9, 5))
bars1 = ax.bar(x - width/2, std_vals, width, label='Standard', color='#e74c3c', alpha=0.8)
bars2 = ax.bar(x + width/2, dr_vals, width, label='Domain Randomization', color='#2ecc71', alpha=0.8)

ax.set_ylabel('Rate')
ax.set_title('Transfer Performance: Standard vs Domain Randomization\n(mass ratio=1.4, noise_std=0.08)')
ax.set_xticks(x)
ax.set_xticklabels(labels)
ax.legend()
ax.set_ylim(0, 1.0)
ax.grid(True, axis='y', alpha=0.3)

# 数値を棒の上に表示
for bar in bars1:
    h = bar.get_height()
    ax.annotate(f'{h:.2f}', xy=(bar.get_x() + bar.get_width()/2, h),
                xytext=(0, 3), textcoords='offset points', ha='center', fontsize=10)
for bar in bars2:
    h = bar.get_height()
    ax.annotate(f'{h:.2f}', xy=(bar.get_x() + bar.get_width()/2, h),
                xytext=(0, 3), textcoords='offset points', ha='center', fontsize=10)

plt.tight_layout()
plt.show()

print(f"Standard Agent - Success: {results_std['success_rate']:.2%}, "
      f"Collision: {results_std['collision_rate']:.2%}, "
      f"Mean Reward: {results_std['mean_reward']:.1f}")
print(f"DR Agent      - Success: {results_dr['success_rate']:.2%}, "
      f"Collision: {results_dr['collision_rate']:.2%}, "
      f"Mean Reward: {results_dr['mean_reward']:.1f}")

この転移性能テストの結果から、以下のことがわかります。

  1. 標準エージェントは未知環境での性能が大幅に低下する: 学習時の環境パラメータ(質量比1.0、ノイズなし)に特化しているため、質量比が1.4、ノイズ標準偏差が0.08という未知の条件では成功率が低下し、衝突率が上昇します。これは宇宙ミッションでは許容できないリスクです。

  2. ドメインランダマイゼーションエージェントは転移に強い: 学習時に様々なパラメータを経験しているため、未知のパラメータ設定でも比較的安定した性能を維持します。質量が40%増加しセンサノイズが加わっても、成功率の低下が抑えられています。

  3. 特に衝突率の差に注目: 宇宙ロボットでは衝突は致命的です。ドメインランダマイゼーションにより衝突率が抑制されている点は、安全性の観点から非常に重要です。

軌跡の可視化

最後に、学習済みエージェントのデブリ接近軌跡を可視化します。

import numpy as np
import matplotlib.pyplot as plt

def visualize_trajectory(agent, randomize=False, seed=99):
    """エージェントのデブリ捕獲軌跡を可視化"""
    np.random.seed(seed)
    env = DebrisCaptureEnv(randomize=randomize)
    obs = env.reset()

    positions = [env.rel_pos.copy()]
    velocities = [np.linalg.norm(env.rel_vel)]
    thrusts = []

    while True:
        action = agent.W_actor @ obs + agent.b_actor
        action = np.clip(action, -1.0, 1.0)
        thrusts.append(np.linalg.norm(action))

        obs, reward, done, _ = env.step(action)
        positions.append(env.rel_pos.copy())
        velocities.append(np.linalg.norm(env.rel_vel))

        if done:
            break

    positions = np.array(positions)

    fig, axes = plt.subplots(1, 3, figsize=(15, 5))

    # 軌跡
    ax = axes[0]
    ax.plot(positions[:, 0], positions[:, 1], 'b-', linewidth=1.5, alpha=0.7)
    ax.plot(positions[0, 0], positions[0, 1], 'go', markersize=10, label='Start')
    ax.plot(positions[-1, 0], positions[-1, 1], 'r^', markersize=10, label='End')
    circle = plt.Circle((0, 0), env.capture_radius, color='orange',
                         fill=False, linestyle='--', linewidth=2, label='Capture zone')
    ax.add_patch(circle)
    ax.plot(0, 0, 'kx', markersize=15, markeredgewidth=3, label='Debris')
    ax.set_xlabel('Relative X [m]')
    ax.set_ylabel('Relative Y [m]')
    ax.set_title('Approach Trajectory')
    ax.legend(fontsize=8)
    ax.set_aspect('equal')
    ax.grid(True, alpha=0.3)

    # 速度プロファイル
    ax = axes[1]
    ax.plot(velocities, 'r-', linewidth=1.5)
    ax.axhline(y=env.capture_max_speed, color='g', linestyle='--',
               label=f'Max capture speed ({env.capture_max_speed} m/s)')
    ax.set_xlabel('Time Step')
    ax.set_ylabel('Relative Speed [m/s]')
    ax.set_title('Speed Profile')
    ax.legend(fontsize=8)
    ax.grid(True, alpha=0.3)

    # 推力プロファイル
    ax = axes[2]
    ax.plot(thrusts, 'purple', linewidth=1.5)
    ax.set_xlabel('Time Step')
    ax.set_ylabel('Thrust Magnitude (normalized)')
    ax.set_title('Thrust Profile')
    ax.grid(True, alpha=0.3)

    plt.suptitle('Debris Capture Mission Visualization', fontsize=14, y=1.02)
    plt.tight_layout()
    plt.show()

visualize_trajectory(agent_dr)

この3つのグラフから、学習済みエージェントの振る舞いを分析できます。

  1. 接近軌跡(左図): エージェントはデブリ(原点)に向かって曲線的な軌跡で接近しています。直線的な最短経路ではなく、速度を適切に調整しながら接近していることがわかります。これは捕獲時の相対速度条件を満たすために必要な振る舞いです。

  2. 速度プロファイル(中図): 接近の初期段階では加速してデブリに向かい、捕獲ゾーンに近づくにつれて減速しています。最終的に捕獲許容速度(緑の破線)以下に減速してから捕獲を試みていることがわかります。この「加速→減速」パターンは、人間の宇宙飛行士が行うランデブー操作と定性的に一致します。

  3. 推力プロファイル(右図): 推力は接近初期と最終減速フェーズで大きく、中間では小さくなっています。これは燃料効率を考慮した合理的な制御戦略であり、RL エージェントが報酬関数の燃料ペナルティを学習した結果です。

Sim-to-Realパイプラインの全体像

ここまでの内容をまとめて、宇宙ロボットへのRL適用のパイプライン全体を整理しましょう。

ステップ1: シミュレーション環境の構築

まず、宇宙環境の物理シミュレータを構築します。必要な要素は以下の通りです。

  • 軌道力学: 重力場、摂動(J2、大気抵抗、太陽放射圧)
  • ロボットダイナミクス: 多体剛体力学、関節モデル
  • 接触力学: 衝突、把持、摩擦
  • センサモデル: カメラ、IMU、力覚センサのノイズモデル
  • アクチュエータモデル: 応答遅延、飽和、量子化

ステップ2: 報酬関数の設計

報酬関数は、ミッションの目的を数値化したものです。デブリキャプチャの例では、距離の縮小、安全な速度、燃料効率、最終的な捕獲成功を組み合わせます。報酬の設計は強化学習の性能を大きく左右するため、ドメイン知識を活用した慎重な設計が必要です。

ステップ3: ドメインランダマイゼーション付き学習

前述のドメインランダマイゼーションを適用して学習します。ADRを使って、方策の能力に応じてランダム化の範囲を自動調整するのが理想的です。

ステップ4: 安全制約の組み込み

Safe RLのフレームワーク(CMDP + Lagrangian緩和、安全シールド)を適用して、制約を満たす方策を獲得します。

ステップ5: 地上検証

学習した方策を、以下の段階で検証します。

  1. シミュレーション内テスト: 学習時に使わなかったパラメータ設定でテスト
  2. Hardware-in-the-Loop(HIL)テスト: 実物のプロセッサでの推論速度検証
  3. 地上施設でのテスト: エアベアリングテーブルや水中施設での実験

ステップ6: 軌道上検証と運用

最終的に実際の宇宙環境での検証を行います。初期はセーフモード(安全シールド付き)で運用し、性能が確認できたら徐々に自律度を上げていきます。

ここで、ステップ3のドメインランダマイゼーションの効果をより定量的に評価してみましょう。様々な環境パラメータの変動に対する頑健性を可視化します。

import numpy as np
import matplotlib.pyplot as plt

def robustness_evaluation(agent, mass_ratios, noise_levels, n_eval=100, seed=200):
    """様々なパラメータ設定での成功率をヒートマップで可視化"""
    np.random.seed(seed)
    success_map = np.zeros((len(noise_levels), len(mass_ratios)))

    for i, noise in enumerate(noise_levels):
        for j, mass_r in enumerate(mass_ratios):
            env = DebrisCaptureEnv(randomize=False)
            successes = 0

            for _ in range(n_eval):
                obs = env.reset()
                env.chaser_mass = env.chaser_mass_nominal * mass_r
                env.noise_std = noise

                while True:
                    action = agent.W_actor @ obs + agent.b_actor
                    action = np.clip(action, -1.0, 1.0)
                    obs, _, done, _ = env.step(action)

                    if done:
                        dist = np.linalg.norm(env.rel_pos)
                        speed = np.linalg.norm(env.rel_vel)
                        if dist < env.capture_radius and speed < env.capture_max_speed:
                            successes += 1
                        break

            success_map[i, j] = successes / n_eval

    return success_map

mass_ratios = [0.6, 0.8, 1.0, 1.2, 1.4, 1.6]
noise_levels = [0.0, 0.02, 0.04, 0.06, 0.08, 0.10]

# 両方のエージェントの頑健性マップを計算
rob_std = robustness_evaluation(agent_standard, mass_ratios, noise_levels)
rob_dr = robustness_evaluation(agent_dr, mass_ratios, noise_levels)

fig, axes = plt.subplots(1, 2, figsize=(14, 5))

for ax, data, title in zip(axes, [rob_std, rob_dr],
                            ['Standard Agent', 'Domain Randomization Agent']):
    im = ax.imshow(data, cmap='RdYlGn', vmin=0, vmax=1, aspect='auto',
                   origin='lower')
    ax.set_xticks(range(len(mass_ratios)))
    ax.set_xticklabels([f'{m:.1f}' for m in mass_ratios])
    ax.set_yticks(range(len(noise_levels)))
    ax.set_yticklabels([f'{n:.2f}' for n in noise_levels])
    ax.set_xlabel('Mass Ratio')
    ax.set_ylabel('Sensor Noise Std')
    ax.set_title(title)

    # 各セルに数値を表示
    for i in range(len(noise_levels)):
        for j in range(len(mass_ratios)):
            color = 'white' if data[i, j] < 0.5 else 'black'
            ax.text(j, i, f'{data[i, j]:.2f}', ha='center', va='center',
                    color=color, fontsize=9)

plt.colorbar(im, ax=axes, label='Success Rate', shrink=0.8)
plt.suptitle('Robustness Map: Success Rate under Parameter Variations', fontsize=13)
plt.tight_layout()
plt.show()

この頑健性マップ(ヒートマップ)は、2つのエージェントの転移性能の違いを鮮明に示しています。

  1. 標準エージェント(左図): 学習時の条件(質量比1.0、ノイズ0.0)の付近でのみ高い成功率を示し、パラメータが変化すると急激に性能が低下します。特に質量比が1.4以上になると成功率がほぼゼロに近づきます。これは方策が特定の環境パラメータに「過適合」している状態です。

  2. ドメインランダマイゼーションエージェント(右図): 広いパラメータ範囲にわたって安定した成功率を維持しています。質量比0.6〜1.6、ノイズ0.0〜0.10という広い範囲で一定の性能を保っており、まさにSim-to-Real転移に必要な頑健性を持っています。

  3. 実用上の意味: 宇宙ミッションでは、対象物の質量は事前に正確にわからないことが多く、センサノイズも温度変化や放射線の影響で変動します。ドメインランダマイゼーションにより、このような不確実性に対して頑健な方策を獲得できることが、この結果から確認できます。

まとめ

本記事では、宇宙ロボットへの強化学習の適用について、Sim-to-Real転移を中心に解説しました。

  • 強化学習の宇宙適用の動機: 未知環境への適応能力が必要であり、事前にすべてのシナリオをプログラムすることは不可能
  • Sim-to-Real転移の戦略: Reality Gapを埋めるために、システム同定、ドメインランダマイゼーション、ドメイン適応の3つのアプローチが存在する
  • ドメインランダマイゼーション: 物理パラメータやセンサノイズをランダム化して学習することで、実環境のパラメータ変動に頑健な方策を獲得できる
  • 宇宙特有の課題: 微小重力環境の特殊な力学、放射線によるハードウェア制約、計算資源の限界、地上検証の困難さ
  • Safe RL: 制約付きMDP(CMDP)やLagrangian緩和法、安全シールドにより、安全制約を満たしながら報酬を最大化する
  • Pythonデモ: 2Dデブリキャプチャ環境でActor-Criticエージェントを学習させ、ドメインランダマイゼーションが転移性能を大幅に向上させることを確認した

宇宙ロボットへの強化学習の適用は、まだ研究段階の技術が多いですが、ESAのe.Deorbitミッションやアストロスケールのデブリ除去ミッション、NASAのISAM(In-Space Assembly and Manufacturing)計画など、実用化に向けた動きが加速しています。

今後の発展として、マルチエージェント強化学習(複数ロボットの協調作業)、メタ学習(新しいタスクへの迅速な適応)、説明可能なRL(方策の判断根拠の理解)が重要な研究方向です。

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