■センサーで目標を探す(KRS788使用)④
前回からの続きです。
4) ロボットを物体の方向に歩かせる
前回までで、目標の位置を特定することができました。今回は、ロボットが見つけた目標に向かって歩くためのモーションの分岐方法を紹介します。
・switch文でモーションを分岐
上記は、モーション分岐のプログラムです。読み取ったアナログ値の最大値の位置の番号は、前回説明したバブルソートによってadk[0]に代入されています。このadk[0]を元にどのモーション再生するか決めます。
switch (adk[0]){
case 0:
case 1:
case 2:
rcb3_motion_play(9); //左旋回2回
rcb3_motion_play(9);
break;
case 3:
・・・(中略)
case 8
rcb3_motion_play(9); //左旋回1回
break;
case 9:
rcb3_motion_play(3); //左サイドステップ
break;
case 10:
・・・(中略)
case 14:
rcb3_motion_play(1); //前進
break;
・・・(中略)
}
画像は、それぞれにモーション割り当てを図式化したものです。0~24までの数字は、adk[ ]に代入したモーションを読み取った位置の番号で、Left turnなどは再生するモーションの名前です。
(画像 クリックで拡大)
上記のプログラムと画像を見て、adk[0]が「3」だった場合を考えてみます。「3」は左側の緑のエリアの番号です。目標に向かうためには、記述のLeft turn(左旋回)を1回再生すれば、ロボットは目標へ向くことになります。
以上で「センサーで目標を探す(KRS788使用)」の説明を終わります。この方法を応用すれば、いろいろ自律ロボットを作ることができると思います。お試しください!
■センサーで目標を探す(KRS788使用)③
前回のプログラムの続きです。
3) どの物体が一番近いのかを求める
void search(void){ // アナログ値の読み取りとバブルソート
unsigned int i;
int s, t, tmp;
rcb3_motion_play(37); // 正面から左に向くモーション再生
wait(300000); // サーボが動ききるまで少し待つ
rcb3_motion_play(38, mesure_distance); // 180度旋回中にアナログ値を読む
wait(600000); // サーボが動ききるまで少し待つ
rcb3_motion_play(39); // 右から方面に向くモーション再生
wait(300000); // サーボが動ききるまで少し待つ
}
// ここからバブルソート開始
for(s = 0; s <= 7; s++){
for (t = s+1; t <= 8; t++){
if (adj[t] > adj[s]){ //adj[t]の値がadj[s]よりも大きかったら順番を入れ替える
tmp = adj[t];
adj[t] = adj[s];
adj[s] = tmp;
tmp = adk[t]; //adj[t] > adj[s]だったらadkも同じ処理を行う。
adk[t] = adk[s]; //最大値のアナログ値の場所はadk[0]に代入される。
adk[s] = tmp;
}
}
}
この関数では首を旋回する一連のモーションの再生と、最大値を求めるためのバブルソートの処理を行います。
・コマンド再生の特殊な使い方
rcb3_motion_play(38, mesure_distance) は、「モーション番号38を再生している間に関数mesure_distanceの処理を行う」という命令です。モーション番号38は頭部を180度旋回させるモーションなので、前回紹介したmesure_distanceの処理を同時に行うと、弧を描くように正面全体のアナログ値を検出することができます。
・バブルソートについて
バブルソートとは、複数の数値の中でどの数値が最も大きいかを求めるための処理です。rcb3_motion_play(38, mesure_distance)で読み取ったアナログ値をバブルソートにかけて最大値を求め、どこに目標があるのかを割り出します。
配列に代入されたアナログ値を2つずつ比べます。もし、ひとつ前の値より今の値のほうが大きかったら順番を入れ替えます。その際、そのまま大きい値を小さい値の配列番号に入れてしまうと、小さい値が消えてしまいます。そこで、小さい値は別の変数(tmp)に一時保存して、大きい値が移動した後に、大きい値がいた配列のところにもう一度小さい値を代入します。これを繰り返すと、最も大きな値が配列の先頭に来て、最も小さな値が配列の一番後ろに来ることになります。 (画像1)
(画像1 クリックで拡大)
アナログ値(adj[ ])が移動すると、読み取った番号(adk[ ])も同時に移動するので、adk[0]には最も高いアナログ値を読み取ったときの番号が代入されます。あとは、この番号にモーションを割り当て、分岐すれば、ロボットは目標に向かって歩き出します。
④へ続く
■センサーで目標を探す(KRS788使用)②
前回の続きです。
2) 頭部が旋回している間にセンサーの値を読み取る
・プログラムの解説
void mesure_distance ( ) // アナログ値を一定間隔で読み取る関数
{
unsigned int i;
wait(47370);
for(i = 0; i < 8; i++){ // 頭を一度振る間に9回アナログ値を読み取り、
adj[i] = ad7_read(); // adj[i]に代入していく
ledgrn_switch();
wait (47370); // アナログ値を読む間隔は47370
// 426330(約0.7秒) / 9 = 47370
}
adj[8] = ad7_read( ); // 最後の1回
for (i = 0; i <= 8; i++) { //読みとった場所の番号を0からadk[]に代入
adk[i] = i;
}
}
この関数はアナログ値を一定の間隔で読み取る処理を行います(画像)。この処理を頭部が旋回している間に行うことによって、ロボットの正面180°のどこに物体があるのかを知ることができます。
読み取るタイミングはwaitで調整します。正面で読み取ることを基準にして、左右がほぼ同じ角度を読み取るように調節してください。読み取ったアナログ値は配列(例ではadj[ ])に代入してください。
同時に、アナログ値を読み取った場所を、別の配列(例ではadk[ ])に代入します。この配列は次回の③で説明するバブルソートで使います。

(画像 クリックして拡大)
・自律ロボット実装例で頭部サーボがシリアルサーボになっている理由
アナログ値を読み取るタイミングを作るために、PWMサーボKRS788では時計を使って旋回時間を計り、waitを調整して読み取る角度を作らなくてはいけませんでした。この方法だと、正確な角度でアナログ値を読み取るために調整を繰り返す手間があります。
ところが、シリアルサーボは、正確に回転角を指定することができるため、角度や読み込むタイミングを調節する手間が大幅に減ります。プログラムで細かい角度を指定し、それを連続して命令するだけで物体を簡単に探すことができるようになるのです。
③に続く
■センサーで目標を探す(KRS788使用)①
ビーチフラッグや、自律バトル競技など、自律ロボット競技に参加するためには、目標を探す処理が必要になります。今回はKRS788を頭部に使用して物体を探すプログラムを解説します。
・目標を探すには
目標を探す方法のひとつに、頭部を旋回している間に一定のタイミングでアナログ値を読み取り、最大値を求めるという方法があります。PSDセンサーや超音波センサーは、物体が近いほど高い値を示します。ビーチフラッグや自律バトル競技の場合、フィールド上で最も近い物体が目標になる確率が高いので、読み取った値の最大値を目標と判断し、その方向へ近づくプログラムを組みます。

(画像1 クリックで拡大)
画像1はロボットが目標を探しているところを、上から見た図です。0~24の番号はアナログ値を取るタイミングと順番です。
・プログラム作成の流れ
1) 頭部を180°旋回させるモーションをつくり、その動作時間を計る
2) 頭部が旋回している間にセンサーの値を読み取る
3) どの物体が一番近いのかを求める
4) ロボットを物体の方向に歩かせる
・用意するもの
1) 頭部を180°旋回させるモーションをつくり、その動作時間を計る
・モーション作成
まず、首を180°旋回するモーションをHeart to Heartで作成します。下記の三つのモーションを作ってください。
- モーション①. 頭部を正面(ホームポジション)から左に向かせる
- モーション②. 左に向いた頭部を180°旋回して右に向かせる
- モーション③. 右に向いた頭部を正面(ホームポジション)に向かせる
モーションを3つに分けた理由は、アナログ値を読むモーション②を別にして、読み込むタイミングを正確に取るためです。
・モーション②の移動時間を測る
左に向いている頭部が右へ動きだしたところから、右に向いて停止するところまでの時間を計ります。計った時間を分割してアナログ値を読む取るタイミングを取ります。
②へ続く
■2008年KHR 4th アニバーサリー情報
毎年6月に行っているKHRアニバーサリーを今年も行います。その中で、今年はKCB-1を使った自律ロボット大会を開催いたします!
競技内容は、自律バトル大会とビーチフラッグです。
自律バトル大会は、今まで手動で行っていたバトルを全てプログラム制御で行います。
ビーチフラッグは対戦相手より先に旗を倒せば勝ちというシンプルな競技です。
自律バトル大会はオープンクラスとKHRクラスの二部門です。日時等の詳細はこちらか、下のバナーをクリックしてください。
自律という新しいステージを一緒に盛り上げましょう。皆様のご応募お待ちしております!

※KHR 4th アニバーサリーは終了いたしました。たくさんのご参加、ご来場誠にありがとうございました。
■自律ロボットデモムービー公開!!
自律ロボットビーチフラッグ大会に向けてムービーを公開します。
ムービー再生はこちらです。
ムービーが始まって最初に写るロボットはコントロール入力値(Autonomous_system_cc)でモーションを再生させています。連続歩行モーションが特徴です。起き上がり、旋回をしてある程度フラッグの方向に向かせたあとで、前進をさせています。数歩進んでフラッグを探し、見つけた後は首のふり幅を狭くするなど、状況によって動作を変化させています。
反対側に小さく見えるロボットはrcb3_motion_play(Autonomous_system_mp)で動作しています。連続歩行はできませんが、KCB-1がRCB3からモーション再生終了後に返事を受け取ることでモーションの間に無駄がなく、サクサクと動き回ります。
デモムービーの試合時間は約1分30秒です。
■自律ロボット作例
今回は自律ロボットの作例を紹介します。
使用センサー:
-
SHARP社製GP2D12 PSD距離計測センサー(頭部 x 1、 足部先端 x 2)
(現在はGP2Y0A21YK0Fが販売されております)
両足のセンサーで壁を検知し、頭部のセンサーで目標を探します。肩部の加速度センサーは起き上がりの分岐に使用しています。また、腰関節をピボットターンユニットに交換することによって、KHR-2HVの細かい旋回を可能にしました。
自律ロボットの詳しい情報はこちらをご覧ください。
<自律ロボット制作例マニュアル>
ビーチフラッグ用のサンプルプログラムも公開しています。下からダウンロードしてください。
<サンプルプログラム ダウンロード>
今大会はセンサーの制限はありませんので、競技レギュレーションに準拠していればどんなセンサーも実装可能です(*1。
フラッグ(目標)には超音波送信機を実装しています。この信号を頼りにフラッグの位置を認識するのもいいし、フラッグ表面の赤を認識して探すのもいいかもしれません。
*1 機体から超音波を送信することは禁止ですので注意してください。
■自律ビーチフラッグレギュレーション
ビーチフラッグ大会のレギュレーションを公開します。
レギュレーションを表示(PDFファイル)
試合時間3分以内に先に旗を倒したロボットが勝ちというシンプルな競技です。1vs1で1試合2ラウンド戦います。同点の場合は旗を倒すまでのタイムが早かったロボットが勝ちになります。
スタートラインでのロボットの設置基準や、競技フィールドの詳しい説明は「フィールド詳細」をよくお読み下さい。
フィールド詳細(PDFファイル)
ビーチフラッグは簡単に見えて、実は制御の基礎をしっかり学べる競技です。センサー情報によるモーション再生の分岐プログラムの構成や、シリアルサーボの制御など、きっと後々の応用に役立つでしょう。
フィールドはロボスポット常設のサッカーフィールドなので練習やシュミレーションを行うときには是非ご利用ください。また、近日、旗も設置予定です。
ロボットマンシップにのっとり正々堂々と戦いましょう!
レギュレーションの変更に関しましてはKCB-1サポートページにて随時発表していきます。