目次
今回の課題は、「青と赤のボールを運搬して空き缶の上に載せる」というものである。
フィールドの説明
時間がなかったのでゴールまでのプログラミングは書けなかったが、ボールを一つ缶の上に置くことはできた。
ロボットに時間をかけたせいで、プログラミングが最後まで書けなかったことがとても悔しかった。
基本ルール
基本得点の計算方法
芸術点の計算方法
以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。
課題3ではNXTが2台あり通信することが目的であったので、当初はそれぞれを独立させボールを回収するロボットと
それを缶の上に置くロボットの2つを作ろうと考えていたが、自分の技術的にも時間的にも厳しかったので、一体型のロボットを作ることにした。
下の部分が各種センサーでライントレースと缶の発見を行うマスター側で、上の部分がアームでボールの回収と設置を行うスレーブ側である。
このロボットを作った当初は後輪がついていたのだが、ゴムの摩擦によって右左折が上手くいかずやむを得ずタイヤを外すことにした。
タイヤのゴムを外してみても解決しなかったので、結果このように少し不細工な見た目になってしまった。
モーターの回転速度を50程度まで上げてみたらタイヤがついていても右左折ができるようになったが、動作が速すぎるために安定しなかったので棒で支えることにした。
光センサーは、課題2での反省を生かして車体との距離を縮めることでカーブを交差点だと認識することを減らした。さらに地面と近すぎず、
遠すぎない位置に設置することで安定した値を取れるようにした。
また、超音波センサーは過去のレポートを参考にして横ではなく縦に設置した。缶は曲面になったいるので、横にするとうまく距離が測れないと考えた。
このように片方から出た音波をもう片方で受け取っているので、横に設置すると正確に距離が測れないことがあった。
今回はボールをすべて回収してから缶の上まで運ぶというロボットなので、ボールをためておく場所が必要であった。
その場所にはブロックで作ったレールを採用した。
本物のボールを載せている画像を撮影し忘れたのでこれで代用するが、このように回収したボールがレールの上に集まっていく。
工夫した点で超音波センサーを盾に設置したと説明したが、それでもやはり正確に距離が測れないことがあった。
このレポートを描いているときに気付いたが、ボールを回収する時に超音波センサーが缶に接触するくらい近くに行かないとうまく回収できなかったので、
センサーをタッチセンサーに変えたほうがプログラムがすっきりするし、上手く缶を認識できたのではないかと思った。
このようにマスター側とスレーブ側が接触しているのはレゴブロックの凸4つ分だけでありとても不安定であった。
スレーブ側の重みで傾き、ボールを回収するときに崩れそうになったこともあるので、縦方向の固定だけでなく横方向にも固定をすべきであった。
ボールを載せるレールは、前の部分は固定をしていたが後ろは固定しなかったので、ボールがたまるにつれて外に開いてしまった。
ボールがレールの上から落ちてしまうことはなかったが、前にあるボールの上下の位置が変わってしまい、缶の上に置くときの障害になっていた。
後ろ側のレールを固定し、スムーズにボールを送り出せたらよかったと感じた。
スレーブ側にはモーターが2つ付いており、1つはボールを回収する機構を動かすため。もう1つは缶が動かないように支えるアームを上下させるためについている。
これはアーム側の歯車であり
こちらはボールをつかむ機構の歯車である。
どちらも歯車の数を調整し、モーターの回る方向と最後の歯車が回る方向が一致するようにした。そのおかげでプログラムを書くときに分かりやすかった。
ボールを回収する時、缶が動かないようにアームで缶を固定しておく。画像のように缶を挟んでおく。
ボールは回転する3本の棒でレールの上にのせる。ボールの下をすくい上げるようにして回収する。
スムーズにボールを回収するために棒の長さを3本とも同じ長さにして、ボールの上から押さえつけずしっかり下からすくい上げられるようにした。
今回作ったロボットはNXTが2台にモーターが4つ、センサーが2つ使われている。マスター側のNXTに2つのセンサーと車体を動かすためのモーターが2つ。
スレーブ側のNXTにはアームとボールを回収する機構を動かすためのモーターが2つ付いている。
#define SPEED 35 //モーターの回転速度 #define STEP 1 //一回の判断で進む時間 #define mae OnFwd(OUT_BC,SPEED); //前進する #define usiro(t) OnRev(OUT_BC,SPEED);Wait(t);Off(OUT_BC); //後退する #define migi1 OnFwd(OUT_C,SPEED); //右折する #define migi2 OnFwd(OUT_C,SPEED);OnRev(OUT_B,SPEED); //右に旋回 #define hidari1 OnFwd(OUT_B,SPEED); //左折する #define hidari2 OnFwd(OUT_B,SPEED);OnRev(OUT_C,SPEED); //左に旋回 #define CONN 1 //スレーブの番号 #define SIGNALON 11 //SIGNALONは11と定義 #define SIGNALOFF 12 //SIGNALOFFは12と定義
sub linefollow1() { SetSensorLight(S3); //S3に光センサーをつける SetSensorLowspeed(S4); //S4に超音波センサーをつける long t0; t0=CurrentTick(); while(CurrentTick()-t0<200){ //t0が0.2秒の間繰り返す if(SensorUS(S4)<=6){ //6cm以内に近づくと Off(OUT_BC); //モーターが止まる PlaySound(SOUND_UP); //ピロピロという音が鳴る break; //whileループから抜け出す } if(SENSOR_3>60){ //値が60以上の時 migi2; //右に旋回 t0=CurrentTick(); //時間をリセット }else if(SENSOR_3>52){ //値が52以上の時 migi1; //右折する t0=CurrentTick(); //時間をリセット }else if(SENSOR_3>40){ //値が40以上の時 hidari1; //左折する t0=CurrentTick(); //時間をリセット }else if(SENSOR_3>30){ //値が30以上の時 hidari2; //左に旋回 }else{ //そのほかの時 mae; //前進する t0=CurrentTick(); //時間をリセット } Wait(STEP); } Off(OUT_BC); //モーターを止める Wait(1000); //1秒待つ }
これがラインの左をトレースするプログラムである。右のトレースはほぼ同じであり、設定した値が違うだけであるので省略する。
課題2と違うところは超音波センサーをプログラムに取り入れたことだけである。いろいろテストしたところ値を6cm以下にするとうまく缶を認識できなかった。
当初はwhileループを抜け出す条件に超音波センサーの6cm以下という条件を入れていなかったためにループを抜け出せず、ライントレースが上手くいかなかった。
先生には迷惑をかけたがbreakを使ってループから抜け出し、わかりやすいように音を出す方法も教えてもらった。
今回の課題をするまでwhileの意味をよく理解せずに使っていたことがよく分かった。しかし、最後には理解し、breakでルー0プを抜け出したり、
音を出して今何をしているかが分かるようになったのは良い収穫であった。
sub kaihi() { OnFwd(OUT_B,SPEED);OnRev(OUT_C,speed);Wait(1600);Off(OUT_BC); //左に1.6秒曲がる OnFwd(OUT_BC,SPEED);Wait(2200);Off(OUT_BC); //前に2.2秒進む OnFwd(OUT_C,SPEED);OnRev(OUT_B,speed);Wait(1200);Off(OUT_BC); //右に1.2秒曲がる OnFwd(OUT_BC,SPEED);Wait(1700);Off(OUT_BC); //前に1.7秒進む OnFwd(OUT_C,SPEED);OnRev(OUT_B,speed);Wait(1700);Off(OUT_BC); //右に1.7秒進む OnFwd(OUT_BC,SPEED);Wait(2100);Off(OUT_BC); //前に2.1秒進む }
これはC'地点の缶を回避するサブルーチンである。タイヤの摩擦によって動作に差が出てしまい3回に1回は避けられないこともあった。
task main()
{ Wait(1000); //1秒待つ PlaySound(SOUND_CLICK); //ピッという音を出す linefollow1(); //左側をライントレースし缶の前まで行く mae;Wait(350);Off(OUT_BC); //缶の前でもう少し前へ行く(タッチセンサーならいらなかったかも) SendRemoteNumber(CONN,MAILBOX1,SIGNALON); //スレーブに11を送る(C地点の缶) Wait(17000); //17秒待つ(これを無くしたかった) usiro(1400); //後退する kaihi(); //缶を回避 linefollow1(); //左側をライントレース mae;Wait(700);Off(OUT_BC); //D地点の交差点を直進 linefollow1(); //左側をライントレース mae;Wait(350);Off(OUT_BC); //缶の前まで調節 SendRemoteNumber(CONN,MAILBOX1,SIGNALON); //スレーブに11を送る Wait(17000); //17秒待つ usiro(1100); //後退する migi2;Wait(1600);Off(OUT_BC); //D地点の交差点を右折 linefollow1(); //左側をライントレース hidari2;Wait(1600);Off(OUT_BC); //G地点の交差点を左折 linefollow1(); //左側をライントレース mae;Wait(350);Off(OUT_BC); //缶の前まで調節 SendRemoteNumber(CONN,MAILBOX1,SIGNALON); //スレーブに11を送る Wait(17000); //17秒待つ usiro(1100); //後退する migi2;Wait(1700);Off(OUT_BC); //G地点の交差点を右折 linefollow1(); //左側をライントレース hidari1;Wait(2000);Off(OUT_BC); //H地点の交差点を左折 linefollow2(); //右側をライントレース migi1;Wait(2000);Off(OUT_BC); //H'地点の交差点を右折 linefollow1(); //左側をライントレース hidari2;Wait(1600);Off(OUT_BC); //G'地点の交差点を左折 linefollow1(); //左側をライントレース mae;Wait(350);Off(OUT_BC); //缶の前まで調節 SendRemoteNumber(CONN,MAILBOX1,SIGNALOFF); //スレーブに11を送る Wait(17000); //17秒待つ usiro(1100); //後退する }
これは言い訳になってしまうが引っ越しの関係で時間がとれず、ボールを1つ置くまでのプログラムしか書けなかった。さらにプログラムを別々に
動かしたときにはしっかり動いてくれたが、プログラムを通して動かしたときには摩擦などによる誤差によって最後まで動いてくれなかった。
練習しているときでもプログラムを通して試してみることが大切なんだと気づいた。
さらにこのプログラムには気に入らない点があり、それはスレーブ側が動いている間にマスターがじっと待っている点である。
本当はスレーブが動き終わった後にマスターに信号を返し、それを受け取ってからマスターが再び動き出すプログラムにしたかった。
しかし僕に能力がなかったせいでただ17秒待つだけのプログラムになってしまった。
#define speed 15 //モーターの回転速度 #define SIGNALON 11 //SIGNALONを11と定義 #define SIGNALOFF 12 //SIGNALOFFを12を定義 #define tukamu OnFwd(OUT_B,speed);Wait(7000);Off(OUT_B); //ボールをつかむ #define hanasu OnRev(OUT_B,speed);Wait(7000);Off(OUT_B); //ボールをはなす #define arm_up OnFwd(OUT_C,speed);Wait(3800);Off(OUT_C); //アームを上げる #define arm_down OnRev(OUT_C,speed);Wait(3500);Off(OUT_C); //アームを下げる
task main() { int msg; //受け取った値を格納する変数 while(true){ //ロボットのボタンを押すまでループを続ける ReceiveRemoteNumber(MAILBOX1,true,msg); //MAILBOX1に変数を受け取る if(msg==SIGNALON){ //11を受け取った時 arm_down; //アームを下げる tukamu; //ボールをつかむ arm_up; //アームを上げる } if(msg==SIGNALOFF) //12を受け取った時 arm_down; //アームを下げる hanasu; //ボールをはなす arm_up; //アームを上げる } } }
メインの中にwhile(true)と書いてあるのでずっとこのループを続ける。whileの使い方をしっかり理解していなかったのでこのようなプログラムになってしまった。
この授業を通して簡単なプログラミングの書き方を学ぶことができた。しかし、ハードがしっかりしていないとソフトがどれだけ素晴らしくても
良い作品にならないことも分かった。時間をもっと作ることができれば最後までプログラムを作ることができたかもしれないという後悔もあった。
さらにすべての課題を通して、ほぼすべて一人で作らなければいけなかったのでもっとチームメイトと協力して作業を進めるべきだったのが反省点である。
しかし、チームメイトにやる気がなく全く作業に参加してくれなかったこともあったので、チームを作る際にはじゃんけんのようにランダムでなく
自分たちで相談してチームを決めることも検討してもらいたいと思った。