目次
#contents
*Mission3の説明 [#offcc809]
今回の課題は、課題2で用いたライントレース用の紙を貼り合わせ、その上に置いた4つの紙コップうち、2つの紙コップに入っている、赤いボールと青いボールをロボットで入れ替えるというものでした。詳しくはこちらをご覧ください。→
http://yakushi.shinshu-u.ac.jp/robotics/?2014b%2FMission3
*当日までの流れ [#y4dba375]
**〜2月4日 [#qe3f457c]
まずはロボットを1台にするか2台にするかで悩みました。話し合った結果、1台の場合より2台の場合のほうが、2台の動作をぴったり合わせることが出来ないといけない分、失敗する可能性が高そうだという事になり、1台の大型ロボットを作成することにしました。
ただ今思い返してみると1台の場合は、本体が重すぎて動作がぎこちなくなり、電位残量により大きく動きが変化してしまったので、2台のほうが安定性があったと思います。
次にどのようなロボットにするか構想を練りました。始めは、ボールの入った紙コップを持ち上げて、そのボールを入れる紙コップのところまで行き、紙コップを傾けてボールを入れるというロボットを考えていました。
しかしそれでは空の紙コップも使わなければならず、移動距離が延びてしまうので、アームで紙コップを持ち上げ、レールに4つのボールを溜めれるようにしました。こうすることで、空の紙コップを使わずに済むので、移動距離を短くすることが出来ます。
本体の組み立ては途中までは順調に進んだのですが、インテリジェントブロックNXTを2つ取り付ける場所がなくなってしまい、このように
左右に取り付けることにしました。
しかし左右に取り付けたことによって重心が傾いてしまいました。ここで直しておけばちゃんと真っ直ぐ進むロボットが作れたはずだと思います。
**2月4日 [#db46c338]
テストも終わり、集まれるようになったので、本格的にプログラムを作り始めました。この日出た問題点はアームと移動の動作です。
アームの問題点は、動作の途中で紙コップや床などに、変に引っかかったりすると、そこで動作が完了していないことになるので、次のプログラムに移動せずに止まってしまう事です。この問題はアームの動作を時間で定めることで、引っかかった場合も時間がたてばしっかり動くようになり解決しました。
***アームの動き [#o10993a9]
#define SPEED1 45
#define SPEED2 60
#define SPEED3 10
#define SPEED4 30
#define SPEED5 50
#define SPEED6 25
float GetAngle(float d)
{
const float diameter=5.45;
const float pi=3.1415;
float ang = d/(diameter*pi)*360.0;
return ang;
}
#define DOWN RotateMotor(OUT_A,SPEED3,105);
#define UP RotateMotor(OUT_A,-SPEED5,105);
#define LDown RotateMotor(OUT_A,SPEED3,25);
#define LUp RotateMotor(OUT_A,-SPEED2,25);
#define Catch RotateMotor(OUT_B,-SPEED4,105);
#define Separate RotateMotor(OUT_B,SPEED4,105); //アームの動き
task main ()
{
OnFwd(OUT_A,10);
Wait(1500);
Catch; //アーム全体を下げ、紙コップをつかむ
OnRev(OUT_A,50);
Wait(3500); //アーム全体を上げ、レールの上にボールをのせる
Wait(2000);
OnFwd(OUT_A,10);
Wait(3500); //アーム全体を下げ、紙コップを置く
Separate;
OnRev(OUT_A,35);
Wait(2000); //アーム全体を上げる(元の位置に戻す)
Wait(500);
}
移動の問題点は、超音波センサーを使った移動に毎回ずれが出てしまうという事です。紙コップの20cm手前まで進み本体が旋回し、アームの位置まで紙コップを持ってきたかったのですが、どうしても毎回位置がずれてしまうので、このように
&ref(2014b/Member/edaeda/Mission3/image7.JPG,50%,画像の説明);
ロボット本体から紙コップの位置を修正するパーツを作り取り付けました。
**2月5日 [#q97bb4f6]
この日は超音波センサーのプログラムの修正、超音波センサーを用いない移動プログラムの作成、アーム、レールのプログラムの改善、レールからボールを落とす際の紙コップの位置を修正するパーツの取り付け、2つのインテリジェントブロックNXTをBluetoothで通信できるかの確認を行いました。特に問題点はなく、このままプログラムをつなげれば、あとは細かい調整だけで、授業前にロボットが完成すると思っていました。
***超音波センサーを使った移動 [#x475c1ac]
#define SPEED 50
#define SPEED_SLOW 40
#define turn_right_here OnFwd(OUT_B,SPEED_SLOW);OnFwd(OUT_C,-SPEED_SLOW); //右旋回
float GetAngle(float d) { //進む距離を計算する
const float diameter=5.45; //タイヤの直径
const float pi=3.1415; //円周率
float ang = d/(diameter*pi)*360.0; return ang; //角度を計算する
}
const float diameter = 5.45;
const float track = 15; //タイヤのトレッド幅
const float pi = 3.1415;
void fwdDist(float d) { //距離 d �兪或�
long angle;
angle = d/(diameter*pi)*360.0;
RotateMotorEx(OUT_BC,SPEED_SLOW,angle,0,true,true);
}
void turnAng(long ang) { //角度 ang 度の時計回りの旋回
long angle;
angle = track/diameter * ang;
RotateMotorEx(OUT_BC,SPEED_SLOW,angle,100,true,true);
}
intsearchDirection(long ang) { //現在の方向を中心に ang 度の範囲で探し、障害物までの距離を返す
long angle,tacho_min=0,tacho_corr;
int d_min;
d_min=300; //仮の最小値
angle = (track/diameter)*ang; //旋回角度からタイヤの回転を計算
turnAng(ang/2); //指定された角度の半分を旋回
ResetTachoCount(OUT_BC); //角度計測をリセット
OnFwdSync(OUT_BC,SPEED_SLOW,-100); //反時計回りに旋回
while(MotorTachoCount(OUT_B)<=angle){
if(SensorUS(S1)<d_min){
d_min=SensorUS(S1); //仮の最小値を更新
PlaySound(SOUND_UP);
tacho_min=MotorTachoCount(OUT_B);
}
}
OnFwdSyncEx(OUT_BC,SPEED_SLOW,100,RESET_NONE);
until(MotorTachoCount(OUT_B)<=tacho_min||SensorUS(S1)<=d_min);
Wait(14); //微調整
Off(OUT_BC);Wait(500);
return d_min;
}
task main()
{
int d = searchDirection(120);
if(d > 15){
fwdDist(d-15.0);}
else {fwdDist(d-15);} //紙コップの方向を探した後音を鳴らし、前後の動きで15�兌蠢阿把篁�
PlaySound(SOUND_UP);
}
***超音波センサーを使わない移動 [#e89fcd1d]
float GetAngle(float d)
{
const float diameter = 5.45;
const float pi=3.1415;
float ang =d/(diameter*pi)*360.0;
return ang;
}
#define SPEED 50
task main()
{
int angle = GetAngle(20);
RotateMotor(OUT_BC,-SPEED,angle);//下がって
OnFwd(OUT_B,-SPEED);
OnFwd(OUT_C,SPEED);
Wait(1500);//180度旋回して
angle += GetAngle(30);
RotateMotor(OUT_BC,SPEED,angle);//対角線上の紙コップに向かって進む。
}
***レール [#f5aef65c]
#define SPEED1 45
#define SPEED2 60
#define SPEED3 10
#define SPEED4 30
#define SPEED5 50
float GetAngle(float d)
{
const float diameter=5.45;
const float pi=3.1415;
float ang = d/(diameter*pi)*360.0;
return ang;
}
#define Into1 RotateMotor(OUT_C,SPEED3,20); //ボールを入れる
#define Return1 RotateMotor(OUT_C,-SPEED3,25);
#define Into2 RotateMotor(OUT_C,SPEED4,30);
#define Return2 RotateMotor(OUT_C,-SPEED4,15);
task main(){
OnFwd(OUT_C,15);
Wait(1000);
Wait(3000); //レールを傾け、4つの内2つだけボールを紙コップに入れる
OnRev(OUT_C,30);
Wait(500);
Wait(5000);
OnFwd(OUT_C,25);
Wait(1000);
Wait(3000); //レールを傾け、レールに残っているボールを紙コップに入れる
OnRev(OUT_C,30);
Wait(2500);
}
**2月6日〜授業直前 [#o9ab4d2e]
午前中はプログラムの細かい修正をしていました。
そして問題は午後に起こりました。
最初はこのように↓
最初にどちらのnxcがマスターかスレイブかを設定する。
***マスター側のプログラム(Aとする) [#i81fb155]
#define CONN 1 // スレーブの接続番号
task main()
{
until (BluetoothStatus(CONN) == NO_ERR);
//プログラム
RemoteStartProgram(CONN, "B.rxe");
}
***スレーブ側のプログラム(Bとする) [#g99879f3]
#define CONN 0 // スレーブの接続番号
task main()
{
until (BluetoothStatus(CONN) == NO_ERR);
//プログラム
RemoteStartProgram(CONN, "C.rxe");
}//これでマスター側のCというプログラムが実行される
と、スレイブ側のプログラムからもマスター側のプログラムを実行できると考えていて、交互にプログラムを実行し合い、アーム・レールの動きと移動を連動させようとしていました。しかし実際はスレイブ側のプログラムからはマスター側のプログラムを実行できず、他の方法を考えなくてはいけなくなりました。
その時は授業まであと2時間となっていたので焦ってしまい、2つしか代案が思いつきませんでした。それは
�\睫製颪暴颪い討△辰織瓮奪察璽犬里笋蠎茲蠅鬚垢襯廛蹈哀薀爐鬚い犬辰董▲好譽ぅ崑Δ離瓮奪察璽犬鮗�け取ったらマスター側のプログラムを起動するようにする。
�◆屮◆璽爐瞭虻遒�完了した=ボールがレールの上を通る」という事なので、レールの上に超音波センサーを設置し、スレイブ側のプログラムにより動いたアームが拾ったボールがレールの上を通ると、超音波センサーが反応し、マスター側のプログラムが起動するようにする。
というものでした。
ですが実際�,蓮∈�までそのプログラムを使ったこともなかったのでよく分からず、いじることが出来ませんでした。�△癲▲廛蹈哀薀爐鬚泙箸瓩世靴討�ら超音波センサーが誤作動を起こすようになっていて、プログラム自体はこのように
***�△離廛蹈哀薀� [#ldc5802b]
#define SPEED 50
#define SPEED_SLOW 30
#define count 3
#define sound PlaySound(SOUND_CLICK);
task main()
{
int nOnline=0;
//最初のプログラム
if(nOnline=0){
if(SensorUS(S3)<count){//ボールが通る=アームの作業終わり
sound;
Wait(10000);
nOnline++;
//超音波センサーを使わない移動するプログラムを入力
}
}
else if(nOnline=1){
if(SensorUS(S3)<count){ボールが通る=アームの作業終わり、ボール4つ乗ってる
sound;
nOnline++;
}
}
else if(nOnline=2){
//この行に超音波センサーを使わない移動するプログラムを入力を入力、ボール2つになる
if(SensorUS(S3)<count){
sound;
Wait(10000);
nOnline++;
}
}
else if(nOnline=3)
//超音波センサーを使わない移動するプログラムを入力
}//超音波センサーを使わない移動プログラムには、スレイブ側のプログラムを実行するプログラムが組み込まれているので、これでボールの入れ替え完了
というものを作ることが出来たのですが、超音波センサーが反応しないので、結局使うことが出来ませんでした。
ここで授業開始の20分前になっていました。このままでは超音波センサーすら反応せず、何もできないロボットにしかならないところでしたが、
ここで、マスター側のプログラムをすべてつなげて、毎回スレイブ側のプログラムを呼び出してからはWaitで待たせておき、スレイブ側のプログラムが完了してからマスター側のプログラムの続きが実行されるようにすれば、スレイブ側のプログラムからマスター側のプログラムを実行する必要がなくなるのではないかという事に気づきました。
そしてこのプログラムを急いで作り、授業の時間になってしまいました。
***その時のプログラム [#o8d234b7]
task main() {
SetSensorLowspeed(S1);
until (BluetoothStatus(CONN) == NO_ERR);
OnFwd(OUT_BC,50);
Wait(5500);
turn_right_here;
Wait(2500);
RemoteStartProgram(CONN, "arm time.rxe");
Off(OUT_BC);
Wait(10000);
Wait(10000);
Wait(10000);
int angle1 = GetAngle(20);
RotateMotor(OUT_BC,-SPEED,angle1);
OnFwd(OUT_B,-SPEED);
OnFwd(OUT_C,SPEED);
Wait(1500);
angle1 += GetAngle(60);
RotateMotor(OUT_BC,SPEED,angle1);
int d2 = searchDirection(120);
if(d2 > 15){
fwdDist(d2-15.0);}
else {fwdDist(d2-15);}
PlaySound(SOUND_UP);
turn_right_here;
Wait(200);
RemoteStartProgram(CONN, "arm time.rxe");
Off(OUT_BC);
Wait(10000);
Wait(10000);
Wait(10000);
int angle2 = GetAngle(20);
RotateMotor(OUT_BC,-SPEED,angle2);
OnFwd(OUT_B,-SPEED);
OnFwd(OUT_C,SPEED);
Wait(1500);
angle2 += GetAngle(60);
RotateMotor(OUT_BC,SPEED,angle2);
int d3 = searchDirection(120);
turn_right_here;
Wait(600);
if(d3 > 15){
fwdDist(d3);}
else {fwdDist(d3);}
PlaySound(SOUND_UP);
RemoteStartProgram(CONN, "rail1.rxe");
Off(OUT_BC);
Wait(10000);
Wait(10000);
Wait(10000);
int angle3 = GetAngle(20);
RotateMotor(OUT_BC,-SPEED,angle3);
OnFwd(OUT_B,-SPEED);
OnFwd(OUT_C,SPEED);
Wait(1500);
angle3 += GetAngle(60);
RotateMotor(OUT_BC,SPEED,angle3);
int d4 = searchDirection(120);
turn_right_here;
Wait(600);
if(d4 > 15){
fwdDist(d4);}
else {fwdDist(d4);}
PlaySound(SOUND_UP);
RemoteStartProgram(CONN, "rail2.rxe");
}
**授業中 [#j11ae266]
何とかプログラムを連携させることはできたのですが、超音波センサーの問題を解決することが出来ないまま本番になってしまいました。
案の定本番では、ロボットが満足に紙コップのところまで移動することも出来ず失敗してしまいました。しかしこのまま、これまで頑張ってきたアーム、レール、修正の動きを見せることなく、点数も低いままで終わってしまうのは嫌だったので、B班は超音波センサーを使うことをやめました。
***最終的なプログラム [#w7bf2987]
task main() {
SetSensorLowspeed(S1);
until (BluetoothStatus(CONN) == NO_ERR);
OnFwd(OUT_BC,50);
Wait(5500);
turn_right_here;
Wait(2000);
RemoteStartProgram(CONN, "arm time.rxe");
Off(OUT_BC);
Wait(10000);
Wait(10000);
OnFwd(OUT_B,-SPEED);
OnFwd(OUT_C,SPEED);
Wait(700);
OnFwd(OUT_BC,50);
Wait(4000);
RemoteStartProgram(CONN, "rail.rxe");
Off(OUT_BC);
}
このようにすべての動作を最初から時間で管理するプログラムを作りました。
これにより、超音波センサーは使うことはできませんでしたが、最後にはボールを1つ移動することが出来ました。
ここまでで紹介しきれなかったプログラムはB班のarisykaさんのページをご覧ください。→http://yakushi.shinshu-u.ac.jp/robotics/?2014b%2FMember%2Farisyka%2FMission3
*ロボットの紹介 [#h0b240db]
どのようにしてロボットが動く予定だったかを紹介したいと思います。
**1.紙コップの15cm手前まで、超音波センサーを使い進む。 [#a453a139]
&ref(2014b/Member/edaeda/Mission3/image8.JPG,50%,画像の説明);
**2.本体を旋回させ、アームの位置に紙コップを持ってくる。 [#fdad5455]
&ref(2014b/Member/edaeda/Mission3/image7.JPG,50%,画像の説明);
**3.アームで紙コップを持ち上げて、レールの上にボールを乗せる。 [#f0ddb00b]
&ref(2014b/Member/edaeda/Mission3/image9.JPG,50%,画像の説明);
&ref(2014b/Member/edaeda/Mission3/image10.jpg,50%,画像の説明);
**4.空の紙コップのところまで、超音波センサーを使い進む。 [#w595b86f]
&ref(2014b/Member/edaeda/Mission3/image11.JPG,50%,画像の説明);
**5.レールを傾けて、空の紙コップにボールを入れる。 [#e625259d]
&ref(2014b/Member/edaeda/Mission3/image12.JPG,50%,画像の説明);
これが一連の動作になります。
*感想 [#o13d5ed0]
*反省と感想 [#o13d5ed0]
最後までなぜ超音波センサーが誤作動を起こしてしまったのかが分からなかったのは悔しかったです。その他にもこの短期間で色々なトラブルが発生しましたが、そのたびにもっとしっかり対応をして、もう少し時間をかけていれば、超音波センサーの問題も解決し、今回のMission3は成功することが出来たと思います。私は機械・ロボット学系で、来年からもロボットを作るので、この経験を活かしてロボットを作っていきたいと思います。