2018a/Member

最終課題概要

フィールドの説明

2018a-mission3.jpg
  • フィールドは課題2で使用した紙を使用する。
  • 2種類の空き缶(Aタイプ,Bタイプ)をそれぞれ3個づつ用意し、円XにABA、円YにBABとなるように3段づつ積み上げる。
  • 空き缶には色をつけたり文字や記号を書いてもよい。あるいは周囲に紙を張ってもよい。

基本ルール

  • 競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。
  • 図のA地点またはA'地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする。上空部分は領域からはみ出していてもよい。
  • タイプの空き缶を円Y内に、Bタイプの空き缶を円X内に運ぶ。
  • 開始の合図から5秒以内にスタートボタンを押す作業を完了すること。
  • 競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。
  • 途中でうまく動かなくなった場合、1回限り再スタートすることができる。
  • 得点は基本得点(運んだ缶の数や位置)と技術得点(採点者による評価)で決定される。

ロボットの概要

今回の課題に対しては二台のロボットを使用し、それぞれに特定の役割を与えることにした。また二台のロボットはBluetooth通信を用いて連携させた。

Master側のロボット

Master側のロボットは三段に積まれた缶の二段目を挟み、固定する役割を担った。
機体は三輪式を採用している。また、缶を掴むところの機構はギアを三枚使用し、掴む部分は役割的に固定した状態で少し強めの力に対応できるようアームを二重にした。
フィールド上の動きは光センサーや超音波センサーなどを使わず缶からの距離、移動の距離を実測し、動きをプログラミングした。

Image_9407a88.jpg

Slave側のロボット

Slave側のロボットは一段目、三段目の缶を挟み運ぶ役割をした。
機体を製作する上でMaster側と同じような三輪式を作ってみると、取り付けたアームが一缶目を掴むことができなかった。また、パーツを駆使して低い位置にアームを取り付けると機体が不安定になってしまった。さらには三段目を掴むために一段目と連動して動く縦に長いアームを取り付ける必要があったため、三段目の缶用のアームに強い力を与えなくてはいけなく、アームを開閉する機構の基礎をきっちり固定させるには本体に直接アームを付ける必要があった。
そのため下図のようになるべく本体をボタンの付いている方を下向きにし、その側面にタイヤを付ける形で地面すれすれにした。これによって思い通りの位置にアームを付けることができた。しかし、これでは自分でプログラムを起動させるのに一度持ち上げなければいけなくとても不便になってしまった。よって、こちらの機体はMaster側からの信号受信によって動き出すようにプログラムを組むことになった。

Image_c53db42.jpg

プログラム概要

二つの機体をつなげるプログラム

二つの機体にはそれぞれの役割があると先でも説明した。そのため機体同士が自分勝手に動いてしまっては缶を思い通りには掴めない。
なので、Master側が缶を掴んだ後Slave側を移動させ缶を掴ませるという様にお互いがメッセージを送り合い連携した。

MasterからのメッセージでSlaveが動くプログラム

  • Master側
    task main()
    {
          SendRemoteNumber(1,MAILBOX1,11); //Slave側のMAILBOX1に11という文字を送る
    }
  • Slave側
    task main()
    {
       int msg,frg1=1;
       while(frg1){
             ReceiveRemoteNumber(MAILBOX1,true,msg);   // MAILBOX1の値を受け取りmsgに格納
       if(msg==11){                                    //もしmsgにある数字が11ならば下の命令を行う
             (命令);
              frg1=0;
                  }
        }
    }

SlaveからのメッセージでMasterが動くプログラム

  • Slave側
    task main()
    {
          SendResponseNumber(MAILBOX1,12); //Master側のMAILBOX1に12という文字を送る
    }
  • Master側
    task main()
    {
        int msg,frg1=1;
       while(frg1){
             ReceiveRemoteNumber(MAILBOX1,true,msg);   // MAILBOX1の値を受け取りmsgに格納
       if(msg==12){                  //もしmsgにある数字が12ならば下の命令を行う
             (動かしたい命令);
              frg1=0;
                  }
        }
    }

プログラムの定義

Master側、Slave側それぞれで以下のようにプログラムを定義した。

  • Master側
    #define kail OnFwd(OUT_B,50);OnRev(OUT_C,50);Wait(500);Off(OUT_BC); //左旋回を0.5秒間行う
    #define kair OnFwd(OUT_C,50);OnRev(OUT_B,50);Wait(500);Off(OUT_BC); //右旋回を0.5秒間行う
  • Slave側
    #define SPEED_H 30
    #define SPEED_L 35
    #define OnRL(speedR,speedL) OnFwd(OUT_B,speedR);OnFwd(OUT_C,speedL);
    #define go_forward  OnRL(SPEED_H, SPEED_H);    // 前進
    #define Back(X) OnRev(OUT_BC,30);Wait(X);Off(OUT_BC);//後退
    #define turn_rt(X)  OnRL(SPEED_L, -SPEED_L);Wait(X);Off(OUT_BC);  // 右旋回
    #define turn_right(X)  OnRL(SPEED_L, 0);Wait(X);Off(OUT_BC);      // 右折
    #define turn_left(X) OnRL(0, SPEED_L);Wait(X);Off(OUT_BC);        // 左折
    #define turn_lt(X) OnRL(-SPEED_L, SPEED_L);Wait(X);Off(OUT_BC);   // 左旋回

サブルーチンを用いてのプログラム

前進、後退など一部動作はMaster側のみサブルーチンを使い組んだ。

  • 前進するプログラム
    sub zen(int i)
    {
        int t;
    	t=i*50;
    	OnFwd(OUT_B,50); OnFwd(OUT_C,49);
    	Wait(t);
    	Off(OUT_BC);
    }

    sub zeny(int i)
    {
    	int t;
    	t=i*100;
    	OnFwd(OUT_B,25); OnFwd(OUT_C,25);
    	Wait(t);
    	Off(OUT_BC);
    }
  • 後退するプログラム
    sub kou(int i)
    {
    	int t;
    	t=i*50;
    	OnRev(OUT_B,50);OnRev(OUT_C,49);
    	Wait(t);
    	Off(OUT_BC);
    }
  • 缶を掴むプログラム
    sub armc()
    {
    	OnFwd(OUT_A,30);
    }
  • 缶を離すプログラム
    sub armo()
    {
    	OnRev(OUT_A,30);
    }

プログラムの完成

完成したプログラムは以下のようになった。連携は一方が動いている最中、もう一方は停止しているため実際にはそれぞれ一つになっているが停止し動く方が変わるところでMaster側とSlave側で交互に表示する。

  • Masterが,侶佻を移動
    task main()
    {
    	int msg,frg1=1,frg2=1;       //関数frg1,frg2を定義
     	zen(51);              //2.55秒、50%の速さで前進
    	kair;                //0.5秒右旋回
    	zen(75);              //3.75秒、50%の速さで前進
    	kair;                //0.5秒右旋回
    	zeny(20);              //2秒、25%の速さで前進
    	armc();               //二段目の缶を掴む Xに移動完了	
           SendRemoteNumber(1,MAILBOX1,11);//送信	//Slave側に11の数字を送信(一旦停止)
  • Slaveが△侶佻を移動
    task main()
    {
       int msg,frg1=1,frg2=1;
       while(frg1){
       ReceiveRemoteNumber(MAILBOX1,true,msg);   //MAILBOX1の値を受け取りmsgに格納
       if(msg==11){ 
          SetSensorLowspeed(S1);  //缶の方向を探した後、近づいて10cm手前で停止
    
          int d = searchDirection(120);
          if (d > 10) {
                        fwdDist(d-10.0);
                         }
          str(500);            //0.5秒前進
          Off(OUT_A);           //モーターAの電源を切る
          str(400);            //0.4秒前進
          OnRev(OUT_A,30);         //一段目と三段目の缶を掴む Xに移動完了
          Wait(1000);           //1秒待つ
          Back(1000);           //1秒後退
          SendResponseNumber(MAILBOX1,12); //Master側に12の数字を送信(一旦停止)
          frg1=0;             //関数frg1に0を代入
             }
       }
  • Masterがの経路を移動
    		ReceiveRemoteNumber(MAILBOX1,true,msg);//受信		
          if(msg==12){
    			armo();       //缶を離す
    			kou(20);      //1秒後退
    			kair;        //0.5秒右旋回
    			zen(44);      //2.2秒、50%の速さで前進
    			kail;        //0.5秒左旋回
    			zeny(20);      //0.5秒、25%の速さで前進 
    			armc();       //二段目の缶を掴む Yに移動完了		
                           frg1=0;       //関数frg1に0を代入
    			SendRemoteNumber(1,MAILBOX1,13); //Slave側に13の数字を送信(一旦停止) 
                        }
    	 }
  • Slaveがい侶佻を移動
      while(frg2){
       ReceiveRemoteNumber(MAILBOX1,true,msg);   //MAILBOX1の値を受け取りmsgに格納
       if(msg==13){   
        turn_lt(600);                       //0.6秒左旋回
        str(4000);             //4秒前進
        turn_rt(1000);           //1秒右旋回
        str(1000);             //1秒前進
        OnFwd(OUT_A,30);          //缶を離す  Yに移動完了
        Wait(500);             //0.5秒待つ
        Off(OUT_A);             //モーターAの電源を切る
        Back(1000);             //1秒後退
        turn_rt(800);            //0.8秒右旋回
        str(500);              //0.5秒前進
        turn_lt(1000);           //1秒左旋回
        str(2000);             //2秒前進
        turn_left(1000);          //1秒左折
        OnRev(OUT_A,30);          //一段目と三段目の缶を掴む
        Wait(1000);             //1秒待つ
        Back(1000);             //1秒後退
        turn_rt(2000);           //2秒右旋回
        str(4000);             //4秒前進
        OnFwd(OUT_A,30);          //缶を離す
        Wait(1000);             //1秒待つ
        Off(OUT_A);             //モーターAの電源を切る
        SendResponseNumber(MAILBOX1,14);    //Master側に14の数字を送る
        frg2=0;               //関数frg2に0を代入(完全停止)
       }
     }
    }
  • Masterがその場で缶を離す
    	while(frg2){
    		ReceiveRemoteNumber(MAILBOX1,true,msg); //43 受信		
           if(msg==14){
    			armo();             //缶を離す
    			frg2=0;       //関数frg2に0を代入(完全停止)
    		}
    	}
    }
    Inked2018a-mission3_LI.jpg

まとめ

結果

結果は一回目は0点、二回目は2点となった。また技術点は平均12.2点で合計が14.2点であった。

反省

最終課題では授業初期に教わったdefineによるプログラムの定義、サブルーチンの使用、超音波センサー、Bluetoothによる通信といった様々なプログラミングを使うことができた。しかし上のような点数になってしまったのは微調整不足、電池残量によるモーターの変化、力の伝わり方の知識不足である。また缶を運んでいる最中に滑り落とさないようアームへの工夫、移動の動きを滑らかにすることで移動の振動を減らし、缶を落とさないようにする、といった方法も考えられる。
しかし、プログラミング構成面での反省点がそんなに挙げられないのは構成技術が進歩したということであろう。完璧にはほど遠いためこれからも改善の余地は多くあるが、プログラミングの知識を学ぶという目標は達成することができた。


添付ファイル: fileImage_c53db42.jpg 34件 [詳細] fileImage_9407a88.jpg 35件 [詳細] fileInked2018a-mission3_LI.jpg 30件 [詳細] file2018a-mission3.jpg 43件 [詳細]

トップ   編集 凍結 差分 バックアップ 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2018-08-13 (月) 22:31:46