詳しくは2019a/Mission3を参照してください。我々の班はロボットを2つずつ、別に動かして、容器に入ってる2つの球と容器の外の2つの球をそれぞれのロボットが回収する分担をしました。私と私のペアは容器の外の2つを回収するのを担当しました。2人で定義を共有し、それぞれ1個分の球を回収する分のプログラミングを書きました。2人の分を合わせてプログラムが完成します。具体的にどこが誰の書いた分かは、下の実際に動かしたプログラムで示します。我我2人が辿ったコースはA'-K'-L'-(1個目の球を回収と同時に発射)-K'-CBの間の線を通過-K-L(2個目の球を回収)-K-I'-(2個目の球を発射)、というルートです。†MQTT通信による連携を模索していたのですが、今回の課題は制作期間が短い上に、期末試験とかぶってしまったので時間が不足し、資料も不足していたので通信による連携をあきらめました。そのかわり、sleep関数による時間での連携を目指しました。具体的には両方のロボットのプログラムを同時に動かすが、片方はもう片方の作業の邪魔しない位置になるまでの時間分だけsleep()により停止します。お互いぶつからないように、片方だけ先に動かすということです。ロボットはいつも完全に同じ時間で作業を完了しないため、時間に余裕を持たせました。お互いの回収の成功率などを考慮しながら4人で話し合い、もう片方のロボットで最初にsleep()を入れることで合意しました。†ロボットの改修を最初はしていましたが、結果が出ず、結局、課題2とほとんど同じロボットになりました。あのままではピンポン球を回収できても、射出することはできませんでした。モーターもこれ以上増やせないので、一つのモーターで回収と射出を兼任させました。↑ピンポン球の位置エネルギーとモーターの加速により、カタパルトのように、レールに沿わせながらピンポン球を射出する。持ち上げて射出するまでの一連の動作は、レスリング技のジャーマンスープレックスやバックドロップのように後方に投げるイメージである。我々のev3は内臓のリチウムイオンバッテリーで動作しており、モーターやセンサーへの給電もこれにより行われる。このバッテリーの性能が非常に低く、満充電してもプログラムを実行すれば1、2回程度しかもたない。時間が非常に少ないこの課題の中で、この状態は非常に憤りを感じるものであった。プログラムのトライ&エラー、バグ修正の作業効率が極端に低下した。その上、全て時間経過でモーターを動かしているので、同じ時間でも出力によって動く距離が変化してしまう。これにより、位置調整が狂ったりするようになってしまった。バッテリーの出力の条件を一緒にするとそこまで再現性は低下しないが、ピンポン球を回収するアームの動作が非常に不安定であった。同じ出力にしていても、アームが自身の重さに耐えられなかったり、ピンポン球を吹っ飛ばすほど早く動くことなどがあった。この出力の不安定さには本番直前まで悩まされ、再現性を下げる最大の要因であった。原因は正確にはわかっていないが、バッテリーの劣化などが原因ではないかと推測している。容量が多く、劣化していないバッテリーが必要だと感じた。これも授業の予算の話などを聞いた後ではあまり強くは言えない。政府はもっと潤沢な資金を大学によこしてほしい。†ロボットを2つに分けてしまったので、今回の課題でもカラーセンサーが一つしかない。よってコースの黒線が測定エリア内にどれだけ入っているかによって動作を決定する。赤い円の中が測定範囲であり、黒の割合が多くなるほどカラーセンサの値が小さくなり、白の割合が多いほど値が大きくなる。これはカラーセンサが光の反射の度合いを測っているからである。実際の動作については、下の図の�のように、黒の割合が高いときは白が増えるように動き、�のように白の割合が高いときは黒の割合が高くなるように動きます。�で�と同じことをする。これらを交互に繰り返し、ジグザグに動きながら線の片側に沿って移動します。使用言語はPythonなので、この繰り返しはwhile文を使ってカラーセンサーの値の条件を満たせばこれらの動作を繰り返すようにする。要は、白にいきすぎたら黒に行き、黒に行きすぎたら白に行くことを繰り返すことで、少しずつ前進する寸法である。実際のライントレースのサブルーチンは以下のようになります。#カラーセンサーの値がcより小さい、つまり黒が多いと左前方に移動。このときスタート時刻は更新しないのが重要。#現在時刻−スタート時刻がtより大きくなる。黒の割合が多いコーナーだと、スタート時刻が更新されず、この差が大きくなる。これによりコーナーを検知し。モーターの動きが止まる。#カラーセンサーの値がcより小さい、つまり黒が多いと右前方に移動。このときスタート時刻は更新しないのが重要。#現在時刻−スタート時刻がtより大きくなる。黒の割合が多いコーナーだと、スタート時刻が更新されず、この差が大きくなる。これによりコーナーを検知し。モーターの動きが止まる。mR.stop()(説明)このサブルーチンを簡単に説明すると、1行目のx=time.time()で現在時刻を記録し、ストップウォッチのように時間を数え始める。白い部分にいる間はストップウォッチをリセットし、黒いところではリセットせず、白のほうに脱出してストップウォッチをリセットする。白のほうにいきすぎると、カラーセンサーでその状況を判断し黒に戻ってくる。黒にきたらまた白のほうに脱出しリセットする。白黒白黒の繰り返しである。雑なイメージで言うと、白にいるあいだは時限爆弾の残り時間が進まず、黒にいるときは時間が進む感じである。これでは永遠に白黒とループしてしまうのではコーナーでは、白に脱出するのに比較的長い時間がかかるのという性質を利用する。そのストップウォッチの値はコーナーのように黒が多いところでは、リセットができず、経過時間が大きくなる。よって、経過時間がある値に達したらそこは白に脱出しにくいコーナーであると判断する。これにより、コーナーを検知し、停止することができる。コーナーだと時限爆弾の時間が進んでしまい、時間が進まない白まで遠く、時間がかかるので、時間切れになり爆発してロボットが止まるイメージである。基本的にはライントレースのコーナー判定時間を短くし、境界線を黒側に寄せることである。コーナーを判定する時間を短くすると、当然、道中でコーナーと誤判定する確率が上がりますが、より確実にコーナーで止まりやすくなります。この誤検知の危険性と、停止する確実性の妥協点を探して調整しました。境界線を黒側に寄せると、コーナーについた際に、より、黒色が入る割合が増えます。同時に黒が多くないと止まらなくなるので、これも、黒を増やす割合と、コーナー判定の厳しさの妥協点を探すことになります。これら2つはt(second),c(cs.value())の2つの変数とし、コースの場所ごとに最適化することが何よりも大切です。今回の課題ではコーナーの数はそこまで多くなく、ライントレースも課題2で書いて、ほとんど失敗しないものを流用しているのであまり問題にはなりませんでした。今回の課題では時間がなく、二人でそれぞれ別のプログラムを制作している時間はなかったので、定義を共有して、プログラミングを分担しました。私のほうの定義は課題2で上手く動いていたので、定義は主に私のものを用いました。片方のロボットの邪魔をしないように撤退するまでを担当してもらいました。1人ではなく、複数で1つのプログラムを作り上げるという経験ができたのは非常に良かったです。これはピンポン玉を保持できない。アームの開放、ピンポン球の射出用に使う。t[s]で動かす時間、yで速度を指定。y>0ならアームは持ち上がり、y<0だとアームは下がる。#ピンポン球を回収し、モーターを固定することでアームを固定する。固定しないとアームは自重に耐えられず下がってしまい、ピンポン球を運んだり、ロボットの上に保持できない。stop_action='hold'であることが肝心。xでモーターの速度を指定し、tで時間を指定する。速度の正負による挙動は上のcatch_upと同様。#上のcatch_upで固定してしまったモーターを開放するためだけの関数。hold状態からout(脱出)するという意味。同名のプロレス入場曲が存在するが関係はない。#時間t[s]だけ前進する。whileうんぬんかんぬんは既述のライントレース関連の説明を参照してほしい。時間t[s]だけ前進する。whileループの条件を満たさなくなったら停止する。Motorは速度が正だと前方に行くように回転する、負だと後方に行くように回転する。#線の右側に沿って動き、コーナーを検知すると止まる。#線の左側に沿って動き、コーナーを検知すると止まる。#実際には使用していないが、プログラムから削除していないので掲載した。xに黒線を何回通過したか記録しようとしたが、上手く黒線で停止しなかった。これは移動スピードが速すぎた為、カラーセンサーの値の読み取りが間に合わなかったからだと思われる。結果としては、既述の移動用関数で位置調整することで問題の解決をした。#何回もデバッグする度にミディアムモーターがhold状態になっていることがあったので、開始条件をそろえるために開放する。#カラーセンサーの値を表示。これは毎回、読み取る値が異常になってないかどうか確認するためのもの。#前方にアームを展開するとピンポン球にあたるので、一旦下がる。#ピンポン球ー打ちー方はじーめ。ピンポン球を射出する。#コース用紙とコース用紙の境目まで移動し、もう一方のパートナーが作ったプログラムに後を任せる。ここからパートナーが作成しました。#Kの手前から線の左側に沿って動き、Kで停止する。#L'の手前からピンポン球を射出する。今回の課題では非常に時間がなかったうえに、バッテリーと出力に起因するトラブルに最後まで悩まされた上に、本番ではバッテリー切れにより大失敗してしまった。この燦燦たる結果は残念無念極まりないが、本授業で学んだ点は多かった。Pythonの基本にはじまり、ロボットの設計から動作させるためのプログラミング、制作スケジュールの管理、MQTT通信の紹介などなど。私は電子情報システム工学科の情報システムコースに進むつもりなので、今回の経験は将来に渡って非常に有意義であったと思う。放課後大学が閉まるまで残ってするデバッグに次ぐデバッグのつらさや、課題を達成したときの快感もわずかながら感じられた。これからも目標たる情報セキュリティの技術者を目指して精進していきたいと思います。ありがとうございました。