Who is さくふわめろんぱん

さくふわめろんぱん(@skfwMelonpan)はロボットとか人工知能に興味があるパンです。
自分のために調べたことがみんなの役に立ったらいいなぁ。

2015年10月6日火曜日

RaspberryPiをロボットに使うこと

コンテスト用のロボットにLinuxボードを使うことについて


RaspberryPiが登場したとき、当時マイコンに挫折してた僕の目は輝きました。そしてRaspberryPiを使ったロボットで2つのコンテストに参加しました。周囲にLinuxボードを使う人が増えてきたのは感じますが、ロボットのコンテスト界隈に変化は起きていないように感じます。対してArduinoは確実に浸透して、変化をもたらしたように思えます。そこで、なんでRaspberryPiでロボコンが難しいのかを考えてみました。

難しさ1:初期設定の手間


マイコンは基本的に初期設定とかないし、あるとしても決まった手順を行えばいいです。RaspberryPiなどの初期設定は自分の持っている環境にもよるし、そもそもOSが違えば全く別物なわけです。さぁ買って使おうというときにこうやってつまづくのはテンション下がる。調べた通りにやってるけど自分の環境のせいでうまくいかないなんてことがザラです。

難しさ2:起動時間


これがマイコンからRaspberryPiにすんなり移行できない最大の要因です。マイコンは電源を投入したらすぐ動いてくれます。(モノによってはスタートボタンがあったり)RaspberryPiの場合は電源を入れてプログラムが勝手に動くようにもできますが、OSの起動時間がしばらくあるのでコンテストの競技開始時にスイッチを入れる訳にはいかないのです。電源はあらかじめ入れておいて、スイッチか通信でプログラムを実行する他ありません。

難しさ3:できることの多さ


これはRaspberryPiを使う目的でもあるので、はまりがちなところ。ネットで調べれば分かるように何でもできるのですが、すべてを同時にできるとは限らなかったり、重要でない処理のために全体の処理能力に負担をかけたりします。

難しさ4:複数のプログラムの実行


LinuxというかOSというものは、複数のプログラムを実行するために存在しています。その技術の恩恵をうけて複雑なプログラムを機能ごとに分割したりできます。それに対してマイコンでは基本的に大きな1つの(全部入り)プログラムを書き込むという発想しかなかったので、こういった知識が足りず難儀します。(しました)
例えば...
・実行するプログラムが増えると処理が落ちる
・どれか1つのプログラムが異常終了してたりする
・機能を細分化しすぎて無駄ができる

難しさ5:ノウハウ


研究でLinuxベースのロボットを作ってたりとなると、ここに書いたようなノウハウがあるのだろうけどみんながそうではないですよね。そういうのってノウハウが一般的(あたりまえ)なことすぎて教科書レベルのことから勉強しなくちゃいけなかったり、それこそ経験しないと身に付かないものだったり。RaspberryPi用のロボットOSを勉強するのもアリかもしれません。

結論


コンテスト用のロボット制作というのは、プログラムを書いてテストして修正するのを何回できるかが大きく結果に関わります。そのルーチンをどれだけ速く回せるかにかかってるのに、OSの起動時間なんて待ってられません。今のところの経験をまとめると3点。

  • RaspebrryPiは起動した状態で扱うこと
なるべく早い段階からモバイルバッテリーなど駆動用とは別の長時間つかえる電源で開発を進めましょう。
  • 確実な通信を確保すること
有線LANで直接パソコンにつなぐ通信がベスト。代替えとしてシリアル通信もあり。とにかく通信できないのが一番焦る。
  • 操作基板をつくること
スイッチやインジケーターを載せた基板を使って開発する。単独でも機能するのが1番強い。

従来のマイコンの代わりように使うことが必ずしも良いとは限りません。また、RaspberryPiを使いこなせばマイコンなんて要らないということもないでしょう。うまく使っていきたいものです。

2015年10月4日日曜日

ArduinoでのGPSのデータ処理(ver2)

このブログのアクセス解析を見るとArduinoでGPSを使う記事がよく見られています。
だけど昔に書いたコードだし、いろいろプログラムとしては微妙だなぁと心苦しかったので書き直しました。

String型のDataという配列のData[0]から順番にNMEAのデータが入っていくようになっています。緯度と経度と方位を取得したいのでGPRMCのフォーマットを想定して書いてあります。

学部1年生にも理解してもらえるようにしたかったので、本当はString型の変数を使わないで、char型だけで数値まで持ってきたかったのだけど、汚くなるので断念。String型はメモリも消費する気がするので、多用したくないね。便利だけど。
あと、文字を判定するif文はswitch case文にしてもいいかもね。

フローチャートはこんな感じ。
まだ一般性のあるプログラムとも言えないですが、前よりは良くなったと思います。

簡単に説明すると、
・1文字ずつ読み込んで、文字列にしています。
・NMEAデータをカンマ区切りで文字列型の配列に入れています。
・NMEAデータを1行ごとにデータ処理(数値に変換)しています。
・緯度と経度をlong int 型に変換しているけれど、本当に使う下部分だけにすればint型で十分です。

そのタイミングでロボットの制御をすれば取得周期(だいたいのGPSモジュールは1秒)で制御できます。
もっと制御したい場合は工夫してください(丸投げ)

2015年9月3日木曜日

能代宇宙イベント2015に参加してきました


すこし報告が遅くなったけど、能代宇宙イベントに参加してきました。
能代に行くのは2度目で2年ぶりです。

機体名は「CLOVER」(クローバー)で、ミツバのクローバーのように3方向にプロペラがついています。パラシュートによって減速しながら推進する方針です。

CLOVERの外観
オレンジのがプロペラで
上についてる白いのがパラシュート
ハードウェア構成は
・RaspberryPi
・ブラシレスモータ
・ブラシレスモータ用のスピードコントローラ
・Li-Poバッテリー
・センサ類(地磁気、加速度ジャイロ、気圧、距離)
・GPS
・Xbee

ソフトはほぼ全てPythonで書きました。
プログラムについては備忘録の意もこめてまた後で詳しく書きます。

結果はブラシレスモータが駆動せず、投下、ログ取り実験に終わりました。
それ以外のセンサやGPSやXbeeの通信はうまくいったので悔しいです。
自作のパラシュートがうまく開いてきれいに減速できてたのは満足しました。

ブラシレスモータが駆動しなかったことを詳しく説明すると、
ブラシレスモータのスピードコントローラの設定がうまくできませんでした。
原因はおそらくRaspberryPiのソフトウェアPWMが安定していないことです。
回路的に作り出したPWM信号ではないため、他の処理に影響されて信号のduty比が乱れます。
設定がうまくいったとしても、実際の駆動が安定したかも保証できません。

現在はPWM信号の発生を専用のICに任せる方針で調整しています。


2015年8月2日日曜日

RaspberryPi 起動したらプログラムが動いてほしい


RaspberryPiを買って、ずっとHDMIとかでディスプレイにつなげて使ってる人は稀ですよね。最初の設定でちょっと使うけれど、ネットワークの設定とかが済んだらパソコンからssh接続したほうが楽ですからね。

そうやってRaspberryPiを使ってて不安なのは、起動はしてるだろうけど、どこまで起動したかわからない。ssh接続したいけど、もう起動したかな・・もうちょっとかな・・。っていうのを毎回考えてしまいます。

それとはまた別で、自律ロボットのためにRaspberryPiを使っている人は分かるとおもうのですが、毎回電源入れてネットワークで接続してプログラムを起動するというのは手間です。それに、ネットワークがない場所(屋外とか)で動かすときや万が一ネットワークがダメなときに、電源を入れ直したら動作するようになっていて欲しいのです。

少なくとも「GPIOピンに繋げたスイッチを押すとプログラムが動き出す」っていうプログラムが起動して欲しいわけです。(ややこしいけどわかるかな?)

最初に書いた起動してるか分からない問題も、起動したらLEDを点滅させるとかネットワークでなんかするとかいうプログラムを書けば解決ですよね。

起動したらプログラムが動く方法その1

Linuxが起動するときに実行させる

LinuxのOSが起動するときに、最初から入ってるプログラムがばーっと動いて実行されます。RaspberryPiをディスプレイに繋げて起動したときに見える大量の文字列は、初期設定とかネットワーク接続とかいろんな作業をしてくれているわけです。

そのうちの1つとして実行する方法があります。
/etc/rc.local
というファイルの exit 0 の前に書き込む方法です。
このファイルで実行するのは初期設定の変更関係にしましょう。
ネットワークのIPアドレスだとかの設定に使えます。

起動したらプログラムが動く方法その2

ログインしたときに実行させる

もう1つの方法はログインしたときに実行する方法です。
ログインしたときにプログラムを起動するのはMacやWindowsでもある機能ですよね。
/etc/profile
にrc.localと同様に書き込むとログイン時に動作します。
あとは起動したときに自動ログインをするようにすればよいですね。
/etc/inittab  の
1:2345:respawn:/sbin/getty 38400 tty1
をコメントアウトしてその下に
1:2345:respawn:/bin/login -f ユーザー名 tty1 </dev/tty1>/dev/tty1 2>&1
って書いて保存っと。

これで起動→ログイン→プログラムが起動という流れになります。
ちなみにsshでログインするともう1つ余分にプログラムが回るので注意。

ちょっとしたメモ

Pythonのプログラムを起動するとき普通は、
$    Python ./program.py
見たいなコマンドにしますが、GPIOとかファイル操作をするときは実行権限がないとプログラムが途中で止まってしまいます。なので自動実行させる時はsudoで実行しましょう。
$   sudo python ./program.py
それと、バックグラウンド処理(背後でプログラムを動かして他の処理をする) をしたい場合はアンパサンドをつけましょう。
$   sudo python ./program.py &
sudoで実行することのもう一つの利点は、sudoのプロセスを止めるとプログラムが止まってくれることです。 killallってコマンドで一斉停止ができます。
$   sudo killall sudo
なんかプログラムが暴走してるときとかに便利です。 

2015年7月31日金曜日

3軸デジタルコンパスHMC5883L 3軸の謎

Amazonとかで手軽に買えるデジタルコンパスにHMC5883Lがあります。
データシート(http://www51.honeywell.com/aero/common/documents/myaerospacecatalog-documents/Defense_Brochures-documents/HMC5883L_3-Axis_Digital_Compass_IC.pdf

これは3軸コンパスといってX軸、Y軸、Z軸方向にかかっている磁場を測定できます。
普通のコンパス用途ならX軸、Y軸の値だけでかまわないし、海外のサイトでもZ軸を扱っていない場合が多いです。

基本的なデータの取得に関しては他のサイトやブログで十分なので、取得できた値をどうすればよいかという話を書いていきます。

補正

まず、重要なのはデジタルコンパスは使うためには補正が必要だということです。
このコンパスをきれいに使うには2つの補正が必要!
理解するためには計測している対象である地磁気について知っておく必要があるかもしれません。(参考:国土地理院のページ
地磁気は地球上どこでも、南極から北極にむかう方向の矢印だと思ってください。
その大きさは東京付近で約45000nTだそうです。(wikipedia より)
(※)1nT(テスラ) = 10μG(ガウス)なので 45000nT=0.45G
センサは±8Gまで測定できます(0.45 < 8 はずいぶん大きい)
測定範囲を設定することができるようです。(データシートP13)
こうした方が精度良く測定できそうですね。(最小範囲は±0.88G : 分解能は0.73mG)
デフォルトでは±1.33G : 分解能は0.92mGになっています。
よく scale = 0.92 という変数がプログラムに散見されたが、このことだったのか。
つまり、センサの値を丁寧にガウスに変換してたのね。
でも最終的に角度が欲しいだけならそんな几帳面さ要りません。
角度は比率でとっちゃうし、地磁気の大きさなんて実際つかえない。
地磁気の大きさ以外に、向きも場所によって変わります。
それが変わっちゃお手上げなのですが、そんなにコロコロ変わるものでもありません。

偏角と伏角(へんかくとふっかく)


偏角は水平方向の角度で、コンパスが指す方向と北極の方向のズレです。
東京では+7°くらいずれます。最終的な方角に-7°してあげましょう。
GPSによって取得できる緯度は北極方向の測地線なので、GPSとコンパスを使う場合には少し気にしましょう。
伏角は磁場が地面にめりこんでる角度です。
僕もこれを知るまでは地磁気は地面に平行だとおもっていたのですが、結構めりこみます。東京で地面の下に49°くらいの角度です。
つまりデジタルコンパスのZ軸方向の値は負です。
図にするとこんな感じ。

センサの内部的な問題


偏角と伏角のように場所に依存するのではなく、センサの内部的な問題で磁気が記憶されて電圧が多く乗ってしまったりということがあるようです。(よくわかってない)
具体的にどういうことになるかというとこんな感じです。



定常的に誤差がのるので使う直前にこの誤差をオフセットとして算出して打ち消すようにします。
どうやるかというと、一定時間センサで値を取り続けながらセンサをグルグル回します。センサをいろんな角度になるようにしてください。グルグルというより、ぐるんぐるんに回さないといい補正はできません。そのようにして取った値を3次元空間にプロットすると、上の図のような球面になります。その中心を計算してオフセットとして差し引きます。簡単に計算するために
球の中心のx座標 = (xの最大値 - xの最小値) /2
球の中心のy座標 = (yの最大値 - yの最小値) /2
球の中心のz座標 = (zの最大値 - zの最小値) /2
としてますが、もっと正確には、数値解析的に最適にフィットする球面で近似して中心を求めた方が良さそうです。(あ、これやってみたい)

角度へ変換

ここまでだとまだセンサの値はx,y,z方向にかかる地磁気の強さです。
補正されたとしても、これを見て方角が分かる人はそんなにいないでしょう。
(x,y,z)という変数の直行座標系を(r,θ,φ)という変数の球面座標系に変換します。
r : 地磁気の大きさ
θ : z軸からの角度
φ: xy平面に投影したときのx軸からの角度
基本的に方角を知る上で必要となるのはφ(xy平面上の角度)だけですね。
θを使えばセンサの傾きも取得できるはずなのですが、うまくできません。

変換公式

逆三角関数をつかうのでマイコンによってはヘビーかもしれません。
また、地磁気の向きがz軸と重なるとφの値が定まりません。
(なるべく水平に使った方がφが安定するよということ)
置き方によってそうなるかもしれない場合は変数を調整するといいかもしれません。

式を見るとわかるようにφの式にzは使われません。
ということで結局z軸の値はあまり使われないということでした。
でも3軸である以上は何か使い道があるはず。

1つは傾きを知れることなのですが、傾きすぎると方位の値がぶれます。
よく考えたら、方位磁針を縦向きに置いたら方位がわからなくなるのはあたりまえですね。

地磁気センサ単体で傾きを知るのは難しいかもしれないので、加速度ジャイロセンサと組み合わせることで、加速度ジャイロセンサの示す姿勢に対して地磁気がどちらに働いているかというのを提示するというのがいいのかもしれません。

球体方位磁針のように考えて、制御に活かせると新しいかもしれませんね。
3次元方向に制御できる対象というのも普及していることですし。

2015年7月28日火曜日

RaspberryPi でセンサーを使おう

今回のCansatに搭載するのは

  • GPSモジュール PA6C
  • デジタルコンパス HMC5883L
  • 加速度ジャイロセンサ MPU6050
  • 気圧センサ BMP180
  • 超音波センサ 
の5つ。
これらを統合して20msec周期での制御ができればよいと考えています。
今回の記事では上3つを扱うPythonプログラムを公開します。
拾ってきたプログラムを改変して、ある一定の時間だけログをとり続けるためのプログラムにしました。
ファイルの読み書きをするプログラムを書くよりも、標準出力するプログラムを
$ ./Program.py > data.txt
のように実行した方が楽です。


GPS PA6C

今回のGPSの取得はRapsberryPi (B+) のGPIOピンにあるTX0,RX0を使ってシリアル通信をします。とりあえず読み込んでファイルに書き込むだけのプログラムです。他のセンサも同様ですが、行頭にプログラム開始からの時間を出力しています。

デジタルコンパス HMC5883L

通信はI2Cです。pythonでI2C通信をするためにはインポートしなくてはいけないモジュールがあります。
今後は35行目のスケールを自動補正するプログラムが必要となります。
加速度センサ MPU6050


通信はI2Cです。
加速度は距離を時間に関して2回微分した値なので2回積分しなくてはいけません。
ジャイロは角速度なので1回微分すると角度になります。
積分操作をする場合は何かデータを処理してからではないと、多くの誤差を含んでしまいます。
そのための操作(フィルタリング)について考える必要があります。

2015年7月12日日曜日

Processingで3D描画してドヤ顔しよう

僕はよくProcessingで3Dの描画をして遊ぶのですが、
これが意外と簡単な割に「なんかすごい」感を出せる。

・キーボード操作 keycheck()
・XYZ軸の描画 drawAxis(float length);
・XYグリッド平面の描画 drawGrid(int size, float length);
という関数に分けて使い回しています。

キーボード操作は、
・矢印:左右回転、上下回転。
・Z,X:ズームイン、ズームアウト
変数を追加すればもっと操作を増やせます。
回転の向きは逆に感じる人もいるかもしれません。正負を逆にしてみてください。

Simple3D.pde (Google Drive)
https://goo.gl/quQW4O