2017年7月
            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 31          

Amazonウィジェット

  • miniPC
  • 最近買った本
  • Raspberry Pi
  • クアッドコプター
  • 書籍ランキング

AdSense

  • 広告
無料ブログはココログ

ARDrone マルチコプター

2014年5月29日 (木)

ARDrone3? Parrot社の新型

Drone関連のページビュー数が増えてきたので、ちょっと調べてみると、新しい製品が出ている模様。

いままでのドローンはこちら。

BEBUP DRONE
・GPSが標準搭載。MAPで指定したコースを自律飛行可能。
・カメラの画角が広い。FullHD画質。
・カメラのスタビライザーを搭載し、撮影にブレが無い。

少しPhantomを意識しだしているのか、空撮機能が強化されている。
いままではカメラ画像を使って飛行させるのが主な楽しみ方だったが、面白い写真を撮るためのマシンとしても活用できそう。GPS自律飛行ができるようになったので、直接操縦しなくても撮影が可能だ。


ちなみにPhantom DJIはこんな製品。テレビでもよく登場するようになった。
空撮のクオリティはほとんどプロ用といえる。こんな”機材”が10万円以下で買えるのだから凄い時代になったものだ。




2014年2月19日 (水)

ARDrone2.0の地磁気センサを使う CVdroneを使う方法

スマホとDroneの地磁気センサーで、AbsoluteModeというのが使えるようになっている。
地磁気センサのデータは北を軸にしてプラスマイナス1.0で読み取ることができる。

DeveloperGuideの21ページ目
ardrone_at_set_progress_cmd_with_magneto
がこれに当たる。


あんまり説明が書いていないので、とりあえず何か数値がでそうなやつを片っ端から試した。

これは一番簡単
          printf( "time %d\n" ,navdata.time.time);

これは何もでなかった。
          printf("heading_unwrapped %3.2f\n",navdata.magneto.heading_unwrapped);

これは配列でx、y、zに分かれている。加速度ではなく、あくまで地磁気を出力していることが触っているとわかる。
          printf( "magneto_raw %3.2f\n",navdata.magneto.magneto_raw.v[0]);

とりあえずmagnet_rawを使えば地磁気の出力が得られることがわかり、水平方向の方位を見たければx方向を見れば良いことがわかった。

          printf("magneto_raw X %3.2f\n",navdata.magneto.magneto_raw.v[1]);
          printf( "magneto_raw Y %3.2f\n",navdata.magneto.magneto_raw.v[0]);
          printf( "magneto_raw Z %3.2f\n",navdata.magneto.magneto_raw.v[2]);

この知識を使って、離陸したら必ず同じ方位に向き、その方位を保持するように制御することにした。getMagnetoRad()を作って、こいつからX軸を拾ってくる。つまり水平方向の向き。
この向きを示す値が、常に-50から50の間にあるように、ループのなかで制御する。

  //MagnetoMeter
  float heading = ardrone.getMagnetoRad();
  if(heading < -50.0 || 50 < heading){
    if(heading<0){
        vr = 1.0;
      }
      else{
        vr = -1.0;
      }
  }

簡単な小細工でも上手くいった。


2014年1月13日 (月)

ARdroneのATコマンドを解読する 続編PART3

スレッドを使ってコマンドの受付とパケットの送信を並列処理させる。

スレッドのプログラミングについてはここのページがシンプル。
セマフォの使い方も書いてある。

キー入力待ちからコマンド内容を反映させるという一連の流れに合っているのが、Example2。
スレッド1で文字列入力を受付。入力されたらセマフォがセットされて、入力された文字列をスレッド2が表示する仕組み。

Example2のソースを丸写しで実行してみたらなぜか"The string entered is :"が延々と表示されるだけで"Enter a string"のスレッドが出てこなかった。何かキーを押すとハングする有様。

ちょっと下にsleep(5)を入れたほうが良いですよとのコメントがあったのでそれを入れてみると、正常に動作した。

気づいたこと。
頭文字を大文字にしたSleep()は短い。
小文字のsleep()にすると長い。

小文字のsleepは1秒単位。
SleepはWin32APIであり、ミリ秒単位。linuxならsleepを使うらしい。
情報元はこちら。

常にコマンドを送り続けるのだからセマフォは要らなかった。
・スレッド1でgetcharによる文字の入力+switch文を使ったコマンド発行。
・スレッド2で30ms周期のUDP送信。
上記2つのスレッドを生成する。


しかしtakeoffやlandは何回も繰り返し送信されると変な感じなので、着陸しているときは送信ループを止めたい。

簡単にやろうと思ってフラグをグローバル宣言し、これがTrueのときだけコマンド送信をさせるようにした。つもりで書いたのがこれ。

void * write1()
{
        while(flying_flag == TRUE){
                       sleep(1);
                printf("command = %s\n",str);
        }

}

しかしtakeoffでフラグがTrueになってもコマンドが一度も送信されない。理由は簡単。このwrite1が無限ループになっていないので判定を一回やって抜けてしまっていた。
正しくはこうする。

void * write1()
{
     while(1){
        while(flying_flag == TRUE){
                       sleep(1);
                printf("command = %s\n",str);
        }
     }
}

ここまでの骨格部分。
「threadCom.c」をダウンロード

ここからUDP送信の部分を埋め込んでいく。
とりあえず動くか見るため、変数をしょっちゅうグローバル化してしまったが、まともに飛べることが確認できた。その時点のソース。
「threadCom.zip」をダウンロード

f,bのコマンドがとっさには押しにくいので、数字キーでコマンドするように改良するのもいい。
※takeoffとhaltは今までどおり"t","h"を使い、"0"で着陸。


2014年1月10日 (金)

ARdroneのATコマンドを解読する 続編PART2

ARdroneをC言語で作ったプログラムを使って操縦するプロジェクト続編。

以前に作成したATコマンドをdroneに送信するプログラムと、
C言語 charで処理を分岐させる switch文の例題で作成したプログラムと合体させた。

このソース
「main-atCom.zip」をダウンロード

飛行に成功!!
あとは上下左右のコマンドを実装すれば、Cのコードだけで自在に飛ばせる。

PCMDというコマンドにMODEとx、y、z、rの4つのパラメータがあって、これに値をいれれば移動ができそう。
SDKガイドの6ページの飛行機の図を見れば、Xが前後方向となっている。


PCMDコマンドの第二引数であるMODEフラグは、1にセットすると移動を受付。0にするとホバリングする。
基本的に1にセットしておけばよい。

フラグを何にセットしてもホバリングしかしないので、cvdroneのページにあったソースをそのままforwardのところにぶち込んでみた。すると、一瞬だけ前に動くそぶりを見せるようになった。コマンドは送信できているみたいだ。


そこで、 下のソースをラズベリーパイで実行し、パイに対してATコマンドを送ることでどんな内容が送られているのか見ることにした(本当はパケット解析ツールを使えばよかったのだが、このときは使い方がよくわからなかった。)
「main-atCom-deb.c」をダウンロード


値を入れたのはvxだけだったのに、なぜかvy,vrまで何やら値をいれたような挙動を示している。
最後の行がforwardを実行したもの。
下から2行目はbackを実行したときのもの。

pi@raspberrypi ~/TameshiSpace/tameUDP $ ./rec5556
AT*FTRIM=1,
AT*REF=2,290717952
AT*REF=3,290718208
AT*PCMD=4,1,-2147483648,-1090519040,0,-2147483648
AT*PCMD=5,7,0,0,0,0
AT*PCMD=6,1,-2147483648,-1090519040,0,-2147483648



わかったこと。
・modeフラグは1をいれればよい。
・cvdroneのソースを見る限り、floatをintとして表示したものをATコマンドのパラメータとして送っている。


6.3 Floating-point parametersというところにPCMDコマンドの例が載っている。

チルト量などをfloatで格納したあと、intの値として格納されている体でintのポインタを使って読み出すことで、floatの変数を整数として読み出している。

*(int*)(&my_floating_point_variable_1),

これをsprintfで%dとしているから送信時に整数として出てくる。


Build0.25
cvdroneの書き方を簡略化し、すっきり書いた版
「main-atCom0.25.zip」をダウンロード


しかしループの中にキーボード待ちを挟んでしまっているので、他のコマンドを受け取るまで前のコマンドを持続させるという動作ができなかった。やはりキーボード直接入力式か、スレッドでキー入力待ちとコマンドをループ送信する動作に分けなければ無理そう。


cvdroneのコマンドの送信のソースを使って飛ばしたときのパケットを解析すると、やはり同じ内容のコマンドを送り続けないとまともに飛べないらしい。

パケット解析ツールの使い方をマスタしたあとで解析した内容についてはこちら。
ARdroneへのコマンド送信内容の解析 cvdroneを使って飛行したときの挙動


次回に続く。

2014年1月 6日 (月)

シリアルポート(linux)のライブラリを作る ARDroneのシリアルポート利用に向けて

ARdrone内蔵のシリアルポートを使いたいので、これを制御しているBusyBox(linux)上で動くシリアル制御プログラムを作成した。
linuxのドキュメントにサンプルソースがあったので、それをベースにやることにした。

ソースをファイル分割してコンパイルするところまで実施。
ところが、受信しても1文字づつしかバッファに入らない。
AVR側の送信の間隔を1sぐらいに遅くしてもだめ。ボーレートも確認済み。

終端文字が違っているのではないかと思い、termios.hの定義を調べた。
VEOLというのがその終端文字を設定するためのもの。元のソースでは'\0'になっている。これをLineFeedに変えればAVRの意図するデータの終わりとして受信できるはず。

これを、
newtio.c_cc[VEOL]     = '\0';

こうした。
newtio.c_cc[VEOL]     = 0x0A;

しかし、結果は全く変わらず。

ちなみに、、、
フロー制御なんか結線してないので消去。

データを読み取るのはread関数なのだからread関数を設定するパラメータを変更すればよいはず。各パラメータはtermios.hの構造体に一個ずつ入っているので、その辺をチェックしてみた。
原因はここか??

newtio.c_cc[VMIN]     = 1;     /* 1文字来るまで,読み込みをブロックする */

read関数は1文字しかブロックしない。だから1文字受け取ったらすぐにブロックを抜けてしまう。3文字連続で送っても1文字ずつしか受信できないのはそのためだった。と思いきや。

5でも10でも変化なし。
結局1文字ずつしか読めないのなら、1文字ずつ受信してバッファに貯めていくのがよかろう。

Raspberryをシリアルデータの送信源としてセッティングし、PC側のUSBシリアルケーブル経由で受信してみた。するとAVRでは1文字ずつ表示されていたのが、何文字かまとめて表示されるようになった。

$ ./a.exe
res=1,a
res=7,dfaefae
res=1,f
res=11,awefaefae

 

res=1,h
res=6,ello

 

res=1,h
res=6,ello

しかし毎回文字数にばらつきがあり、ちょっと扱いづらい。どうせなら1バイトずつ受信のほうが簡単にできそう。

read関数の3つ目のパラメータを1にすると、1文字ずつ読める。
これをCR,LFを受け取るまで繰り返せば纏まったバイト数読める。

まず、文字コードを表示させて正しく文字が受け取れるかどうか確認した。
readのあと、

     char c;
     char temp[BUFF_LEN];

 

        res = read(fd,&c,1);
        printf("%c ,code = %d \n",c,c);

%dで文字コードが表示できる。
その結果、

$ ./a.exe
h ,code = 104
e ,code = 101
l ,code = 108
l ,code = 108
o ,code = 111
,code = 13

 

,code = 10

このように、最後に2バイトが空欄になっている。
こいつがCRとLF。文字コードは13と10。十進数表記。

     char c;
     char temp[BUFF_LEN];

 

        res = read(fd,&c,1);
        printf("%c ,code = %d \n",c,c);
        if(c == 0x0A)printf("ok\n");

最後にIF文をつけて、LFが来たことを確認すれば完璧。
CRで終端させて最後にNULL文字を入れれば、printfで文字列を表示させることが可能。

void getSerialData(int fd){
     int res,i;
     char c;
     char temp[BUFF_LEN];

 

     i = 0;
     do{
          res = read(fd,&c,1);
        printf("%c ,code = %d \n",c,c);

 

        temp[i] = c;
        i++;
     }while(c != 0x0D); //CRで受信終了

 

     temp[i] = '\0';
   printf("%s\n",temp);
}

2013年12月28日 (土)

ARDroneのATコマンドを解読する。

ARDroneを飛ばすには、ATコマンドという文字列をUDPというプロトコルで送ればよいことになっている。

これについてはSDKのドキュメントのほか、CVdroneというシンプルなC++プログラムで動かせることが紹介されている。

まずはCVdroneのサイトを参考にさせてもらって、なじみのあるC言語でATコマンド送信部分を書いていくことにした。


STEP1
まず、飛行せず試せるやつ。バージョン情報の取得から。
http://pukulab.blog.fc2.com/blog-entry-5.html

いきなり躓いた。
LPCWSTRに: 'char [783]' から 'LPWSTR' に変換できません
意味不明。検索したらこれが出てきた。
文字コードが問題らしい。

解決方法は、プロジェクトのプロパティを設定
No.6の回答者さんを参考にされたし。

上記プロパティを設定すると解決した。
実行すると、確かにバージョンが表示された。ウインドウは一瞬で閉じるけど。


STEP2
こんどは基本的なATコマンドを実行できるようにした。

インクルードで躓き。
プリコンパイル済みヘッダファイルを使わない設定にしないと、VC++に文句を言われてコンパイルが通らない。どうもMSは苦手だ。

ここを参考にされたし。
要は「プリコンパイル済みヘッダーは使わない。」に設定する必要がある。

ソリューションエクスプローラのペインのソリューションを右クリックで、
プロパティ→構成プロパティ→C/C++→コンパイル済みヘッダ→プリコンパイル済みヘッダーの欄
”プリコンパイル済みヘッダーを使用しない”を選択。

最後に、fabsという関数が勝手に使われていると文句を言われるので、math.hをインクルードした。これでコンパイルが通り、実機飛行もできた。

STEP3
ARMコンパイラにコンパイルさせるために、Step2の内容をlinux用に書き換える。

Step2ではキーボード入力で操作していたが、Step3ではDrone内で動作させることにする。telnetでコマンドラインから操作することを想定。

キー入力内容の判定で、多少ワーニングが出た。
sleep関数をどうするか。これがないとコマンドが正しい間隔で送れない。

sleep関数
http://linuxc.info/time/time6/

va_start,listなどはstdarg.hをインクルード
http://hitorilife.com/verargs.php

コンパイルが通ったソースがこれ。
「basicCommand.zip」をダウンロード
最初の一回しかコマンドを受け付けないものの、飛行はできるようになった。

※後ほど、コマンドの入力受付のところがまずいことがわかった。
  詳しいことはここのページへ

2013年12月24日 (火)

ARdroneへのコマンド送信内容の解析 cvdroneを使って飛行したときの挙動

cvdroneを使って飛行したときのUDPパケットを、Wireshark 1.10.2を使って解析した。
ARdroneへのコマンド送信内容を解析することで、最低限どんな処理が必要なのか見たい。

※Wiresharkはネットワークに流れているパケットを詳細に表示するためのフリーツールで、追いたいパケットだけをフィルタリングする機能がついている。

ARDroneはATコマンドの中でもPCMDコマンドが移動の命令を与えている。このコマンドだけをフィルタリングすれば、飛ぶために最低限必要なことがわかるはずだ。

とりあえず何秒か飛行させてみて、パケットを追っていくとtakeoffのコマンドのあとにPCMDを含むコマンドが見られた。

そこで、ar_drone.commandというパケットだけをフィルタで抽出する。
ワイヤレスネットワーク接続を選択してスタートした後、いつもどおりにCプログラムからDroneを操縦。着陸してからログを調べる。

画面上部のFilterという欄の右横に、Expressionというボタンがある。これを押すとこんな画面が出るので、AR Drone PacketというのをプルダウンしてCommandをセレクトする。

Ws000014


すると、
こんな感じでコマンドだけがフィルタされる。 30ms間隔で同じ内容のコマンドが継続的に送信されていることがわかる。

Ws000015

コマンドは一発送ればよいというのではなく、このような短い間隔で送り続けることが要求されていることがわかった。

2013年12月 1日 (日)

Linuxでシリアル通信 ARDrone内臓シリアルの利用に向けて。

ARDrone内臓のシリアルポートを使うには、まずDrone内で動いているLinux(BusyBox)について理解し、Linux上でのシリアルポートの利用方法を調べる必要がある。

Linuxというだけで敷居が高そうに感じるが、シリアルポートのプログラムを書いて試すだけなら、わざわざLinuxマシンを用意しなくても可能。今はCygwinという便利なツールがある。

基本はLinuxの仕様を書いたこのページを参考にする。

まずはCygwinとAVRを使って簡単な通信を試してみるのが一番の近道だった。
サンプルソースで感覚を掴んでからlinuxネイティブ環境やBusyBox環境に移っていくと楽。

AVRにシリアルプログラムを書き込んで、
FTDIのUSBシリアルケーブルを使ってPCと接続。
まずはacknowrichでウインドウズ上の動作を確認した。
1s毎ぐらいで"abc"という文字列がAVRから送信される。

「sendABC.c」をダウンロード

AVRを走らせた状態で
cygwin上で次のようなソースを作成し、gccでコンパイルしたものを実行。

☆linuxjfページにある、カノニカル入力処理のソースコードをそのままコピーし、
・USBシリアルのポートナンバーに変更
・ボーレートを変更


一応cygwin側のボーレートを調べるには、
stty -F /dev/ttyS10


<補記>
linuxにおけるシリアル通信は、
カーネル内で一旦加工してから端末に出す方法と、
すぐに出す方法(raw)と2通りある。
一行受けてから出す。改行コードを受けてから出す。
色々なやり方がある。 マルチユーザー時代の名残。
だから、Windowsのときの感覚で行きたければrawモードを指定する。



2013年11月30日 (土)

Linuxにおけるシリアル通信の扱い ARDroneのシリアルポート

まずは参考資料をよむ→ droneduino

最初のソースで目につくのは、シリアルポートの設定部分と思しき部分。
/dev/ttyO3
というのがDroneの持っているシリアルポートのデバイスファイル。
リナックスはIOもデバイス”ファイル”として扱っている。

※C言語で言うところのopen,close,read,writeを使って、どんなIOも同じ方法でコントロールできるという点が、リナックスの設計の面白いところ。

Droneについているシリアルポートのデバイスファイルの調べ方はdroneduinoのサイトの中ほどに書かれている、

cat /proc/cmdline

で表示させることができる。
著者のマシンで試したところ、こんな表示が出てきた。

# cat /proc/cmdline
mtdparts=omap2-nand.0:512K(Pbootloader),8M(Pmain_boot),8M(Pfactory),32M(Psystem),81408K(Pupdate) console=ttyO3,115200 loglevel=4 ubi.mtd=Pfactory,2048 ubi.mtd=Psystem,2048 ubi.mtd=Pupdate,2048 root=ubi1:system rootfstype=ubifs parrot5.low_latency=1

出力結果のconsoleというところに115200というビットレートが書いてあるので、それがシリアルと判別できるということのようだ。


<PCでDroneと通信を試す場合のハードウェアセッティング>
USBシリアルでPCとDroneをつなぐには、レベル変換ICに5Vを供給する。
Drone側にUSB5Vがあるが、これは使わない。

Droneのコネクタのピン配置はこれ。
RXとTX。GNDの3本をレベル変換ICにつなぎ、それを介してUSBシリアルケーブルとつなぐ。


<Linuxコマンドで動作確認>
動作確認のためにlinuxコマンドを使って通信するには、echoコマンドでシリアルポートのデバイスファイルにリダイレクトするだけ。以下DroneからPCに向けて送信する例。

こんな風に打ち込む
echo "hello" > /dev/ttyO3

PC側でシリアル端末を起動しておけば、"hello"の文字列が表示される。

2013年11月29日 (金)

Raspberry PiからAR Droneにアクセスする。

ARDroneへは、Linuxが稼動するRaspberry Piからももちろん操縦が可能。GPIOがいじりやすいRaspberry Piを使えば、いろいろな応用が考えられる。たとえば、Raspberry Piに赤外センサをつなぎ、人が接近するとDroneが迫ってくるようにするなどのセキュリティ用途。Raspberryに直接USBなどのゲームパッドをつないで、パッドから操作するなど。
Raspberry自体が小さいので、ARDroneの背中に乗せて飛ばすことも可能。筆者も載せて飛ばしてみたが、重量的には問題なかった。

<セッティング>

無線LANのセットアップが必要。
接続の設定にはRaspPiのwpa_guiから行う。

Droneの電源を入れてからwpa_guiのScanを押す。
確認のためにPCから一度DroneのBusyboxにTelnetできるか試すのもよい。複数の端末をDroneにアクセスしてもかまわない。

※Droneの電源を切ると、wpa_guiの設定はクリアされ、USB無線デバイスも停止してしまうらしい。USBをさしなおせば再起動できる。

node.jsをRaspberryにインストールし、node-ar-droneを起動。replを使って飛行コマンドを実行することができた。

ARDroneの中のbusyboxという特殊なLinuxをいじくるよりは、RaspberryのほうがソフトのインストールやWifi接続。GPIOのやり取りが簡単に実現できる。