2025年1月27日

021-2.SPIKEプライムヒント集-第7回「カラーセンサー1個で十字路を走破するには?」

この連載ではロボットコンテスト(ロボコン)で役立つロボット作りのヒントを紹介していきたいと思います。ヒントを実感しやすいように、ここでは競技風の「お題」を出します。お題をクリアするロボットを作ってみましょう。自分の手を動かすことが大切です。この記事では「レゴ エデュケーションSPIKEプライム(以下、SPIKE)」とSPIKEアプリ3を使用しています。(文/松原拓也)

◆ ポートが足りない問題を考える

前回はロボットで「十字路(交差したライン)」を走破する」というお題に対して、カラーセンサーを2つ使うということで解決しました。 しかし、実際にロボット競技でカラーセンサーを2つ使おうとすると、無理な時があるかもしれません。一概(いちがい)には言えませんが、ある程度、複雑なロボットになると、ライントレースに使えるポートは1つくらいしか余っていないような気がします。 そこで今回は「カラーセンサー1個で十字路を走破する」というお題に挑戦してみたいと思います。果たしてうまくクリアできるでしょうか?

ロボットは前回のものを使います。ラージハブに取り付けるパーツは次の通りです。
ポートA:カラーセンサー
ポートE:左モーター
ポートF:右モーター
カラーセンサーは1個だけにします。

競技フィールドは前回と同じです。
ルールも同じです。ロボットがスタート地点から出発したら、最初の十字路で右に曲がって、2番目の十字路で左に曲がり、ラインを抜け出したらゴールとします。

◆ 十字路を走破する方法を考える

十字路を走破する方法を考えてみましょう。
前回のプログラムは「ライントレースをする処理」「十字路をさがす処理」を2つ同時に行っていました。これはカラーセンサーが2つだから可能だったことです。カラーセンサーが1つの場合では「縦方向のライン」と「横方向のライン」の区別がつかないので、同時に処理することができません。
そこで、「ライントレース」と「十字路をさがす」処理を切り替えて行うことにします。ロボットの進んだきょりに応じて処理を切り替えます。

十字路を走破するプログラムを作ってみました(singlesensor1.llsp3)。プログラムの量が多いので、2画面に分かれています。これは1画面目です。
ライントレース用として「center」という変数を新たに追加しました。この変数にはカラーセンサー(反射光モード)の「白色と黒色の中間の値」を入れます。
十字路をさがす前に、まず3cmだけライントレースを行うようにしました。これでロボットの進む向きを直しています。

2画面目のプログラムです。
ライントレースとその場せん回のマイブロックです。前回と同じく「比例制御」を使ってライントレースを行っています。

カラーセンサー(反射光モード)の特性を確認します。
センサーをライン上(白と黒の中間の場所)に置いた状態では値は「75%」でした。この値を丸めて、変数「center」に「70」を代入することにしました。
センサーを十字路の上に置いた状態では「16%」でした。変数「black」には「20」くらいを入れるべきなのですが、センサーが反応しない場合が怖いので、少し増やして「30」を入れました。これにより、十字路に対して反応が良すぎる結果となります。

プログラムの実行中の様子です。
ライントレース中は「L」の文字が表示されます。これで「十字路を探す」処理に切り替わるタイミングを確認することができます。
ロボットが無事にゴールしました。もうこれでお題をクリアしたことにしてもいいのですが、まだまだ改良の余地があります。

◆ ラインをさがす処理を追加

ロボットの動きを観察してみると、おかしな点に気が付きました。2つ目の十字路で止まる直前で、ロボットがラインから大きくズレています。
ライントレースをしない時間が長すぎて、ラインとのズレがたまってしまうのが原因です。

ロボットとラインとのズレを無くしてみたいと思います。
そこで改良してみたプログラムがこちらです(singlesensor2.llsp3)。 変数「white」を新たに加わえました。この変数には床面の「白色」を判別するための値を入れます。

「find_edge」というマイブロックを追加しました。 このマイブロックでは、その場せん回を行って、床面の「白色」を探して、それから「黒色」をさがします。これを「エッジ検出」と名付けました。エッジ検出でラインのズレを無くすことができるでしょうか。

実行してみた様子です。
一応、ゴールすることはできました、、、が、問題があります。エッジ検出によってラインとのズレは減ったのですが、ひんぱんにその場せん回をするのでテンポが悪くなってしまいました。
その場せん回をすると、ロボットの向きが90度単位ではなくなってしまうので、動きが美しくありません。
良いアイデアに思えたのですが、エッジ検出は失敗だと思います。しかし、良いロボットを作るには、こういう試行錯誤が必要です。じゃんじゃん失敗しましょう。

◆ その場せん回での工夫

試行錯誤の途中で気が付いたのですが、 十字路を見つけてから→停止(その場せん回)するまでのきょりを見直してみましょう。 停止までのきょりを「タイヤとカラーセンサーまでのきょり」に合わせていたとすると、このようにその場せん回すると、センサーがラインの真ん中に乗ってしまいます。
このままライントレースを続けてしまうと、「真っ黒」の状態からスタートするので、ロボットの動きが不自然になります。ライントレースするなら白色と黒色の中間であることが理想です。

センサーがラインの右側に位置するようにするには、ロボットの停止位置をずらす必要があります。ロボットが十字路でどちらに曲がるかによって理想的な停止位置は違ってきます。 これは当然のことなのですが、気が付くまでに時間がかかってしまいまいた。
時計方向に曲がりたい場合には短めに進んでから止まる必要があります。反時計方向に曲がりたい場合には長めに進んでから止まる必要があります。

以上の点をプログラムに反映させてみたのですが、なぜかうまくいきません。これはロボットの停止位置を短く修正してみた場合の写真ですが、このように誤作動を起こすようになってしまいました。
方向転換する位置がずれてしまって、まっすぐ進めなくなって、「十字路を見つけた」という誤作動を起こしています。

修正後のプログラムです(singlesensor3.llsp3)。
問題の原因は変数「black」の値が大き過ぎて、せん回のタイミングが早すぎることでした。といっても値を直すと、十字路に反応しなくなる危険があるので、代りに停止までのきょりで調整しました。理屈通りなら一つ目の十字路は少し差し引いたきょりで止まるのが正解なのですが、0センチとしています。
ラインの読み飛ばしのあと、ちょっとだけライントレースを再開して、できるだけロボットの進行方向がズレないようにしました。

2画面目のプログラムです。
エッジ検出(find_edge)のマイブロックは削除しました。

プログラムの実行結果です。
無事にゴールしました。動きの不自然さが解消されました。ラインを読み飛ばす時に「プ」という音を出すようにしました。このように確認できるようにすると、問題を発見しやすくなります。
これでお題をクリアとしますが、まだ気になる点も残っています。処理の合間でロボットがいちいち止まってしまうのが不自然です。もっと流れるように動いて欲しいです。どなたか改良してみてはいかがでしょうか。

今回作成したプログラム(SPIKEアプリ3用)

当ブログの内容は、弊社製品の活用に関する参考情報として提供しております。
記載されている情報は、正確性や動作を保証するものではありません。皆さまの創意工夫やアイデアの一助となれば幸いです。