LEGO Mindstorms EV3+MonoBrick+F# で倒立振子ロボット

F# Advent Calendar 2015 – connpass の 12日目です。

中身的には 倒立振子ロボットを MonoBrick で作成する(F#編) | Moonmile Solutions Blog の延長線上で、何故 F#(関数型言語)でロボット制御をやろうとするのか?ってのをつらつらと書いていきます。

C# 版は、EV3 + MonoBrick + C# なスライドを参照して貰うということで、計算のところを少し突っ込んで行きます。

物理方程式を解く

実は、制御工学を習ったことが無かったので知らなかったのですが、倒立振子ロボットのように「状態の変化に対して少しずつ対応していく」という方式は単純な線形の式で表せます。線形と非線形の違いは、直線近似とそれ以外の複雑な変化を解くという違いにもなりますが、ある意味で物理現象のような「とある時刻 t の状態から、少し異なった t+Δt の状態を予測する」という場合には、線形に近似をしても問題はありません。Δt のサンプリング周期にも依りますが、とある複雑な予測解析を行う場合は、未来の t’ の値を直接計算するよりも Δt の積み重ねのほうが簡単に計算できたりします。

image

これは、よくやる重力の物理方程式で、惑星の動きとかをシミュレーションするときによく使われる方法ですね。太陽と地球の場合は、楕円として計算できるけど、三体問題として太陽・地球・月の場合は複雑に絡み合っているので直接計算はできません。別途 Δt で計算するというアレです。

当然、Δt は近似であるので、その積み重ねによって計算された未来予測値は正しい値とは限らないし、むしろずれています。誤差が累積されますからね。しかし、制御工学のように、その時々の時刻 t’ の値を観測することによって、Δt による線形近似のずれは、その t’ 毎によって補正されるため直近の値のみ正確であればそれでよいのです。このあたりを踏まえると、倒立振子ロボットのように一見、実現不可能ようなもの(私自身が倒立振子ロボットを見たのは、つくば博覧会のときですから30年以上前です。そのときに出品していた、一本足ロボットが現在の iRobo の前身なのですから驚きですね)であっても、意外と簡単な近似だけで行けるものです。

上記の運動方程式をあれこれラグランジュ方程式で解いて、変換すると、

角度θ、φに対するゲインの式

image

予測値に円滑に近づけるための PID 制御

image

の 2つだけで十分なのです。

それぞれの定数(K1, k2 等)を決めるためには複雑な方程式を解かないければいけませんが、最終的に倒立振子ロボットを制御するためのロジックは、上記のような単純な式であらわせます。これが組込みで動くので、Arduino のようなメモリが少ないマイコンでも動くという仕組みです。

科学計算の式をプログラム言語で解く難しさ

ここで注目したのは、最終的な式は簡単に見えるけども、途中の計算は複雑だということです。それぞれの K1 のような定数は、既知の数値のように見えますが、ロボットの重心位置や質量、タイヤの半径や質量、モーターの角速度や逆電流などに関わってくる定数になります。このあたり、科学計算の式をプログラム言語に直すときのむずかしさがあり、その間はギャップがあります。

  • 数式として解いたときの式
  • プログラムコードで実現するコード

の間には結構な隔たりがあります。

image

このような式を、プログラム言語(C言語や、C++、C#,Fortran など)に直していくわけですが、これがなかなか大変です。書き直すときのコツもあるのですが、問題は「式」の表現と「コード」の表現に大きな隔たりがあることです。

仕事上、数式を Fortran、C++ で書き直すことをやっていますが、よく間違えます。ただし、数式として抱えている様々な条件(前提条件なども含む)を写し間違えるあわけですね。その間違い、実際もとの数式に当てはめないとわからなかったり、複数の式が絡み合っているとなかなか見つかりません。

そんな仕事の中でよく使っているのは、F# による検算です。

  1. 数式を書く(与えられる)
  2. F# で書く
  3. C++、Fortran で書き直す。
  4. 3 と 2 の答え合わせを xUnit で行う。

という方法をよくやります。これをやると数式の写し間違えが激減しました。理由は F# が関数型言語で、式の取り扱いが得意だからというのもあるのでしょうが、検算することにより不具合率が減ります。また、この F# で書くコードは、巷の関数型言語特有の複雑さ(モナドとかオプショナルとか)をまったく使わず、ごく普通に式をプログラム言語に直す、というスタイルでしか使っていません。ですが、不具合が激減します。

束縛(バインド)と関数内関数の活用

ここ 2 年間の経験上ではありますが、この不具合率の低さは、

  • 束縛(let)の利用により、できるだけ値を不変にしようとする努力をする
    → 影響範囲が少なくなる
  • その場でしか使わない関数は、関数内関数として定義する。
    → 関数名が短くて済む。影響範囲が狭い。
  • if文、switch/match 文が値を持つ
    → 型システムの利用

なところです。

image

値の束縛は、C言語であれば define 定義すればよいし、C# であれば const にすれば ok です。ですが、F# の場合(関数型言語一般)は、デフォルトが束縛(let)であって、値を変えたいときはわざわざ、mutable にしないといけないという面倒臭さがあります。これが「面倒くさい」ことによって、より値が変化しない束縛(let)のほうにコードが寄ってきて、影響範囲の少ないコードが書きやすくなるという利点が出てきます。

逆に言えば、オブジェクトのプロパティをがりがりと変化させるようなオブジェクト指向とは別の向きを関数型言語は示してくれます。それは相反するものではなくて、その場その場でより使いやすい方向に向ければよいので、オブジェクト指向も関数型言語も相補的な形で使えるでしょう。

そういった場合、倒立振子ロボットのような物理的な制御をする場合には、物理量が不変であるからこそ数式的に関数型言語を使う法が適しているといえます。逆にロボット制御であっても、リモートコントローラーでアクチュエーター(サーボモーターやアームなど)を適切に動かすような主導的な制御はオブジェクト指向/UML を使ったほうがうまく作れるとも言えます。そういうパターンを踏まえて、物理値を逐次観測していてアジャイル的に制御を加えていく制御工学な自立コントロールはなかなか面白い分野になります。

サンプルコード

倒立振子ロボットを F# で書いたコードです。

moonmile/MonoBalancer
https://github.com/moonmile/MonoBalancer

C# と見比べると面白いかも…というか、今は C# から F# に書き直しただけなので、そのうち F# らしいスタイルに直していきましょう。

カテゴリー: F# | LEGO Mindstorms EV3+MonoBrick+F# で倒立振子ロボット はコメントを受け付けていません

Raspberry Pi で Xamarin.Forms を動かそう(Advent編)

この記事は、Xamarin Advent Calendar 2015 の 4日目の記事です。以前、ざっと書き流していたのですが、もうちょっと詳しく書いていきます。

Xamarin が動作するプラットフォームで、相当異色な感じの Android on Raspberry Pi なので、読み物的にお楽しみください。

Raspberry Pi を用意する

そもそも、なぜ Raspberry Pi で Android なんて動かすのか…は、さておき(苦笑)、Raspberry Pi を用意します。Android のインストールに BerryBoot というインストーラー ディストリビューションを使うのですが、バイナリを見る限り最新の RasPi 2 でも、それ以前のものでも大丈夫なようです。

image

動作確認は、Raspberry Pi 2 と5inch ディスプレイで確認しています。Raspberry Pi には HDMI 出力がついているので、普通の HD の液晶ディスプレイでも動きます。が、GPU まわりが遅いらしく 1920×1080 のサイズでは非常に遅くて使い物になりません。この 5inch 液晶ディスプレイだと 800×480 でちょうどいい感じに動きます。ちなみに、あとで設定しますが、config.txt を弄ってディスプレイ解像度を変えた後は、据え置きの液晶ディスプレイでも 800×480 の解像度になるので、800×600 などの適当な荒い解像度にして起動しなおせばよいでしょう。

BerryBoot をダウンロードする

BerryBoot v2.0 – bootloader / universal operating system installer から、RasPi 2 ならば berryboot-20150916-pi2-only.zip を、それ以前の RasPi ならば berryboot-20140814.zip をダウンロードします。

image

最新のファイルは berryboot download | SourceForge.net からダウンロードができます。

micro SD カードに焼きこむ

ダウンロードした zip ファイルを解凍して、micro SD カードに焼きこみます。焼きこむといはいえ、解凍したファイルを micro SD カードにコピーするだけです。micro SD カードは 8GB 程度で十分です。

image

途中で、起動に失敗したり、micro SD カードが見えなくなった&容量が減った場合は、SDFormatter でフォーマットしてください。オプションで、論理サイズ調節を「ON」にしてフォーマットすれば大抵回復します。

image

Android のフォーマットは、Windows から読み込めないので micro SD カードが読み込めなくなった(Windows 標準でフォーマットできなくなった)、あるいは Linux で使っていたら 50MB ぐらいしか容量が無くなった(本来は8GBあるはずなのに)、ときにフォーマットするとよいです。

BerryBoot を起動する

BerryBoot は、最初に起動すると SD カードをフォーマットします。

image

USB キーボードをつなげて、OK を押してください。

RasPi 2 の初期ロットの制限かもしれませんが、HDMI ケーブルをつなげて RasPi に電源を入れるとうまく立ち上がりません。多分、起動時の力不足で立ち上がらなくなってしまうのでしょう。USB キーボード/マウス、有線LAN をつなげっぱなしでも立ち上がらないことが多いので、電源を入れる前は外して、起動しているときに繋げるという技を使っています。

image

こんな感じでフォーマットをします。

Android をインストールする

“Add OS” ボタンで、OS を追加するのですが、OS イメージはインターネットからダウンロードする方式になっているので、有線LAN をつなげておきます。Android は 4.4(KitKat)がダウンロードできます。最新版はないですね…

image

Android 4.4 を選択するとダウンロードが始まります。

image

ダウンロードが終わると、メニューに追加されます。

image

ここでメニューの「Exit」を選択すると、Android が起動されます。

image

いちおう、FullHD 解像度で使えるのですが非常に重いです。これでは実験用には使いづらいので、もうすこし低解像度にします。

config.txt で解像度を調節する

再び、RasPi に電源を入れなおして起動すると、BerryBoot → Android の順に立ち上がります。このときに、BerryBoot メニューで Edit Menu ボタンを押します。このボタンを押さないと、10秒後に自動的に Android が立ち上がるので注意してください。

image

メニューから「>>」に隠れている「Edit config」をクリックして、config.txt を書き換えます。

image

hdmi_group=2
hdmi_mode=1
hdmi_mode=87
hdmi_cvt 800 480 60 6 0 0 0

のように 800×480 で書き換えています。config.txt を書き間違えると画面がでなくなってしまうので、その時は micro SD カードを焼くところから再スタートしてください。

液晶ディスプレイで 800×480 で動かしたときんは、こんな感じになってスムーズに動くようになります。動かすにはマウスが必要ですが。

image

Android on Raspberry Pi を起動する

5 inch ディスプレイをつなげて動かすとこんな感じになります。

image

5 inch 液晶の場合は、電力が十分足りるのかつなぎっぱなしで起動しても大丈夫なのです。Bluetooth は使えないので有線マウスが必須なのが難点ですが。無線マウスは反応がにぶいですが一応動くようです。

adb でデバッグ接続する

やっとこさ、Android の領域に入りました。Android on RasPi の場合、USB デバッグはできるかどうかわからないのですが、既に 5555 ポートが開いていてデバッグモードで動くようになっています。

adb connect <IPアドレス>

でデバッグ接続をします。IP アドレスがどれに割り振られているかを調べるのが大変ですが、Android 起動時の表示にちらっと出てくるので覚えておいてください。

image

これで Visual Studio や Xamarin Studio からデバッグができるようになります。

Visual Studio で Android on RasPi を動かす

Xamarin Studio 2015 で Android プロジェクトを作ってデバッグ起動をします。

image

起動メニューのところに「ARM vexpress」と出るので、これを選択します。

image

Android テンプレートの Hello World プロジェクトが起動できます。

Xamarin.Forms を Android on RasPi で動かす

Xamarin.Forms のサンプルとして My Shoppe をダウンロードして動かしてみましょう。

Visual Studio 2015 Update 1 ではエラーが出てビルドができないので、Xamarin Studio でビルドしています。

image

ビルド実行は、ARM vexpress(API 19) を選択すれば ok です。

image

image

いくつか動かしてみると、画像のロードやテーブルもうまく動いています。これで Android のデバッグも順調にできますね。いや、普通に Android を使ったほうが便利なのですがw

Android on RasPi を何に使うか?

さて、Android が Raspberry Pi で動くことが分かったのですが、これを何につかうか?です。もともと、組込み系の展示会に行ったときに Android 試験ボードを見て、結構高い(2,3万円程度)ので何かで代用できないかな、と思ったところがスタートです。Android 拡張ボードには、ネットワークの他にも Bluetooth や各種ピンが配置されています。Android on RasPi の場合には、Bluetooth ドングルが有効にならないのですが、ピンのほうはなんとかできるのでは?と考えています。UI 部分を Xamarin で作って、内部的には Linux で GPIO 等を操作できればいいですよね。

まあ、5 インチ液晶を載せてしまうとピンが隠れてしまうので駄目なんですが、ピンがつながるようにして、戦車やロボットアームが動かないかな、と考えているところです。Rasbian と同じように /sys/class/gpio/export にアクセスすることで制御が可能だと思うんですけどね。

カテゴリー: Android, RaspberryPi, Xamarin | Raspberry Pi で Xamarin.Forms を動かそう(Advent編) はコメントを受け付けていません

EV3 + MonoBrick + C# で倒立振子ロボットを動かそう、とプロジェクト管理の話

11月の.NETラボ勉強会で発表した倒立振子ロボットの補足です。

EV3 + MonoBrick + C#
http://www.slideshare.net/moonmile/ev3-monobrick-c

実は、制御工学の話からプロジェクト管理とかアジャイルとかテスト技法に繋げてみたかったのですが、話し忘れました。私自身は工学部出身なのですが、制御工学は習わずじまいだったんですよね。電磁気学とか量子力学のところは通っているので座標変換まわりは大丈夫なのですが、一番の驚きは時間軸の t の項を式に加えるというところです。

以下は雑多な話として、かつ既に制御工学/品質工学の専門の方には当たり前のことかもしませんが、ちょっと比較として面白かったのでメモ的に残しておきます。

制御工学はハンドリングの技術

ハンドリング、フィードバックは、アジャイルプロセスやプロジェクト管理の世界ではよく聞かれる用語です。その元ネタは、制御工学にあると知ってはいたものの、そのままの言葉とそのままの手法が制御工学の中にある(当たり前といえば当たり前)のちょっと吃驚です。制御工学の教科書として「はじめての制御工学」「はじめての現代制御理論」の本を使っているわけですが、一番わかりやすい制御のたとえとしては、車のハンドリングがあります。人が車を運転するときに少し左にずれれば少し右に、少し右にずれれば左にと小刻みにハンドルを動かします。この「ハンドリング」は当たり前といえば当たり前ですが、初期値のハンドルを決めた後、ずっとそのままではなくて、途中でハンドルをちょこちょこと動かすわけです。たとえ、直線の道であっても道の凸凹や車の揺れなをを修正しながらまっすく走るように制御をします。

ちょうど同じ例えば、アジャイル技法にもあって、プロジェクトを進めるときには途中途中でハンドリングをするたとえ話が出てきます。最初に決めた仕様や設計に従って、まっすくぐに進むのではなくて、途中途中の動きに合わせてちょっとずつ目的に向かうように修正していく手法です。ウォーターフォールの管理(本当のウォーターフォール技法ではなく、一般的に知られている/嫌われている「ウォーターフォール」の方)では、最初の仕様/設計に従って突き進みます。つまり、最初の角度に従って真っすぐに進むという方法ですね。そうなると、ウォーターフォール管理に「制御」があるかというと、制御はありません。途中途中でみられるものは単なる「観測」であって、観測を本線の制御にフィードバックする仕組みがありません。また、アーンドバリューは予測にはなりますが、予測をした後にどうするか?の基準がありません(現在の価値の傾きからどのくらいの遅れが発生するのか?という予測は立てられます)。どちらにせよ、出発時点で方向を変えないのであれば、制御ではありません。厳密にいえば、初期値=時間が0 のときだけ考慮するので、制御工学の大切な t の項が出てこないためです。

そんなわけで、制御工学を IT のプロセス管理/改善に含めるためには、必ず時間軸の t 項が必要になってきます。

理想状態では制御がいらない

image

これは、倒立振子の座標軸を示したものですが、完全な倒立状態の場合には、θとφは0になります。倒立状態のときに、これまた理想的な状態の場合は、完全な倒立が成立した後は永遠に倒立します。理想的な棒と理想的なタイヤが、理想的な倒立をした場合には永遠に倒立するであろうことは容易に想像できますが、それは「理想」でしかなくて、現実的なところは必ずすぐに倒れます。何故でしょう?

倒立のために理想的な初期値を与えたときは、時間軸の t の項に対する変数は常に変化が 0 になります。永遠に倒立しているのだから、θもφも 0 のままですよね。しかし、現実には時間 t によって変化をするので、θ(t) と φ(t) になります。t に依存するわけですね。ここで面白いのは、

  • t = 0 のときに初期値が 0 ではない。
  • t > 0 のときに初期値とは異なる値になる。

という 2点があります。t = 0 の場合は、まさしく初期状態で、倒立振子ロボットを最初に手で立たせようというところです。また、壁に倒立振子ロボットを寄りかからせて立っているところを想像してください。どちらにせよ、θ = 0 に近い値がいいのですが、現実問題として 0 にはなりません。なんらかの揺れが発生するわけです。かつ、時間が進んで t > 0 の状態では、なんらかの要因で θ の値は刻々と変わります。それは倒れる瞬間かもしないし、ゆらゆらと制御しながら立っている瞬間かもしれません。少なくとも t > 0 の時点では、θ と φ は一定ではない状態が続きます。

これもプロジェクト管理やアジャイルプロセスと同じで、初期の状態はどうやっても理想形にはなりません。むしろ理想形にはならないという前提に立つことが、制御工学からわかります。また、時間が進みに従って、いろいろな要因がかかわってプロジェクト内の設計や要件が揺れるわけですが、これも t > 0 の条件にあたります。初期値は理想的ではないし、途中の進捗率も理想的にはならないのだから、なんらかの制御が必要になりますよね。逆に言えば、理想的なプロジェクトでは制御なり管理(マネージメント)は必要ありません。ですが、現実は理想ではないので、なんらかのマネージメントが必須になります。

フィードバック制御の効果は遅れてやってくる

image

制御工学ではブロック線図が使われます。音響関係やコイル/コンデンサを使った発振も、このブロック線図を書いてフィードバックの向きを入れます。

このフィードバックですが、オブジェクト指向的には一瞬で終わる( t の項目がない)ように見えますが、実はフィードバックは遅れてやってきます。この図はラプラス変換されたものですが、目標値とのずれをC(s)で制御として記述し、それに外乱要因が D(s) として追加された後、操作を P(s) で行います。これが時間の項目がないと、オブジェクト指向的に一瞬で計算が収束する Δt = 0 となるわけですが、実際にはΔt > 0 になります。このために時間軸が発生して、

image

こんな感じで、時間軸のそれぞれの出力値 y(t) が変わってくるわけです。オブジェクト指向やアスペクト指向自体も、遠地のメッセージングやネットワーク環境などを考えると t の項目が出てきます。それが複数のスレッドの場合は、遅延を考えたり、デットロックを考えたりする基準になるのですが、このあたりもオブジェクト指向と時間 t の関係を考えると色々と面白いです。

さて、最終的な出力からのフィードバックは、次の t にマイナス制御として働きます(なんらかの値へと収束させようとする力)。これをより安定的に制御するためには、グラフのように上に飛びぬけた「オーバーシュート」の状態では困る場合があります。また、なかなか収束せずにゆらゆらと振動してしまう場合も困ります。

これを安定稼働させるために PID 制御があって、それぞれ差分と積分と微分の項があります。

image

この Kp,Ki,Kd をうまく決めてやることによって(行列の状態方程式を解くことで値を計算できます…まだ私は計算できていませんが)、オーバーシュートをせず、振動が起こらずに目標値に着地させることができます。それぞれの項目が何を意味するのかは、最初の車のハンドリングの話に戻ります。地面の揺れや車の揺れに従って、時間 t に沿ってちょこちょことハンドルを動かして真っすぐ動かすようにします。しかし、大きくハンドルが外れた場合、大きく戻すと簡単にオーバーシュートしてしまいます。ハンドルが切りすぎの状態になって蛇行してしまいますよね。大きくハンドルが外れた場合、あるいは大きく曲がる場合は、少しずつハンドルの向きを調節して、最終的に大きなずれをなくすようなハンドリングの仕方をします。当たり前といえば当たり前の動作ですが、これをプロジェクト管理に当てはめてみましょう。

何らかの大きなトラブルがあって、プロジェクトの進捗が大きく遅れたとします。1日がっつりと進捗が遅れた場合はどうすればいいのか?ってことですね。1日遅れたのだから、プロジェクトメンバを休日出勤させて1日取り戻してはどうか?というのが、よく使われる進捗管理の方法だと思うのですが、どうでしょうか。制御工学的には、大きなずれは少しずつの制御を積み重ねたほうが、オーバーシュートや振動が少なくなるわけです。ならば、プロジェクトの進捗が大きく遅れた場合に、1日の休日出勤を行ってはダメですよね。オーバーシュートが起こりそうです。そうなると、遅れはちょっとずつ取り戻したほうがよいのではないか、というのが制御工学的な考え方です。

制御がうまくいかなくて、元の値の上下を振動してしまうのは、元に戻す力が早すぎる(たいていは加速度のゲインが大きすぎる)ことです。これを、ゆるゆるとやるのが制御の基本です。何故、少しゆるくやるのかというと、フィードバックの効果は遅れてやってくるからです。これは、RC 回路の高周波のフィルタでも同じで、少し遅れるために振幅が相殺されてしまう現象と同じです。となれば、物理現象をプロジェクト管理に応用すれば、なんらかの対策を打ったとしてもその効果があらわれるのは少しあとになりますよね。大抵の場合は、すぐに効果が表れると思って(期待してしまって)なんらかの効果が出るものに執着したり、効果がでないとすぐに別の対策を立てたりしますが、実はフィードバック効果自体は少し遅れてくるのが物理現象なのです。ならば、ならかの対策を打ったときには対策の効果がでるまで、時間が掛かることを知って対策を打ちましょうということです。

フィードフォワードで予見する

倒立振子ロボットのプレゼン資料には「フィードフォワード」の話はできません。フィードフォワードは、フィードバックの逆で、先に手を打つことです。先に書いた通り、フィードバック制御だけでは、効果が遅れて発生するので常に後手後手の制御になってしまいます。ならば、目標値に沿うように、外乱の要因をあらかじめ低減するのがフィードフォワード制御の役目です。外乱ってのは何かというと、予期しない揺れみたいなものですね。ですが、外部からの揺れであっても一定の法則があってり、一定の範囲で測定できたりするわけで、その項目が過敏に働かないように制御を入れることができます。

まだ学習途中なのですが、フィードフォワード制御を使って外乱に過敏にしないようにするためには、多変量解析の仕組みを利用して、加味する値の影響度(ゲイン)を調べるといいでしょう。余分な雑音を雑音とみなすために、影響度を小さくします。これはちょうど、数式の中に sin θ を θ が微小のときには sin θ ≒ θ とみなす、ことと似ています。より小さくなる自乗の項目を減らしたり、局値を取ったりして式を簡単にして解きやすくします。

じゃあ、これがプロジェクト管理の場合にはどれに対応するのだろうと考えてみると、ちょうどスクラムプロセスのスクラムマスターの役割に似ています。プロジェクト内のエンジニアが外部の雑音(金額交渉やスケジュール交渉など)に惑わされないよに防壁に役割をします。雑音を雑音と扱い、重要なものだけ通すフィルターの役割をする分けですね。

また、常に対策が後手後手になってしまうフィードバック制御(「進捗どうですか?」など)ではなくて、何らかの予測のものに先手を打つことが必要です。マイルストーンを置いたり、バーンダウンチャートで不具合の収束度を見極めたり、増員をしたりという早期対策ですね。

このあたり、色々考えながら制御工学の式を解いています。最終的には、いくつかの固定値と簡単な足し算の式だけで、倒立振子ロボットが倒れないで済むのが驚きです。簡単な式だからこそ、マイコンとしてメモリの少ないチップでも十分制御ができるしアセンブラで書くこともできる(まあ、そのほかの動作がややこしいんですが)のですね。このあたり、サーボモータも PID 制御をしていて面白いです(というか、サーボというのがその制御そのもの名前だった)。

このあたり、本格的な制御工学とプロジェクト管理/アジャイルプロセスが、どう組み合わさるのかは考えてみたいところです。少なくとも、私にとって制御工学というジャンルはそういう目でも見ています。

カテゴリー: 開発 | EV3 + MonoBrick + C# で倒立振子ロボットを動かそう、とプロジェクト管理の話 はコメントを受け付けていません

倒立振子ロボットを MonoBrick で作成する(F#編)

つらつらと、はじめての制御工学 を読んで、やっとこさ 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 で最初のプロジェクトを作ります。

image

プロジェクトができあがったら、参照設定で「MonoBrickFirmware」がきちんと参照されていることを確認して(なぜか時々エラーになるので、そのときはいったん削除してもう一度参照すればokです)、おもむろに F# でコーディングをします。

image

Xamarin Studio で F# プロジェクトをビルドする

なぜか、ビルドをするときは「有効なランタイム」を「Microsoft .NET」にしておきます。Mono のほうだとビルドできないんですよね。環境の違いかもしれませんが。

image

でもって、デバッグ実行するときは「Mono 4.0.3…」に直してデプロイをします。このあたりが面倒なのですが、仕方がない。

デバッグ実行する

Xamarin Studio でデバッグ実行をすると MonoBrick にアセンブリがアップロードされて、そのまま実行されます。このときには、「有効なランタイム」を「Mono 4.0.3…」にしておきます。

image

そうすると暫く時間が立つと EV3 + MonoBrick で F# のコードが実行されます…が、この立ち上がりが結構を遅くて閉口するので、アップロードだけ Xamarin Studio に任せて、その後は Tera Term で MonoBrick に接続して直接立ち上げます。このほうが、コンソールを使えるのでログ出力とかできて便利です。

デバッグ実行で Upload program to brick … が終わったあたりで、ぶちっと止めてしまいます。止めるぐらいだから、WinSCP でアップロードしても同じなんですが、まあ、Xamarin Studio だけでできるのでこれはこれで便利。

image

その後で、適当なターミナルで接続して、apps フォルダ内にあるアセンブリを直接起動します。

image

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

https://www.youtube.com/watch?v=w_4HxiHnwAM&feature=youtu.be
も MonoBrick + F# で書かれていたりします。

カテゴリー: EV3, F#, MonoBrick | 倒立振子ロボットを MonoBrick で作成する(F#編) はコメントを受け付けていません

倒立振子ロボットを MonoBrick で作成する(C#編)

ここ2週間ほど倒立振子ロボットにハマっていたのがようやく形になって来たので、メモ代わりに残しておきます。初手は ET ロボコンの EV3Way用のサンプルプログラム なのですが、そのままだとうまく動かかなったので(今考えると車輪の径の設定等が必要だった)、もうちょっと簡単に組み立てて動くところから始められるように、BALANC3R にある LabVIEW のコードから C# に移植しています。

moonmile/MonoBalancer
https://github.com/moonmile/MonoBalancer

移植先

Robot Square – Tutorial: Building BALANC3R – Robot Square のコードを忠実に C# に移植しているつもりです。「つもり」というのは、コードの意味をいまいち把握していないからですね。いくつかパラメータの意味もわかっていないので、そのまま C# に移してパラメータもそのまま持ってきています。

よく知らなかったのですが、倒立振子ロボットは制御工学では定番の教材で色々なものがあります。ジャイロセンサや、モーターの特性(角速度、ギアボックスの比率、トルクなど)、重心位置、車輪の半径など、いろいろな要素が絡み合って倒立するように(倒れないように)する訳ですが、それらをモデル化してフィードバック回路にするところがミソです。複雑な要素をうまくモデル化して時間軸で定常値に近づけます…と今のところ理解しています(まだ、教科書でPID制御のあたりまでしか行ってないので)。

MonoBrick

LEGO Mindstorms EV3 は主に LabVIEW を使ってコードブロックを組み合わせてプログラミングをしていきます。が、そのままでは普通のプログラミングがしずらいので、MonoBrick.DK | Home of MonoBrick を使います。Linux に Mono を入れて C# でも動かそう(F#/VB等でも動きます)という方法です。EV3 への制御は MonoBrickFirmware ライブラリを通して使います。

MonoBrickFirmware のコードは、Larsjep/monoev3 にあります。豊富なサンプルコードがあるので色々な機能を動かすには苦労しないでしょう。MonoBrickFirmware を見ていくと、中間コード生成して EV3 に渡していることがわかります。ここの中間コードの形式などは、ダウンロード – レゴ®マインドストーム LEGO.com にある EV3 Firmware Developer Kit 等で公開されています。

ちょっとしたコードの解説

制御工学的な話は勉強中なので、ちょっとだけコードの解説をしておきます。

センサーとしては「ジャイロセンサー」と「モーターの角速度」だけを使います。倒立振子ロボットを作る際のセンサーは「ジャイロ」「ロータリーエンコーダ」「トルクセンサ」が必要なことが多いらしいのですが、EV3 の倒立振子ロボットは2つだけです。

double GAIN_ANGLE_VELOCITY = 1.3;
int GAIN_ANGLE = 25;
int GAIN_WHEEL_SPEED = 75 ;
int GAIN_WHEEL_POSITION = 350;

ba.Initialize(
    0,  // LEGO Jyro 
    42, // wheel 42 mm
    22);// sample time 22msec
ba.SetConstants(
    0.6,    // Kp
    14,     // Ki
    0.005,  // Kd
    GAIN_ANGLE_VELOCITY,    // Gain Angular Velocity 
    GAIN_ANGLE,     // Gain Angle    
    GAIN_WHEEL_SPEED,     // Gain Wheel speed 
    GAIN_WHEEL_POSITION);   // Gain Wheel position 

ba.Initialize で指定するのはタイヤの直径と、サンプリングタイムです。重心位置は寄与していないのかもしれません。計測間隔は 2,3msec と短いものが多いのですが、Baranc3R では 22msec(内部的に補正して 20msec)になっています。これでもバランスが取れているので、C# などで制御するときには非常に楽です。ちなみに .NET Framwork 等では Timer クラスを使うと 30msec 以上になってしまうので、ちょっと手を入れています。元の LabVIEW のコードで 2msec 補正しているのは、計算時間(2msec)+ 待ち間隔(20msec)という感じなんだと思います。

ba.SetConstants で指定しているのは PID パラメータと、ゲインです。この値は制御工学を紐解くのと実測値を調節しないと駄目なので、そのまま使います。通常は、モデル化→ ブロック線図 → 伝達回路 → ラプラス変換 → PID 制御 に直して定常値を計算する(らしい)のですが、このあたりはまだ勉強中。

double motorPosition = Position();
double robotPosition = 0.0;
double robotSpeed = 0.0;
ReadEncoders(out robotPosition, out robotSpeed);
double angle = 0.0;
double angleVelocity = 0.0;
ReadGyro(out angle, out angleVelocity);
double inputVal = CombineSensorValues(angleVelocity, angle, robotSpeed, robotPosition, motorPosition);
double pid = PID(_kp, _ki, _kd, _dt, 0.0, inputVal);
Errors(pid); // エラーの場合は例外が発生する
SetMotorPower(_steering, pid);

制御ループの中で、CombineSensorValues 関数が入力値を計算しているところです。参照値は、倒立させるために常に 0.0 です。ただし、リファレンス値を 0.0 にしてしまうと、ステアリングとロボットのスピードも殺されてしまうような気がするんですけど、どうなんでしょうね。私のコードの移植が変なのかもしれません。

PID 関数でモーターに与えるパワー(PWD値、-100%から100%の間)を計算します。このあたりの定数値は Arduino や Raspberry Pi で倒立振子ロボットを作ったときに異なってくるところです。まあ、そのあたりも理解して作りたいなと思っているので、やっぱり制御工学の知識は必要ですね。

あと、平均スピードの計算方法とかジャイロセンサーの取得方法とかが少し工夫してあります。ジャイロセンサーの揺れに過敏にならないように近傍の平均値を使っていますね。

数式に直すのと、モデル化に戻すのは後で。

参考先

姿勢制御のコードを理解してプログラムを書きたかったので、既存のプログラムを読み直している途中です。結局のところ、制御工学の教科書 はじめての制御工学 (KS理工学専門書) [Kindle版] に行きついています。

etroboEV3 / Wiki / Home
http://sourceforge.net/p/etroboev3/wiki/Home/
LEGO Mindstorms EV3でGyro Boyを動かしてみた。(その1) – robo8080のブログ
http://blog.goo.ne.jp/roboz80/e/455074cc58e99474d4daf6a24d5ebcc0
2輪倒立振子ロボット2号機作成。 – robo8080のブログ
http://blog.goo.ne.jp/roboz80/e/e485f7efa259e44baaa298fd6989c556
Robot Square – Tutorial: Building BALANC3R – Robot Square
http://robotsquare.com/2014/06/23/tutorial-building-balanc3r/
NXTway-GS (Self-Balancing Two-Wheeled Robot) Controller Design – File Exchange – MATLAB Central
http://www.mathworks.com/matlabcentral/fileexchange/19147-nxtway-gs–self-balancing-two-wheeled-robot–controller-design
倒立振子の研究
http://www.instructables.com/id/%E5%80%92%E7%AB%8B%E6%8C%AF%E5%AD%90%E3%81%AE%E7%A0%94%E7%A9%B6/
みのくらロボット
http://minokura.net/works/wheelpendulum.html

カテゴリー: C#, EV3, MonoBrick | 1件のコメント

[C#] ミリ秒単位のタイマーを作成する

MonoBrick を使い倒立振子ロボットを C# に移植したところですが、ジャイロやサーボの回転数のサンプリングレートに問題があります。もともとのコードがだいたい 20 msec 単位(1秒間に50回)ぐらいのサンプリングを行っているものの、途中で C# で Timer クラスを使うと 30 msec ぐらいの精度しかないんですよね。しかも、だんだんと値がずれていきます。

ちょっと考えて、きちんと 20 msec 単位でサンプリングできる TickTimer クラスを作ったので公開しておきます。

TickTimer クラス

System.Diagnostics.Stopwatch と Thread を使って正確に msec 単位の割り込みを発生させます。使い方は、Timer クラスと同じようにコールバック関数を指定して使います。
最初は Task で作ったのですが、mono の Task 生成が遅いらしく Thread に切り替えています。MonoBrick が .NET 4.0 ベースなので async/await が使えないし、まあ Task である必要もないので。

public class TickTimer
{
	TimerCallback _cb;
	Stopwatch _sw;
	int _dueTime;
	int _period;
	bool _loop = true;
	Thread _task;

	public TickTimer(TimerCallback callback, object state, int dueTime, int period)
	{
		_cb = callback;
		_dueTime = dueTime;
		_period = period;
		_sw = new Stopwatch();
		_task = new Thread(onTimer);
		_task.Start( state );
	}
	public TickTimer(TimerCallback callback, int period)
	{
		_cb = callback;
		_period = period;
		_sw = new Stopwatch();
		_task = new Thread(onTimer);
	}
	public void Start( object state = null )
	{
		_dueTime = 0;
		_task.Start( state );
	}

	public void Stop()
	{
		_loop = false;
	}
	private void onTimer(object state)
	{
		Thread.Sleep(_dueTime);
		_sw.Restart();
		while (_loop)
		{
			long msec = _sw.ElapsedMilliseconds;
			int rest = _period - (int)(msec % _period);
			// 200msecだけ余らせてスリープ
			if (rest > 200)
			{
				Thread.Sleep(rest - 200);
			}
			// 200msecの間、ちょうどになるまでループで待つ
			while (true)
			{
				if (_sw.ElapsedMilliseconds >= msec + rest)
				{
					break;
				}
			}
			if (_cb != null)
			{
				_cb(state);
			}
		}
		_sw.Stop();
	}
}

利用コード

class Program
{
	static void Main(string[] args)
	{
		// 1秒毎にタイマーを発生させる
		// System.Threading.Timer で間隔 20msec を指定すると 30msec 程度になる.
		// 1.0sec を指定しても完全に1.0にはならない。1msecぐらいずれていく
		Timer tm = new Timer(timerCB,null,0,1000);
		Console.WriteLine("Timer start.");
		Console.ReadKey();
		tm.Change(System.Threading.Timeout.Infinite, System.Threading.Timeout.Infinite);

		// System.Diagnostics.Stopwatch を利用して、正確なタイマーを作る 
		TickTimer tm2 = new TickTimer(timerCB, null, 0, 1000);
		Console.WriteLine("TickTimer start.");
		Console.ReadKey();
		tm2.Stop();
		// 20msecも正確に測れる
		// TickTimer tm3 = new TickTimer(timerCB, null, 0, 20);
		TickTimer tm3 = new TickTimer(timerCB, 20);
		tm3.Start();
		Console.WriteLine("TickTimer start at 20msec.");
		Console.ReadKey();
		tm3.Stop();
	}
	static void timerCB(object obj)
	{
		var msec = DateTime.Now.Millisecond;
		Console.WriteLine("msec: {0}", msec);
	}
}

実行すると、こんな感じ。

Timer クラスを使うと 1msec ずつずれていくけど、TickTimer の場合は、1msec 程度ずれても元に戻るので正確な 1000msec や 20msec で割り込みを入れられます。

この割り込みを使って、PID 制御の積分成分を出せば良いはずで、これで平均値を出すときのずれが減るかなと。いまのところ、こんな感じで倒立できています。

20151106_01

カテゴリー: 開発, C# | [C#] ミリ秒単位のタイマーを作成する はコメントを受け付けていません

Onion Omega 着弾

Onion Omega: Build Hardware with JavaScript, Python, PHP by Onion — Kickstarter
https://www.kickstarter.com/projects/onion/onion-omega-invention-platform-for-the-internet-of
Raspberry Piの4分の1でWi-Fi機能。小型ボード「Onion Omega」 | fabcross
https://fabcross.jp/news/2015/04/20150403_onion_omega.html

勢いで Kickstater で買った Onion Omaga が届きました。当時の私は Raspberry Pi と Arduino でモーターを動かして喜んでいた頃で、ともかく「1/4 のサイズで」というのに惹かれて買ってみました。まあ、何に使うかわからない感じだったので、どういう風に使うか決めてはいなかったのですが…意外とさっくりと動きます。

これは、セットアップした後に Tera Term で Omega に接続しているところです。中身は組込み Linux が入っているので電源を入れるだけで動きます。CPU速度やメモリ容量は Raspberry Pi 2 などよりも低いのですが、大きさが小さいのと電力が少なくて済むことです。ワットモニターで測ったところ、1.0 から 1.2W 程度で動いています。Raspberry Pi が 2.0W 程度なので半分ぐらいの電力で動きます。

大きさでは 1/4、値段は Orange Pi より高い

Omega のピン幅は 2.54mm より狭いので何らかの変換基盤が必要です。

Omega – Onion Store – Onion
https://store.onion.io/products/omega-dock?variant=7907062145

写っているのは MiniDock を加えたもので、あわせて $25 です。使い捨て…な感じでは使えないけど、Raspberry Pi 2 ほど高いわけでもないという感じですね。ただし、単に Linux ボードで実験したいだけならば、Orange Pi が $15 で手に入ります(実際は、micro SD カードが必須になるので、結果的には $25 ぐらいになるかと)。

ただし、Omega の場合は小さいので、そのまま Arduino mini 感覚でラジコンカーやロボットに載せることが可能かなと。

Onion Omega は WiFi が標準で使える

おそらく、Onion Omega の最大の特徴は、WiFi が標準で搭載されているところです。すでにボード自体に Wifi が載せられているので別の拡張ボードを買う必要がありません。単純に組込み Linux 上で何かをやらせるだけならば、先の MiniDock にある USB コネクタに電源を供給すれば ok です。

WiFi は通常のクライアント方式と、アクセスポイント方式の2つから選べます。通常はクライアントとしてネットワークに参加させておけばよいでしょう。

image

セッティングは USB ケーブル直結でもよいし、WiFi の設定をした後はブラウザから操作ができます。ブラウザは Firefox や Edge は動かないないので、Chrome を使っています。たぶん、内部で使っている JavaScript の関係のような気がします。

こんな感じでブラウザ上でターミナルを動かすことも可能です。

image

opkg で python をインストールする

中身をみていくと OpenWrt がベースになっているようです。OpenWrt は Intel Edition にも載っているそうなので、その練習用にもよいかもしれませんね。

OpenWrt – Wikipedia
https://ja.wikipedia.org/wiki/OpenWrt

パッケージのインストールは opkg コマンドでやるそうなので、opkg install python とすると python がインストールできます。結構な容量を使ってしまいますが、ちょっとした Python スクリプトを動かすぐらいだろうから、これで十分でしょう。ちなみ、私は Python は詳しくないので、これからどうやるのかよくわかりません(苦笑)。サーボモーターを動かすスクリプトを見つけてきて試してみましょう。

image

残念ながら opkg install mono は動かないかったので、.NET は動かないようです。.NET Core とか別途インストールすればいけますかね?

工場出荷状態に戻す

ブラウザからさっくりと工場出荷状態に戻すことができます。

image

というわけで、組込み Linux として使えば結構応用範囲は広いんじゃないかと思います。画像エンコード等は CPU パワー的には無理ですがカメラキットがあるので、撮影はできるようです。Rolling Spider も組込み Linux なので、このあたりも似たような感じじゃないかなと。

Mini Dock に USB コネクタがあるので、何か接続できるのかもしれません。マウスとかキーボードとか、ひょっとしたら UVC Camera とか(カメラキットが 720p WebCam になっているのでたぶんできると思う)。そのあたりの調査はおいおいに。

カテゴリー: 開発 | Onion Omega 着弾 はコメントを受け付けていません

LEGO Mindstorms EV3 を Xamarin Studio でデバッグする

怒涛の EV3 シリーズの第3弾めです。

LEGO Mindstorms EV3 を C# で動かす | Moonmile Solutions Blog では、Visual Studio で作成した実行ファイルを WinSCP でアップロードしていたのですが、これが結構手間です。プログラムを修正するたびにいちいちアップロードをしないといけませんね。バッチ化してアップロードしてもよいのですが、Xamarin Studio を使うとビルド後にアップロード、かつ C# でデバッグ実行ができるので、これを紹介します。

ET ロボコンで MonoBrick が使われている

etroboEV3 / Wiki / MonoBrickWin
http://sourceforge.net/p/etroboev3/wiki/MonoBrickWin/#11-monobrick-ev3-firmware

参加するのはなかなか(財布的に)大変なのですが、個人的に使ってみる分にはタダです。このサイトの解説で十分ではあるのですが、メモ的に Bluetooth 接続部分と Xamarin Studio のアップロード部分を補足しておきましょう。

ETロボコンには、TOPPERS/EV3RT という uTronベースのリアルタイム OS も使われているので、こっちのほうも後で試してみます。EV3RT のほうは C++ で記述するようです。RTOS の勉強によいかと。

Windows 10 では USB ケーブル接続ができない

最初に注意しておきますが、Windows 10 では MonoBrick との USB ケーブル接続ができません。Windows 7/8 の場合は可能なのですが、10 の場合は、RNDIS/Ethernet Gadget が自動的に COM ポートに割り当てられてしまうらしく、etroboEV3 / Wiki / MonoBrickWin にあるようにネットワークアダプタに割り当てられませんでした。

EV3 Connection problem – USB and BT – Windows 10 – leJOS 海外でも問題になっているようです。

Bluetooth 接続する

そんな訳で、Bluetooth を使って接続をします。WiFi ドングルの場合は、IP が割り当てられますが、Bluetooth のほうはどうするのかというと、TCP/IP on Bluetooth というのを使って、同じように IP アドレスで接続ができます。EV3 側が「10.0.1.1」にして接続ができます。

Bluetooth ドングルを EV3 インテリジェントブロックに差し込んで MonoBrick を起動します。以前、もともとの EV3 と接続している場合にはペアリングをやり直します。

image

ペアリングをすると、パスコードが出るのでそのまま「はい」を押してください。パスコード自体が インテリジェントブロック側に出て来ないので不安といえば不安ですがw。

image

うまくペアリングができると接続状態になります。

ここでネットワーク接続を開いて、×印になっている Bluetooth ネットワークをダブルクリックします。

image

ペアリングができていると、EV3 が見えていると思うのでこれを選択して、「接続方法」→「アクセスポイント」を選択します。

image

すると、Blueooth のマークが暫く出て接続が完了します。この「アクセスポイントに接続する」作業は EV3 を起動するたびに行います。

ping を飛ばすと、きちんと応答を返すし、

image

Tera Tearm で SSH 接続して、ifconfig を見ると 10.0.1.1 が割り当てられていることが解ります。

image

ちなみに、PC 側は 10.0.1.10 で接続が可能です。

image

Mono runtime をインストールする

デバッグ実行するのに、Mono Runtime が必要です。Xamarin Studio だけを入れた状態では入っていないので、別途入れます。

Download | Mono
http://www.mono-project.com/download/#download-win

からダウンロードしてインストールすれば ok です。

Xamarin Studio にアドインを入れる

MonoBrick EV3 Firmware | MonoBrick.DK
http://www.monobrick.dk/software/ev3firmware/

から Xamarin Studio の Add-in をダウンロードします(もともと、MonoBrick とワンセットなんですね)。ファイル名は「addin.mpack」です。

Xamarin Studio を起動して、「Install from file」から、先の addin.mpack をしてします。

image

インストールができると「ツール」→「オプション」の「その他」の項目に MonoBrick が増えているのが解ります。

image

ここで、デバッグ先の EV3 の IP を指定(Bluetooth 接続なので 10.0.1.1)しておきます。

Xamarin Studio でプログラミングする

やっとこさ準備が整ったのでデバッグ実行してみます。Xamarin Studio を立ち上げて、新しいプロジェクトを作るときに、「その他」→「Miscellaneous」→「MonoBrick Project」を選択します。

F# でも作れるのですが、少しコツがいるので、また後で。

image

サンプルプロジェクトが作成されます。

image

Visual Studio で作ったときと同じように、コマンドラインのプロジェクトで、MonoBrickFirmware を読み込んでいるところです。

ダイアログ(EV3 の液晶ディスプレイ)にメッセージを表示させてモーターを3秒間だけ動かします。

(現状ではテンプレートに間違いがあるらしく、一か所だけ修正が必要です。InfoDialog クラスのコンストラクタにある ture を削除してください)

デバッグ実行をする前に「プロジェクト」→「有効なランタイム」で、「Mono 4.0.3 …」のほうを選択しておきます。

image

Microsoft .NET にしておくとビルドは通るのですが、デバッグ実行時に You must use the Mono runtime for debugging! のエラーがでます。もちろん、

image

有効なランタイムを Mono に変更してビルド、そしてデバッグ実行をすると、以下のようにアプリケーション出力がでて、EV3 インテリジェントブロックへアセンブリが自動アップロード、かつ実行されます。

image

インテリジェントブロックにダイアログが出るので、真ん中の OK ボタンを押します。すると、モーターが3秒だけ動いて、プログラムが終了します。

image

ブレークポイントは貼れないみたいですね。ダイアログを表示しているときに、一時停止ボタンを押すとスタックトレースが出るので、何らかのブレークはできそうです。

Debug.WriteLine をしても何処にも出ないので、いわゆるプリントデバッグは難しそうですね。インテリジェントブロックの液晶ディスプレイに出すか、別途 PC にログを飛ばす方式を考えたほうがよさそうです。

やっぱり F# で作ってみる

往年の F#er(ってほど使ってないけど)、としては F# プロジェクトを使ってみたいですよね。

そんな訳で C# と同じように組んでみます。

open System
open System.Threading
open MonoBrickFirmware
open MonoBrickFirmware.Display.Dialogs
open MonoBrickFirmware.Display
open MonoBrickFirmware.Movement

let main() = 
    Lcd.Clear()
    LcdConsole.WriteLine("Hello World!")
    Thread.Sleep(2000)
    Lcd.Clear()

    let dialog = InfoDialog("Attach a motor to port A in F#")
    let b = dialog.Show()
    let motor = Motor(MotorPort.OutA)
    motor.SetSpeed(sbyte(50))
    Thread.Sleep(3000)
    motor.Off()
    Lcd.Clear()
    Lcd.Update()

main()

F# の場合は、何故かビルド時に「有効なランタイム」を Mono にするとビルドができないので、

  • ビルド時には「Microsoft .NET」を選択する
  • 実行時には「Mono 4.0.3 …」を選択する

という妙なことをやります。

image

こんな風に無事 F# で動いていることが解ります。

Mono 4.0.3 を使ってビルドをするとこんな感じになります。

image

「指定された実行可能ファイルはこのOSプラットフォームに対して有効なアプリケーションではありません」と出るので、Mono 4.0.3 のランタイムと F# コンパイラのバージョンがずれていると思うんですけどね。これは後で調査しましょう。

Visual Studio では動かないのか?

アドインのコードは、monoev3/AddIn at release · Larsjep/monoev3 にあるので、SCP で送るだけなのでなんとかなるかなと。SshNet を使って SCP しているようなので、monoev3/AddIn/Source at master · Larsjep/monoev3 アドイン自体のコード量はそう多くないので、おいおいに。

カテゴリー: C#, EV3, Xamarin | LEGO Mindstorms EV3 を Xamarin Studio でデバッグする はコメントを受け付けていません

LEGO Mindstorms EV3 を C# で動かす

レゴ エデュケーションと日本マイクロソフトが日本発 IT 人材育成を目的としたプログラミング ロボット教育カリキュラムの提供で連携 | News Center Japan
http://news.microsoft.com/ja-jp/2015/10/27/151027-azure-lego-education/

ということで、日本でも LEGO と Microsoft が組むそうです。カリキュラム自体は Azure が必須(まあ Microsoft としてはそれが IoT の売りなので外せない)なのですが、個人的には Azure はいりません…が、ドキュメントがダウンロードできるので利用させていただきます。

ロボット×クラウドではじめての本格プログラミング~レゴ® マインドストーム® で地球を探査 | Microsoft Virtual Academy – 専門家が提供する e ラーニング コース – | Channel 9
https://channel9.msdn.com/Series/Microsoft-Virtual-Academy-Japan/lego-mindstorms-programming-curriculum

image

上記からカリキュラムで利用するプレゼン資料とプログラム一式がダウンロードできます。この中で結構ありがたいのは、EV3Azure_Workshop_SetupManual.pptx のプレゼン資料です。この中で、

  • MonoBrick Firmware のインストールの仕方
  • WiFi の設定の仕方

が書いてあります。ちなみに、WiFi は、暗号化なしか、WPA2(WPA-PSK(AES)) の二種類しか選択できません。無線ルータの設定にもよるので、結構ここは躓きやすいところです。探査機ロボットの場合は、センサーで取得した結果を Azure に飛ばすので WiFi が必須になっていますが、無線だけやりたいのであれば Bluetooth のほうが手軽です。

MonoBrick の micro SD カードを作る

Creating A Bootable SD Card On Windows | MonoBrick.DK
http://www.monobrick.dk/guides/firmware-guides/monobrickfirmwaresdcardwindows/

image

上記から MonoBrick のイメージをダウンロードできます。Win32 Disk Imager の使い方も書いてあるので解りやすいでしょう。512MB, 2GB, 4GB 版と3種類ありますが中身は一緒で容量だけが違います。8GB のメモリカードに 512MB を入れてもよいし、4GB 版を入れてもよいでしょう。作業領域の違いだけですね。Raspberry Pi や Windows IoT の場合は 8GB が必要なのですが、MonoBrick の場合はグラフィック系がないためか 512MB でも十分なようです。

EV3 で MonoBrick を起動する

micro SD カードに MonoBrick を焼きこんだら、インテリジェントブロックに差し込んで電源を入れます。CPU が遅いのか、Linux の起動が遅いためか分かりませんが、起動時間は1分弱ぐらいかかります。

image

起動が終わると、Main Menu が出るので「Brick Information」を選択すると、ファームウェア等の情報が見れます。

image

現時点(2015/10/29)では、

  • Firmware 1.2.0.39486
  • Mono version 2.10.9
  • Mono CLR v4.0.30.319

になっています。.NET Framework のバージョンは最新が v4.6 なので、ちょっと古いのですが、愛艇の C#/F# のプログラムは動くはずです。

WiFi を設定する

WiFi の暗号化が「None」か「WPA/2」しか選べないので、うまくつながらないときは無線ルーターの設定を見直してください。暗号化なしが選べるので、パスワードなしのオープンな無線ルータに接続できるかもしれません。

image

SSIDとパスワードの設定が結構面倒(DSでぽちぽち設定するぐらい面倒)ですが、きちんと設定すると「Brick Information」で割り振られた IP が見れます。

image

Tera term で SSH で入ることができます。ユーザ名は「root」で、パスワードはありません。Linux 2.6 が動いていることが解りますね。

image

ifconfig などのコマンドも動くので、細かい設定は /etc/network/interface をいじったほうが早いかもしれません。ただ、iwconfig 等のコマンドがないので、別で設定している可能性もあります。

image

Visual Studio プログラムを書く

Microsoft 提供のサンプルコードを見ると、プログラムはコマンドラインアプリになります。参照設定に「MonoBrickFirmware」を加えて、EV3 のモーターやセンサーの類が使えるようになりますね。

image

他にも、MonoBrickFirmware.UserInput でインテリジェントブロックのボタン押下のイベントが取れたり MonoBrickFirmware.Services.WebServer で簡易 WebServer が作れたりします。ネットワークを通じて EV3 のロボットを操作することが可能ですね。

CLR のバージョンが v4.0 なので async/await が使えないはずですが、これは後で確かめます。

MonoBrick のサンプルは Larsjep/monoev3 で公開されています。MonoBrickFirmware 自体は monoev3/MonoBrickFirmware at master · Larsjep/monoev3 で公開されているので、C# から直接 EV3 のセンサーを叩く時に参考になるでしょう。

WinSCP で実行ファイルを EV3 に送る

Visual Studio でビルドした実行ファイルを、EV3 に送るには、WinSCP を使います。SCP クライアントならば何でもいいはずですが、MS のドキュメントにもあるのでそのまま使うのがいいかなと。

WinSCPとは :: WinSCP
https://winscp.net/eng/docs/lang:jp

転送プロトコルを「SCP」にして、ポート番号は「22」のまま。ユーザ名は「root」で、パスワードはなしです。ログインボタンを押すとと、接続時に戻り値のエラーがでますが、そのまま接続ができます。

image

SSH 上でファイル転送をできるようにした方式だそうなので、FTP のように2ポート開けなくてすみます。使い方は同じですね。

image

/home/root/apps/ の下に適当なフォルダ名をつけて(これが EV3 で動かすプログラム名になります) *.exe と *.dll をコピーします。画像をディスプレイに表示する場合は、それらもコピーします。

 

プログラムを実行する

WinSCP で実行ファイルをコピーしたら、インテリジェントブロックでプログラムを実行します。

image

ぽちぽちとカーソルを動かして、実行すれば EV3 で動きます。これは何もモーターなどがついていませんが、ディスプレイに表示だけするとかもできますね。

そんな訳で C# で EV3 が動く環境までできたのですが、この実行の部分が面倒くさい。先の LabVIEW のように PC から直接動かしたり、なんかデバッグしたりできないですかね?というので、Xamarin Studio の登場です。

etroboEV3 / Wiki / MonoBrickWin
http://sourceforge.net/p/etroboev3/wiki/MonoBrickWin/#11-monobrick-ev3-firmware

この手順に従って環境を構築すれば、Xamarin Stduio で EV3 をデバッグ実行することができます。これ自体もともと MonoBrick に含まれているので、ET ロボコン専用という訳ではなくて普段の EV3 開発にも使えます。

というわけでで引き続き。

補足
SSH で接続して apps に移動した後、「mono プログラム名」で起動できますね。WinSCP をバッチ化して Tera Term で常時繋げておけば、インテリジェントブロックのカーソルキーを使わなくてもアプリを起動できます。

カテゴリー: C#, EV3 | LEGO Mindstorms EV3 を C# で動かす はコメントを受け付けていません

LEGO Mindstorms EV3 をフリーの LabVIEW で動かす

手元にある LEGO Mindstorms EV3 は、以前いきおいで買ったもので基本+拡張セットがひと揃いあります。引っ越し前に買って、家で動かしてみたもののかなりの間放置状態だったんですよね。実は、同時に教育プログラムセットの LiveVIEW 版も一緒に買ったのですが使わず仕舞い。引っ張り出そうと思ったんですがダウンロードURLだったか会員番号だったかを SSD ごと紛失してしまったので、なんともなりません。株式会社アフレル で買ったので、再問合せすればダウンロードできたりしませんかね。

フリーの LabVIEW を使う

プログラミング自体は、四角いインテリジェントブロックのボタンを使ってぽちぽち押せば作れるのですが、まあ、なかなか大変です。確か EV3 の Bluetooth シリアル通信は解析されているので、それ経由でハックすることも可能なはずですが、パンダ Scratch みたいに手軽にやりたいところです。

ソフトウェアをダウンロード – ダウンロード – レゴ®マインドストーム LEGO.com
http://www.lego.com/ja-jp/mindstorms/downloads/download-software?ignorereferer=true

ということで、上記からフリーの LabVIEW がダウンロードできます。製品版との違いは、Community: NI LabVIEW for LEGO® MINDSTORMS® / LabVIEW Module for LEGO MINDSTORMS – Download – National Instruments にあるのか…ちょっとわかりませんが、インテリジェントブロックと似たような感じで PC 上でプログラムができます。

image

が…、残念なことに EV3 の基本セットに入っている超音波センサーと地軸センサーがありません!

image

その代わりに、最近発売されたらしい赤外線距離センサーが入っています。モジュール自体が追加できるかどうかわかりませんが、まあモーター制御とカラーセンサー、タッチセンサーがあれば、それなりに使えるでしょう。

※既存のプロジェクトから「インテリジェントブロックのインポート」をすると超音波センサーの画像が出て来るので何らかのガードがかかっているのかもしれません。

追記 2015/11/01

いや、違った。Downloads – Mindstorms LEGO.com  にある EV3 Software Block Download から特定のブロックをダウンロードできます。その後に、「ツール」→「ブロックのインポートウィザード」で取り込みができます。なんか、外部ブロックの仕様書もダウンロードできるので、かなりオープンな体制になっているようです。

20151101_01

EV3 と無線接続する

PC と EV3 インテリジェントブロックとの接続は、USB ケーブルか Bluetooth の2種類になります。Bluetooth ドングルは手元の安価な iBuffalo の USB ドングル(千円弱)で動くのでたいていのものが動くと思います。Raspberry Pi もそうなのですが、Linux では iBuffalo か Planex が確実に動くので財布的に助かります。

ちなみに、Wi-Fi ドングルは EV3 では動きません。というか、フリーの LabVIEW では動かず、製品版では動くそうです。まあ、Bluetooth で十分なのでこれを使います。

EV3 インテリジェントブロックに Bluetooth のドングルを差し込んだら、設定→Bluetooth を指定します。この中で「Visibility」と「Bluetooth」だけチェックを入れます。「iPhone/iPad/iPod」にチェックを入れると PC から繋がりません。たぶん、BLE 専用のドングルを使うパターンだと思うんですが、ちょっとよくわからず。

image

Windows PC 側はペアリングが必要です。ペアリングします。

image

ペアリングをしようとすると、コントローラ側でホスト名が出るので、ok ボタン(真ん中のボタン)を押します。パスコードの初期値が「1234」なので、そのままにしておいてokボタンを押すと、

image

PC 側でパスコードを要求するダイアログがでるので同じように「1234」を入れます。

image

その後で、LabVIEW の左下で Bluetooth 接続します。先にPCでペアリングしないとうまくいきません。たぶん、Mac のほうはここだけで設定できるのかも。

image

USB ケーブルでつなげるときは、左の「USB」にチェックを入れれば ok です。

LabVIEW でプログラミングする

で、ブロックを使ってぽちぽちと作って、実行ボタンを押すと EV3 が動きます。転送は自動的に行われるし、今どのブロックが動いているかがちかちかするので分かりやすいです…が、実は作りにくい。EV3 インテリジェントブロックでぽちぽち作っているのに慣れていれば大丈夫なのかもしれませんが。やっぱり C# とかで作りたいですよね。

image

これは、タッチセンサーでボタンを押したらピープ音を鳴らしてちょっとだけモーターを動かします。よくわからないと、これを作るだけでも結構面倒くさい。

接続しているモーターとかセンサーとかは、接続したときに右下に表示されます。また、プログラムは EV3 インテリジェントブロックにアップロードが可能です。既存のプログラムはメモリブラウザを使って追加削除ができます。

image

LabVIEW で作ったプログラムと、インテリジェントブロックで作ったプログラムは互換がないのですが、「ツール」→「インテリジェントブロックプログラムのインポート」を行うと、既存のプログラムを LabVIEW に取り込めます。

このあたりは、LabVIEW 付属のヘルプがあるので読むとよいでしょう(ネット上にはない模様)。

お次は C# で動かそう

そんな訳で手始めに LabVIEW を使ってブロックプログラミングをしておきます。じゃあ、これでは物足りないから普段使っているプログラム言語の場合はどうなるのか?ってのが、

レゴ エデュケーションと日本マイクロソフトが日本発 IT 人材育成を目的としたプログラミング ロボット教育カリキュラムの提供で連携 | News Center Japan
http://news.microsoft.com/ja-jp/2015/10/27/151027-azure-lego-education/

になる訳です。これでは MonoBrick という Linux を使うわけですが、これを引き続き。

カテゴリー: EV3 | LEGO Mindstorms EV3 をフリーの LabVIEW で動かす はコメントを受け付けていません