レスキューチャレンジという競技についての簡単な説明です。
Switch文を用いたプログラムの改良
障害物回避(赤外線センサ1個のロボット

レスキューチャレンジにおける重要課題の一つである障害物回避行動について、赤外線センサ(IRセンサ)が1個のロボットで、そのプログラムについて考えていきましょう。

左の図のロボットの形状は、実際に障害物回避をおこなう上では問題があります。角をなくして、障害物に引っかからないようにする必要があります。さらに、できるだけ広い範囲(ロボットの側面も含む)で障害物に反応するような工夫が必要です。ここでは、障害物回避の基本動作を確認することが主目的なので、アニメーションや実験ロボットの形状には言及しないこととしておきます。

障害物回避の仕方は、大別すると2種類です。
タッチセンサ(接触式センサ)で障害物を検知すると、あらかじめ設定しておいた回避経路をだどるものです。カタカナの「コ」の字のように、直進と直角ターンを組み合わせて進みます。この方法は、プログラムが単純なため、初めて障害物回避をおこなう初心者には向いていると言えます。ただし、一度回避行動を始めると、センサを使って状況を確認しながら進むわけではないので、予期せぬ動きをする場合があります。事前に、障害物の大きさやコース上での設置状況に応じて、細かな動作設定が必要です。

もう一つの方法は、回避動作中も、一定時間間隔で障害物との位置関係を確かめながら進む方法です。一般的には、競技会レベルではこちらの方法を採用することになります。アニメーションをよく観察すれば、どんな動きをしているかおよそ見当が付くことでしょう。

ここでの基本動作は、「タッチセンサが反応 → 後退 → 右転回 → 前進 → 赤外線センサで床面の状況を読み取り、黒色でなければ左旋回」をくり返しています。障害物回避動作を始めると、タッチセンサの反応を読むのは、左旋回動作中だけです。上記動作をくり返すうちに、赤外線センサが黒色の反応を示すので、そうなるとロボットの向きがラインと平行になるように姿勢制御をして、ライントレース動作に戻ります。障害物の右側から回り込んで回避する動作について、アニメーションで示しながら解説をしましたが、左側から回り込ませることも可能です。

ロボットの形状を工夫して、障害物に引っかかることがないようにし、さらにはタッチセンサの検知範囲を側面にまで広げると、ロボットは障害物に側面をこすりつけるようにしながら進み、小回りをします。また、このことで、ラインにほぼ垂直な状態で安定して戻ってきますので、その後の姿勢制御も比較的楽におこなえるはずです。



では、ここからプログラミング開始です。はじめに、ロボットの動作状態を考えてみましょう。

T.ライントレース
U.障害物を検知して、後退 → 右転回 → 直進
V.Uの後、黒色のラインを探して、左旋回
W.Vのとき、ラインを発見すると、ロボットがラインに平行になるように、右転回(または、右旋回)

上記の4つの動作状態に分けることができそうです。このことから、状態変数の取り得る値は4つとなります。
フローチャートは、下の図のとおりです。ここでは、状態変数に「mode」を使っています。余談ですが、mode(モード)という単語は、一般的には「流行」を意味する英単語ですが、コンピュータ用語では「状態」を意味します。

実際のプログラム(RDP−903による)は、ダウンロードして確かめてください。
ロボットの構成は次のようになります。
CN1・・・タッチセンサ,CN3・・・赤外線センサ
M1・・・右側のモータ,M2・・・左側のモータ
▲ このページのトップにもどる
SWITCH文を用いたプログラムの改善

if文を多用したプログラムは、時にはとても分かりにくいものになることがあります。とくに、if文の中にif文が入っている(通称、入れ子、またはネスト)場合は、インデントをすると右へ右へとプログラムが広がり、かえって見難いものとなります。

if文を全く使わないプログラムはあり得ないと言っても言い過ぎではありませんが、適切に使うべきです。プログラムを一生懸命につくっているときはいいのですが、少し時間を置いて見直してみると、自分でもどうなっているのか分からないことがあります。そうなると、不具合が見つかった場合、その修正作業は大変なことになります。

そこで、障害物回避のプログラムのように、整数値を取る状態変数によって条件分岐をする場合は、「switch文」を見やすく書き直すことができます。


この場合のフローチャートは上図のとおりです。

switch文」では、条件式の値は整数値に限定されます。

その記述形式は、
   switch(条件式){
   case 数値A:
      処理A;
      break
   case 数値B:
      処理B;
      break
   case 数値C:
      処理C;
      break
   default
      処理D;
      break
   }
となります。

条件式の値がAなら、処理Aを実行します。条件式の値がBなら処理Bを、条件式の値がCなら処理Cを実行します。条件式の値がいずれにも該当しない場合は、処理Dを実行します。今の場合は、状態変数「mode」の値は0〜3までの4通りなので、defaultは使用せずに、4つの値を明示する方がいいでしょう。

また、switch文の記述で注意することは、caseの最後はセミコロン(;)ではなく、コロン(:)を用いる点です。

さらに、case 数値A:
     case 数値B:
        処理C;
        break
と記述すると、条件式の値がA、またはBなら処理Cを実行します。これから分かるように、break;がないと、次のcaseも実行してしまうのです。

実際のプログラム(RDP−903による)は、ダウンロードして確かめてください。
ロボットの構成は次のようになります。
CN1・・・タッチセンサ,CN3・・・赤外線センサ
M1・・・右側のモータ,M2・・・左側のモータ
▲ このページのトップにもどる