[[2016a/Member]]
*目次 [#t6aa239e]
#contents
*課題3の説明 [#xeb46890]
**基本ルール [#h818305c]
ロボットコンテスト(課題3)は課題2で作成したコースを用いてタイムレースを行い、最終得点で勝負する。今回は2台以下のロボットを使用して、C地点(3個)とD地点(3個)の2箇所に設置された紙コップをコース中央の輪の中に交互に重ねる。最終的な点数は紙コップの個数に応じた基本点と動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性についての技術点の合計とする。
**注意点 [#h405738f]
-2台のロボットはA地点とB地点からスタートする。
-紙コップは(C地点のコップ)→(D地点のコップ)の順に重ねる。
-最終的に紙コップはロボットが触れていない状態で自立していること。
-競技時間は紙コップをすべて(最大6個)重ねるか、審判が続行不能と判断するまで。
-競技が終わるまでロボットに触れてはいけない。
~課題3のルールの詳細は[[こちら:http://yakushi.shinshu-u.ac.jp/robotics/?2016a%2FMission3]]を参照
~課題2の詳細は[[こちら:http://yakushi.shinshu-u.ac.jp/robotics/?2016a%2FMember%2Ffujison%2FMission2]]を参照
**紙コップの配置 [#y9f21e8b]
今回の課題では各地点の枠内であれば自由に紙コップを配置してよい。
~私たちの班は次の図のように紙コップを配置した。
#ref(./紙コップ配置.png,50%,紙コップの配置)
*ロボット1 [#jaa4c235]
**役割 [#y6ef6d56]
このロボットはA地点からスタートし、コース中央で待機する。その後、ロボット2が運んできた紙コップを挟んで抑え、重ねるときに倒れないようにすることを目的に制作した。
~光センサを2個ともロボット2に使ってしまったので、ロボット1の動作はすべて時間指定になった。
※本来はその予定で作ったが、最初のスタート位置のずれやロボットの調子によって、正しい場所で待機できず、ロボット2の動作の邪魔、紙コップをうまく固定できないなど課題の成功率が下がると判断し、ロボコンの2回目の挑戦では使用しなかった。
**構造 [#m7793056]
【ロボット全体像】
#ref(./image17.JPG,70%,ロボット1全体像)
【ロボット前側】
#ref(./image16.PNG,25%,ロボット1前側)
【力の向きの変換】
~今回使用したモーターの回転はもともと縦方向である。そのため、そのままではモーターの力を使用して左右にアームを開いたり、閉じたりすることはできない。しかし、写真のように歯車(水色で囲ったもの)を使用することで、縦向きの力(赤い矢印)を横向きの力(青い矢印)へと変換している。
#ref(./image19.PNG,70%,力の変換)
【改良点】
-緑の枠…ロボット2がコップを下すときにロボット1のアームが邪魔にならないように、できるだけアームの位置を下げた。
-青の枠…タイヤを小さくし、ロボット2の動作の邪魔にならないようにした。ただ小さくするのではなく、コップをつかんだ時の安定性も確認しつつ、タイヤのサイズを決めた。
-赤の枠…留め具はできるだけ小さいものを選び、高さをなくすことで、ロボット2がコップを下すときに引っかかり、コップが転倒しないようにした。
#ref(./image20.JPG,100%,改良点)
**プログラム [#b64112f4]
~【定義】
#define SIGNALON 121 //121の値をロボット2から受信したとき、次の指定された動作を行う。
~※値は0〜255までの値をメッセージとして送受信できる。
~【基本動作】
ClearMessage //メッセージ( )の値を0に初期化する
ClearTimer(0) //Timer(0)をリセット
OnFwd(OUT_A) //Aのモータを正回転させる
OnRev(OUT_AC) //AとCのモータを逆回転させる
Wait(t) //前の動作をt秒間行い、その間次の動作には進まない
Off //モータを停止させる
~【メインプログラム】
task main()
{
ClearMessage();
ClearTimer(0);
OnRev(OUT_AC); //Q地点まで移動する
Wait(450);
Off(OUT_AC);
OnRev(OUT_A); //ロボット1の向きの調整をする
OnFwd(OUT_C);
Wait(5);
Off(OUT_AC);
until(Message() == SIGNALON); //until…ある条件が満たされるまで動作を停止する
Wait(150); //ロボット2が運んできた紙コップの位置を調整
OnFwd(OUT_B);
Wait(10);
Off(OUT_B);
Wait(30000); //紙コップがすべて重ね終わるまで停止
OnRev(OUT_B); //アームを広げ、紙コップを離す
Wait(20);
Off(OUT_B);
OnRev(OUT_AC); //紙コップから離れる
Wait(30);
Off(OUT_AC);
}
*ロボット2(つかむ・重ねる) [#je00e591]
**役割 [#r1389d1c]
このロボットはB地点からスタートし、ライントレースを行って、紙コップのある地点へ行く。さらに、紙コップをつかむ役割と重ねる役割を持っている。
**構造 [#d57fe889]
【ロボット2全体像横側】
#ref(./image25.jpg,90%,全体像横側)
【ロボット2全体像前側】
光センサーをアームと同じ面に付けることで、紙コップをつかむ時に生じる、ロボットと紙コップの間合いのずれをできるだけ抑えた。
このロボットは紙コップを重ねる際にロボット1との衝突を減らすために、各アームにタイヤを1つしか取り付けていない。つまり、紙コップを持ち上げたり、運んだりするときの安定性が低いので、各動作を行うときに別の理由で紙コップがずれたり、落としたりすることを減らしている。
#ref(./image26.jpg,90%,全体像前側)
【光センサー】
タッチセンサーでは紙コップに反応しない・紙コップがずれる可能性が考えられたので光センサーを使用した。
上側(赤色の枠で囲まれた)光センサーは紙コップの識別のために使用。
下側(青色の枠で囲まれた)光センサーはライントレースのために使用。
※上側に紙コップ用、下側にライントレース用を付けた。この形(全体像前側及び下の光センサーの写真参照)にしたのは、光センサーが真ん中にあることで、挟む時にアームが紙コップに対して、同時に力を加えることができるようにするためである。その結果、アームの力のつり合いが取れずコップが転倒したり、つかめなかったりすることを防いでいる。
#ref(./image21.jpg,50%,光センサー)
**つかむ・重ねる仕組み [#v8827f28]
紙コップを重ねるまでの手順は以下の通りである。
+アームが(アーム写真�,寮屬ぬ隶�の方向に)閉じる。
+紙コップをつかむ。
~※紙コップ上側の淵がアームのタイヤ部分に引っかかることで紙コップを持ち上げている。
#ref(./image24.png,50%,つかみ方)
+限界まで紙コップをつかむ。つまり、アーム写真�,寮屬ぬ隶�の方向にそれ以上力を加えることができない状態に達する。
+それまで、アームを閉じる方向にかかっていた力が、上向き(アーム写真�△寮屬ぬ隶�の方向)に力がかかり始める。
+アームは上へと動き紙コップが持ち上がる。
+下すときはモーターを逆向きに回せば、自動的に下り、アームが開くので、重ねることができる。
~※モーターの力の変換方法(アーム写真�,寮弔は函砲肋綢�(ロボット1/構造)に記載している。
~【アーム写真� �
#ref(./image23.jpg,50%,アーム前側)
【アーム写真�◆�
#ref(./image11.JPG,50%,アーム横側)
【問題点】
~アームを上下に動かすときのスピードはアームのギア比(各ギアの大きさとギア同士のサイズの違い)によって決まる。しかし、そのことをあまり詳しく知らなかったこともあり、改良することができなかった。次の機会で困らないように調べておきたい。
**プログラム [#n60595f3]
【定義】
#define SIGNALON 121 //通信用
#define MIDDLE 50 //ライントレースをするための値
#define WHITE 50 //紙コップを判断するための値
#define turn_left1 SetPower(OUT_AC,2); Off(OUT_A); OnFwd(OUT_C); //左折
#define turn_left2 SetPower(OUT_A,1); OnRev(OUT_A); OnFwd(OUT_C); //左旋回
#define turn_right1 SetPower(OUT_AC,2); OnFwd(OUT_A); Off(OUT_C); //右折
#define turn_right2 SetPower(OUT_C,1); OnFwd(OUT_A); OnRev(OUT_C); //右旋回
#define go_forward SetPower(OUT_AC,7); OnFwd(OUT_AC); //前進
int cup_count=0; //コップのカウント
【サブルーチン】
MIDDLE+3 //上でMIDDLEは50と定義されているので、50+3=53となる
While(条件式) //括弧内の条件が満たされている間、指定された動作を続ける
if(条件式) //括弧内の条件が成り立つとき、指定された動作を行う
else if(条件式) //if以外の条件を決めることができる
~�.薀ぅ鵐肇譟璽�
~課題2で行ったライントレースを利用している。ライントレースとは光センサを用いて、ロボットに黒い線を認識させ、トレースさせることである。
sub trace() //ライントレース
{
while(FastTimer(0) < 26) //左旋回が一定時間続くまでループ
{
if(SENSOR_2 < MIDDLE-5) //黒
{
turn_left2; //左旋回
}
else
{
if(SENSOR_2 < MIDDLE-2) //中間に近い黒
{
turn_left1; //左曲がり
}
else if(SENSOR_2 < MIDDLE+3) //中間
{
go_forward; //直進
}
else if(SENSOR_2 < MIDDLE+6) //中間に近い白
{
turn_right1; //右曲がり
}
else //白
{
turn_right2; //右旋回
}
ClearTimer(0);
}
}
}
~��直進する
sub i_forward() //直進
{
turn_right2;
Wait(30);
go_forward;
Wait(50);
Off(OUT_AC);
}
��左折する
sub i_left() //左折
{
turn_left2;
Wait(45);
Off(OUT_AC);
}
�け�折する
sub i_right() //右折
{
turn_right2;
Wait(30);
go_forward;
Wait(30);
turn_right2;
Wait(80);
Off(OUT_AC);
}
��CとDの1つ目のコップをつかみライントレースできる位置に移動する
紙コップの配置と番号は上に記載している。
sub cup1() //CとDのそれぞれの1つ目のコップ
{
turn_right2; //紙コップまで方向調整
Wait(25);
SetPower(OUT_AC,1); //紙コップまで移動
OnFwd(OUT_AC);
while(SENSOR_3 <= WHITE);
Off(OUT_AC);
OnRev(OUT_B); //紙コップをつかむ
Wait(150);
Off(OUT_B);
turn_right2; //ラインまで移動
Wait(180);
go_forward;
Wait(20);
}
��CとDの2つ目のコップををつかみライントレースできる位置に移動する
sub cup2() //2つ目のコップ
{
SetPower(OUT_AC,1); //紙コップまで移動
OnFwd(OUT_AC);
OnFwd(OUT_AC);
while(SENSOR_3 <= WHITE);
Off(OUT_AC);
OnRev(OUT_B); //紙コップをつかむ
Wait(150);
Off(OUT_B);
turn_right2; //ラインまで移動
Wait(180);
go_forward;
Wait(120);
}
��CとDの3つ目のコップををつかみライントレースできる位置に移動する
sub cup3() //3つ目のコップ
{
turn_right2; //紙コップまで方向調整
Wait(45);
SetPower(OUT_AC,1); //紙コップまで移動
OnFwd(OUT_AC);
while(SENSOR_3 <= WHITE);
Off(OUT_AC);
OnRev(OUT_B); //紙コップをつかむ
Wait(150);
Off(OUT_B);
turn_right2; //ラインまで移動
Wait(170);
go_forward;
Wait(100);
}
�┘灰奪廚魏爾掘▲蹈椒奪�1と通信する
~コップを前に押すことで2つ目以降のコップを重ねるときに、ひっかかりコップが転倒することのないようにした。
sub cup_down() //コップを下すときの動作
{
turn_left2; //コップを下す位置まで移動
Wait(5);
OnRev(OUT_AC);
Wait(5);
Off(OUT_AC);
if(cup_count == 1) //最初のコップを置くとき
{
SendMessage(SIGNALON); //もう一台の動作を再開する
}
OnFwd(OUT_B);
Wait(50);
Off(OUT_B);
if(cup_count == 1) //最初のコップを置いたとき
{
OnFwd(OUT_AC); //コップを少し前に押す
Wait(10);
}
OnRev(OUT_AC); //ラインまで移動
Wait(60);
turn_left2;
Wait(120);
go_forward;
Wait(50);
}
【メインプログラム】
~ロボットが交差点を判断するたびに変数cの値を増やしていき、正しい順番で動作するようにした。course_checkはC地点とD地点のどちらに行くかを交互に判断できるようにし、cup_countはどの紙コップでどの動作を行うのか区別した。変数dはすべてのコップを回収したとき1になり、動作を停止する。
task main()
{
SetSensor(SENSOR_2, SENSOR_LIGHT);
SetSensor(SENSOR_3, SENSOR_LIGHT);
int c=1; //交差点の確認
int d=0; //1になったら動作停止
int course_check=0; //0ならC地点へ、1ならD地点へ
SetPower(OUT_B,1); //コップをつかむときのモータ強さを弱くする
go_forward; //ラインまで直進
Wait(80);
while(d == 0)
{
ClearTimer(0);
trace(); //ライントレース
Off(OUT_AC); //交差点確認
PlaySound(SOUND_UP);
Wait(100);
switch(c)
{
case 1: //最初の交差点
i_left(); //S地点へ
break;
case 2: //S地点の交差点
if(course_check == 0)
{
i_right(); //C地点へ
}
else
{
i_left(); //D地点へ
i_left(); //D地点へ
}
break;
case 3: //C地点かD地点
if(cup_count < 2) //集めたコップが2つより少ないなら
{
cup1();
}
else if(cup_count < 4) //集めたコップが4つより少ないなら
{
cup2();
}
else //集めたコップが4つ以上なら
{
cup3();
}
cup_count++;
break;
case 4:
if(course_check == 0) //C地点から戻ってきたら
{
i_left(); //P地点へ
course_check = 1; //次はD地点へ
}
else //D地点から戻ってきたら
{
i_right(); //P地点へ
course_check = 0; //次はC地点へ
}
break;
case 5: //P地点の交差点
i_left(); //Q地点へ
break;
case 6: //Q地点の交差点
cup_down();
if(cup_count == 6) //コップを集め終わったら
{
d = 1; //動作停止
}
break;
case 7: //p地点の交差点
i_right(); //S地点へ
c = 1; //case 2に戻る
break;
}
c++;
}
Off(OUT_ABC);
}
*結果 [#uef4b412]
私たちの班は1回目はうまくいかず失敗したが、2回目の挑戦で紙コップを1つC地点から運ぶことに成功した。
私たちの班は、1回目はロボット1が正しい場所に行かず、そのずれによってロボット1のアームにコップが当たり、コップが倒れてしまって失敗したが、2回目の挑戦で紙コップを1つC地点から運ぶことに成功した。しかし、そのあとライントレースに失敗した。
~その結果、基本点は3点、技術点は9.2点の合計12.2点を獲得し、2位だった。
*感想及び反省 [#jbbeb619]
今回は今までの技術を組み合わせた課題だった。しかし、プログラムが前回よりも少し長く・複雑化するだけで、ロボットは自分の想像と異なる動作をし、少しのずれが最終的に大きなずれへとつながってしまう。今回は紙コップを運ぶだけだったが、航空機などのプログラムならば失敗は許されない。この講義を通じてプログラムの正確さ・簡潔さの重要性とロボットを組み立てる発想力の乏しさに気づくことができた。