目次

今回の課題

マップに散らばるピンポン玉を覆って伏せられた紙コップを回収する。 ピンポン玉と紙コップを別々のサークルに置き、紙コップは重ねて回収するほど高得点となる ほかに技術点などで総合点が決まるロボコンを行った。

今回作成したロボット

概要

今回は2つのNXT を1つの車両にまとめて搭載したロボットを作成した。

私は大まかな構造などには関与しておらず、動きを実現するためのパーツ作成を主にしたため、ロボットの機構自体の構想はチームのほかのページを参照されたし。

ロボット制作担当のレポート  http://yakushi.shinshu-u.ac.jp/robotics/?2017b%2FMember%2Fcyanomelana%2FMission3

↓実際のロボットの写真

ロボットの機構

アーム部

コップをつかむのとアーム自体を上下するのとで2つのモーターを使用した。初期では1つのモーターで実現しようともしていたが繊細な動きを要するため2つのモーターを使用することになった。

光センサー

今回は光センサーを2つ使用した。 それぞれ車体の左前方と右前方に地面に垂直に設置した。 ロボットの構造的に光センサーをロボット前方中心につけることができず2つ使用することになった。

超音波センサー

今回のロボットの最大の特徴を担う構造の1つといっても過言ではないパーツ 超音波センサーでコップを見つけた後、超音波センサーを取り付けたビームごと上部に回して内部にコップを取り込んだ後にアームでコップをキャッチする。

親機・プログラミング概要

今回は以下のようなルートで紙コップを回収した。 また、制作時間の都合でどうしても3つ目のコップを回収するに至らず、2つ目のコップを回収して円内に置いて終了となった。

aa

今回のロボットの構造上、地点QにてXにピンポン玉を入れた後にその場でYに紙コップを置くことができるという利点がある。これのおかげで紙コップの得点率はほぼ100%であった。

定義

最初に、今回のプログラミングで頻出されるプログラミングコードを定義した

#define SPEED 100
#define SPEED_SLOW 60
#define turn_left1 OnFwd(OUT_A,80 * x); OnRev(OUT_C,35 * x);    //強く左回転
#define turn_left2 OnFwd(OUT_A,100 * x); OnFwd(OUT_C,40 * x);   //緩く左回転
#define turn_left3 OnFwd(OUT_A,80 * x); OnRev(OUT_C,90 * x);      //超信地左旋回
#define turn_left5 OnFwd(OUT_A,80 * x); OnRev(OUT_C,1 * x);      //右の車輪のみで左回転
#define go_forward OnFwd(OUT_A,80 * x); OnFwd(OUT_C,87 * x);     //前進
#define go_back OnRev(OUT_A,100 * x); OnRev(OUT_C,85 * x);       //後進
#define turn_right1 OnRev(OUT_A,35 * x); OnFwd(OUT_C,80 * x);    //強く右回転
#define turn_right2 OnFwd(OUT_A,30 * x); OnFwd(OUT_C,100 * x);   //緩く右回転
#define turn_right3 OnRev(OUT_A,80 * x); OnFwd(OUT_C,80 * x);    //超信地右旋回
#define AD SendRemoteNumber(1,MAILBOX1,01);       //アームを閉じて締める 
#define AU SendRemoteNumber(1,MAILBOX1,02);       //アームを上げる  
#define TD OnRev(OUT_B,45 * x); Wait(1000);                      //超音波センサーを下げる
#define TU OnFwd(OUT_B,45 * x); Wait(1000);                      //超音波センサーを上げる
#define CupOff SendRemoteNumber(1,MAILBOX1,03);   //コップを離す
#define turn_right4 OnRev(OUT_A,80 * x); OnFwd(OUT_C,60 * x);   //左右の光センサーでの
#define turn_right5 OnRev(OUT_A,80 * x); OnFwd(OUT_C,1 * x);    //右の車輪のみで右回転
#define turn_right6 OnRev(OUT_A,1 * x); OnFwd(OUT_C,80 * x);    //左の車輪のみで右回転
#define DO  523
#define x 0.65             //出力のかけ数
#define z 1.0              //時間のかけ数

サブルーチン

今回はサブルーチンとして「センサー2(光センサー)を使用して(左・右)に沿ってライントレースを行い、次の交差点に到着したら停止して音を鳴らす」「センサー3(光センサー)を使用して、左に沿ってライントレースを行い、次の交差点に到着したら停止して音を鳴らす」という3つのものを作成した。

右に沿ってライントレースするサブルーチン

sub IKK()
 {
 int BP = 0; 
 while (BP < 125){
  if (SENSOR_2 < 45) {
       turn_right1;
       BP++;

  }else{
     if (SENSOR_2 < 49 ) {
      turn_right2;
    } else if (SENSOR_2 < 56 ) {
      go_forward;
    } else if (SENSOR_2 < 58) {
      turn_left2;
    } else {
      turn_left1;
    }
    BP = 0;
    }
   Wait(1);
   }
   Off(OUT_AC);
   PlayTone(DO,100); Wait(100);
   Wait(10);
   BP = 0;
} 

左に沿ってライントレースするサブルーチン

sub DKK()
 {
  int BP = 0;
  while (BP < 200){
  if (SENSOR_2 < 45) {
       turn_left1;
       BP++;
       }else{
     if (SENSOR_2 < 49 ) {
      turn_left2;
    } else if (SENSOR_2 < 56 ) {
      go_forward;
    } else if (SENSOR_2 < 57) {
      turn_right3;
    } else {
      turn_right4;
    }
    BP = 0;
    }
   Wait(1);
   }
   Off(OUT_AC);
   PlayTone(DO,100); Wait(100);
   BP = 0;
} 

右側の光センサーを使い左に沿ってライントレースする

sub DKK2()
 {
  int BP = 0;
  while (BP < 170){
  if (SENSOR_3 < 45) {
       turn_left1;
       BP++;
       }else{
     if (SENSOR_3 < 49 ) {
      turn_left2;
    } else if (SENSOR_3 < 54 ) {
       go_forward;
    } else if (SENSOR_3 < 55) {
      turn_right3;
    } else {
      turn_right4;
    }
    BP = 0;
    }
   Wait(1);
   }
   Off(OUT_AC);
   PlayTone(DO,100); Wait(100);
   BP = 0;
}

関数

そして今回は、紙コップを探し前進するプログラミングを関数として定義した。

const float diameter = 5.45;   //タイヤ直径
const float track = 10.35;    //タイヤトレッド幅
const float pi = 3.1415;     //円周率

void fwdDist(float d) //距離 dcm前進
{
 long angle = d/(diameter*pi)*360.0;   //必要なタイヤの回転角度
 RotateMotorEx(OUT_AC, SPEED_SLOW, angle, 0, true ,true);
}

void turnAng(long ang) //角度ang度の時計回りの旋回
{
 long angle = track/diameter * ang;
 RotateMotorEx(OUT_AC, SPEED_SLOW, angle, 100, true, true);
} 

int searchDirection(long ang) //現在の方向を中心にang度の範囲で探し
                                   //障害物までの距離を返す
{
 long tacho_min;  //最も近い距離を実現するタイヤの回転数
 int d_min = 300;  //最も近い距離の仮の最小値(十分大きくとっておく)
 
long angle = (track/diameter)*ang;  //旋回角度からタイヤの回転を計算
turnAng(ang/2);   //指定された角度の半分を旋回
ResetTachoCount(OUT_AC);   //角度計測をリセット

OnFwdSync(OUT_AC,SPEED_SLOW,-100);  //半時計回りに旋回
while(MotorTachoCount(OUT_A)<=angle) {
 if (SensorUS(S1)<d_min){ //現在の距離が借りの最小値より小さい場合
  d_min = SensorUS(S1); //仮の最小値を更新
  tacho_min = MotorTachoCount(OUT_A); //この時のタイヤの回転数を記録
 }
}
OnFwdSyncEx(OUT_AC,SPEED_SLOW,100,RESET_NONE);
until(MotorTachoCount(OUT_A)<=tacho_min || SensorUS(S1)<=d_min);
 Wait(14); //微調整
 Off(OUT_AC);Wait(500);
 return d_min;
}
 

task main

task main()
{
SetSensorLowspeed(S1);
SetSensorLight(S2);
SetSensorLight(S3);
go_forward;
Wait(500);  //少し前進
turn_left3;
Wait(200);
while (SENSOR_2 > 45)
{
turn_left3;  
}

turn_right1;
Wait(100);
IKK(); //Fまでライントレース
turn_left3; 
Wait(1000); //左向く 

int d = searchDirection(70);//コップ探す
if (d > 10){
 fwdDist(d-10.0);//コップに近づく
 } 

TU; //超音波センサーをあげる

go_forward;
Wait(2900);
AD; //コップを取る
Off(OUT_AC);
Wait(3000);
go_back;
Wait(500); 

turn_left3;
Wait(700); 

while (SENSOR_2 > 45)
{
go_back;  
}
go_back;
Wait(250);
Off(OUT_AC);
Wait(200);    

while (SENSOR_2 > 45)
{
go_back;  
} 

go_back;
Wait(450);

Off(OUT_AC);
Wait(450);  

while (SENSOR_2 > 45)
{
go_back;  
}

go_back;
Wait(250);

Off(OUT_AC);
Wait(200);

turn_right5; 
Wait(700);

while (SENSOR_3 > 45)
{
turn_right5;  
}
 


DKK2(); //Sを左折
//Qに到着
turn_right6;
Wait(1100);
while (SENSOR_2 > 45)
{
turn_right6;  
}

turn_right3;
Wait(300);

Off(OUT_AC);
Wait(1000);

go_forward;  //Xに入る
Wait(2500);
AU; //Xでコップを上げる
Off(OUT_AC);
Wait(3000);

go_back;
Wait(1200);
Off(OUT_AC);
Wait(2000);
while (SENSOR_2 > 45)
{
go_back;  
}
go_back;
Wait(500);
while (SENOSR_2 > 45)
{
go_back;  
}

Off(OUT_AC);
Wait(1000);
turn_right5;
Wait(500); 

while (SENSOR_3 > 45)
{
  turn_right5;
}
turn_right5;
Wait(600);

while (SENSOR_3 > 45)
{
  turn_right5;
}

Off(OUT_AC);
Wait(1000); 

go_forward;
Wait(1000);

while (SENSOR_2 > 45)
{
go_forward;
}
Off(OUT_AC);
Wait(1000);

while (SENSOR_3 > 45)
{
turn_left5;
}
turn_left5;
Wait(300);

 go_forward;
 Wait(500);
TD; //超音波下げる

Off(OUT_AC);
Wait(2000);
d = searchDirection(120);//コップ探す
if (d > 10){
 fwdDist(d-10.0);//コップに近づく
 }
TU; //超音波センサーをあげる
Off(OUT_AC);
Wait(1000);
go_forward;
Wait(1300); 

Off(OUT_AC);
Wait(1000);

turn_left3;
Wait(1400);

Off(OUT_AC);
Wait(2000);
go_forward;
Wait(2300);
go_back;
Wait(100);
Off(OUT_AC);
Wait(500);
AD; //コップを取る(重ねる)
Off(OUT_AC);
Wait(3000);

go_back;     //kaiki
Wait(1900);
turn_right3;
Wait(1400);
go_back;
Wait(1300);

while (SENSOR_2 > 45)
{
go_back;  
}

turn_left5;
Wait(1200);
while (SENSOR_3 > 45)
 {
turn_left5;  
}

turn_right5;
Wait(300);
go_forward;
Wait(1000);
while (SENSOR_2 > 45)
{
go_forward;  //Xまで直進
}


AU; //Xでコップを上げる

turn_left3;
Wait(200);
go_back;
Wait(300);

CupOff;
} //終わり

追加プログラム

前述したとおり今回は2つ目のコップまでを回収したが初期はもちろん3つ目までのコップを回収する予定だった。しかしながら時間が足りず調整が間に合わなかったため、調整前のプログラミングではあるがここに添付する。

while (SENSOR_2 > 45)
{
go_back;  
}               //黒い線までバックする

turn_right3;
Wait(1000); //右折する

go_forward;
Wait(1000); //少し直進する


d = searchDirection(120); //コップ探す
if (d > 10){
 fwdDist(d-10.0);//コップに近づく
 }
TU; //超音波センサーをあげる
go_forward;
Wait(1000);
AD; //コップを取る

go_back;
Wait(1000);  //バックしてコースにもどる   
DKK();  //Bまでライントレースする

turn_left3; //左折する
Wait(1000);
DKK(); //Pに到着

turn_right3;
Wait(200);
go_forward;
Wait(1000); //Xにはいる

AU; //コップを上げる

go_back; 
Wait(1000); //Xから出る
turn_left3;   //左を向く
Wait(1000);

DKK(); //PからQまで円周上をライントレース
turn_left3;
Wait(1000);
DKK(); //Sに到着

turn_right3;
Wait(200);
go_forward; //Yに入る
Wait(1000);
AD; //コップを置く
CupOff; //コップ離す

子機・プログラミング概要

子機の動きはすべて親機からの信号にゆだねている

定義

子機ではアームの動きをすべて定義化している

#define ArmDown OnRev(OUT_A,50); Wait(500);  //アームを下げる
#define ArmUp   OnFwd(OUT_A,70); Wait(300);  //アームを上げる
#define ArmClose OnRev(OUT_C,70); Wait(1000);  //アームを閉じる(コップをとる)
#define ArmOpen OnFwd(OUT_C,30); Wait(500);  //アームを開ける(コップを置く)
#define ArmStay OnRev(OUT_AC,1);  //アームを締め続ける

task main

task main ()
{
 int msg;
while(true)
{
 ReceiveRemoteNumber(MAILBOX1,true,msg);
 
  if (msg == 01)
 {
 Off(OUT_AC);
 ArmDown;
 ArmClose;
 msg = 04;
 }   
 
  if (msg == 02)
 {
 ArmStay;
 ArmUp;
 msg = 04;
 }  
 
  if (msg == 03)
 {
 Off(OUT_AC);
 ArmUp;
 ArmOpen;
 }
  if (msg == 04)
 {
  ArmStay;
  Off(OUT_A);
  }
 }
}

結果

ロボコンでの結果はまさに「不振」といった感じであった。ロボットは1度も想定した動きをすることはなかった。ロボコンの得点は技術点を除くと0点となってしまった

とてもではないが良い出来とは言えず、 プログラミングの完成度に悔いが残る結果となってしまった。

自評・感想


添付ファイル: filemap2.png 50件 [詳細] filemap.png 22件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-02-13 (火) 23:59:58 (557d)