生成AIコンテスト！AIが作成した制御プログラムを箱庭ドローンシミュレータで走らせて比較してみよう！！

# はじめに

進化が激しい生成AIの優秀さを競うコンテストをシミュレータでやってみました。

利用したのは、今流行りの[箱庭ドローンシミュレータ](https://github.com/toppers/hakoniwa-px4sim)です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244147/49e221d8-1c8b-3525-e810-7dc1d74a567f.png)

# 選手紹介

コンテストに参加するのは、以下の３名です。

* **ChatGPT3.5**
  * OpenAIによって開発された初期バージョンの言語生成AIで、そのアクセシビリティの高さから多くの開発者に利用されています。基本的なドローン制御プログラムを生成する能力を持つかどうか、このコンテストで試されます。
* **ChatGPT4**
  * ChatGPTシリーズの最新版であり、前バージョンよりも洗練された言語理解と生成能力を持ちます。この進化したAIがどのように複雑なプログラミングタスク、特にドローン制御における課題に対処できるかが注目されます。
* **Gemini**
  * Googleからリリースされた新しい生成AIで、創造性と独自のアプローチで知られています。ドローン制御という具体的な技術的課題への取り組みにおいて、どのようなユニークな解決策を提案できるかが見どころです。

# 競技内容

[ドローンをホバリング制御する課題](https://github.com/toppers/hakoniwa-px4sim/blob/main/drone_control/README.md)を解いてもらいます。

## コード生成してもらうためのプロンプト

```
あなたは、ドローン制御プログラム向けの演習課題を作成している大学教授です。
以下の演習プログラムの解説を作成しました。制御の専門家として、
学生向けに答えとなるプログラムを作成してください。
この際、PID制御パラメータの導出理由も合わせて解説してください
```

## 課題

ドローンを 10m 浮上させてホバリングしてください。

評価ポイントは以下のとおりです。

* 50点：100 秒後にホバリング状態になっていること
* 30点: ホバリングするまでの時間が 10秒以内
* 20点: オーバーシュートが 1m以内

## 演習内容
### 前提とする情報

* 質量：0.1kg
* シミュレーション時間ステップ：3msec

### プログラミング言語

C/C++言語で作成します。

### ファイル構成

`hako_module_drone_controller_impl.cpp` を実装します。

```
drone_control
├── CMakeLists.txt
├── README.md
├── cmake-build
├── include
│   └── hako_module_drone_controller.h
└── workspace
    ├── DroneAvator
    │   ├── CMakeLists.txt
    │   └── hako_module_drone_controller_impl.cpp
    ├── hako_module_drone_controller.c
    └── hako_module_drone_controller_impl.h
```

### プログラム構成

以下の２関数を実装してください。

* hako_module_drone_controller_impl_init
  * プログラム起動時に１回だけ呼び出されます。制御に必要な初期化処理を実装します。
  * 成功した場合は 0 を返してください。失敗した場合は 0 以外の値を返します。
* hako_module_drone_controller_impl_run
  * 制御タイミング毎に呼び出されます。ホバリング制御に必要な処理を実装します。
  * 入力引数 in に、ドローンの状態（位置と姿勢角）が与えられます。
  * 戻り値には、ドローンの制御指示値(推力とトルク)を返します。

**実装対象関数:**
`TODO` 部分を書き換えてください。
```
int hako_module_drone_controller_impl_init(void* context)
{
    //TODO
}

mi_drone_control_out_t hako_module_drone_controller_impl_run(mi_drone_control_in_t *in)
{
    //TODO
}
```

### 入出力データ情報

#### mi_drone_control_in_t

現在の機体の位置と姿勢情報です。

**データ型:**
```
typedef struct {
    double pos_x;
    double pos_y;
    double pos_z;
    double euler_x;
    double euler_y;
    double euler_z;
} mi_drone_control_in_t;
```
* 座標系：NED
* pos_x, pos_y, pos_z
  * 単位：メートル
  * pos_x: North
  * pos_y: East
  * pos_z: Down
  * 初期値：全て 0 
* euler_x, euler_y, euler_z
  * 単位：ラジアン
  * euler_x: x軸方向の角度（ロール）
  * euler_y: y軸方向の角度（ピッチ）
  * euler_z: z軸方向の角度（ヨー）
  * 初期値：全て 0 

#### mi_drone_control_out_t

機体への制御出力情報です。

**データ型:**
```
typedef struct {
    double thrust;
    double torque_x;
    double torque_y;
    double torque_z;
} mi_drone_control_out_t;
```
* thrust
  * 単位：Newton (N)
  * 機体の垂直方向の推力
* torque_x, torque_y, torque_z
  * 単位：Newton-meter (Nm)
  * torque_x: ロール方向のトルク
  * torque_y: ピッチ方向のトルク
  * torque_z: ヨー方向のトルク

# ３者の成果物

生成されたコードは以下で一般公開しています。

* **[ChatGPT3.5](https://github.com/toppers/hakoniwa-px4sim/blob/main/drone_control/workspace/ChatGPT3_5/hako_module_drone_controller_impl.cpp)**
* **[ChatGPT4](https://github.com/toppers/hakoniwa-px4sim/blob/main/drone_control/workspace/ChatGPT4/hako_module_drone_controller_impl.cpp)**
* **[Gemini](https://github.com/toppers/hakoniwa-px4sim/blob/main/drone_control/workspace/Gemini/hako_module_drone_controller_impl.cpp)**

# よーい、ドン！


https://twitter.com/kanetugu2020/status/1759422532741136754

# 勝者

<p><strong style="color: red;">ご覧の通り、勝者は、圧倒的な安定性を見せつけた <code>ChatGPT4</code>に軍配が上がりました！</strong></p>


以下、細かな評価内容です。

* ChatGPT3.5
  * コンパイルには成功しましたが、動作しませんでした。微修正後には動作するようになりましたが、点数は獲得できませんでした。動画は微修正後のものです。
* ChatGPT4
  * コンパイルも動作できましたし、ホバリングできています！ただし、ホバリング時間とオーバーシュートが目標値にかろうじて到達できずでした。なので、50点という評価です。惜しい。
* Gemini
  * コンパイルに失敗し、動作テストにも進めませんでしたが、微修正により動作可能になりましたがが、ChatGPT3.5と同様に点数は獲得できませんでした。動画は微修正後のものです。

|参加者|コンパイル可否|動作可否|微修正による動作可否|点数|所感|
|---|---|---|---|---|---|
|ChatGPT3.5|○|×|○|0|もう少し頑張ろう|
|ChatGPT4|○|○|○|50|良くできました|
|Gemini|×|×|○|0|もう少し頑張ろう|

# 勝敗を分けたコードはどこか？

勝敗を分けたコードを見てみましょう。

まずは、ChatGPT4のコード断片です。

**ChatGPT４:**
```
double error = target_altitude + in->pos_z; // 目標との偏差計算(NED座標系なので、+にする)
```

コメントにある通り、座標系がNEDなので、Z軸の値は浮上するとマイナスになります。なので、ChatGPT4は`+`にしています。素晴らしい。

一方で、その他の競技者ここで引っかかってしまっています。

**ChatGPT3.5:**
```
// 目標高度
#define TARGET_ALTITUDE 10.0
// 現在の高度を取得
double current_altitude = in->pos_z;
// 高度の誤差を計算
double error = TARGET_ALTITUDE - current_altitude;
```

**Gemini:**
```
// 高度偏差の計算
double error_z = 10.0 - in->pos_z;
```

# 総評

今回のコンテストの結果ですが、ChatGPT4が優勝することになりましたが、他の競技者もそれなりに動作できるところまで持ってきています。PID制御の一般的な知識はお持ちのようでした。

PID制御パラメータは、試行錯誤しながら進めていく形になるのは致し方ないところもありますから、初期コードでここまでの成果を出せたところは評価すべきですよね。

今後、LangChainなどを利用して、生成AIにシミュレータと連携させて実験させながらPID制御パラメータをチューニングさせると面白そうですよね。