Crew(スカイクルー)の技術ブログ。技術の共有・伝達を目的に、ロボットに関するいろいろな情報やガイドを載せていきます。日本大会の懇親会にて人気者のkossanの隣で爆睡していた、篠川です。大会がひとまず一段落したので、またパラパラと記事を出していくつもりです。...今回は私たちが日本大会で使った、全方位カメラでの相手ゴール周りの認識方法をものすごくざっくり説明します。全方位ミラーを使う場合しか適応できない話が多くなりますが、ご容赦ください。カメラの仕事は、相手ゴールの認識と、自陣ゴールの認識に大きく分けることができます。この記事では前者についてです。一応言っておくと、これはあくまで私たちが私たちのロボット向けに書いたプログラムの流れを、参考になるかもしれないと書き下しているだけのものです。これは必ずしもベストとは限らないということです。ほかのチームにどれだけ当てはまるか、役に立つかは私もわかりませんし、もっといい方法も当然そのうち見つかるでしょう。参考としてお読みください。他にいいアイデアがあれば、ぜひコメントにお寄せください!「この部分をもっと詳しく・よくわからない」といったご意見もどんどんお願いします。内容カメラが「相手ゴール周り」で認識するのは以下のことです。自機が前の角にいるかボールを蹴りだしてよいかカメラは毎ループこれらを計算し、UART通信でメインマイコンに投げています。大まかにこの順番に、どういうことをしているのかを説明していきます。プログラムの書き方などはこの記事では扱いませんが、OpenMVに関してはIDEのメニューからFile→Examples以下のサンプルプログラムがとても参考になります。そのまま貼り付けて使用するのはルール違反ですが、プログラムの書き方、ライブラリの使い方を理解する助けになると思います。相手ゴールの方向まずは相手ゴールの検知をするところから始まります。全体的な方針として、角度を知りたいので、視野の中心、ミラーのてっぺんに当たる位置からぐるっと放射状に見ていきます。※画像左がロボットの正面OpenMVで色を認識するといったら普通はimage.find_blobs(thresholds)を使うと思いますが、ここではそこまでする必要はありません。カメラをロボットに乗せた状態で、PCで視野を見ながらゴールのすぐ前→遠くまでだんだん離していくと、(当たり前ですが)ゴールが遠ざかっていくように見えますね。ここで、下の写真の白い2円上をぐるっと見ていくと、その角度にゴールがあるなら、必ずその円上のどちらかの点がその色になっているはずです。(手書きの雑な図ですみません)ロボットが相手ゴールから背を向けるような向きになっている時はジャイロセンサーでまず正面(画像左)の向きに復帰する動きをさせるので、とりあえず前半分を回って確認していって、相手ゴールがあるかどうか調べていけばいいことになりますね。ひとつ前のフレームとそこまでゴールの見える位置が変わることはないはずと考えると、毎ループで180度すべてを見回す必要もなく、直前にゴールがあった位置のすぐ近くを探索すれば、すぐにゴールが発見できます。ある角度で黄色・青色のものを認識したとき、念のため+10度、ー10度の角度も確認し、干渉でないかどうか確認できます。周りに同じ色がなく孤立した小さなエリアはゴールではなく、ロボットのLED等の小さな部品が黄色・青色に見えているのだろうと判断できるからです。いうわけで、これによりゴールの左端の角度、右端の角度がわかりました。相手ゴールキーパー回避ゴールの位置が分かったところで、大抵はそこに相手ゴールキーパーがいます。イナズマイレブンでもあるまいし、真ん中のゴールキーパーめがけてシュートしたり、ドリブルで突進していっても切ないので、ついでに相手ゴールキーパーも認識して、避けるように進ませたいところです。いうわけで、ゴールがある角度を7つくらいに分割して、それぞれの角度で「中心からどれだけ離れたところでゴールの色が出てくるか」ということを調べます。中心から外側に向かって見ていって、最初に黄色・青色になるまでの距離を見るということです。ここで、平均から明らかに外れて距離が遠いところがあります。上の写真で黄色く十字が打ってあるところです。ここら辺を避けていくと、いい感じになりそうです。いうわけで、青の十字が一番長く並んでいる範囲に進めばよいですね。補足すると、単に「平均より少しでも遠くに十字があれば、そこには相手!」とするのは良くないです。コートの前側の角あたりにいてゴールの形が歪んでいたり、カメラの色認識に誤差が多少あったりすると、相手ロボット認識がいろんなところに出て荒ぶってしまうからです。多少のマージンをつけましょう。image.find_blobs(thresholds)はここらへんのところがごちゃごちゃにされています(よくわからん)。相手ゴールキーパーがいるところもざっくりまとめて「ゴール」と認識されてしまったり、そもそも全方位に向いていないということで、この関数は結局一箇所も使わないことになりました。ライブラリの関数はC言語で書かれてコンパイル済みになっており、Pythonで自力でループをまわして探して認識するより効率は良いはずなので、出来ればそちらを使いたいというのはあったのですが...シンプルにゴールの位置を探すだけなら、きっとimage.find_blobsが一番楽なのでしょう。ちなみに、去年の世界大会からは前向きにPSDセンサーを付けていて、正面の相手ロボットを認識してよけていくので、ドリブル時の敵よけはそちらにより頼るようになりました。斜め前などの相手ロボットを避ける、相手ロボットの背丈が低い・肉抜きがすごくてあまり距離センサーが反応しない、もともと距離が遠いなどであれば、カメラの働きは大きいです。コート前角検知こちらは簡単なのでさらっと。ゴールがめちゃくちゃ右・左に見えたら、それは自機がゴールに対して左・右にいるということです。ゴールが真横近くにあるなら、自機がコートの前の方の角にいるとわかりますね。相手ゴールの真横まで言ってボールを追いかけてもシュートにはつながらないし、角でアウトオブバウンズしたりゴールに引っ掛かったりすると、角は嫌なことづくしです。いうわけで、深追いせずに中立点の手前くらいまで後退し、アウトオブリーチやラックオブプログレスがかかるのを待つことにします。ゴールの端っこが相手キーパーで隠されたりすると多少ずれてしまいますが、そこはあまり深く気にしないことにしました。メインマイコンからジャイロセンサーの数値を送ってもらって、それを使って視界に映るゴールの角度を補正すると、割といい感じになります。ボールを蹴りだしてよいかここら辺はキーパー検知と絡んできます。ロボットの正面と、左右数度を見渡して、ゴールがあり、相手ロボットがいなければ、キッカーを発動していいよ、となります。メインマイコンは、ボールをキャッチした時、この情報をもとにキックするかを決めます。これが「キッカーNG」という判定であれば、まだシュートせずに、相手ロボットの回避をがんばりつつドリブルしていくことになります。その他の補足・小ネタカメラ(OpenMV)を使っているうちに気が付いた、本記事に関連するいくつかのことを、何かのために書いておきます。FPSPCにつないでカメラを走らせているときは、FPS(メインループが1秒で何周するか)を見ることができます。IDEであれば右下にFPSというものが映っているはずです。IDEに付属しているサンプルプログラムも、FPSを表示させるものがほとんどですね。実は過去、後先考えずに相手ロボットの認識プログラムを書いていた時、気がつくとこれが5とか6になりました。ループごとに間隔が0.2秒くらい空いてしまうことであり、さすがに...という話になりました。やって処理をショートカットして楽にするか、またどこの精度を落として手を抜けるか考えるのも大切そうです。Bufferを表示させるだけで、通信でなかなかの時間がかかります。Buffer用の通信をしなくなるので、よりPCにつないでいないときに近いFPSを確認できます。IDE側でFPSを表示してくれなくなるので、サンプルプログラム通りにclock.fps()をprintしてみるのがよいと思います。ちなみに現在の最新プログラムのFPSは30弱です。実はこれでも割と頑張った。errorOpenMVのメモリは実をいうとけっこう貧弱なようです。memory"系のエラーが出て途方に暮れました。それから衝撃的なことに、静的変数を多く使用する、400行くらいになったプログラムをOpenMVに書き込み、実行させたとき、プログラムが長すぎてメモリに載りきらずに、エラーが出たり、ビジー状態になって手に負えなくなったりしました。PCにつないで給電された際に、書き込んだプログラムをメモリに読み込み、さらにPCから「このプログラムを実行してくれ」と流し込んだことにより、400行プログラム2個分を読み込むことになっていたようです。Worldレベルの短いプログラムを一回だけ実行させてからだと、いったんメモリの中身がリセットされるのか、その直後長いプログラムをPCから実行してもエラーを吐かないことを発見しました。Pythonプログラム中の半角スペースをTabで置き換えるのも地味に大きいです。これ1000行とか行ったら実行できなくなりそうだな...通信ほとんどの場合、メインマイコンに比べるとカメラのFPSはずっと低いです。通信でデータを投げるペースが全く違うので、メインマイコンでループ毎にカメラからの情報が来るまで待ち受けていると、それにメインマイコンの処理全体がものすごく足を引っ張られることになります。メインマイコン側では「データが来るまで待つ」ではなく、「データが来ていたらなくなるまで受け取る」とするのがよさそうです。一つ重要な点として、print()をPCとつないでいないときに呼び出すと、秒単位で遅くなります。passとか書いておきましょう。相手ロボットが黄色や青の部品を積んでいたり、LEDが青色に見えたりすることがあります(私たちもあまりほかのチームのことを言えないところはあります)。多少の小さなもので影響を受けないような仕組みにすることも大切です。なにかとびとびで小さく変な黄色・青色(・オレンジ色)のものを検知したら、ゴール(・ボール)と区別し、弾いてしまいましょう。試合が始まる前に相手ロボットをしっかり見ておくのも大切です。まとめここまで、実際にどうプログラムを書くのかという部分は全ておいておいて、「なにを行っているか」ということを書いてきました。雑でわかりにくいところもあると思うので、ご指摘、ご質問はどんどんお願いします。流れを書いたので、「この部分をもっと詳しく知りたい」というような意見は大歓迎です。自陣ゴール周りの仕事やキーパーの動きについても、そのうち記事を書きたいと思っているので、よろしくお願いします。Tweet2019/05/05プログラム公開&アンケートこんにちは。GitHubに現在のプログラムをすべて公開していますので、良かったら参考にしてください。ライブラリ自分用のバックアップのためコミットメッセージ等は適当なので、そこは気にしないでください。時間があれば(たぶんない)解説記事も書こうかと考えています。質問等あればコメント欄やTwitterでお願いします。参考にしていただけた場合、コメント欄等で教えていただけると嬉しいです。プログラム関係の記事で書いてほしいことについてアンケートのご協力をお願いします。Tweet2019/05/04日本大会の動画kossanです。4/27〜29に行われたロボカップジュニアジャパンオープンの試合動画をYouTubeにアップしました。以下のリンクからご覧いただけます。(日付と大会名を修正しました。JapanOpenまた、得点シーンの一部(ちょっとかっこいいやつ)を集めたダイジェスト動画、失点シーンを集めた失点集も作成しました。試合の解説などなど記事を書きたいですが、如何せん世界大会まで時間がないのです。記事を書けなくなるかもしれませんが、ご了承ください。RoboCupJunior2019皆さん、お久しぶりです!SYです。更新が止まっており、申し訳ありません。4/27(土)~29(月)に、ロボカップジュニア・ジャパンオープン2019和歌山に出場しました。本日はその結果報告だけ先にすることにします。各試合の解説記事も後日出しますので、お楽しみに。3回オウンゴールが少し多かったことと、マカオシュートを何回か決められてしまったことが反省点のひとつです。アウトオブバウンズが何回か起きてしまったのはラインの角でラインセンサがうまく反応しなかったことが原因だと思われます。故障はカメラの不具合やジャイロのリセット忘れが原因です。ジャイロのリセット忘れのような人為的ミスは防げるものなので、試合前には焦らないことが大切です。大会の様子64チームが参加。去年と参加チーム数は同じのようです。調整用コートはビギナー用1台とライトウェイト、オープン用3台がありましたが、1台はコートの色が少し違ったせいか少し空いていました。用意された試合用コートはA~Kの11台です。技術委員会のブログに書いてあるスケジュール通りに試合等は進行していきました。全6回のスイス式トーナメント。6チーム(9.4%)チーム数も多く、ライトウェイトとオープンを交互に行うため、試合と試合の間には1時間ほどの調整時間がありました。昼休みもちろんそんなものはない決勝リーグ6チームで総当たり戦。10分弱5試合連続で試合を行うため調整時間がほとんどなく、かなり大変でした。忙しくて更新が止まることもありますが、どうか長い目で見守ってください。