目次
#contents

*課題 [#ra7beac2]
今回の課題はボールを運搬するロボットを作ることである。
青と赤のボールを運搬して、それぞれ所定の350ml缶の上に乗せる。

&ref(2018b/Member/Yoshi/Mission3/ロボティクス課題3.png,100%,完成);

フィールドの説明~
     ◦フィールドは課題2で使用した紙を使用する。~
     ◦350ml缶(中が入っていても空でよい)は逆さまにして使い、ロボットのスタート直後にサイコロを振って出た目の番号の位置に置く。~
     ◦その番号の次の番号のところにもダミーの缶を置くことができる。ただし6の目が出た場合は6の位置と25cm以上離れていない場所ならどこに~
      置いてもよいものとする。距離は缶と缶のもっとも近い部分で測る。~
     ◦空き缶には色をつけたり文字や記号を書いてもよい。あるいは周囲に紙を張ってもよい。~
     ◦赤と青のボールは、図のように所定の場所に置いておく。その際、キットに含まれない小さな輪ゴムを使用するものとする。~

**ルール[#df79f5bf]
基本ルール ~
   ◦競技時間は審判が続行不能と判断するまで、あるいはリタイアするまで。~
   ◦図のX地点または(および)Y地点からスタートする。ただし接地している部分はそれぞれの領域内に収まるものとする(線上はOK)。上空部分は領域から~
    はみ出していてもよい。~
   ◦赤いボールを図のピンクのいずれかに置いた缶に、青いボールを図の水色のいずれかに置いた缶に、それぞれ乗せる。~
   ◦開始の合図から5秒以内にスタートボタンを押す作業を完了すること。~
   ◦競技が終了するまで、ロボットに触ったり人間が遠隔で操作してはならない。~
   ◦途中でうまく動かなくなった場合、1回限り再スタートすることができる(再スタートの際に別プログラムで起動してよい)。~

基本得点の計算方法 ~
   ◦ボールを一つ乗せればそれぞれ10点、二つとも乗せればボーナス点としてさらに10点。~
   ◦ダミーの缶を設置した上で、正しい缶に乗せれば、それぞれさらに6点加点する。~
   ◦ボールを目的の缶に当てることができれば、それぞれ4点。~
   ◦ボールを同じ領域内の間違った缶に乗せた場合は、それぞれ6点。~
   ◦ボールを同じ領域内の間違った缶に当てた場合は、それぞれ2点。~
   ◦ボールを違う領域内の缶に乗せた場合は、それぞれ2点。~
   ◦ボールを違う領域内の缶に当てた場合は、0点。~
   ◦目的の缶をもとの位置(直径7cmの円)から少し出してしまった場合は1点減点、半分以上出してしまった場合は2点または取得した得点の半分のいずれか~
    少ないほうを減点、その缶を完全にだしてしまったときは点数を半分にする。~
   ◦ダミーの缶がもとの位置から移動しても減点はしない。~

技術点の計算方法~
   ◦以下の動作の精度・スピード・確実性などを含めた技術的な工夫や芸術性について他の全てのチーム(5チーム)が20点満点で採点し、その平均点を求める。 
   得点の目安:~

   ◦ボール探し取りにいくまでの動作 (3点)~
   ◦ボール掴む動作 (3点)~
   ◦ボールを運ぶ動作 (2点)~
   ◦ボールを缶に置く動作 (2点)~
   ◦2台のNXT、EV3の連携の良さ(2点)~
   ◦自立型のロボットとしての形や動作の美しさ、斬新さ(2点)~
   ◦その他 (3点)~

*作戦 [#pe756174]

**コースについて [#i0c8289e]
コースに関しては以下のように進むことにした。~
赤の線は赤いボールを赤の缶に置くまでを示したもので青の線は青いボールを青の缶に置くまでを示したものである。~

まず、XからスタートしGで赤のボールを拾う。~
そしてEまで行き、そこで正しい缶を見つける。~
見つけたら、その缶まで一直線に進み(どの缶に進むかの線は書いていない)、ボールを置く。~
置いたらE地点に戻り、Iで青のボールを拾い、Kまで行き、正しい缶を見つけ、ボールを置く。

&ref(2018b/Member/Yoshi/Mission3/ロボティクス課題3.jpg,100%,完成);

**ロボットについて [#ec55b3e1]

ロボットは以下の写真のようなものにした。

&ref(2018b/Member/Yoshi/Mission3/課題301.JPG,100%,完成);

全ての動作を1つで行うロボットである。本体を2つ使っているように見えるが、後ろの1つはアームがボールを持つとき前のめりになって倒れるのを防ぐためのものなので、実際には1つしか使っていない。アームはモータを2つ使って上下の動きと開閉ができるようにした。~
以下の写真は、超音波センサとカラーセンサについてのものである。赤丸が超音波センサ、青丸がカラーセンサである。~
超音波センサはボールを見つけるため、アームと同じ軸にあるようにした。~
カラーセンサは最初2つ使ってライントレースしようと思ったが、結局うまくいかず1つだけで行うことにした。

&ref(2018b/Member/Yoshi/Mission3/課題302 (2).jpg,100%,完成);


**ライントレースについて [#m7ad7c36]

ライントレースは最初、カラーセンサを2個使い行おうと思ったが、先述のように、うまくいかなかった。~
この原因として考えられるのは、カラーセンサの位置が高く,うまく値を読み取ることができなかったことが考えられた。~
直して、カラーセンサを2つ使ってライントレースさせても良かったが、テストがあり、あまり集まれなかったのもあり、今回は前回の課題のように1つだけ使う方法にした。

**プログラムについて [#leba3965]

プログラムに関しては、大きく分けて2つのことをどのような関数で処理すればよいか考えた。~
1つ目は缶を探す関数である。~
赤と青の缶の位置が違うのでそれぞれの缶を見つける関数を分けた。~
赤の缶ではカラーセンサの最短距離によって缶を見つけるものにし、青の缶ではカラーセンサの距離をあらかじめ決めておいた缶とロボットの距離でどの缶に行くかを分けた関数を用いた。~
2つ目は缶に近づく関数である。~
1つ目でどの缶に行くかは決まったので、あとはその方向を向き、近づいてボールを缶に置くだけである。~
主にこの2つが課題3で問題になったプログラムだ。~
その他のプログラムに関しては、今までの課題を使えばよかったので、それほど苦労しないと思った。

*プログラムの説明 [#nf30f369]

**プログラムの導入 [#t49ebfe6]
 #!/usr/bin/env python3
 from ev3dev.ev3 import *
 import time
 mL=LargeMotor('outA') #装置AのモーターをmLとおく
 mR=LargeMotor('outD') #装置DのモーターをmRとおく
 mA=MediumMotor('outC') #装置CのモーターをmAとおく
 mC=MediumMotor('outB') #装置BのモーターをmCとおく
 csR=ColorSensor('in1') #装置1のモーターをcsRとおく
 #csL=ColorSensor('in2') #結局使わなかった
 us=UltrasonicSensor('in3') #装置3のモーターをusとおく

**定義の導入 [#ldeee58a]
 def turnR1(): #緩やかに右に曲がる関数を定義
    mL.run_forever(speed_sp=100,stop_action='brake')
    mR.stop()

 
 def turnL1(): #緩やかに左に曲がる関数を定義
    mR.run_forever(speed_sp=100,stop_action='brake')
    mL.stop()


 def run1(): #速めにまっすぐ進む関数を定義
    mR.run_forever(speed_sp=100,stop_action='brake')
    mL.run_forever(speed_sp=100,stop_action='brake')

 
 def turnR2(): #右に急カーブする関数を定義
    mL.run_forever(speed_sp=100,stop_action='brake')
    mR.run_forever(speed_sp=-70,stop_action='brake')


 def turnL2(): #左に急カーブする関数を定義
    mR.run_forever(speed_sp=100,stop_action='brake')
    mL.run_forever(speed_sp=-70,stop_action='brake')


 def traceR(): #右側をトレースする関数を定義
    t0=time.time()
    while time.time()-t0<0.35:
        if cs.value()<35:
    while time.time()-t0<0.35: #0.35秒間行う
        if cs.value()<35: #カラーセンサの値が真っ黒だったら行う
            turnR2()
        if 35<=cs.value()<40:
        if 35<=cs.value()<40: #カラーセンサの値が黒だったら行う
            turnR1()
            t0=time.time()
        if 40<=cs.value()<=50:
        if 40<=cs.value()<=50: #カラーセンサの値がグレーだったら行う
            run1()
            t0=time.time()
        if 50<cs.value()<=60:
        if 50<cs.value()<=60: #カラーセンサの値が白だったら行う
            turnL1()
            t0=time.time()
        if cs.value()>60:
        if cs.value()>60: #カラーセンサの値が真っ白だったら行う
            turnL2()
            t0=time.time()
    mR.stop()
    mL.stop()


 def traceRa(t): #好きな時間だけ右側をライントレースする関数を定義
    t1=time.time()
    while time.time()-t1<t:
            if cs.value()<35:
    while time.time()-t1<t: #t秒間だけ行う
            if cs.value()<35: #カラーセンサが真っ黒だったら行う
                turnR2()
            if 35<=cs.value()<40:
            if 35<=cs.value()<40: #カラーセンサが黒だったら行う
                turnR1()
            if 40<=cs.value()<=50:
            if 40<=cs.value()<=50: #カラーセンサがグレーだったら行う
                run1()
            if 50<cs.value()<=60:
            if 50<cs.value()<=60: #カラーセンサが白だったら行う
                turnL1()
            if cs.value()>60:
            if cs.value()>60: #カラーセンサが真っ白だったら行う
                turnL2()
        mR.stop()
        mL.stop()


 def run2(): #遅めにまっすぐ進む関数を定義
    mL.run_forever(speed_sp=50, stop_action='brake')
    mR.run_forever(speed_sp=50, stop_action='brake')

 

 def forward(): #少し進む関数を定義
    mL.run_to_rel_pos(position_sp=360, speed_sp=500, stop_action='brake')
    mR.run_to_rel_pos(position_sp=360, speed_sp=500, stop_action='brake')
 

 def forward_bit(): #ほんの少し進む関数を定義
    mL.run_to_rel_pos(position_sp=200, speed_sp=500, stop_action='brake')
    mR.run_to_rel_pos(position_sp=200, speed_sp=500, stop_action='brake')

 

 def catchup(): #ボールに近づいて取って持ち上げる関数を定義
    while us.value()>=50:
    while us.value()>=50: #カラーセンサの値が50以下の時行う
        run2()
    mR.stop()
    mL.stop()
    mC.reset()
    mC.run_to_abs_pos(position_sp=60 ,speed_sp=20, stop_action='brake')
    time.sleep(3)
    mA.run_to_abs_pos(position_sp=100, speed_sp=30, stop_action='brake')
    time.sleep(4)
    mC.run_to_abs_pos(position_sp=0, speed_sp=20, stop_action='brake')
    time.sleep(6)
    mA.run_to_abs_pos(position_sp=0, speed_sp=100, stop_action='hold')
    time.sleep(3)


 def puton_red(): #赤の缶に近づいてボールを置く関数を定義
    time4=time.time()
    while us.value>=40:
    while us.value>=40: #カラーセンサの値が40以下の時行う
        run()
    time_kan=time.time()
    mC.run_to_rel_abs(position_sp=30, speed_sp=20, stop_action='brake')
    time.sleep(1)
    timenow=time.time()
    while time.time()-timenow<=time_kan-time4:
    while time.time()-timenow<=time_kan-time4: #赤の缶に近づくまでの時間分バックし元の場所に戻る
        mL.run_forever(speed_sp=-50, stop_action='brake')
        mR.run_forever(speed_sp=-50, stop_action='brake')


 def puton_blue(): #青の缶に近づいてボールを置く関数を定義
    while us.value>=40:
    while us.value()>=40: #カラーセンサの値が40以上の時行う
        run()
     mC.run_to_rel_abs(position_sp=30, speed_sp=20, stop_action='brake')


 def direct_one(): #赤の�,隆未諒�向を向く関数を定義
    time1=time.time()
    while time.time()-time1<=20:
    while time.time()-time1<=2: #2秒間行う
        mL.run_forever(speed_sp=-50, stop_action='brake')
        mR.run_forever(speed_sp=50, stop_action='brake')
 

 def Round_red(): #赤の缶のエリアを回る関数を定義
    time1=time.time()
    while time.time()-time1<=fuga:
    while time.time()-time1<=fuga: #fugaの時間だけ行う fugaはのちに説明
        mL.run_forever(speed_sp=50, stop_action='brake')
        mR.run_forever(speed_sp=-50, stop_action='brake')


 def direct_redkan(): #赤の正しい缶を見つける関数を定義
    time1=time()
    while time.time()-time1<=fuga-(think_red()-time_start):
    while time.time()-time1<=fuga-(think_red()-time_start): #fuga-(think_red()-time_start)の時間だけ行う
        mL.run_forever(speed_sp=-50, stop_action='brake')
        mR.run_forever(speed_sp=50, stop_action='brake')
 

 def direct_I(): #位置Iの方向を向く関数を定義
    time1=time.time()
    while time.time()-time1<=think_red()-time_start+いくらか:
    while time.time()-time1<=think_red()-time_start+いくらか: #think_red()-time_start+いくらかの時間だけ行う
        mL.run_forever(speed_sp=-50, stop_action='brake')
        mR.run_forever(speed_sp=50, stop_action='brake')


 def direct_B(): #位置Bの方向を向く関数を定義
    time1=time.time()
    while time.time()-time1<=20:
    while time.time()-time1<=2: #2秒間行う
        mL.run_forever(speed_sp=-50, stop_action='brake')
        mR.run_forever(speed_sp=50, stop_action='brake')
 

 def Round_blue(): #青の缶のエリアを回る関数を定義
    time1=time.time()
    while time.time()-time1<=fuga2:
    while time.time()-time1<=fuga2: #fuga2の時間だけ行う fuga2についてはのちに説明
        mL.run_forever(speed_sp=50, stop_action='brake')
        mR.run_forever(speed_sp=-50, stop_action='brake')
 

 def direct_bluekan(): #青の正しい缶を見つける関数を定義
    time1=time()
    while time.time()-time1<=fuga2-(think_blue()-time_start):
    while time.time()-time1<=fuga2-(think_blue()-time_start): #fuga2-(think_blue()-time_start)の時間だけ行う
        mL.run_forever(speed_sp=-50, stop_action='brake')
        mR.run_forever(speed_sp=50, stop_action='brake')
 

 time_start=0
 time_a=0
 time_b=0
 def search(fuga,hoge): #どれが正しい缶かを見つける関数を定義 fugaはこの関数を使う時間 hogeは最短の距離の缶を見つけるために入れる適当な距離の数字
    global time_start
    global time_a
    global time_b
    a=1250
    b=1250
 def search(fuga,hoge): #どれが正しい缶かを見つける関数を定義 fugaやfuga2はこの関数を使う時間 hogeは最短の距離の缶を見つけるために入れる適当な距離の数字
    global time_start #関数外からtime_startの値を持ってくる
    global time_a #関数外からtime_aの値を持ってくる
    global time_b #関数外からtime_bの値を持ってくる
    a=1250 #aに最短距離を入れるので遠い値、つまり大きい値を代入しておく
    b=1250 #bに最短距離を入れるので遠い値、つまり大きい値を代入しておく
    time0=time_start=time.time()
    while us.value()>=hoge: 
    while us.value()>=hoge: #カラーセンサの値がhogeより大きければ何も行わない
        continue
    while time.time()-time0<=fuga:
        if us.value()<=hoge:
            if us.value()<=a:
                a=us.value()
                time_a=time.time()
        else:
    while time.time()-time0<=fuga: #fuga以下の時間だけ行う
        if us.value()<=hoge: #カラーセンサの値がhoge以下の時行う
            if us.value()<=a: #カラーセンサの値がa以下の時行う
                a=us.value() #aにカラーセンサの値、つまり最短距離を代入
                time_a=time.time() #time_aにその時の時間を代入
        else: #hogeより大きいときは、この繰り返しを抜ける
            break   
    while time.time()-time0<=fuga and us.value()>=hoge:
    while time.time()-time0<=fuga and us.value()>=hoge: #fuga以下の時間かつカラーセンサがhoge以上の値の時何も行わない
        continue
    while time.time()-time0<=fuga:
        if us.value()<=hoge:
            if us.value()<=b:
                b=us.value()
                time_b=time.time()
        else:
    while time.time()-time0<=fuga: #fuga以下の時間時行う
        if us.value()<=hoge: #カラーセンサがhoge以上の値の時行う
            if us.value()<=b: #カラーセンサがb以下の値時行う
                b=us.value() #bにカラーセンサの値、つまり最短距離を代入
                time_b=time.time() #time_bにその時の時間を代入
        else: #hogeより大きいときは、この繰り返しを抜ける
            break
 

 def think_red(): #赤の正しい缶を決める関数を定義
    if a<b:
        return time_a
    else:
        return time_b
    if a<b: #aがbより小さいとき行う
        return time_a #time_aを戻り値として返す
    else: #bがa以上の時行う
        return time_b #time_bを戻り値として返す


 def think_blue(): #青の正しい缶を決める関数を定義
    if a<150 and b<150:
        return time_b
    if a<150 and 150<=b<300:
        return time_a
    if 150<=a<300 and 150<=b<300:
        return time_a
    if a<300 and b=1250:
        return time_a
    if a>=300 and b=1250:
        return time_b
    if 450<b<550:
        return time_b
    if a<150 and b<150: #aとbが150未満の時行う つまり1の缶の時
        return time_b #time_bを戻りとして返す
    if a<150 and 150<=b<300: #aが150未満、bが150以上300未満の時行う つまり2の缶の時
        return time_a #time_aを戻り値として返す
    if 150<=a<300 and 150<=b<300: #aが150以上300未満、bが150以上300未満の時行う つまり3の缶の時
        return time_a #time_aを戻り値として返す
    if a<300 and b=1250: #aが300未満、bが1250の時行う つまり4の缶の時
        return time_a #time_aを戻り値として返す
    if a>=300 and b=1250: #aが300以上、bが1250の時行う つまり5の缶の時
        return time_b #time_bを戻り値として返す
    if 450<b<550: #bが450より大きく550未満の時行う つまり6の缶の時
        return time_b #time_bを戻り値として返す

*解決すべきだった問題 [#mf770ef7]
作業をしていていろいろな課題が出てきた。~
大きく分けて、4つある。~
1つ目はカラーセンサについてである。~
これについては先述である。~
2つ目はロボットについてである。~
ロボットの問題は2つ出てきて、1つ目がボールの重さでアームが持ち上がらないことである。~
特別ボールが重いわけではないが、ボールがないときはしっかりとアームが上がるので、おそらくボールを持つことでできなくなってしまう。~
これに関しては、原因がよくわからず、解決策も思い浮かず解決できなかった。~
2つ目はボールを使うとき、ロボットが前のめりになって倒れてしまうことだ。~
これは後ろにもう1つの本体をつけることによって解決された。
3つ目の課題は缶を見つける関数だ。~
赤と青の缶の位置が違うのでそれぞれの缶を見つける関数を分けた。~
赤の缶ではカラーセンサの最短距離によって缶を見つけるものにし、青の缶ではカラーセンサの距離をあらかじめ決めておいた、缶とロボットの距離でどの缶に行くかを細かく分けた関数を用いた。~
これでできるはずだったが、そこまで行くまでに4つ目の課題の時間による準備不足が訪れてしまった。~
今回はテスト期間と被り、あまり作業を効率よく行うことができず、うまくいかなかった。

*結果 [#h00a5b75]
結局、課題を解決できず、練習では、赤のボールをつかみEまで行くことができたので、そこまでやることにした。~
しかし、本番ではボールをつかむこともできなかった。~
原因は良く分からなかったが、完全に準備不足だった。~
その結果、基本点は0点で、技術点は他の班からの慈悲点ということで数点もらったのみになってしまった。

*感想 [#hc9ee2de]
今回の課題3まで授業でいろいろな課題をやってきて授業が始まる前の自分と比べて、プログラミングやロボット、レポートの書き方も成長できたように思う。~
特にプログラムに関しては、授業前はpythonというプログラミング言語の名前すらよく知らなかったのに、それを用いてプログラムを書くことができるようになった。~
最後はとても不甲斐ない結果に終わってしまったし、ほかの授業に比べて何倍も大変な授業だったが、自分が大きく成長できた授業になったと思うので良かった。

トップ   編集 差分 履歴 添付 複製 名前変更 リロード   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS