前回の記事の通り、クローラーの目はPSDです。

PSDの距離測定は精度がそれほどないとは言え、超音波センサなどと比べると小さな範囲を限定して測定するので、固定してしまうと探知できる範囲が狭く見回すことができません。そうなると、複数個搭載して周囲の障害物を探知するか、クローラー自身を超信地旋回(かっこいいw)させて周囲を見回す必要があります。
さらに、移動に関しては履帯を使った車両的なモノなので、自律ロボットとしてはなんだか寂しい感じがします。

そこで、PSDをサーボモーターで左右に首振りさせることにしました。
これで左右を見ることができます。クローラーより高さのある障害物の方角を探知できるはずです。ですが、渡ることのできない深さ、幅、の溝やテーブルの上などで動かした場合にはその縁など、左右を見回しただけではそれらを探知できません。そのままでは溝にはまるか、テーブルの下に落ちます。つまり、少なくとも足元を見るために下に首を振る必要が生じます。

ということで、PSDを上下左右にサーボモーターで振ることにします。
2軸でPSDの探知方向を制御するわけです。

2軸サーボ_PSD

しかし、2軸で振ると言っても上下方向にはあまり重要性はないと判断しました。左右X軸、上下Y軸、PSDによる測定の距離Z軸で3次元空間を把握する必要ない、ということです。
簡単に言ってしまえば、

クローラーは空を飛ばない。


から、ということですw。
とは言え、上下に首を振ることができるのはいろいろ可能性があって応用範囲が広がりそうです。これは今後のお楽しみということで、まずは左右首振りX軸とPSD測定距離Z軸の2次元平面上の障害物探知を考えてみることにします。

まず、最も簡単なものは、左右X軸サーボを等間隔の角度で回して単位角度毎にPSDで距離を測定し、最も近い障害物を探知し、それとの距離がある値以下、つまりクローラーの前進を妨げる距離以下ならば、障害物と逆の方向に進むようにArduinoにプログラムすればいいのわけです。

この方法は最もシンプルかつ有効に機能します。
必要な情報は、左右X軸に首を振った範囲のPSDが測定する距離の最小値だけがわかればいいからです。同様に最大値がわかれば、障害物のない方向もわかります。

しかし、今後の発展性を考えた場合、視覚として情報を持たせたいと考えました。
例えば、今後、クローラーに行かせたい場所を指示するような場合、周囲の障害物の状況がわかることで、距離の最小値や最大値の障害物以外、つまり、2番目に近い障害物、あるいは、2番目に見通しのいい方向などの情報が必要になる場合もあるでしょうし、さらには、クローラーが自身の探知した障害物をマッピングして再利用していく場合、単純な障害物との距離の最小値と最大値だけでは周囲の状況を把握するのに情報が不足することが考えられます。

と、理屈はいろいろありますが、


使える情報はなるべく1回の探査でたくさん保持しておきたい。


という貧乏性な欲望と、


曲がりなりにもロボットなんだからちゃんと視覚と言えるもので周囲を見てなくちゃいかん。



という理不尽な思い込みで、そうすることに誰が何と言おうと決めましたw。

と意気込んだわけですが、力技で簡単に済ませるなら、配列などを用意してPSDの距離測定値を最小値、最大値なんて言わず、回転単位角度毎に記憶させてしまえばいいわけです。(今思うと、この方法の方がいいような気がしてきましたw)

でも、ArduinoはATmega328でRAMは2kbyteしかなく、左右角と距離を一組で考えて2byte、サーボ回転単位1度角で20度~160度まで回すと240byte、上下角を入れると一組3byteで420byte、後々このデータを処理する手間がかかるなら、距離測定しながらデータの整理をしたいわけだし、今後の拡張を考えるとなるべくRAMを使いたくないなぁ、などと今思えばあまり力んだり考えたりしなくていいようなことをやってました。

どこをどう捻ったのか、その時の考えの前提として、

1)距離情報は1cm単位はいらない。せいぜい5cmくらいでよい、10cm単位でもおそらく大丈夫(クローラーの車体幅、長さが10cmくらいはあるから)

2)距離も重要だが障害物の幅がある程度わかれば方角のデータを圧縮したり、幅の情報を元にクローラーが通過できる場所を見つけることができるかもしれない。

今思えば、2)が元凶かもしれませんがサーボ回転単位1度角で20度~160度まで回すだけで、1120byteRAMを消費する状況になりましたw。が、データが整理されたことと新たに障害物の幅、あるいは見通しのよいクローラーが通れそうな場所の幅を考慮して選択することができるようになりました(苦しいw)。さらにはサーボ回転単位1度角という細かさは必要なくせいぜい5度単位でよいこともわかりました。もっと細かい角度で探査したい場合は一度大まかに探査した後に範囲を絞って探査させることもできますが、PSDの限界やサーボモーターの精度の問題もあり、あまり意味がなさそうです。

PSD方位距離データ解析

<クリックして拡大して見てね>


上記が障害物の幅、あるいは見通しの幅情報を付け加えてそこから方位角の個数を圧縮した形に処理し、データが生成されるまでの考え方をまとめた図です。

ArduinoのIDEはシリアル通信が簡単に使えるので、上記のPSDで測定され整理されたデータをモニターできるようにしました。

以下が結果ですが、まず、探査範囲に何も障害物が存在しない場合。

<各値の説明>
--min_max--
測定範囲の障害物までの最大、最小距離。前方中心は900=90度。
dis:距離(cm) x_ang:左右首振り角度0.1度単位を整数で表現1600=160度。y_angも同じ。
(注:0.1度単位なんて必要なかったorz)
(単純に測定した距離の最大、最小値をモニターしているので、首振りの方向に依存して最大値と最小値の角度が決定されている。この場合は20度から160度に方向にPSDを回転させている)

--result--
dis_area = 0~7:距離の範囲10cmm単位。0なら0cm~10cmまで。1なら11cm~20cmまで…。
x_ang = [x:左右x軸角度(障害物の幅)y:上下y軸角度]
(上下y軸角度は拡張して設けた。これで一応3次元な空間情報も格納可能。クローラー空飛ばないのにね(^^;;)

--short_range_search--
もっとも近い障害物で幅が広いものの選別結果(現状のクローラー行動指針として利用)
--targ_range_search--
外部から指示された目標物への方位にもっとも近く見通しのよい方向を選別(現状は90度に固定。事実上、指定された目標物への方位なし)

---min_max---
min: dis = 80, x_ang = 1600, y_ang = 850
max: dis = 80, x_ang = 1600, y_ang = 850
---result---
dis_area = 0 : x_ang =
dis_area = 1 : x_ang =
dis_area = 2 : x_ang =
dis_area = 3 : x_ang =
dis_area = 4 : x_ang =
dis_area = 5 : x_ang =
dis_area = 6 : x_ang =
dis_area = 7 : x_ang = [x:90(29)y:85],
---short_range_search---
Xang = 90, width = 29, yang = 85
---targ_range_search---
Xang = 90, width = 29, yang = 85

PSDの測定範囲を超えているので放射された赤外線は反射して戻ってきません。ですので、幅29で方位90度のデータひとつで事足ります。

次が、図で紹介した探査方法と同じように障害物を配置した場合。(もっとも近い障害物が図とは逆ですが)

---min_max---
min: dis = 22, x_ang = 650, y_ang = 850
max: dis = 80, x_ang = 1600, y_ang = 850
---result---
dis_area = 0 : x_ang =
dis_area = 1 : x_ang =
dis_area = 2 : x_ang = [x:55(7)y:85],
dis_area = 3 : x_ang = [x:120(4)y:85], [x:35(1)y:85],
dis_area = 4 : x_ang = [x:135(3)y:85],
dis_area = 5 : x_ang =
dis_area = 6 : x_ang =
dis_area = 7 : x_ang = [x:155(4)y:85], [x:90(7)y:85], [x:25(3)y:85],
---short_range_search---
Xang = 55, width = 7, yang = 85
---targ_range_search---
Xang = 90, width = 7, yang = 85


わかりやすいところで、注目して欲しいのは、

dis_area = 7 : x_ang = [x:155(4)y:85], [x:90(7)y:85], [x:25(3)y:85],

です。70~80cm以上の無限遠で25度、90度、155度にそれぞれ隙間の幅3,7,4とありますから25度と90度の間に障害物がひとつ、そして、90度と155度の間にひとつ、計2つ存在します。探査範囲内では幅は7が最大ですからここを選択して進むと障害物の間をすり抜けられる可能性があります。

障害物そのものは、25度と90度の間に[x:120(4)y:85]および[x:135(3)y:85]と、90度と155度の間が[x:55(7)y:85]および[x:35(1)y:85]が存在します。それぞれ円形の探査距離範囲(図参照)にまたがって存在するので分裂した障害物として認識されています。
(分裂した障害物の解釈など、ここらへんをどうするかは課題です)

ちなみに上下角が85度なのはやや下向きをPSDが見ている設定になっているだけで特に意味はありません。

総じて…。

ここまでこだわる必要性や意味があるのかどうかわかりませんが、このクローラー自体いろいろと可能性を試すためのテストベッドとしての役割があるので、いろいろな意味でよい勉強になりました。(まだこれからですがw)元々はハード屋さんでプログラムは素人丸出しですのでソースはご勘弁を。(どうしても見たいと言う方はコメント欄にその旨お願いします。その時のどうするか考えますw)

ここまで面倒くさいくて分かりにくいものをを読んでくださった方々(本当にそんな人いるのかなぁ)もしよければ、もっといい方法がある、とか、それはダメじゃないのかとか、忌憚なくコメントくださるとうれしい限りです。