目次
#contents

*今回の課題 [#s9b3f120]

自立走行 またはその他の自動化された方法で、ロボットが持っているペンで紙の上に自分の出身地を描くプログラミングおよびロボットを作成する。
決められたコース上をライントレースするロボット、およびプログラミングを作成する。

今回私は「札幌」という文字を書いた。
&ref(2017b/Member/waitu/Mission2/daiji.png,90%,aa);

*今回作成したロボット [#d94af0fc]
矢印の通りに進み、「!」のマークの場所で一時停止をする。

**概要  [#laadc8d8]
縦と横の動きを別々のモーターが担う、いわゆる「XY軸型ロボ」を採用した。
モーターを3つ使用し、それぞれを「縦の動き」「横の動き」「ペンを上げ下げする動作」へと分担した。


*今回作成したロボット [#sd04361d]

**概要 [#h78ca1b4]
デフォルトのロボットをそのまま流用し、光センサーをアーム部を取り付けた。
デフォルトロボットの拡張性の良さを利用し少し無理をしたアームや光センサーの取り付けをした。

↓実際のロボットの写真

&ref(2017b/Member/waitu/Mission1/IMG_3127.JPG,10%,aa);
**主な機構 [#wcf272b4]
***メイン車両機構 [#yd579baf]
ロボット全体を縦の方向に動かす機構。 車輪の幅を可能な限り広くし、斜め方向へのズレを減らしている。また、タイヤ四輪を一列に設置することでさらに直進の安定性を得た。
&ref(2017b/Member/waitu/Mission2/IMG_3441.JPG,30%,aa);

&ref(2017b/Member/waitu/Mission1/がが.png,40%,aaa);
***サブ車両+ペン機構 [#ob2d5e00]
「車両の上のレールを横の方向に動く小さな車両」と「ペンを上げ下げする装置」の二つを合体させて1つの機構としている。 メイン車両機構とは合体していないがレールからはみ出ないようにガイドがついている。 また、ペン機構には複数回のモーターの回転により発生するモーターのズレを防ぐストッパー機構も備わっている。 また、ペン機構とペン本体は輪ゴムでのみの固定を施した。
** ロボットの機構 [#q2a03362]

&ref(2017b/Member/waitu/Mission1/ああああ.png,40%,aaa);
***アーム部 [#a945ee92]
紙コップを取得し運ぶための機構である。
できるだけ大きなアームを実現しようとしたが、今回の場合それが仇となりアーム内でコップの位置が安定しないという事案が発生した。もう少しプログラミングとともに洗練することでとてもマシになる部分なので改良が望まれる部分であった。

↑レールの上にガイド機構がまたがっているような設計になっているのがわかる


&ref(2017b/Member/waitu/Mission2/IMG_3579.JPG,30%,aaa);

***光センサー [#d8813d23]
地面に垂直に取り付けた
紙コップが光センサーの邪魔をしないようにバリアがついている
できるだけセンサーを地面につけるように努力をした、、、と言いたいがほぼデフォルトのロボットの流用なのであまりオリジナリティはない。

&ref(2017b/Member/waitu/Mission2/IMG_3580.JPG,30%,aaa);


*プログラミング概要 [#zb3e4ac0]
**書き方 [#m0bf708d]
今回は書き順にこだわり、どちらの文字も正規の書き順通りに書くようなプログラミングを作成した。


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

 
 #define GL(t) OnRev(OUT_A,22); Wait(50 * t); Off(OUT_A); Wait(100);
 #define GR(t) OnFwd(OUT_A,22); Wait(50 * t); Off(OUT_A); Wait(100);
 #define GU(t) OnRev(OUT_C,17); Wait(30 * t); Off(OUT_C); Wait(100);
 #define GD(t) OnFwd(OUT_C,17); Wait(30 * t); Off(OUT_C); Wait(100); 
 #define GRU(t) OnFwd(OUT_A,24); OnRev(OUT_C,17); Wait(50 * t); Off(OUT_AC); Wait(100);
 #define GRD(t) OnFwd(OUT_A,24); OnFwd(OUT_C,17); Wait(50 * t); Off(OUT_AC); Wait(100);
 #define GLU(t) OnRev(OUT_A,24); OnRev(OUT_C,17); Wait(50 * t); Off(OUT_AC); Wait(100);
 #define GLD(t) OnRev(OUT_A,24); OnFwd(OUT_C,17); Wait(50 * t); Off(OUT_AC); Wait(100);
 #define PD OnRev(OUT_B,21); Wait(150); Off(OUT_B); Wait(500);
 #define PU OnFwd(OUT_B,21); Wait(150); Off(OUT_B); Wait(500);
 #define PDB OnRev(OUT_B,21); Wait(158); Off(OUT_B); Wait(500);
 #define PUB OnFwd(OUT_B,21); Wait(150); Off(OUT_B); Wait(500);
 #define turn_left1 OnFwd(OUT_A,50 * x); OnRev(OUT_C,20 * x);  //急な左折
 #define turn_left2 OnFwd(OUT_A,60 * x); OnFwd(OUT_C,40 * x);  //緩やかに左折
 #define turn_left3 OnRev(OUT_C,30 * x); OnFwd(OUT_A,35 * x);  //超信地左旋回
 #define go_forward OnFwd(OUT_AC,50 * x);  //前進
 #define go_back OnRev(OUT_AC,50 * x);  //後進
 #define turn_right2 OnFwd(OUT_A,40 * x); OnFwd(OUT_C,60 * x);  //急な右折
 #define turn_right1 OnRev(OUT_A,20 * x); OnFwd(OUT_C,50 * x);  //緩やかに右折
 #define turn_right3 OnRev(OUT_A,35 * x); OnFwd(OUT_C,30 * x);  //超信地右旋回
 #define turn_right4 OnFwd(OUT_C,30 * x);  //信地右旋回
 #define DO  523  //音の高さ(適当である)
 #define x 0.9              //モーター出力のかけ数
 #define z 1.0  //モーター駆動時間へのかけ数
 #define AD OnRev(OUT_B,30 * x); Wait(800); Off(OUT_B);  //アーム部を下げる (コップをとる)
 #define AU OnFwd(OUT_B,30 * x); Wait(800); Off(OUT_B);  //アーム部を上げる(コップを置く)

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

上から順に 
-Xの分だけペン機構を左へ
-Xの分だけペン機構を右へ
-Xの分だけ前進
-Xの分だけ後進
-Xの分だけ前進しながらペン機構を右へ(右上へ)
-右下へ
-左上へ
-左下へ
-ペンを下降させる
-ペンを上昇させる
-ペンを大きく下降させる
-ペンを大きく上昇させる
右に沿ってライントレースするサブルーチン

を実行する。 (モーターにより同じ入力値でも動きが違うということがあったのでXにかけられる関数はモーターにより違う)
 sub IKK()
  {
   int BP = 0;
   while (BP < 160){
   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;
 }

ペンの上げ下げに関する定義が二つあるのは、文字の太さを考慮した結果である
**札を書くプログラミング [#ge0ba48c]
漢字の右側の部分の微妙なカーブをできるだけ再現できるようにした。
左に沿ってライントレースするサブルーチン

 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_right2;
     } else {
       turn_right1;
     }
     BP = 0;
     }
    Wait(1);
    }
    Off(OUT_AC);
    PlayTone(DO,100); Wait(100);
    BP = 0;
 } 

 task main ()

***交差点判別のしくみ [#aff0c1a9]
今回、サブルーチンの核となっている交差点を判別するプログラミングだが、BPという変数を使用し、連続して黒い線上にいる時間を計測、BPがある一定の値を超えると交差点と判別しそこでサブルーチンを停止するという仕組みをとっている。
**task main [#oea2b8bb]
***スタート- [#zd1ef030]
 task main()
 {
  while (SENSOR_2 > 45) {
  go_forward; }
  go_forward;
  Wait(600);
  turn_right3;
  Wait(300);
  while (SENSOR_2 > 45) {
  turn_left3;
  }

Aの枠線まで直進した後、一定量直進しさらに右を向いた後に線が見つかるまで左に回転する

 左側
    PD;
    GR(20);              
    PU;
    GL(10);
    GU(15);
    PD;
    GD(70);
    PU;
    GU(51);
    PD;
    GLD(20);
    PU;
    GRU(19);
    GU(3);
    PD;
    GRD(15);
    GR(5);
    PU;
    GLU(15);
    GU(15);    
    GR(30);
***BーC [#z6137dd9]
 SetSensorLight(S2);
  IKK();
  turn_left2;       //B
  Wait(300 * z);  
 
  IKK();
  turn_right4;       //C
  Wait(1900 * z);
  while (SENSOR_2 > 45) {
  turn_left3;
  }

 右側
    PD;
    GD(50);
    GRD(5);
    GR(25);
    GU(15);
    PUB;    
    GD(15);
    GL(65);
    GD(35);
右側に沿ってライントレースをする

**幌を書くプログラミング [#t7653621]
はばへん(漢字の左側)のハネを再現しようと努力をした。
また、光の最後の画の形とハネにもこだわった
 はばへん
    PDB;             
    GD(40);           
    PUB;
    GU(40);
    PDB;
    GR(20);
    GD(40);
    GLU(5);
    PUB;
    GRD(5);
    GL(12);
    GU(55);
    PDB;
    GD(80);
    PUB;
    GU(75);
    GR(30);

 日 の部分(右上)
    PDB;    
    GD(30);
    PUB;
    GU(30);
    PDB;
    GR(33);
    GD(30);
    PUB;
    GU(16);
    GL(27);
    PDB;
    GR(30);
    PUB;
    GL(25);
    GD(16);
    PDB;
    GR(35);
    PUB;        
    GL(20);
***F-E [#w5030cbc]
 IKK();
  go_forward;   //F
  Wait(200 * z);
  while (SENSOR_2 > 45) {
  turn_left3; }
 
  IKK();
  turn_right4;
  Wait(1700 * z);        //急カーブ
  while (SENSOR_2 > 45) {
  turn_right4; }
  turn_right4;
  Wait(100);
  while (SENSOR_2 < 45) {
  turn_right4;
  }
 IKK();
  Wait(1000);  //E
  go_forward;
  Wait(300 * z);
  turn_right3;
  Wait(100 * z);
  while (SENSOR_2 > 45) {
  turn_right3; }
  turn_right3;
  Wait(100 * z);
  while (SENSOR_2 < 45) {
  turn_right3;
  }

 光 の部分(右下)
    PDB;
    GD(20);
    PUB;
    GLU(10);
    PDB;
    GRD(9);
    PUB;
    GRD(3);
    GRU(10);
    PDB;
    GD(15);
    PUB;
    GU(3);
    GL(25);
    PDB;
    GR(40);
    PUB;
    GL(19);
    PDB;
    GD(5);
    GLD(20);
    PUB;
    GRU(20);
    GU(5);
    GR(13);
    PDB;
    GD(25);
    GRD(5);
    GR(10);
    GU(15);
    PUB;    
}

* 結果 [#i5c885e9]
&ref(2017b/Member/waitu/Mission1/IMG_3132.JPG,10%,zoom,画像の説明);
実際に書いた文字の写真↑
右に沿って動くと、Fの後の2つ目のカーブを交差点として認識するので、それを利用した。

「札幌」と書いてあることは判別できるが、ロボットが書いているような不自然さが際立つ結果となった。
***R-P [#e172cada]
  IKK();
  turn_left3;  //R
  Wait(300 * z);
  go_forward;
  Wait(210);
  while (SENSOR_2 > 45) {
  turn_left3; }
  turn_left3;
  Wait(80 * z);
  while (SENSOR_2 < 45) {
  turn_left3; }
  turn_left3;
  Wait(600 * z);
  go_forward;
  Wait(300 * z);
 
  DKK();            //P

R部での交差点認識が鬼門となった。また、R地点でで右沿いのライントレースから左沿いのライントレースにシフトしている。 円をトレースするときは内周より外周で回ったほうが都合がいいためだ。

***コップ取得-回帰 [#b6def031]
 turn_right3;
  Wait(1750 * z);       //coppu1
  go_forward;
  Wait(150);
  Off(OUT_AC);
  AD;
  Off(OUT_B);
  go_back;
  Wait(150);
  turn_left3;
  Wait(1950 * z);
 
  turn_right3;
  Wait(200 * z);
  go_forward;
  Wait(500 * z);
  while (SENSOR_2 > 45) {
  turn_right3;
  }
  Off(OUT_ABC);
  PlayTone(DO,100); Wait(100);
  PlayTone(DO,100); Wait(100);
  Wait(3000);

右を向きX地点にあるコップを取得し原点回帰する

***Q-S [#s29e1d62]

  DKK();        
  Wait(1000);         //Q→S
  turn_right3;
  Wait(400);
  go_forward;
  Wait(300);
  while (SENSOR_2 > 45) { 
  turn_left3; }

S地点にて、円Yを回るときはコップを置く関係上外周を回るほうがいいため、左沿いから右沿いにシフトするための行動をとった。

***コップ配置-回帰 [#xe4a68a6]
  IKK(); 
  Wait(1000);     //S2度目 
 
  turn_left3;
  Wait(3000 * z);       //koppu2
  go_forward;
  Wait(500);
  Off(OUT_AC);
  AU;
  go_back;
  Wait(500);
  turn_right3;
  Wait(2500 * z);
  Off(OUT_ABC);
  Wait(1000);
  turn_left3;
  Wait(100);
  go_forward;
  Wait(600);
  while (SENSOR_2 > 45) { 
  turn_left3; }
  

二度目に地点Sに差し掛かった時に後ろを向きYにコップを置いて、回帰する。

***-ゴール [#m910d157]
 
  IKK();
  Wait(1000);      //F
  OnFwd(OUT_A,20); OnRev(OUT_C,60);
  Wait(200 * z);
  OnFwd(OUT_A,60); OnRev(OUT_C,1);
  Wait(800 * z);
 
  DKK();
  Wait(1000);         //C
  OnFwd(OUT_C,40); 
  Wait(1700 * z);
  OnRev(OUT_A,30); OnRev(OUT_C,30);
  Wait(1700 * z);
 
 
  DKK();
  turn_right3;
  Wait(200 * z);
  OnFwd(OUT_C,50); OnFwd(OUT_A,50); //D,ゴールへ
  Wait(300 * z);
 }

F地点で右沿いから左沿いのライントレースへと変化させている。
このほうがF地点で超信地旋回する際によりコースとロボットの向きが水平になり、ライントースの安定性が増す。



*結果 [#i5c885e9]
ライントレース自体は完璧であったが、コップの運送において大きな失敗をしてしまい、本番では一発で成功させることができたなった。


*自評・感想 [#o87782c1]
上に書いた通り、文字に不自然さが残る結果となった。それの主な原因が線の始点と終点のズレによるものだが、これにはどうしても環境やバッテリー残量などの細かい要因が絡むため、完璧な文字を作成するのは難しいと感じた。しかしながら、大まかな動きはほぼ完成されていたのでその点は満足できた。より時間があれば、ペンの上げ下げをする際に発生する始点と終点の余分な線や、漢字のトメ、ハネなどのディテールを追及していきたいと感じた。 また、プログラミングの方面ではサブルーチンを駆使するともっと見やすいプログラミングコードが書けるはずなので、そこを改善していきたいと感じた。
上の通り、ライントレースのみでの成功率はほぼ100%であった。が、コップの取得についてプログラミングの作成が難しく、試行ごとのズレも大きく明確な打開策がないまま本番を迎えてしまった。
次回の課題でその打開策が見つかるように努力したい。


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS