2012年10月28日日曜日

ハンドジェスチャによるラジコン操縦システムの開発

無駄に格調高いタイトルだけど、ただこれまでのプログラムを全混ぜしただけ

まずラジコンの話↓

先週どうにかxbeeが使えるようになったのでラジコンでも作ってみた(有給2日取って)。


同僚「ラジコン作ったんだって?」
筆者「おう!テンション上って動画まで撮ってきたぜ!!」
同僚「マジかよ見せて」
筆者「もちろん!」




同僚「え・・・ああ、なんか微妙だな・・・」
筆者「そうか、まあこんなもんだよ実際・・・(´・ω・)」

しょうがないよね。単三電池4本でArduinoとxbeeとDCモータ2つ動かしてるからね(´・ω・)

〜材料〜 
タミヤのキット(これ)の下半分
Arduino uno
xbee ZBのやつ
モータドライバ(TA7291P)✕2
ブレッドボード
電池ボックス、単三✕4
100均の使い捨てお弁当箱
ジャンプワイヤ✕多分14本くらい

〜操作インターフェース(上の動画はこれで操作してた)〜







2本のスライダで前後と左右(回転)を制御する極めて洗練された(必要な機能まで削ぎ落した)インターフェース。
・一旦止まらないと曲がれない酷い仕様。
・PWMで速度は無駄に細かく(最大1024段階)調整できる。

上半分はテスト用のGUIなので今回の話とは無関係

ラジコンの話 〜おわり〜


過去に作ったopencvのプログラム(過去記事)にラジコン操作プログラムをぶち込んで、
特定の指の状態のとき上のインターフェースのスライダの値を変化するようにしてみた。

手の形:動作
パー:前進
親指曲げたパー:後退
グー:停止
チョキ:左回転(回転は人差し指基準に左右の指を立てるイメージ)
指でっぽう:右回転

でやってみた結果、当然ながら成功。ラジコンの動きは上の動画と同じで、手の認識は過去記事と同じ。気分は超能力者 (´д`)ノシ   ミ凸

これでとりあえず、カメラ→PCで画像処理、判断→無線→Arduino→モータの流れが実装出来た。

しばらくはコードの最適化、高速化(一部をboost.pythonでC++にしただけでフレームレートが5fps増えた) でもやりながら、機械学習やら制御やらを勉強する予定。

〜おわり〜

2012年10月20日土曜日

arduino-xbee-firmata-python連携キター(´∀`)ー

いろいろ参考にしまくってどうにかxbee(簡単に無線でシリアル通信できるユニット)でいつも通りにarduino動かせるようになったので要点をメモ(忘れると1日潰れる箇所あり。注意)

筆者環境:ubuntu 12.04 (32bit)  pythonはeclipse(PyDev) 他はふつうのはず

主な参考文献、ソフトなどの入手先

1、ubuntuでのxbeeのソフト設定方法を参考にさせて頂きました。
 ttp://d.hatena.ne.jp/abikounso/20100506/1273106924

2、オライリーの「XBeeで作るワイヤレスセンサネットワーク」、今回の話の基盤になる書籍。

3、FTDI(PCとxbeeをつなぐUSBコネクタのドライバ)
    ttp://www.ftdichip.com/FTDrivers.htm(目次的なページ)
 http://www.ftdichip.com/Drivers/VCP.htm(ubuntuはこっち)
 ページにあるTN-101という資料に具体的な入れ方が書いてあるから見ながら入れる(英語)

■xbeeを使えるようにする
 上記3のドライバを入れる → xbeeをエクスプローラ(xbee-USBコネクタ)に装着
 → PCのUSBに挿し込む

 → 参考資料1や2を参考にwineでX-CTUを起動 、ファームウェア(〜ATのバージョン最新のやつ、バージョンは16進数なので注意)をxbeeに書き込む

 →picocom(コマンドラインでxbeeの通信設定できるソフト) を導入
  apt-get でも入れられるがバージョンが古い(1.4)ため参考資料のやり方でできない。
  最新のtar玉落としてきて 「cd (最新版のフォルダ)  ./picocom」で起動
  これを使ってATコマンドネットワークIDなどの登録、設定を行う。無いと詰む

 → 順序は変わるが、ここでボーレートをデフォルトの9600から57600に変更する。
  やらないとfirmata使えない解決に半日)やり方は以下





















 ファームウェアの設定画面のSerial〜 のBaud Rateを57600にする。





















メイン画面の右上のBaudも57600にしておく


2個目のxbeeも同様に設定する(USB引っこ抜いて、アダプタのxbeeを載せ替え)。ファームウェア片方はコーディネータ(AT)、片方はルータ(AT)になるようにしておく。あと、ATDH、ATDLのシリアルは相手側の番号を入力する。

コーディネータをPC(USBコネクタで)に繋ぎ、ルータの方をarduino(xbeeシールド)載せる。




図は配線後の写真(サンプルスケッチでLEDを光らせてみた) 

シールド使うとき 注意点として、arduinoにスケッチ(arduinoに書き込プログラムのおしゃれな言い方)を書込むときはシールド上「serial select」スイッチをUSB、書き込み終わって実際に無線で動かすときはMICROにすること間違えると動かないし、スケッチ書き込みでバグる。


arduinoにstandardfirmataのスケッチ(サンプルの中にある)を書き込む

pythonでpyfirmata(ググる→githubらへんから入手→setup.pyでインストール→pythonのインクルードパスにフォルダ登録しとく)を使って普通にプログラム書く。使い方はpyfirmataのサンプル参照。そのうち自分でまとめるかもしれないけど。

→以前に作ったfirmata用テストプログラムの接続ポートだけ変えてサーボモータを動かすことに成功。スライドバーの動きに応じてサーボが動く、楽しすぎワロタ


















上がテストGUI(作りが雑)、下が実機の構成(arduino、電池、サーボ、ブレッドボード )。
ブレッドボードに今回の話と関係ないセンサが刺さってるのはご愛嬌

明日と来週で適当にラジコンでも作ってみるか。

・・・書き忘れがあったら嫌だな(;´д`)。ああ、無線モノは認識に時間かかる(X-CTUとか)から気長に待つべし。連打するとろくなことにならない。

  


2012年10月14日日曜日

boost python の導入

C/C++でglade使ってGTKのUI作ってOPENCVも使って、同時にArduinoも(firmataで)動かせればいいな〜と思いつつここ2週間ほど足掻いてきたけど

「もうむりぽ・・・(´ω`)、いまのぼくではpythonでしかopencvとarduinoを繋げないお・・」

 な感じになってきたので、やっぱりpythonで諸問題の解決に当たることにしました。

pythonにおける実行速度の問題解決方法はだいたい以下の路線になります。

1,cpython
2,pypy
3,boost python
4,そもそものアルゴリズムを変更

今回は3の「boost python」とかいうのに(C++勉強したのがもったいなかったので)挑戦したのでメモ

boost python・・・C++のコードを普通にpythonにimportできる神ライブラリ(boostっていうのはC++の準標準ライブラリ群のことらしい)

これでやたら計算時間がかかるベクトルの角度計算のとこだけ高速化できればめでたくHappyENDを迎えることができる。

で、Boostのインストールから(ubuntu 12.04 32bit)

synapticで「boost」で検索→libboost-python1.46.1(2012年10月現在)を インストール(依存関係にあるものも全部)。ほかの方法(apt-getとかtar玉から手動でインストールとかはなぜかうまく行かなかった(インストールはうまく行ったがその後が・・・)。ふつうはうまく行くはずなのでそちらで行けるならどうぞ)

おわり

使い方:
参考文献:
1.「[c++][python][boost]boost::pythonを使ってC++のPythonラッパーを作る」: ttp://d.hatena.ne.jp/sleepy_yoshi/20111120/p1

2.Boost.Python の機能をざっと紹介してみる : 
ttp://d.hatena.ne.jp/moriyoshi/20091214/1260779899

参考文献を参考にさせていただきながら、どうにかhello world的な行為に成功。


□まずc++のソースを書く(ほぼ参考文献2からの引用、コードの解説はそちらでどうぞ)

#define BOOST_PYTHON_STATIC_LIB
#include <string>
#include <boost/python.hpp>
using namespace std;

string add_hello( string s )
{
    return "Hello, " + s;
}

int square( int n )
{
    return n * n;
}

BOOST_PYTHON_MODULE(kakudo)
{
    // C++のadd_hello関数を、greetという名前でpython用に公開
    boost::python::def( "greet", add_hello );

    // C++のsquare関数を、squareという名前でpython用に公開
    boost::python::def( "square", square );
}

流れとしては、ヘッダ書く→関数書く(クラスもいけるらしい)→pythonの関数名との対応関係を記入という感じ。これだけ見るとわかりやすくて簡単そうだが・・・

□これをpythonで動かす

g++でコンパイル(コンパイルのオプションなんかは参考文献1からのパクr引用)

 g++ -I`python -c 'from distutils.sysconfig import *; print get_python_inc()'` -DPIC -shared -fPIC -o kakudo.so kakudo.cpp -lboost_python

↑何がなんだかわからない。ちょっと調べて簡略化(太字部分)

g++ -I/usr/include/python2.7 -DPIC -shared -fPIC -o kakudo.so kakudo.cpp -lboost_python

どうやらここはこの前の`pkg-config 〜`みたいな感じで「python.h」のおいてあるフォルダの位置(だいたいpythonのインストールフォルダ)と思われる(他のページでpython.hがいるって書いてたきがする) 。

次に、 -DPIC -shared -fPIC の部分。-DPICはよく分からなかった(削除してもとりあえず問題なかった) -shared -fPIC は共用ファイル(〜.so)を作るのにセットで必要なオプションっぽい(-fpicはなくても機能したけど直感的に入れといたほうが良い気がする)

その次は -o (出力ファイル名) (入力ファイル名) 

最後に -lboost_python は-l(ライブラリの検索) とboost_pythonなのでインクルードパス(どこだかしらないけどboostを入れた時にg++のデフォルト探索範囲に設定されてるはず)からboost_pythonを探してくるコマンド。もし無いと


ImportError:〜.so: undefined symbol: _ZN5boost6python6detail11init_moduleEPKcPFvvE

↑python側でこんなエラーが出る(知らずにこんなエラーが出たら泣くね。ライブラリ忘れには注意したいところ)。

〜python側の処理(筆者のオリジナルコード)〜
pythonのインクルードパスにkakudo.so (名前は↑のコマンドで自由に変更できる)のあるフォルダを入れてから以下の高度なpythonプログラムを記述し、実行する。

import kakudo

a=kakudo.greet("hello")

print a







〜出力〜
 Hello, hello

以上、おわり。

来週はベクトルの角度求める関数でも書いて見る予定。これで高速化出来なかったら精神的ダメージを受けそうだわ・・・わりとその可能性もあるし

2012年10月10日水曜日

eclipseでC++でGTKで動かす(その1)

先月末ごろ

筆者「じゃんけんマシンの基礎キターーー(略」
筆者「・・・でもどう頑張っても20fpsくらいしか出ない。
  しゃーなしC++やってみるか。死ぬほど嫌だけど。」

ということでC++の 勉強を始めました。今回はそのメモ

eclipseだとCDT(C Develop tool(?))というのをいれるとC/C++が使えるようになる。
CDT入れるとこまではググってどうにか・・・・

で、問題はここからだよ。先週の土日を消費しても間に合わず今日(いまさっき)どうにか到達

1,gtkmm(pythonでいうところのpygtkにあたるもの)の導入


sudo apt-get install libgtkmm-3.0-dev  

sudo apt-get install libgstreamermm-0.10-dev 

sudo apt-get install libgdamm4.0-dev 
 
という感じでインストールするだけ(ubuntu12.04)。 

2,gtkmmの動作を確認

ようつべにて
 「Creating a simple GUI programm with C++ and GTKMM with a Button」
という偉大な動画からテスト用のコードを拝借

#include <gtkmm.h>

int main( int argc, char *argv[] )
{
    Gtk::Main kit( argc, argv );
    Gtk::Window window;
    
    Gtk::Main::run( window );

    return 0;
}

これでウィンドウが表示できるぜ!!ってなればよかったんだけどね・・・
 
当然コンパイラが<gtkmm.h>とかいうのをどここから探して
持ってこないといけないわけでして・・・
 
ここでeclipseの設定をいじらないといけなくなりました。
まあ当然と言われるとそうなんだが。

以下設定のしかた。 
1,プロジェクトのプロパティから下のような設定画面を出す。
  ここでC/C++ビルドの「設定」をクリック

 
 
 
2,この中の 「〜C++ Compiler」の「その他」をクリック
 
 
 
 で、「その他のフラグ」に`pkg-config --libs --cflags gtkmm-3.0`と書いておく
(かいせつ) 
「`」はshift+@キーで出る(shift+7キーじゃないよ) 
 pkg-config はいつの間にか入ってたがアプリっぽい。もし無いなら入れるべし。
 --libs --cflags はpkg-configのオプション。C++(多分Cも)にインクルードする関連の
ファイルのパスを全部表示してくれる便利な奴。  

これでgtkmm使うに当って必要なファイルは全部リンク出来る感じになる。多分他のツール
(opencvとか)使うときにも活用できる。
その他の3つほど上に「インクルード」とかいうのがあってそれで
参照するパスを入れることもできるが(多分そっちが普通か?)
gtkmmは参照ファイルが多いので止めた方がいい。 日が暮れるので。
 
 
 
 これで使えたらいいんだけどまだやることがある。
今まで触ってた項目の親である「GCC C++ Compiler」をクリックして「エキスパート設定
コマンド行パターン」とかいう難しそうなところに注目。


どうやらここでコンパイル時のコマンドラインの入力順を規定しているっぽい。
eclipseも所詮はコマンドライン入力を自動でやってくれるだけの存在でしかない。

ここで「g++ (ファイル名)(オプション)(出力ファイル名)(なんとか〜)」の()の
順番をいろいろ入れ替えられるようになってる(はず)。

デフォルトだとgtkmm込のコンパイルが通らないのでここの順番を
${COMMAND} ${FLAGS} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS}
から
${COMMAND} ${OUTPUT_FLAG} ${OUTPUT_PREFIX}${OUTPUT} ${INPUTS} ${FLAGS}
に変更(ここの丸写し。いいのだろうか:スタックオーバーフロー
  
でビルド→実行→窓出現
ビルドで警告出るし、実行で「必要なプロジェクトにエラーがあります」とか出るけど
無視して実行(そのうち解決できるといいね)。


結果↓
 
 
 pythonなら10分くらいで出来そうな話だったけどさすがC++。そらみんな別の言語使うわ。
 気軽にGUI作れるgladeっていうソフトで作れるようになるとこまで持っていくので次回へ
 続く(諦めてpythonに戻ったら続かない)