2024年11月7日
001-1.ロボットの基礎-第6回「自分で考えるロボットをつくる」
レゴマインドストームNXT(以下、NXTと呼びます)を使ったロボット作りの基本的なノウハウを紹介していきます。この連載は今回が最終回です(「ちゃれんじ教室」はまだ続きます)。連載では「ロボット競技に出られるレベル」を目標としてかかげてきましたので、最後を飾るにあたり、それに見合うような自律性の高いロボットを作りたいと思います。(文/松原拓也)
◆ 超音波センサを使ってみる

写真は前回に紹介した「ものをつかむロボット」です。このロボットは10cm手前にある物体しかつかむことができませんでした。ロボットが自分で考えるという要素が少し足りていません。
そこで、今回は超音波センサを使って、ある物体がどんな距離にあっても自動的につかめるように改良したいと思います。
果たしてうまくできるでしょうか?

こちらが、「コップを自動的につかむ」プログラムです。もし正しく動けば、コップが一定の距離に近付くと自動的に手が閉じるはずです。逆にコップが遠ざかると手が開きます。
超音波センサを読み取るためには「NXT前方距離X」と「NXT逆距離X」という命令を使いました。「NXT前方距離X」はセンサが「しきい値」よりも大きくなるまで処理を待つ命令です。逆に「NXT逆距離X」はしきい値よりも小さくなるまで待つ命令です。
しきい値の初期値(デフォルト値)は20cmに設定しています。
[Download]コップをつかむプログラム(RoboLab2.9用)

プログラムを実行してみました。
コップをロボットに近づけると手を閉じる……はずですが、どうも様子がおかしいです。
とっくに20cm以内に入っているのに、手が開いてくれません。コップを近付けて、やっとつかんだかなと思ったら、すぐに手が開いてしまいました。
◆ 超音波センサの特徴

ついでながら、超音波センサについてよく考えてみましょう。
RoboLabでは実行中、センサの値をインテリジェントブロックの画面で確認することができます。この表示によると、センサの感度が落ちていて、距離が長めに(値が大きめに)出てしまうことが分かりました。さらに値が不安定でバラついています。

センサの状態はRoboLabにある「検出(SCOPE)」という機能でも確認することができます。

超音波センサとは超音波を出して、その反射(時間)から距離を求めるセンサです(ちなみに超音波というのは、周波数20kHz以上の人間の耳に聞こえないくらいの音のことです)。つまり、「音」がちゃんと反射しないとセンサが動きません。表面が平らなもの、固いもの、面積が大きいものだとセンサの感度が良く、距離が正確に出ます。

コップの場合だと表面が丸くて小さいため、超音波がうまく反射せず、センサがうまく動かないことがあるようです。これは予想外の事態です。

この問題については対策してみたプログラムです。複数回センサを測定して、センサの読みのがしを減らすというものです。写真のプログラムでは15回測定して、1回でも反応があったら、「反応あり」とサブルーチンの結果を返しています。
ただし、プログラムがちょっと複雑で、そのわりに効果が見られなかったので、後に作ったプログラムには取り入れませんでした。なので参考までに留めてください。
[Download]コップをつかむプログラム2(RoboLab2.9用)
◆ コップを探す

さらにプログラムを改良して、ロボット自身がコップまでの距離を検出するだけでなく、方向も検出できるようにしてみたいと思います。

ただし、超音波センサは正面の距離しか測れません。そして、方向を検出する機能はありません。そこで、方向転換(信地回転)を続けて、ロボットの正面にコップがくるように動く必要があります。

ここで初めて登場するのが分岐命令です。分岐命令は関数パレットの「ストラクチャ」→「分岐」をクリックすると出てきます。

分岐命令とは処理の枝分かれのことです。入り口が1つ対して、出口が2つ。ある決めた条件によってどちらか一方を選択します。
たとえば、写真のような分岐では、超音波センサの求めた距離が20cm以下なら下の処理が選ばれ、21cm以上なら上の処理が選ばれます。このように分岐命令を使うことによって、ロボット自身が条件判断をすることができるようになります。
なお、分岐した処理は「分岐合流」という命令で1つに合流させないといけません。プログラムのさいに注意してください。
◆ 分岐命令を使ったプログラム

写真が「コップを自動的に探してつかむ」プログラムです。
処理をいったん止めたのは、コップをつかんだまま止めておきたかったからです。そして、人が手でコップを取り上げることで、処理が再開するはずだからです。
[Download]コップを探してつかむプログラム2(RoboLab2.9用)&

方向転換や前進などを制御するプログラムは分かりやすくするためにサブルーチンにしました。
サブルーチンは「サブルーチンを作る」命令で作ることができます。作成したサブルーチンは「サブルーチンを実行」という命令で実行できます。
サブルーチンの中身は前回(第5回)に紹介したものとほぼ同じです。サブルーチンは最大で8個まで作って登録することができます。登録してサブルーチンは0~7までの番号で管理します。

ロボットのプログラムの機能を箇条書きにまとめると次のようになります。
- 超音波センサの値が25cmより大きい(遠い)だと45度の方向転換をします。
- 超音波センサの値が16cm~25cmの範囲だと10cm前進します。
- 超音波センサの値が15cm以下だと手を閉じます。その場合、センサの値が35cmより大きくなるまで処理が止まります。
距離の測定と方向転換、前進を繰り返すことでコップに近付くわけです。

実際にプログラムを実行してみました。
手は閉じた状態で実行させてください。手はプログラムの実行直後に開きます。
ロボットは45度単位に方向転換し続けます。そして、センサの距離が25cm以下だとロボットは10cmほど近付きます。

15cm以下だと「コップに近付いた」と判断して、手を閉じます。うまくいくとコップをつかむことができます。

コップを外すと手を開いて、またコップを探し始めます。
◆ 効率的にコップを探す

現在のプログラムだと、関係ないところにまで向きを変えてしまいますので、動きにムダがあります。そこで、特定の方向だけに方向転換に範囲をしぼりこんでみたいと思います。

これが出来あがったプログラムです。どこが変わったか分かるでしょうか?
変更した部分は「コップが見つからなかった場合」の処理です。前回では左に45度回転するだけだったのに対して、こちらでは右にも45度回転します。
[Download]コップを探してつかむプログラム2(RoboLab2.9用)

つまり、新しいプログラムでは向きを左右に交互に振るのです。まず、黄色コンテナの値を0→1→2→3→0→1→2→3のように0~3の範囲で循環させます。次に分岐命令によって、コンテナの値が1以下だったら左回転、2以上だったら右回転させています。これによって右に45度、左に45度、合計で90度の範囲を交互に方向転換させることができます。
実際にプログラムを動かしてみると、うまく、左右に向きが変ったのですが、コップをうまく検出できず、その場で留まうことが多くなってしまいました。
原因は方向転換の量が多すぎて、超音波センサが働いていないためのようです。
◆ より細かくコップを探す

そこで、もうひと工夫して、角度をさらに細かくしてみました。
22.5度ずつの方向転換を左4回、右4回に割り振りました。検出の範囲は同じく90度です。

方向転換のサブルーチンを修正します。プログラムの変更箇所は矢印のところです。

黄色コンテナの値は0~7の範囲で循環させます。値は0から始まり、1つずつ増えていき、7よりも大きくなったら0に戻します。値が3以下だと左回転、4以上だと右回転させます。
[Download]コップを探してつかむプログラム3(RoboLab2.9用)

プログラムを実行させてみました。
前回よりも、うまくコップを見つけられるようになりました。
しかし、コップをつかむところでは失敗が多いようです。コップをつかんだ直後、「コップが無くなった」と間違って認識してしまい、手を開いてしまうことが多いようです。
他にコップを素早く取り外してしまうと、手が閉じたままになってしまうことがあります。これは超音波センサがエラー(距離が遠すぎる)となり、前回に測った距離がそのまま残ってしまうためです。
あと、コップをつかむ時、手が閉じきれてないという場面がありました。手のモーターは角度制御ではなく、時間制御にしたほうがいいかもしれません。
[Movie]ロボットが動いているところのムービーです。
まだまだ改良の余地があるかと思いますが、以上で基礎講座は終了です。ロボット作りには終わりがないなと思い知りました。今後の参考として役立ててみてください。
次回からはRoboLabのプログラム方法について、より詳しく紹介したいと思います。
当ブログの内容は、弊社製品の活用に関する参考情報として提供しております。
記載されている情報は、正確性や動作を保証するものではありません。皆さまの創意工夫やアイデアの一助となれば幸いです。