- 追加された行はこの色です。
- 削除された行はこの色です。
#author("2020-02-15T00:49:15+09:00","shabuhara","shabuhara")
#author("2020-02-15T13:34:06+09:00","shabuhara","shabuhara")
[[2019b/Member]]
*目次 [#n59ddf45]
#contents
*課題の内容 [#j2e5d9fc]
#ref(2019b-mission2.png)
それぞれのC,E,F上に置かれた缶の上にボールを乗っけるというもの、ライントレースを使うと上手くいく?~
*ロボットの説明 [#tc18b0ce]
#ref(IMG_20200207_160029.jpg)
最終的に出来上がったのはこの2台のロボットです。手前にある卍が特徴的なロボットがボールを集めて置く役割、奥の長い棒がついているロボットが最初に玉が乗っかっている缶をごと纏めて集めてくる役割を持っています。最初は1台のロボットですべてを行ったほうが楽だという流れが班の中で大きかったのですが、せっかくだから2台にしようという事でなんとか役割を分けることで棒長ロボットが誕生する運びとなりました。
#ref(IMG_20200207_160051.jpg)
たまを回収する卍部分は2台にロボットを分ける際、多彩な意見が出てしまったが為の停滞が発生している際に暇で遊んでいた風車に由来します。画像の光センサーの前にある変なぶら下がりは、班の工学部の男が完成させたもので、缶にぶつかって押されると光センサーを隠すことで超音波センサーが使えない超近距離でも缶の存在を見つけることができる君です。コレのすごいところは空気を押すかのような僅かな力で動かす事ができ、更に自動で戻ってくれる点にあります。卍くんがしっかり缶をとらえる必要があることが発覚し正確に認知する方法が思いつかない中開発された神パーツでした。
#ref(IMG_20200207_160502.jpg)
卍を動かすためのモーターはこのように2つのモーターの間を広げることで確保しています。ちょっと強度が不安になる固定具合になりましたがピタリハマったときは感動を覚えました。
#ref(line_92535412058952.jpg)
なんとか開発された2台目の缶集めロボットですが基本は今までのロボットで横に棒を上下させるモーターがついています。こだわった点は先端の棒の長さです。あまり長い棒が残っておらず、微妙な長さの棒をつける事になりました。短すぎると用をなさないし、中途半端だと反対側の棒の下に回ってしまいます。
最終的には当たらないスレスレにすることで落ち着きました。
アームがとっても長いのでD地点からEFまで届き、缶をかっさらうことができて、プログラムにも少しやさしいいい子になりました。
*プログラムの紹介 [#bd2499de]
残念ながら最後までプログラムが完成していなかったので調整や終わってから追加された部分があるので説明はコンセプトになってしまった。
*卍ロボ [#df650907]
#define Low_S 30 //普通のスピード
#define S 35
#define Fast_S 50
#define Center 45 ライントレースの中央値
#define GF OnFwd(OUT_BC,S);
#define A 1 //短い時間がほしいとき
#define SIGNALON 11 //通信先のロボを動かすための番号
前回作ったライントレースは早くもないし挙動が不安定なので新しく作りました。Centerはライントレース用の数値
const float diameter =5.45;
const float track =10.35
const float pi =3.141592
int p=0; //行動指定用のカウンタ
缶の位置を見つけるためのconstたちが入っています
sub rough_trace(){
if(SENSOR_2>Center){ /中心から白に行ったとき
p=0; //交差点カウンタリセット
long f=0; //速度を変更するための数
f=(SENSOR_2-Center); //速度を変更する数を作る
long g=0;
g=f*1.4;
OnFwd(OUT_B,S-g); //速さに違いをつけて曲がる
OnFwd(OUT_C,S+g);
Wait(A);
}else if(SENSOR_2<Center){ //中心から黒に行ったとき
long F=0;
F=(Center-SENSOR_2);
long G=0;
G=F*1.4;
OnFwd(OUT_C,S-G);
OnFwd(OUT_B,S+G);
Wait(A);
p++;
if(p>300){ //pのカウントが300を超えると交差点とみなして行動を行う
Off(OUT_BC);
Wait(100);
}
}else{
GF; //何事もなければ直進
Wait(A);
}
}
授業中に説明された中心から離れるほど速度が急速に変化するものを作ろうとしたが簡易版のようになってしまった。必要なカーブは曲がれるので今回はこれでも大丈夫だった。
void GO_distance(float d){
long angle;
angle=d/(diameter*pi)*360.0; //角度計算
RotateMotorEx(OUT_BC,Low_S,angle,0,true,true); //角度代入して進む
}
距離から角度を計算し直進する関数
void Ang(long ang){
long angle;
angle=(track/diameter)*ang; //角度計算
RotateMotorEx(OUT_BC,Low_S,angle,100,true,true);//角度代入して回る
}
指定した角度回る関数
int search(long ang){
long angle,tacho_min=0,tacho_corr; //変数
int d_min; //最短の位置の缶の位置をとる変数
d_min =300; //仮の最短
angle=(track/diameter)*ang;
Ang(ang/2);
ResetTachoCount(OUT_BC); //角度測定用リセット
OnFwdSync(OUT_BC,Low_S,-100);
while(MotorTachoCount(OUT_B)<=angle){ //指定角度内を測定しつつ回転
if(SensorUS(S1)<d_min && SensorUS(S3)>10){
d_min=SensorUS(S1); //最小距離更新
tacho_min=MotorTachoCount(OUT_B);
}
}
OnFwdSyncEx(OUT_BC,Low_S,100,RESET_NONE)
until(MotorTachoCount(OUT_B)<=tacho_min);
Wait(14);
Off(OUT_BC);
Wait(500);
return d_min; //測定値を返す
}
いつか紹介された缶を探すプログラムを少しだけ変えたもの。最短距離にある缶の方向を測定する。
sub catchball(){
p=0;
while(p<3){ //3回とるまで繰り返す
for(int i=0;i>5000;i++;){//5000は適当たりればよい
GF;
Wait(A);
if(SENSOR_2<40){RotateMotor(OUT_A,20,86); //例の接触機構により黒を見つける
RotateMotor(OUT_C,S,-90);
RotateMotor(OUT_C,S,90);//ボールを取った缶を弾き捨てるところ
p++;
break;
}
}
}
}
一列に並んだ缶からボールを奪う関数。缶を払いのける動作を入れなければ次が取れない
地味に失敗しやすい。
sub putball(){
for(int i=0;i>3000;i++;){//3000は適当
OnFwd(OUT_BC,20);
Wait(A);
if(SENSOR_2<40){RotateMotor(OUT_A,20,86); //缶を見つけたら卍を回転して乗っける
RotateMotor(OUT_BC,S,-90); //缶から離れるため
break;
}
}
}
取るときとほとんど同じ、インパクトだけでない卍のまさかの利点がプログラムに出た。
float GA(float a){
const float pi =3.1415926535;
const float diameter = 5.45;
float ang =a/(diameter*pi)*360.0;
return ang;
}
距離から角度とって移動するやつ
task main()
{
SetSensorLight(S2);
SetSensorLowspeed(S3);
long t=CurrentTick();
while(CurrentTick();-t>=7000){ //7000は適当
rougth_trace();
if(CurrentTick();-t>7000){ //交差点が見つからなかった場合の
break;}
}
int msg;
while(msg=!SIGNALON){ //masterからの信号待ちするところ
ReceiveRemoteNumber(MAILBOX1,true,msg);
}
catchball(); //マスターが停止したところでスタート
RotateMotorEx(OUT_BC,-60,360,100,true,false); //取り終わったら一回転
int angl=GA(25.0); //フィールドの長さからおおよその缶がある位置へ
RotateMotor(OUT_BC,S,angl);
int d = search(180); //180度捜索
if(d>6.0){
GO_distance(d-6.0); //6cmまで接近
}
putball; //ボールを乗せる
}
今回は1機体が大きくなりすぎていたので2個め以降は諦めてしまった
*缶キャッチロボ [#t3b70fcd]
#define Low_S 30
#define S 35
#define Fast_S 50
#define Center 45
#define GF OnFwd(OUT_BC,S);
#define A 1
#define CONN 1 //通信するNXTの番号
#define SIGNALON 11 //通信先のNXTを動かす番号
int p=0;
int y=0;
sub rough_trace(){
if(SENSOR_4>Center){ /中心から白に行ったとき
p=0; //交差点カウンタリセット
long f=0; //速度を変更するための数
f=(SENSOR_4-Center); //速度を変更する数を作る
long g=0;
g=f*1.4;
OnFwd(OUT_B,S-g); //速さに違いをつけて曲がる
OnFwd(OUT_C,S+g);
Wait(A);
}else if(SENSOR_4<Center){ //中心から黒に行ったとき
long F=0;
F=(Center-SENSOR_2);
long G=0;
G=F*1.4;
OnFwd(OUT_C,S-G);
OnFwd(OUT_B,S+G);
Wait(A);
p++;
if(p>300){ //pのカウントが300を超えると交差点とみなして行動を行う
Off(OUT_BC);
Wait(100);
if(y==0){
RotateMotor(OUT_C,180); //これでボールが載った缶を2つ回収
y++; //同じプログラムを使うのでカウンタで変更
}
}
if(y==1){RotateMotorEx(OUT_BC,-60,180,100,true,false);
}
}else{
GF; //何事もなければ直進
Wait(A);
}
}
授業中に説明された中心から離れるほど速度が急速に変化するものを作ろうとしたが簡易版のようになってしまった。
float GA(float a){
const float pi =3.1415926535;
const float diameter = 5.45;
float ang =a/(diameter*pi)*360.0;
return ang;
}
距離を計算し角度に落とし込む関数
task main(){
SetSensorLight(S4);
RotateMotor(OUT_A,Low_S,-82); //アームを上げる
long t=CurrentTick();
while(CurrentTick()-t<7000){//7000は適当
rough_trace();
}
RotateMotor(OUT_A,Low_S,82);//3つ缶を持っているはずなのでアームを閉じる
long t2=CurrentTick();
while(CurrentTick()-t2<5000){//5000は適当
rougth_trace();
}
RotateMotor(OUT_A,Low_S,-82); //缶をおいたらアームを上げて下がる
RotateMotor(OUT_BC,Low_S,-500);
SendRemoteNumber(CONN,MAILBOX1,SIGNALON); //終わったら信号を送って終了
}
*反省 [#i09e7fde]
結局今回も最後まで終わらせることができなかった。~
実際作ってみてカント管の間が思ったよりも狭く機体が大きすぎる状況になってしまった。~
他のチームは機体の大きさを考慮しているところも多く、ちょっと悔しかった。~
ちょっと班の仲間のプログラムを見たが、自分のとはまず見やすさが違った。最後ながら括弧を探すのが大変なのは自分の粗雑さ故だと学んだ。~
*おわりに [#b5ebafea]
半年という短い間だったけれど、はじめは遠い存在に思えていたプログラミングがぐっと近づいて来たように思える。確かに課外学習が多くて大変だったけれど、協力して作業することの楽しさがわかった。~
ありがとうございました。お疲れさまでした。~