制御のゲーム

# １．はじめに
倒立振子のレースゲーム[Paul Kart](https://hppyctrlengnrng.github.io/paul_kart_publish/)を作りました。
(サイズがでかいのでCtrl-で適宜縮小推奨)
![無題1.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/b7ed0197-bfc8-5672-5626-62c59e8d3aaa.gif)

# ２．遊び方
とりあえずタイムアタックモードのみ実装しています。トップ画面から
[**START GAME**]→[**Select Stage**]でゲーム画面へ遷移できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/27875b5b-1cae-7e83-321f-94293d7bd94e.png)

## ２．１操作方法
デフォルトの操作は以下の通りです。

- WASD: 並進移動
- QE: 回転

## ２．２エネルギーの制限
**制御入力に利用できるエネルギーには制限があり**、エネルギー残量以上の制御入力は実行できません。ポールカート背面のゲージでエネルギー残量を確認できます。エネルギー残量は時間経過により回復します。

# ３．制御系の調整、設計
本ゲームではポールカートの操作に用いる制御系の調整と設計を行うことができます。制御器はデフォルトの可調整パラメータ付きの**PID制御器**か、**WebSocket通信**を経由した外部アプリケーションから選択可能です。

倒立振子「ポールカート」各部詳細
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/62ee55e2-c1f6-4980-a5ac-2dc18644b0c5.png)

- Paul: 
- Pole: 振子本体
- Flywheel：振子の上下軸回転制御のためのフライホイール
- Wheel: 振子の並進移動のための球状車輪
- Energy Indicator: 制御入力に利用できるエネルギー残量表示

## ３．１ポールカートのアクチュエータ
ポールカートには以下２種類のアクチュエータが搭載されています。

- ホイール：ポールカート底面の球状の車輪です。ポールの前後方向および左右方向に駆動します。
- フライホイール：ポール中央部のフライホイールです。上下軸周りの回転を制御します。

## ３．２ポールカートの座標系とセンサ

ポールカートの座標系は右-上-前の左手系で表現されます。各アクチュエータの回転方向も各軸左ねじ方向を正と定義します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/3283a0bc-9b62-ba76-3fee-11c7573e32be.png)

ポールカートの制御のため、以下の情報がセンサから取得可能です。

### ３．２．１ポール姿勢
ポールの姿勢は、ポール座標系と、ポール座標系の上下軸が鉛直上向きとなるように平面上で回転させた座標系との各軸の角度差で計測されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/e02982df-1805-5141-e160-21077ed1bc65.png)

### ３．２．２ポール角速度
ポール座標系各軸周りの角速度です。

### ３．２．３ホイール角速度
球状ホイールの各軸周りの角速度です。

### ３．２．４フライホイール角速度
ポール座標系上下軸周りの角速度です。

## ３．３制御方式

### ３．３．１デフォルトPID制御器

トップ画面の[CONTROL DESIGN]で制御設計画面に遷移し、[Type]をDefault PIDとすることで利用するコントローラをPIDに切り替えて調整、走行が可能となります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/3b7f1643-c67a-8e47-99dc-5096910239cc.png)

この画面でパラメータを調節し、Applyすることで制御器を調整できます。転倒した場合は[Reset]してください。

デフォルトPID制御器では、$x$, $y$, $z$の３軸のPID制御器が構成されています。$x$および$z$軸の制御器はそれぞれ左右軸、前後軸方向にホイールを駆動し安定化を行います。ユーザ制御はアクチュエータへのオフセット入力として印加されます。

$y$軸の制御器は上下軸回りの回転安定化のため、角速度0を目標に安定化制御を行います。ユーザ制御は目標角速度へのオフセット入力として印加されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/788180c0-a43e-0798-638d-35d288bb1ede.png)

### ３．３．２カスタムWebSocket通信

より高い設計自由度のため、WebSocket通信を用いて外部アプリケーションによる制御を行うことができます。外部アプリケーションの一例としてPythonおよびMATLABを用いた[実装サンプル](https://github.com/HppyCtrlEngnrng/paul_kart_controller)を用意しています。

WebSocket制御器を利用するためには、制御設計画面で[Type]をCustom WebSocketに設定します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/211913/b92992a5-0f55-0b40-5cec-154f648a854a.png)

センサ情報は以下の41バイトのデータで送信されます。

信号名 | 型 | バイト長
--|--|--|
リセットフラグ(制御器の初期化時に1) | uint8 | 1 |
ポール角度x | float32 | 4 |
ポール角度y | float32 | 4 |
ポール角度z | float32 | 4 |
ポール角速度x | float32 | 4 |
ポール角速度y | float32 | 4 |
ポール角速度z | float32 | 4 |
ホイール角速度x | float32 | 4 |
ホイール角速度y | float32 | 4 |
ホイール角速度z | float32 | 4 |
フライホイール角速度y | float32 | 4 |

外部アプリケーションが返す制御入力は以下の12バイトで送信されます。

信号名 | 型 | バイト長
--|--|--|
ホイール入力トルクx | float32 | 4 |
フライホイール入力トルクy | float32 | 4 |
ホイール入力トルクz | float32 | 4 |