CV Droneは当初Windowsのみサポートしていました。
開発後期でクロスプラットフォーム化するにあたり、それまで使っていた
WinINetでのFTP通信が使用できなくなりました。
これはマズい。何がマズいかというと、バージョン情報の取得方法を考え直さないといけないんですよ。
まぁ、FTPが使えなくても
TCP経由でconfig.iniを取得できますので、なんとかなるといえばそうなのですが...
初期化の順番を考えると、ATコマンド初期化→いろいろ設定→設定情報を取得、というように設定情報の取得は後に回すのが良いかなーと思うんですよね。
TCP通信に関しては自分で作ったTCPクラスがありますからこれを使うとして、AR.DroneのFTP通信ってどうなってるのかを見つつ実装していきましょう。
1. ポート5551を開く これは簡単、ただソケット作ってconnectするだけです。
ポートを開くと何か文字列がやってきます。適当なバッファに突っ込んでおきましょう。
2. ログインする USERプロトコルを使って匿名(anonymous)でログインします。
AR.Droneにはログインパスワードが設定されていないのでPASSは送らなくてもOKです。
3. Passiveモードに切り替え ここからがちょっと面倒です。
PASVを送るとAR.Droneから"227 PASV ok (192,168,1,1,a,b)"といった文字列が送られてきます。
Passiveモードにおけるデータ転送用のポート番号は「a * 256 + b」で与えられます。
1.で作ったものとは別のソケットを用意し、上記のポートを開きましょう。
4. ファイル送信のリクエスト ポート5551を開いたソケットで"RETR ファイル名"を送りファイルを要求します。
ファイル名には"version.txt"を設定します"
5. ファイル受信 ファイルはデータ転送用のポートを開いたソケットに送られます。
"version.txt"はただのテキストなので、char型のバッファに入れると良いでしょう。
バッファに入れたら後はsscanfなり何なりでバージョン情報を抽出します。
↓実際のコードはこちらです。
#include <stdio.h>
// TCP通信
#include "tcp.h"
// マクロたち
#define ARDRONE_DEFAULT_ADDR "192.168.1.1" // AR.DroneデフォルトIPアドレス
#define ARDRONE_FTP_PORT (5551) // FTP用ポート
// バージョン情報
struct ARDRONE_VERSION {
int major;
int minor;
int revision;
};
int main(void)
{
TCPSocket socket1, socket2;
// ソケットを開く
if (!socket1.open(ARDRONE_DEFAULT_ADDR, ARDRONE_FTP_PORT)) {
printf("TCPSocket::open(port=%d) failed. (%s, %d)\n", ARDRONE_FTP_PORT, __FILE__, __LINE__);
return 0;
}
// ウェルカムメッセージを受け取る
char buf[1024] = {'\0'};
socket1.receive(buf, sizeof(buf));
// ログイン
socket1.sendf("USER %s\r\n\0", "anonymous");
socket1.receive(buf, sizeof(buf));
// PASVモードに切り替え
int a, b, c, dataport;
socket1.sendf("PASV\r\n\0");
socket1.receive(buf, sizeof(buf));
sscanf(buf, "227 PASV ok (%d,%d,%d,%d,%d,%d)\n", &c, &c, &c, &c, &a, &b);
dataport = a * 256 + b;
// データソケットを開く
if (!socket2.open(ARDRONE_DEFAULT_ADDR, dataport)) {
printf("TCPSocket::open(port=%d) failed. (%s, %d)\n", dataport, __FILE__, __LINE__);
return 0;
}
// ファイル送信リクエスト
socket1.sendf("RETR %s\r\n\0", "version.txt");
// ファイル受信
socket2.receive(buf, sizeof(buf));
// バージョン取得
ARDRONE_VERSION version;
sscanf(buf, "%d.%d.%d", &version.major, &version.minor, &version.revision);
printf("AR.Drone Ver %d.%d.%d\n", version.major, version.minor, version.revision);
// さようなら
socket1.close();
socket2.close();
return 1;
}
tcp.hWinINetがないと結構手間がかかりますね。タイムアウトの設定も出来ませんし。
さて、当ブログがスタートしてからそろそろ1年になります。
「1年間続ける」ことと「毎週更新する」ことをは決めていましたので、
とりあえず目標達成 といったところでしょうか。
フフフCV Droneも卒業研究や学会の論文や飛行ロボット大会などでも使われるようになるなど(公式SDKと間違われたりしているとか...マジか)、まぁぼちぼち有名になってきて嬉しい限りです。