国内・海外AR.Droneプロジェクトまとめ

プログラム公開から1ヶ月ほど経ちました。

今回は開発を進める上で参考になったサイトやライブラリを紹介していこうと思います。
  • AR.Drone SDK 1.8
  • 公式SDK。バグだらけでビルドがまともに通らない。信じられないだろ...公式なんだぜ、コレ。
  • AR.Drone SDK 2.0
  • 相変わらずの心折設計。Win32はサポート対象外に ナンテコッタ/(^o^)\ ※SDK 2.0.1で復活!
  • AR.Drone Development
  • 1番参考になるサイトです。ここがなければCV Droneは生まれなかったでしょう。
  • ARDrone-Control-.NET
  • 計器がカッコ良くて有名、多くのプロジェクトのUVLCデコード部分はこれが元になっています。
  • ARDroneForP5
  • みんな大好き工学ナビのProcessingによるAR.Droneハック
  • AR.Drone+OpenCV For AR.Drone SDK 1.5
  • VS2008から動かすデモ、中の人スゲェ。でも、もう公式SDKは使いたくありません。

これらを参考に作ったのが、
  • CV Drone
  • 国内で公開する1か月前に、海外のフォーラムで公開しました。
    いろんな人達の反響があって楽しかったです。

その他のプロジェクトたち
こうして見ると、結構いろんな人が自分でSDK組んでますね。

AR.Drone 1.0なら工学ナビさんのProcessingライブラリがオススメです。
2.0はAR.Drone Developmentが大変参考になります。

VisualC++で作るなら是非CV Droneを使ってみて下さい。1.0 / 2.0両対応です!
スポンサーサイト



GitHub (ギットハブ) を使おう

最新版のプログラムはGitHubで公開しています。

cvdrone_github.jpg

GitHubは最近人気のバージョン管理サービスです。

Subversion + Apacheでやってた頃もありましたが、GitHubの方が楽です。

あとOctocatがキモ可愛いです。

cvdrone_github.jpg

さっそくアカウントを作成してみましょう。「Sign Up」をクリック!

github_signin.jpg

必要事項を記入したら「Create an account」をクリックしてください。

github_create_account.jpg

アカウントができたらリポジトリを作りましょう。

github_create_repo.jpg

こちらはクライアント用のアプリです。

github_client.jpg

なかなかオシャレな作りになっています。

GitHub上のリポジトリを自分のPCに「Clone」します。

github_client_clone.jpg

ファイルを変更すると自動で認識されるので「Commit」。そして「Sync」を押すとネット上のリポジトリが更新されます。

簡単、簡単♪

今後の更新はGitHub上で行う予定です。

最新のCV Droneに触れたい方は是非GitHubへ使ってみましょう!

本当にあった怖いコード

ところでこのコードを見てくれ、こいつをどう思う?
気が付きましたか?...そう、

val[i]

と書かなければならないところが、

i[val]

となっています。

でもこれコンパイル通るんですよ。

そしてちゃんと動く!ヒエーッ!



まぁ、[]演算子の仕組みが分かっていればどうということはありませんね。
要は、*(val + i) と書くか、*(i + val) と書くかの違いです。

こんなのよりnewで確保してfreeで解放するコードの方がよっぽど怖い...って、え?何?

ネタ挟んでないで下カメラ早くやれ?

な、何のことかなー、全然わからないなー(棒)。

タイマー関数

AR.Droneネタばっかりなので、たまにはちゃんとしたプログラミングの話を。

Win32APIで時間を計測するには、
・GetTickCount()
・timeGetTime()
・QueryPerformanceCounter()
の3つの方法があります。

精度は GetTickCount < timeGetTime < QueryPerformanceCounter です。

実行速度は逆に QueryPerformanceCounter < timeGetTime < GetTickCount です。

QueryPerformanceCounterは環境が対応していない場合もあるそうです。現行のPCであれば問題ないと思いますが、状況に応じて切り替え出来るタイマー関数を作っておくとよいでしょう。
そういえば、OpenCVのcvWaitKey関数は内部でGetTickCount関数を呼んでいるので、

 cvWaitKey(1)

と書いてもcvWaitKey(15)と変わらなかったりします。timeBeginPeriodを使えば精度が上がるそうですが、GetTickCount自体あまり使いませんし、それならtimeGetTimeかQueryPerformanceCounterでいいじゃないか、という話ですよね。

CV Drone 現状の課題

「CV Drone」はこれまでに何度かバージョンアップを重ねてきましたが、まだ課題は残っています。
 https://github.com/puku0x/cvdrone
 ↑開発ページです。☆をつけてくれると中の人が喜びます。

・AR.Drone 1.0でZ方向の速度が常に0.0になることがある ※ 2013/7/11 _navdata_altitude_tより取得可
 取得できたという報告もあるので、こちらの環境だけかもしれません。

・AR.Drone 1.0でカメラのチャンネル1と3に対応していない ※ 2012/11/23 解決しました
 現在、ARDroneForP5のコードを参考に書き換えているところです。もう少しお待ちください。

・AR.Drone 2.0でnavdata.altitudeが常に0.0になる※ 2012/03/20 飛べば更新されます
 取得できた人っているのでしょうか?フォーラムにも同様の問題を抱えている人がいるようです。

・設定情報を取得できない ※ 2013/03/23 解決しました
 sockCommand.sendf("AT*CTRL=%d,4\,0r", seq++);
 とすればTCPのポート5559から現在の設定情報が文字列で送られてくるらしいのですが、
 アクセスしても何も来ません(Telnetを使えば見れます)。


・USB動画保存ができない ※ 2012/12/20 解決しました
 下の信号を送っても保存されません。
 sockCommand.sendf("AT*CONFIG=%d,\"video:video_on_usb\",\"TRUE\"\r", seq++);
 うーん、USBメモリの相性の問題でしょうか?
 OpenCVの動画出力機能を使うという選択肢もあるので、大した問題ではありませんが。


いかんせん、情報が少ないです。

海外のフォーラムでは、AR.Drone 1.0の画像をVGA(640x480)で取ってこれないか?という
質問もありましたが、残念ながら不可能です。

フォーラムでは公式のエンジニアから回答されています。
 https://projects.ardrone.org/boards/1/topics/show/992
 https://projects.ardrone.org/boards/1/topics/show/1609

CPUの処理性能の限界とWifiの品質を保つため、あえて禁止しているとのことでした。

あとはフォームアプリ作らないの?とかありましたが、恥ずかしながらOpenCVに頼りっぱなしで...
フォームはあまり作った経験ないんですよ。

技量が足りませんね。火守女にソウル捧げてきます。

AR.Droneを動かそう(LEDアニメーション)

ATコマンドの中には「AT*LED」という命令があります。

"AT*LED=%d,%d,%d,%d\r"
 第1引数 - シーケンス番号
 第2引数 - アニメーションID
 第3引数 - 周波数
 第4引数 - 時間

これでAR.DroneのLEDを21種類のアニメーションで点滅させることができます。

// アニメーションID
enum ARDRONE_LED_ANIMATION_ID {
BLINK_GREEN_RED = 0,
BLINK_GREEN,
BLINK_RED,
BLINK_ORANGE,
SNAKE_GREEN_RED,
FIRE,
STANDARD,
RED,
GREEN,
RED_SNAKE,
BLANK,
RIGHT_MISSILE,
LEFT_MISSILE,
DOUBLE_MISSILE,
FRONT_LEFT_GREEN_OTHERS_RED,
FRONT_RIGHT_GREEN_OTHERS_RED,
REAR_RIGHT_GREEN_OTHERS_RED,
REAR_LEFT_GREEN_OTHERS_RED,
LEFT_GREEN_RIGHT_RED,
LEFT_RED_RIGHT_GREEN,
BLINK_STANDARD
};
SNAKE_GREEN_REDとかが面白いですよ。

実装するときは、

void ARDrone::setLED(int id, float freq, int duration)
{
sockCommand.sendf("AT*LED=%d,%d,%d,%d\r", seq++, id, *(int*)(&freq), duration);
}
このように第3引数をintのポインタに変換しましょう。

ちなみにデベロッパーガイドにはAT*CONFIGを使って

sockCommand.sendf("AT*CONFIG_IDS=%d,\"%s\",\"%s\",\"%s\"\r", seq++, ARDRONE_SESSION_ID, ARDRONE_PROFILE_ID, ARDRONE_APPLOCATION_ID);
sockCommand.sendf("AT*CONFIG=%d,\"leds:leds_anim\",\"%d,%d,%d\"\r", seq++, id, *(int*)(&freq), duration);
とすれば出来ると書かれてあります。

AT*LEDは将来的に無くなるということでしょうか?

OpenCV 小ネタ

前回の記事の反響もあり、FC2ブログランキングでは いつの間にか1位に。
今は違うかもしれませんが。まぁ、超マイナーブログであることに変わりはありません。

OpenCVは1.0の頃から遊んでいますが、昔気付いたバグやちょっとした小技を紹介していこうと思います。

・HighGUIのトラックバーをカーソルキーで動かす
 一見すごく地味ですが、1目盛ずつ動かせたほうがいろいろ便利です。
 やり方は簡単、たった1行消すだけです。

if( trackbar )
{
if( trackbar->pos != pos )
icvUpdateTrackbar( trackbar, pos );
}

//SetFocus( window->hwnd ); // ここをコメントアウト
return 0;
 HighGUIは最近になってやっとダブルクリック判定のバグが修正されましたね。

・cvConDensInitSampleSetの初期値は実は...
 ランダムと思わせて実は(状態次元数により決定される)固定値です。このパーティクルフィルタ、
 もといCvConDensationは「cxcore」→「cvaux」→「legacy」行きとなった不遇な子でもあります。

/* Initializing the structures to create initial Sample set */
for( i = 0; i < conDens->DP; i++ )
{
cvRandInit( &(conDens->RandS[i]),
LBound[i],
UBound[i],
// i ); // <- これがその原因
i + (int)cvGetTickCount()); // <- cvGetTickCountを追加するといいかも

}
/* Generating the samples */
for( j = 0; j < conDens->SamplesNum; j++ )
{
for( i = 0; i < conDens->DP; i++ )
{
cvbRand( conDens->RandS + i, conDens->flSamples[j] + i, 1 );
}
conDens->flConfidence[j] = Prob;
}
/* Reinitializes the structures to update samples randomly */
for( i = 0; i < conDens->DP; i++ )
{
cvRandInit( &(conDens->RandS[i]),
(LBound[i] - UBound[i]) / 5,
(UBound[i] - LBound[i]) / 5,
// i ); // ここも
i + (int)cvGetTickCount()); // 変更
}
 ロボットの自己位置推定プログラムを組んでいる時に気が付きました。
 パーティクルの再分布をcvConDensInitSampleSet関数で行うときは注意が必要です。

・GetTickCount と cvGetTickCount の違い
 Win32APIのGetTickCountとcvGetTickCountは名前は似ていますが、返す値は全く異なります。
 前者はミリ秒単位の経過時間、後者はTick数を返します。
 ミリ秒に変換するには1000.0*cvGetTickCount()/cvGetTickFrequency()としましょう。

・cvGetTickFrequency とcv::getTickFrequencyでは戻り値が違う
 OpenCV.jpにも書いてあることですが、cvGetTickFrequencyは1us毎のTick数を返し、
 cv::getTickFrequencyは1s毎のTick数を返します。

・STLのバージョンが合っていないと…
 例えば、OpenCVをVisual Studio 2005でビルドして、出来上がったライブラリをVisual Studio
 2008などバージョンの違う環境で作ったプログラムにリンクする場合、std::vectorを引数に取る
 関数(SIFTやSURF)を実行しようとするとヒープが壊れます。
 これはSTLのテンプレートがLIB/DLL側、EXE側で個別にインライン展開されてしまうために起こる
 問題です。必ずEXE、LIB、DLL全て同じ環境でビルドしましょう。

特に、最後のは開発環境を新しくする際に陥りやすいエラーです。

CV Droneはこれを回避するためにVS2005/2008/2010/2012用のライブラリを全てビルドし、
Visual Studioのバージョンに合わせて対応するライブラリをリンクするようにしています。

解凍後のファイルサイズが200MB近くもあるのはそのためです。

VisualStudio2012 で OpenCV2.4.3 のビルド

OpenCVの最新版が先週リリースされましたね。

今回は備忘録も兼ねてVisual Studio用のライブラリのビルドの方法を紹介します。

1. Visual Studioのインストール
「Visual Studio Express 2012 for Windows Desktop」をインストールしましょう。
vs2012.jpg

※ 注意: VS2012をインストールするとVS2010でコンパイルができなくなります。
  .Net Framework4.0を再インストールすると解決しますがVS2012が起動できなくなります。

2. CMakeのインストール
OpenCVのビルドに必要です。「cmake-2.8.10-win32-x86.exe」をダウンロードし、インストールしてください。
2.8.9ではうまくいかないという報告もあります。
cmakeorg.jpg

3. OpenCVのインストール
「OpenCV for Windows」をクリックしてOpenCVの最新版をダウンロードしてください。
opencvorg.jpg

ダウンロードしたファイルを開くと、どこに解凍するか尋ねてくるので、
opencv_extract_7z.jpg

今回は「C:\Program Files」を指定しましょう。
opencv_extract.jpg

しばらく待つと「C:\Program Files\opencv」にファイルが解凍されます。

4. OpenCVのビルド
CMakeを起動しましょう。
start_cmake.jpg

入出力ディレクトリにOpenCVを解凍したフォルダを指定して「Configure」をクリック。
cmake_vs2012.jpg

「Visual Studio 11」を選択して「Finish」をクリック。

画面が真っ赤ですが気にせず「Configure」をクリック→「Generate」をクリック。
なんかうまくいかない、というときは「WITH_CU○○」「WITH_OPENCL○○」「WITH_GIGEAPI」を外しましょう。

opencv_cmake_setting.jpg cmake_generate.jpg
CV Drone付属のものは↑こちらで設定しています。

「C:\Program Files\opencv」内の「OpenCV.sln」を開いてください。
opencv_sln.jpg

Visual Studioが起動したら「Release」を選んで、
vs2012_release.jpg

「ソリューションのビルド」を選ぶか「F7」を押してOpenCVのビルドを実行します。
vs2012_build.jpg

しばらくするとビルドが完了します。

ヘッダ は「C:\Program Files\opencv\build\include」に、ビルドしたライブラリは「C:\Program Files\opencv\lib\Release」、DLLは「C:\Program Files\opencv\bin\Release」に入っています。

適当なフォルダを1つ作ってまとめてコピーしておくと後でプログラムを作る時に便利です。

5. 新規プロジェクトの作成

続きを読む

AR.DroneとOpenCVで遊ぶ(基本プログラム)

AR.DroneをC++で動かしたい、ついでにOpenCVで画像処理させたい!

そんな方に「CV Drone (=OpenCV + AR.Drone)」

もう試していただけたでしょうか?

まだ、という方はこちらへどうぞ!

↓前回は画像表示だけでしたので、今回はちゃんと動くサンプルを紹介します。

それでは早速、これが何をしているか見ていきましょう。

13-14行目、クラスの宣言。

// ARDrone
ARDrone ardrone;
16-20行目、open()でAR.Droneを接続。

// 初期化
if (!ardrone.open()) {
printf("ARDroneの初期化に失敗しました\n");
return -1;
}
24-25行目、AR.Droneの情報を更新。

// ARDroneの更新
if (!ardrone.update()) break;
27-28行目、IplImage形式の画像を取得。

// 画像の取得
IplImage *image = ardrone.getImage();
30-51行目、get***()でナビゲーションデータを取得。

// ナビゲーションデータの取得
double roll = ardrone.getRoll();
double pitch = ardrone.getPitch();
double yaw = ardrone.getYaw();
55-56行目、takeoff()で離陸、landingで着陸。

if (ardrone.onGround()) ardrone.takeoff();
else ardrone.landing();
69行目、move3D()でXYZ軸速度と旋回速度を設定。
move3Dの他にもZ軸の速度指令の無いmove()もあります。

ardrone.move3D(x, y, z, r);
72-74行目、カメラの切り替えはsetCamera()。AR.Drone 1.0は0(前カメラ)、1(下カメラ)、2(前+下カメラ)、3(下+前カメラ)に、AR. Drone 2.0は0(前カメラ)または1(下カメラ)に対応しています。

// カメラ切り替え
static int mode = 0;
if (KEY_PUSH('C')) ardrone.setCamera(++mode%4);
76-78行目、cvShowImage()で画像を表示。

// 表示
cvShowImage("camera", image);
cvWaitKey(1);
81-82行目、close()で終了。デストラクタに入っているので実は呼ばなくても良かったりします。

// さようなら
ardrone.close();

ね、簡単でしょう?

公式SDKでの開発を諦めてProcessingで作ろうとしたけど動作スピードが気になる、という方は是非!
プロフィール

puku

Author:puku
暇な時はゲームかプログラミングしてる人だよ。
だいたい月1更新。
CV Drone はこちら(GitHub)

最近はQiitaでOnsenUI2で遊んでいる。

最新記事
最新コメント
最新トラックバック
検索フォーム
カレンダー
10 | 2012/11 | 12
- - - - 1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 -
月別アーカイブ
カテゴリ
スポンサードリンク
RSSリンクの表示
FC2カウンター
リンク
ブロとも申請フォーム

この人とブロともになる

アクセスランキング
[ジャンルランキング]
コンピュータ
754位
アクセスランキングを見る>>

[サブジャンルランキング]
プログラミング
158位
アクセスランキングを見る>>
FC2ブログランキング

FC2Blog Ranking

QRコード
QR