つらつらと、はじめての制御工学 を読んで、やっとこさ PID 制御のところを過ぎて講座12のボード線図のところに来たところですが、C#版をF#版に直します。F# なのだから、関数型っぽい式の作り方とか制御工学で使われている変数をそのまま流用するとかしたいところなのですが、そのあたりはまだ理解&コードの読み進めが足りず…ひとまず、C#からF#にコンバートして倒立振子できるところまでいきました。
コード
moonmile/MonoBalancer
https://github.com/moonmile/MonoBalancer
ここの MonoBalancerF が F# のコードです。
Xamarin Studio で F# プロジェクトを作る
MonoBrick を使う場合、Xamarin Stduio を使う方法と Visual Studio + WinSCP を使う方法の2種類がありますが、Xamarin Studio で最初のプロジェクトを作ります。
プロジェクトができあがったら、参照設定で「MonoBrickFirmware」がきちんと参照されていることを確認して(なぜか時々エラーになるので、そのときはいったん削除してもう一度参照すればokです)、おもむろに F# でコーディングをします。
Xamarin Studio で F# プロジェクトをビルドする
なぜか、ビルドをするときは「有効なランタイム」を「Microsoft .NET」にしておきます。Mono のほうだとビルドできないんですよね。環境の違いかもしれませんが。
でもって、デバッグ実行するときは「Mono 4.0.3…」に直してデプロイをします。このあたりが面倒なのですが、仕方がない。
デバッグ実行する
Xamarin Studio でデバッグ実行をすると MonoBrick にアセンブリがアップロードされて、そのまま実行されます。このときには、「有効なランタイム」を「Mono 4.0.3…」にしておきます。
そうすると暫く時間が立つと EV3 + MonoBrick で F# のコードが実行されます…が、この立ち上がりが結構を遅くて閉口するので、アップロードだけ Xamarin Studio に任せて、その後は Tera Term で MonoBrick に接続して直接立ち上げます。このほうが、コンソールを使えるのでログ出力とかできて便利です。
デバッグ実行で Upload program to brick … が終わったあたりで、ぶちっと止めてしまいます。止めるぐらいだから、WinSCP でアップロードしても同じなんですが、まあ、Xamarin Studio だけでできるのでこれはこれで便利。
その後で、適当なターミナルで接続して、apps フォルダ内にあるアセンブリを直接起動します。
mono MonoBalancerF.exe
のようにして起動します。ターミナルを使うと Console.WriteLine(“MonoBalancer start…”) のようなコンソール出力が見れるので、EV3 のディスプレイに出さなくてもデバッグがやりやすくなります。まあ、TCP/IP 通信しているので、転送スピードを考えてログの出力は控えめにしないといけませんが。
mono が 4.0 ベースだからなのか、非常に F# の立ち上がりが遅いです。ロボットの倒立が始まるまで5秒以上待たされるのは、Thread 生成が遅いのかコードが悪いのかわかりませんが、まあ、C# 版よりもスタートに時間がかかります。時間はかかりますが、20msec でジャイロセンサーの値を読み取って、倒立できるぐらいまでのスピードは出ているので実用的でしょう。
何故 F# で作るのか?
ロボット制御の場合、たいていの制御プログラムは C/C++ で書かれているのでオブジェクト指向的に書かれているものが多いのですが、関数型言語で書いたらどうなるのかなというのと、制御の式あたりは関数型で書いたほうが色々とデバッグ/試行錯誤しやすいだろう、という発想がもとです。
SketchBot doing Turtle Graphics! – YouTube
も MonoBrick + F# で書かれていたりします。