警備ロボ発進せよ!

Arduinoを使った車輪走行ロボを作ります。

広告

※このエリアは、60日間投稿が無い場合に表示されます。記事を投稿すると、表示されなくなります。

新たなる挑戦

2010-01-17 | 日記
GPSシールドプレゼントから始まったGPSロボプロジェクトであるが、本来の目的は庭に離して夜間警備のような事ができるものを作ることであったのだ。

平坦とは言えない地面を自在に移動し、暗闇に動くものを検出し、威嚇行為ができる機械を今年はどうにかしようと思う。足回りはやはり超信地旋回。ただし、過去の反省を踏まえて新たに各車輪をサーボモータで駆動し、スムーズに旋回出来る仕組みに作り替える。これにより横移動や斜め移動も可能になるはず。12月に宙展で見かけた惑星探査ロボットの足回りを参考にする。

センサも前方だけでなく、四方に取り付け、衝突防止だけでなく移動物体の検出にも利用したい。

自律的に動く警備ロボを今年は作ることにすると年頭に当たり決意表明することとしたい。
コメント (8)

データロガーの結果?

2009-11-30 | GPS
ロボ君に搭載したデータロガー(m241c)のデータをGoogleMapで書いてみた。一応競技中のはずなんだが、競技エリアにいないことになっている。
すんごい誤差です。参考にならないな。
コメント

GPSデータの選択方法

2009-11-30 | 思いつきメモ
今回のコンテストに使ったスケッチでは取得されるGPSデータはすべて有効と見なしていたが、事前確認試験でかなりのふれまわりがあることは承知していた。時間もアイデアもなかったので仕方がなかったが、有効なGPSデータの選択をすればもう少しどうにかなるかもということで実験してみようかと思う。

基準の位置は最低一つ既知のものがなければいけないが、更新時間の1秒間の間にロボットが到達するであろう位置は、速度誤差と方位誤差を含んだ台形状のエリアに入っているはずである。取得されたGPSデータがその中にあれば採用して、新たな位置データとして使用し、外れていたら捨てる。次の1秒後の存在エリアは更新された値を用いて計算する。このようにすれば、精度的に有効なデータだけ使うことでまあまあの動きをするのではないのではないだろうか。ただし、有効なデータが得られる頻度があまりにも少ないと誤差が蓄積して明後日の方向へ突き進んでしまうなあ。自分の位置がある程度わかっていれば、目標までの方位に向けるようにステアリングすればいい。とりあえずやってみよっかなと思う。

コンテスト参加者の皆さんはどうやっていたのか聴けばよかったと今更に後悔。ロボ君の中で何が起きているのかを考えるあまり、周りがあまり見えていなかったです。これは大きな反省点。でも、余裕が持てるような状況ではなかったので仕方がないかも。いつか余裕が持てる日が来ることを願いまする。
コメント (1)

スケッチ(メイン)

2009-11-29 | Arduino
//***************** Main ********************************
void loop() {

getposition(); //現在位置情報を取得
gettheposition=0;
Serial.print(nowlat);
Serial.print(" ");
Serial.println(nowlon);
nowlat=21398965; //point 0 lat
nowlon=83875980; //point 0 lon


// waypointをたどり始める 配列データの順番に巡る(全数+1= nop)

for (int k=0; k <= nop-1; k++){


// waypointへの方位を計算する。
dlat=lat[k]-nowlat;
dlon=lon[k]-nowlon;
fdir=atan2((double)dlon*0.81244,(double)dlat); //目的地点の方位 Echujima固有定数0.81244を使用。
dir=fdir*180.0/3.1415926535-7; //radianからdegreeへ変換し、磁気偏角(7度)を補正
if (dir <0 ) {dir=dir+360;} //方位を-180~180から0~360に変換。コンパス出力とあわせる // まず移動体のヘディングを測定し、右回りもしくは左回りを開始する。
getcompass();
errordir=abs(dir-(reading-90)); //目的方位と現在方位との差を求める

//ウォーミングアップで前後に動く
motor(1);
delay(200);
motor(2);
delay(200);


//目的方位に向くように本体を回転させる。右回りか左回りか
if (errordir <180) { //方位誤差が180未満の場合は時計回り }
else{ //方位誤差が180以上の場合は反時計回り
motor(8);//超信左
}

//車体が目的方位に向くまでセンサの読み取りから判断する
//ヘディングが目標方向に向く(誤差1度以内)まで回転を維持
while(errordir > 3){
getcompass();
errordir=abs(dir-(reading-90));
if (errordir >= 180) { //方位誤差が180以上の場合は反時計回りの誤差に修正
errordir=abs(errordir-360);
}
Serial.print(dir);
Serial.print(" ");
Serial.println(reading);
Serial.print("dir error");
Serial.println(errordir);
}


//ヘディングが目標方向を向いたら回転を停止する。
motor(0);
delay(200);
iok=1; //目的地探索状態とする


icount1=0; //障害物検知回数リセット
icount2=0; //障害物検知回数リセット

while(iok==1){ //目的地に到着するまで繰り返す
motor(1); //直進
rangeval1=analogRead(rangePin1); //UltraSonicセンサ読み取り
rangeval2=analogRead(rangePin2); //IRセンサ読み取り
Serial.println(rangeval1);
Serial.println(rangeval2);
if(rangeval1<=threshold1) { icount1++; } // 連続して1回以上障害物判断されなければ無視する。入力の不安定さに対応
else {icount1=0;}
if(rangeval2>=threshold2) { icount2++; } // 連続して1回以上障害物判断されなければ無視する。入力の不安定さに対応
else {icount2=0;}

if(icount1>=1 & icount2>=1) { //前方に障害物あり。ブレーキをかけて停止
Serial.print("Warning!");
Serial.println(rangeval1);
motor(2); //後退してブレーキとする
delay(200);
motor(0); //STOP!
delay(1000); //1秒間停止
//障害物が目的地かどうかを判断する。
getposition(); //現在位置を取得
gettheposition=0;

Serial.print(nowlat);
Serial.print(" ");
Serial.println(nowlon);

dlat=lat[k]-nowlat;
dlon=lon[k]-nowlon;
distidx=dlat*dlat+dlon*dlon*66/100;//現在位置と目的地までの距離指数の計算

if(distidx > errorrng){ //距離指数値が大きすぎる!目的地ではなかった!
motor(2); //Back!
delay(500); //1秒間同一モードで走らせる
motor(0); //STOP!
delay(500); //0.5秒間停止
motor(7); //超信右
delay(1000); //1秒間方向転換する
motor(1); //GO!
delay(700); //0.7秒間前進する

//***** Reset the direction to waypoint ******

// waypointへの方位を計算する。
dlat=lat[k]-nowlat;
dlon=lon[k]-nowlon;
fdir=atan2((double)dlon*0.81244,(double)dlat); //目的地点の方位 Echujima固有定数0.81244を使用。
dir=fdir*180.0/3.1415926535-7; //radianからdegreeへ変換し、磁気偏角(7度)を補正
if (dir <0 ) {dir=dir+360;} //方位を-180~180から0~360に変換。コンパス出力とあわせる // まず移動体のヘディングを測定し、右回りもしくは左回りを開始する。
getcompass();
errordir=abs(dir-(reading-90)); //目的方位と現在方位との差を求める

//ウォーミングアップで前後に動く
motor(1);
delay(200);
motor(2);
delay(200);

//目的方位に向くように本体を回転させる。右回りか左回りか
if (errordir <180) { //方位誤差が180未満の場合は時計回り }
else{ //方位誤差が180以上の場合は反時計回り
motor(8);//超信
}

//車体が目的方位に向くまでセンサの読み取りから判断する
//ヘディングが目標方向に向く(誤差1度以内)まで回転を維持
while(errordir > 3){
getcompass();
errordir=abs(dir-(reading-90));
if (errordir >= 180) { //方位誤差が180以上の場合は反時計回りの誤差に修正
errordir=abs(errordir-360);
}
}


//ヘディングが目標方向を向いたら回転を停止する。
motor(0);
delay(200);
iok=1; //目的地探索状態とする

}
else{ //目的地に到着!
motor(0);
delay(10000); //目的地に到着したら10秒間停止
iok=0; //目的地に到着したことをマーク
}

icount1=0; //障害物検知をリセットする
icount2=0; //障害物検知をリセットする
}

//障害物はないが、ひょっとして目標waypointをかすっているかもしれないので確認する
//ついでに自分は今競技エリア内にいるのかを確認して退所する
else{
getposition(); //現在位置を取得
gettheposition=0;

dlat=lat[k]-nowlat;
dlon=lon[k]-nowlon;
distidx=dlat*dlat+dlon*dlon*66/100;//現在位置と目的地までの距離指数の計算

if(distidx <= errorrng){ //距離指数値が設定値以下だ!目的地に到着した!
motor(0);
delay(10000); //目的地に到着したら10秒間停止
iok=0; //目的地に到着したことをマーク
}
//エリアの中か外かを判定するための係数を計算する
B=nowlat-nowlon*8/10;
D=nowlat+nowlon*84/100;


if ((B>-45702034 & B<-45701824 )&(D>91854694 & D<91854878 )) {}
else
//エリア外なので再度waypoint方向に向かせる
{
//一旦停止
motor(0);
delay(200);

// waypointへの方位を計算する。
dlat=lat[k]-nowlat;
dlon=lon[k]-nowlon;
fdir=atan2((double)dlon*0.81244,(double)dlat); //目的地点の方位 Echujima固有定数0.81244を使用。
dir=fdir*180.0/3.1415926535-7; //radianからdegreeへ変換し、磁気偏角(7度)を補正
if (dir <0 ) {dir=dir+360;} //方位を-180~180から0~360に変換。コンパス出力とあわせる // まず移動体のヘディングを測定し、右回りもしくは左回りを開始する。
getcompass();
errordir=abs(dir-(reading-90)); //目的方位と現在方位との差を求める

//ウォーミングアップで前後に動く
motor(1);
delay(200);
motor(2);
delay(200);

//目的方位に向くように本体を回転させる。右回りか左回りか
if (errordir <180) { //方位誤差が180未満の場合は時計回り }
else{ //方位誤差が180以上の場合は反時計回り
motor(8);//超信左
}

//車体が目的方位に向くまでセンサの読み取りから判断する
//ヘディングが目標方向に向く(誤差1度以内)まで回転を維持
while(errordir > 3){
getcompass();
errordir=abs(dir-(reading-90));
if (errordir >= 180) { //方位誤差が180以上の場合は反時計回りの誤差に修正
errordir=abs(errordir-360);
}
}
//ヘディングが目標方向を向いたら回転を停止する。
motor(0);
delay(200);
iok=1; //目的地探索状態とする
}
}



}
// いろいろあって無事にwaypointに到着したとする。
// 次にいくポイントを探すための準備をする。

nowlat=lat[k]; //現在地を今到達したポイントの座標にする
nowlon=lon[k]; //現在地を今到達したポイントの座標にする


}


}
コメント

スケッチ(センサ用関数部分)

2009-11-29 | Arduino
//******************************* モータ駆動 **********************************
void motor(int mode) {
switch(mode) {
//-----mode 1 直前進
case 1:
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
break;

//-----mode 2 直後進
case 2:
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
break;

//-----mode 3 右前進
case 3:
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
break;

//-----mode 4 右後進
case 4:
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
break;

//-----mode 5 左前進
case 5:
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
break;

//-----mode 6 左後進
case 6:
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, LOW);
break;

//-----mode 7 超進右
case 7:
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, LOW);
digitalWrite(motor2Pin1, LOW);
digitalWrite(motor2Pin2, HIGH);
break;

//-----mode 8 超進左
case 8:
digitalWrite(motor1Pin1, LOW);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, LOW);
break;

//-----mode 0 停止
default:
digitalWrite(motor1Pin1, HIGH);
digitalWrite(motor1Pin2, HIGH);
digitalWrite(motor2Pin1, HIGH);
digitalWrite(motor2Pin2, HIGH);
}

}

//************************** get compass data ******************************
int getcompass(){

//デバイスに2バイト分のデータを要求する
Wire.requestFrom(compassAddress, 2);
//要求したデータが2バイト分来たら

if(Wire.available()>1){
//1バイト分のデータの読み込み
reading = Wire.receive();
//読み込んだデータを8ビット左シフトしておく
reading = reading << 8;
//次の1バイト分のデータを読み込み
//一つ目のデータと合成(2バイト)
reading += Wire.receive();
//2バイト分のデータを10で割る
reading /= 10;
// Serial.println(reading);
//処理のために少し待つ(20Hz)
delay(50);
}
}

//***************** GPS ********************************

long getposition()
{
int d;
char c;
char h;

int i;
long lat,lon,alt;
char nsat;
long vel;
short dir;

while (gettheposition==0)
{
d = mySerial.read();
if (d==-1)
continue;

c = (char)d;

if (nbyte>=BUFF_SIZE)
{
// Buffer overflow
fheader = 0;
nbyte = 0;
}

if (fheader)
{
buff[nbyte] = c;
nbyte++;

if (d==0xEA)
{
digitalWrite(LED1, HIGH); // Turn LED1 off

if (buff[0]==(char)0xE0)
{
lat = 0L;
lon = 0L;
alt = 0L;
vel = 0L;
dir = 0;
nsat = 0;

// Check navigation flag
if (buff[1]&0x01)
{
digitalWrite(LED2, LOW);

// Read latitude
for (i=0; i<4; i++) lat <<= 7;
lat |= (long)(buff[3+i]&0x7F);
}
lat = ((long)(lat<<4))>>4; // Two's complement

// Read longitude
for (i=0; i<4; i++) lon <<= 7;
lon |= (long)(buff[7+i]&0x7F);
}
lon = ((long)(lon<<4))>>4; // Two's complement

// Read altitude
for (i=0; i<4; i++) alt <<= 7;
alt |= (long)(buff[11+i]&0x7F);
}
alt = ((long)(alt<<4))>>4; // Two's complement

// Read velocity
for (i=0; i<3; i++) vel <<= 7;
vel |= (long)(buff[15+i]&0x7F);
}

// Read direction
for (i=0; i<2; i++) dir <<= 7;
dir |= (short)(buff[18+i]&0x7F);
}

// Read number of satellites
nsat = buff[20];
}
else
digitalWrite(LED2, HIGH);

sprintf(buff, "%9ld %10ld %7ld %4ld %4d %2d", lat, lon, alt, vel, dir, nsat);
nowlat=lat;
nowlon=lon;
nowdir=dir;
gettheposition=lat;

}
else if (buff[0]==(char)0xE1)
{
sprintf(buff, "20%02d %2d %2d %2d %2d %2d %1d",
buff[2], buff[3], buff[4], buff[5], buff[6], buff[7], buff[1]);

}

// Clear header found flag
fheader = 0;
nbyte = 0;
}
}
else
{
if ((d==0xE0)||(d==0xE1))
{
digitalWrite(LED1, LOW); // Turn LED1 on

fheader = 1; // Set header found flag
nbyte = 0;

buff[nbyte] = c;
nbyte++;
}
}
}
}

コメント

スケッチ(setup部分)

2009-11-29 | Arduino
//****************************** setup routine *********************************

void setup() {
// ------------------------------------------- GPS
// Initialize serial ports
Serial.begin(BAUD_RATE);
mySerial.begin(BAUD_RATE);

// Initialize LEDs
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);

// Set LEDs off
digitalWrite(LED1, HIGH);
digitalWrite(LED2, HIGH);

// Send the command to the receiver
buff[0] = 0xc0; // Continuous data output command header
buff[1] = 0xa3; // Every one second
buff[2] = 0x83; // Position and time
buff[3] = buff[2]^(buff[1]^buff[0]); // Parity check
buff[4] = 0xca; // Terminator
buff[5] = 0; // Zero-terminated string

delay(100);
mySerial.print(buff);


// --------------------------------------------Compass
pinMode (ledPin, OUTPUT);
//I2C通信開始
Wire.begin();
//角度表示のためのシリアル通信開始
Serial.begin(9600);

pinMode(calPin, INPUT); // 入力に設定
val = digitalRead(calPin);

if(val == HIGH) {
//キャリブレーション開始コマンド送信
Wire.beginTransmission(compassAddress);
Wire.send('C');
Wire.endTransmission();
//30秒ほど待つ(6秒 03分まで)
//この間に数回モジュールを回転させる
delay(30000);
//キャリブレーション終了コマンド送信
Wire.beginTransmission(compassAddress);
Wire.send('E');
Wire.endTransmission();
}

//Continuous Modeに設定する
Wire.beginTransmission(compassAddress);
//RAM書き込み用コマンド
Wire.send('G');
//書き込み先指定
Wire.send(0x74);
//モード設定 Continuousモード(20Hz,Periodic Set/Reset=ON)
Wire.send(0x72);
//通信終了
Wire.endTransmission();
//処理時間
delayMicroseconds(70);

// ------------------------------------- motor
pinMode(motor1Pin1, OUTPUT);
pinMode(motor1Pin2, OUTPUT);
pinMode(motor2Pin1, OUTPUT);
pinMode(motor2Pin2, OUTPUT);

}
コメント

スケッチ(初期設定部分)

2009-11-29 | Arduino
//******************************* initialize **************************************

//--------------------------- GPS ------------------------

#include  stdio.h
#include  NewSoftSerial.h

#define LED1 9
#define LED2 8

#define BAUD_RATE 9600
NewSoftSerial mySerial = NewSoftSerial(2, 3); // Rx and Tx pins

uint8_t fheader = 0;
uint8_t nbyte = 0;

#define BUFF_SIZE 50
char buff[BUFF_SIZE];

long nowlat;
long nowlon;
long nowdir;
long gettheposition;

#include math.h

long lat[]={21398965,21398925,21398906,21398871,21398888,21398921,21398965}; //target point lattitude
long lon[]={83876037,83876026,83875988,83876040,83876101,83876103,83875980}; //target point longitude
int nop=7; //number of waypoint
//long dummy=2147483646; //
long distidx; // "from here to waypoint"index
long dlat;
long dlon;
long B;
long D;


//----------------------- Comppass --------------------------
//I2C通信ライブラリを取り込む
#include  Wire.h

//デジタルコンパスモジュールのアドレス設定
int compassAddress = 0x42 >> 1; //=0x21 元々のアドレス0x42を1ビット右にシフトして0x21となる。
//読み込み値(角度)の変数を用意
int reading;
int calPin = 7; //キャリブレーション設定用ピンの番号
int val = 0;
int ledPin = 13; // DIGITALの13番にオンボードのLED
int errordir; //現在方位と目的方位との差
int dir;
float fdir;
long errorrng = 105; // 距離誤差1.9m相当の値


//----------------------- Ultrasonic sensor, IRsensor, motor --------------------------
int rangeval1; // 超音波センサの読み取り値
int rangeval2; // 赤外線センサの読み取り値
int threshold1 = 45; // 障害物回避距離設定値
int threshold2 = 100; // 障害物回避距離設定値

int motor1Pin1 = 6; // モータ1入力ピン
int motor1Pin2 = 7; // モータ1入力ピン
int motor2Pin1 =10; // モータ2入力ピン
int motor2Pin2 =11; // モータ2入力ピン

int mode=0; //移動体駆動モード番号

int rangePin1 = 0; // 超音波センサ入力ピン(アナログ)
int rangePin2 = 1; // 赤外線センサ入力ピン(アナログ)
int icount1 = 0;
int icount2 = 0;

int getcompass();
int iok=0;

コメント

これをやったらだめだという見本さらします!

2009-11-29 | 日記
GPSロボットカーコンテスト終了である。我がロボ君の成績は奇跡とも微妙とも言える4位であった。

ぎりぎりの時間に会場に到着。そうそうたるロボの中に中学生の夏休みの宿題のような我がロボ「試作機第壱号」は肩身が狭い。今回は天候も不安定だったため、3組のチームが欠場していたようである。

抽選の結果、3番目となり非常に焦る。しかも、ロボにデータを入れ込むためのMacBookがなかなか起動しない。もしかして、会場に到着したはいいもののモータを回すことなくリタイアという最悪の事態も頭をよぎったが、どうにか起動してデータの流し込みは完了した。

結果は惨憺たるものであった。偶然のたまものでwaypoint領域に入ったものの、意図した動きではなく、なぜにあのような動きだったのかはログを保存するように作っていないので永遠の謎となってしまった。

本日の教訓および反省および得られた知見は以下の通り。

やはり、超信地に4輪は向かない!
デジタルコンパスは環境に依存するセンサらしい!
ログは保存できるようにすべきである。


というわけで、
本日ロボに注入したスケッチをさらします。私と同じ構成でロボットを作り、このスケッチを導入すると同じ目に遭うので気をつけてください。
なお、デジタルコンパスの読み込み部は建築発明工作ゼミから、GPSシールド読み込み部はgpsrobocarで示してあったプログラムを元にしていますが、改変している部分もあるので、ご注意ください。




くれぐれも気をつけましょう!
コメント

まだまだやることがある。

2009-11-25 | 日記
あと3日だというのにまだまだやらねばならないことがあった。

すっかり忘れていたのが、GPSの北と磁北の差を組み込むこと。東京では約7°のずれを考慮しないといけなかったのだ。
目標方位をGPS座標から計算し、それに磁気偏角を考慮した値と、デジタルコンパスの値を比較しないといけない。7°のずれは大きいのだ。

現場は開けた場所みたいなので衛星の受信状態には期待!普段庭で計測している精度よりも向上していることを祈ります。
コメント

がんばるぞい

2009-11-21 | 日記
本日GPSロボットカーコンテストの締め切り。ということで申し込みました。図々しくも!
ロボットのできは、これをロボットと呼んでよいのかという部分はさておき、まあまあ動きます。
気になるのは路面の摩擦。テニスコートの状態がわからないのでうまく回転できるかが心配である。
いざとなったら、爆死覚悟でモータ電圧をあげるという最終手段も考えている。

来週!がんばってくれい、我がロボよ!
その名は・・・・

試作機第壱号!!!

他に考えられなかったよ。

プログラムは作ったが動作確認や、センサの校正については不安たっぷり。前日までは調整である。

行け行け!試作機第壱号!
コメント

気がついたら1ヶ月!!

2009-11-01 | 日記
気がついたら1ヶ月更新していない。

移動体部分は台にモータを4つつけただけというシンプルなものなのでそんなに苦労がないものと思っていたが、やはりいろいろな面で苦労した。まず、方向転換をすべて超信地回転でやることにしたのだが、これが結構うまくいかない。回転する際の摩擦力にモータの力が負けてしまうのだ。
以下の方策を試行錯誤して、本日苦しいながらもどうやらいけそうになった。

1 車輪を変える。(田宮スポーツタイヤ→ナロータイヤ)
2 モータ電圧を上げてトルクを増加させる。(5V→10V:すごく無駄かも!)
3 車輪部分の構造をかえる。(後輪をキャスターにする)

この中でもっとも効果があったのが3番だが、いかんせん効果がありすぎ!回転中に車体の方向をセンサで観測して向けたい方向で止めるのであるが、回転の勢いがよすぎて思った方向に向かないのだ。回転時にPWM制御で速度をゆるめるという方法もあるが、面倒くさいのでやめた。

結果、効果があったと思われるのは、

1 重心を前方に持って行けるように電池を前に移動。
2 前輪と後輪の間隔を変化させる。

重心を前方にもっていくと後輪にかかる重量が減って前輪と後輪の摩擦力に差が生じて重心を中心として回転するトルクが発生するのでは。前輪と後輪の間隔の変化は理屈はわからないが、効果があるようである。

というわけで、現在のところ、指定した方位にむいて移動し、障害物をセンサで見つけて回避するという部分まではできた。ここにGPSシールドの情報を絡めて指定した位置に向けて移動し、目印のコーンを見つけて停止し、次のwaypointに向かう機能をプログラムし、確認する予定だ。

どこか確認に使える屋外の広い場所を見つけなければ。
コメント

なかなか難しい

2009-09-28 | 日記
連休時の作業は思った以上には進まず、スケッチの全体構成のみ一応完了。いくつかのセンサの特性を確認するにとどまる。コンテスト条件が変わったため、当初の想定通りに開始位置から最短の目標ポイントを求めてその方向までまっしぐら、障害物(赤コーン)はセンサで検出してよける。そして再度目標までのコースを設定して突き進むというアルゴリズムに従って全体スケッチを書くことにする。

あいかわらずGPSシールドからの位置情報の精度を以下に克服するかのアイデアがない。開始位置は与えられた値が使えたとして、途中の障害物回避時に再度自分の位置を計測した場合に大きな誤差があれば明後日の方向に進んで行ってしまう。もともとジャイロを使うとか車輪の回転回数から距離を測りながらとか、あんまり複雑なものをつくる技量もなければ暇もないのでシンプルに決めたかったが、位置情報の誤差が命取りになりそう。10分ほどしないと位置情報が安定しないことから、移動しながら取得する位置情報を用いた補正が必要なのかも。カルマンフィルタとかはやりたくないな。

とりあえずデジタルコンパスの情報から移動体のヘディングを目標ポイントに向けるスケッチの完成がとりあえずの目標である。
コメント

ゆるゆると進行中

2009-09-18 | 日記
無事にコースもテニスコートに変更したということで少しはどうにかなりそうな気になりました。が、肝心のロボット君は未だ張りぼて状態での試験を行いつつも、まだまだGPSで誘導という本来の機能は有していないのであった。

スイッチサイエンスからデジタルコンパスモジュールを入手してテスト。建築工作ゼミのサンプルスケッチで動作確認。少し変更してキャリブレーションモードと通常モードをスイッチで切り替えて行うようにしたど。

赤外線距離センサGP2Y0A21YK0Fを取り付けて、障害物を検知して回避するような動きができそうなことまで確認した。

この連休にはGPSシールドからの情報とデジタルコンパスの情報から移動体のヘディングを目標ポイントに向けるようにするスケッチを完成したいものである。

まずはマスキングテープで部品をとめている移動体をきちんとしなければ。
コメント

コース変更?

2009-09-14 | 日記
大会オフィシャルブログを見たら、コース変更の可能性ありとのこと。8の字コースは難しい、しかも障害物が縁石だとなるとなおさらである。などと思っていたが、建物に囲まれGPS電波が届かないらしい。それでなくともGPS精度の変動(これは電波が弱いからなのか?)が結構あると思っていたので、好ましい方向にすすんでいるのかな。
コメント

GPS位置精度

2009-09-13 | GPS
GPSシールドをつけて90分ほど放っておいたログを解析した。
位置誤差の標準偏差が6m以上という結果が出た。
この値は場所や時刻によっても変わるのだろうか。これから何回かログをとって確認する。
目的地までの誘導はさておき、ちゃんとポイントをクリアしたかどうかを判断するのは難しそうだ。
もうひとつの問題もある。シールドを動かさなくても、時折GPS信号を受信できなくなってしまい、100秒ぐらいロストする場合もある。何が原因かは不明。
いろいろと癖のあるセンサなのだ。
コメント