二足歩行ロボットコミュニティサイト

【サイトの使い方】  【サイトマップ】  【お問い合わせ】 
ロボット動画  |   ロボット写真  |   BBS  |   ダウンロード  |   イベント予定  |   スタッフ日記  |   リンク  |  
ログイン パスワード    新規登録   パスワード紛失  

 

第8回 自律バトルモーションの作成(後編)

さて、引き続き後編です。しばらくまとまって執筆する時間が取れそうにないので、今回は特別に小出しで更新していきます。

ちなみに、Robovie-XとRB2000の自律動作は下記からダウンロードできます。
記事を読み進める上で参考にしてください。
●Robovie-X自律バトルモーション
●RB2000自律バトルモーション

思考ルーチンの考案

プログラム作成を始める前に、まずロボットがどうすれば自分で考えて賢く行動できるかを把握しておかなければいけません。
まず、ロボットの行動パターンを決める「思考ルーチン」を考えます。

今回のセンサの構成から、非常に大まかに下記のような流れのプログラムを作成したいと思います。

自律プログラムの大まかなフローチャート

探査アルゴリズムなどを細かく説明すると長くなりますが、大まかに上記のようなパターンで自律バトルが成立します。

では、これを実際にRobovieMakerで作るとなるとどうすれば実現できるのでしょうか?
まず前提として、動作中に「センサの値を確認し、状況によって行動を分岐させる」ということが必要になってきますね。

幸いなことにRobovieMaker2ではモーションの最中に変数の値を確認して、任意の条件で動作を二手に分岐させることができます。ということはこれを使えばよいのでしょうか?
今回作成する動作が、ポーズ数がせいぜい10〜20位の規模の小さいものであれば対応できますが、何せバトルモーションです。必要な動作は「前後起き上がり」「攻撃」「歩行」「旋回」など少なく見積もっても、一つのモーションにまとめると非常に規模が大きくなります。

そこで、「センサの値を確認し、状況によって行動を分岐させる」もう一つの手段として、操作マップV2を使います。
操作マップV2もRobovieMaker2で追加された機能の一つで、従来の「ボタン入力を判断してモーションを再生する」操作マップV1から、「ボタン入力を含めた任意の変数の変化を任意の条件で判断してモーションを再生する」方式に拡張された操作マップですね。

ちなみに操作マップV2の詳しい解説は過去の回を参照してください。

モーションと操作マップV2で可能な条件分岐設定はほぼ同じなので、今回は「ポーズを省いた条件判断部分をモーションで行う」「実際にモーションを呼び出す条件分岐を操作マップV2で実装する」という構造で作っていきます。

変数の確認・準備

実際のモーションを作成する前に、今回使用する変数を確認しておきます。
あらゆるプログラミングに共通しますが、基本的にプログラム中で使用する変数はプログラムを作成する前に確認しておき、後でごちゃごちゃにならないようにメモしておくことが重要です。
(そうは言ってもプログラム中につい想定外の変数が必要になりその場で急遽追加してしまうのが人間なのですが)

今回の解説ではRB2000の自律バトル設定に準じて行います。こちらで自律動作用に設定されている主な変数は下記の通りです。

・130:転倒検出(加速度センサ値)取得(Robovie-Xの場合は129になります)
・146:PSDセンサ値取得

これらは前回でも見ることができますね。動作中は上記の変数にセンサの値が常に格納されます。

・80:状態記録変数

この変数の役割については後でも説明しますが、前述の「実際のモーション再生を操作マップV2の条件で行う」を実現するため、アイドリングモーションでの分岐の結果をモーションの外に持ち出す必要があります。そこで、分岐先に任意の番号を割り振り、各分岐の最終点で状態記録変数として設定した変数にその分岐の番号を書き込めば、アイドリングモーションは終了しても最後に選ばれた分岐先は記録しておけます。

最低限の自律動作はこれら三つの変数でも実現可能ですが、更に下記のような変数を準備することで動作を高度化できます。

・77:探査角度設定無効変数
・78:探査角度設定変数
・79:汎用カウンタ

これらの変数は探査処理をより高度化するために使用します。一旦は「後で詳しく使う」程度で気に留めておいてください。

基本的な設定

ここまで長々と説明してきましたが、理論ばかりではなく実践していくことでより理解が進められます。
まず、非常に簡単な骨組みとして下記のような動作を作成してみたいと思います。

「ターゲットを正面遠距離に発見したら歩いて近づく」
「ターゲットを正面至近距離に発見したら攻撃する」
「倒れたら起き上がる」

前述の説明の通り、まずは「実際のポーズ部分を除いた条件分岐などの骨組みをアイドリングモーションの中で実行する」という部分を作成します。

フローチャート通りに捕らえると、「モーションを開始したらまず加速度センサの値を確認して転倒検出を・・・」と考えますが、今回のプログラムでは転倒検出は操作マップV2側の条件分岐で行います。理由は後述しますが、操作マップV2に組み込むほうが、より確実で早く起き上がり動作を再生できるためです。

では、モーションでは起き上がりの条件分岐を飛ばして「PSDセンサによるターゲットの認識」を行います。
前回説明したとおり、PSDセンサの値は対象物との距離が近いほど大きい数値になります。
数値の範囲はだいたい700〜3000程度で、ロボットの形にもよりますが、遠距離であまり誤認識をせずにターゲットを発見できる数値が約1300以上、また、攻撃が届くほどの至近距離は約2300以上の値が目安です。

その通りに分岐ブロックの作成・設定を行うと下記の通りになります。
なお、今回は、お使いのロボットの正面に実際にターゲットを置いてみて、適切なセンサ値を調べてください。

モーション中のPSDセンサによる動作分岐

まず「ターゲットが至近距離に存在するか」を判断し、条件がNOであれば「ターゲットが遠距離に存在するか」を判断します。
それぞれの分岐ブロックの「YES」の側にはモーションを再生させるギミックがつながります。ターゲットが遠距離なら前進して接近し、近距離なら攻撃するようにします。
また、どちらもNOであれば図のようにENDにつながります。

つづいてモーションを再生させるギミックを作成します。「変数の確認・準備」の項目でも説明したとおり、今回設定した「変数80:状態記録変数」に、分岐先の番号を記録します。今回はターゲットが至近距離なら「1」、ターゲットが遠距離なら「2」をそれぞれ書き込むように設定します。

状態記録変数に分岐先の番号を記録

これで一旦アイドリングモーションの作成を終了します。つづいて、「前進」「攻撃」のモーションを作成したいと思います。
これらの動作はサンプルなどに含まれる歩行・パンチモーションを流用しても問題ありませんが、自律動作に組み込むモーションには必ず「変数80に0を代入する」という演算ブロックを入れてください。

状態記録変数に分岐先の番号を記録 状態記録変数に分岐先の番号を記録

このように分岐結果に応じて一つの動作を実行した後は状態記録変数を初期化しないと、操作マップV2の条件分岐設定により一度発動したモーションをずっと繰り返してしまう場合があります。
また、状態記録変数の初期化は、なるべくモーションの先頭に入れてください。

モーションの作成が完了したら、今度は操作マップの設定を行います。操作マップV2では、下図のように設定を行います。

状態記録変数に分岐先の番号を記録

まずアイドリングモーションに先ほど作成したPSDセンサによる条件分岐のモーションを設定します。
そして、アイドリングモーションの分岐結果で記録される状態記録変数80に対して、実際に再生するモーションを条件付けしていきます。
変数80の値が、「閾値=」の条件で「1」と同じになった場合には、「攻撃」にあたるモーションを割り当ててください
また、変数80の値が、「閾値=」の条件で「2」と同じになった場合には、「接近」にあたるモーションを割り当ててください

これで、アイドリングモーションの再生結果に応じて任意のモーションを実行するようになります。

また、先ほど省いた起き上がりモーションの設定も行います。
加速度センサY軸の変数130(RB2000の場合)の値が一定以下の場合にうつ伏せ起き上がり、一定以上の場合に仰向け起き上がりを設定します。
このときのセンサの値は、実際にロボットを前後に倒して調べてください。

なお、後でプログラムを実行した際に、起き上がり後すぐに連続して起き上がりモーションを実行してしまう場合は、起き上がりモーションの最後に長い時間で基準ポーズを入れ、直立待ち状態を作ってください。

そして、うつ伏せ・仰向けの起き上がりモーションに対して「アイドリング割り込みキャンセル」の設定を有効にします。
idling割り込みは使う機会が少ないのでどのようなものかわからない人も多いかと思いますが、これは「アイドリングモーションを再生中のときだけ、条件が成立したらキャンセルがかかる」設定です。
これを設定すれば、比較的動きが安定したアイドリングモーションを実行している時のみ、転倒を検出したら割り込んですぐ起き上がりを実行しますが、アイドリング以外のパンチなど激しい動作をして加速度センサが転倒を誤認識してしまった場合でもキャンセルがかからず動作を続けます。

すべての設定が終わったら、操作マップを保存してロボットに書き込んでください。

プログラムの実行

プログラムを実行すると、ロボットの正面にターゲットを置くと、遠距離であれば前進して接近し、近距離であれば攻撃を出すようになると思います。
また、ロボットを倒すと自分で転倒状態を認識して立ち上がると思います。
ただし、まだまったく調整していないため、かなり見当違いな動きをすることも有ります。また、ターゲットが正面以外にあっても探しにいきません。

本格的な自律動作を作成する際は、この状態から更に細かい条件分岐を作成してより高度なアルゴリズムに仕上げていきます。

探査ルーチンの作成

ここまでで作成したプログラムには、正面にターゲットが見つからないと何もできないという問題がありました。
そこで、ターゲットが見つからない場合は自ら動いてターゲットを探す動作を組み込みたいと思います。

では、どのようなプログラムを作成すればよいのでしょうか?
最も簡単な方法は、「何も見つからない場合、一定方向に少しずつ旋回する」という手段です。これなら、ロボットの現在位置を中心にPSDセンサの検出範囲内にターゲットが存在すれば認識することができます。

しかし、この方法には、「ターゲットの発見が遅くなることが多い」「旋回動作自体が不安定要素となる」などの欠点があります。
前者は、例えば旋回方向の反対側にターゲットが存在する場合、わざわざ一周近く回らないとターゲットを発見できません。
また後者は、旋回動作を作りこまないと常に現在位置がずれずに一定の角度で回れる保証ができない、旋回動作中に体が揺れてターゲットの検出が鈍る、動作自体に隙が大きくバッテリの消耗や転倒の可能性が高くなるなどが上げられます。

自分自身が回転してターゲットを見つける

そこで、RB2000及びRobovie-Xに存在する首ヨー軸を利用して、体を回転させずに前方180度を探査する方法をとりたいと思います。
具体的には、下記のように直立状態で左右に首を振って前方約180度を見渡し、ターゲットを発見したらそちらの方向に何らかのアクションを起こすという形にします。

首だけを回して前方180度を検索

ここでポイントとなるのは首の回し方です。単純に首を回すだけならモーションで簡単にできますが、ここでは「首をゆっくり回して、ターゲットを見つけた次点で監視を中断して何らかのアクションを起こす」という具合に、いわばポーズの途中にキャンセルをかけるようなことを考えなければいけません。

これを実現するための方法として、「変数演算で首の角度を調整する」というものが有ります。これまで講座では「アナログスティックの傾きを首の角度に反映させる」など、ポーズ以外での関節の動かし方を紹介してきましたが、今度はユーザ変数に首の角度値を設定して、それを変数演算で動かすという形になります。

具体的な方法としては、まず前項に登場した「78:探査角度設定変数」を設定します。こちらが先ほどの「首の角度を設定する変数」になります。
使用する変数を決めたら、首のサーボモータ出力式を下記のように設定します。

首ヨー軸の角度を設定する変数

ここの77番の変数は「77:探査角度設定無効変数」として前項に登場しましたが、要するに変数演算による首の回転を有効にするか否かを切り分ける変数です。
今回の設定では、この変数に256を設定すれば78番の変数で首を動かすことができるようになります。

これで、変数演算で77番の変数に256を入れた状態にして、モーション中で変数演算により78番の変数に数値を代入すると首ヨー軸を動かすことができるようになります。

では、具体的な探査モーションはどうすればよいのでしょうか?
前述の通り首を少しずつ動かしていくことになるので、いわゆるプログラミングの「for文」と同じように、何十回かに分けて変数78に数値を少しずつ加算(減算)していく方法になります。

RobovieMakerで「for文」のような繰り返しを行う方法は、第2回 RobovieMaker2でのモーション作成(後編) で説明しましたね。
繰り返し回数のカウンタとなる変数を1つ設定し、変数演算で1回のループごとに回数を加算(減算)して、分岐ブロックで規定回数に達したかを確認するというプログラムになります。

その途中でターゲットを発見した場合、繰り返しをすぐに中断して次の行動に移ります。
ここでポイントなのは、中断した瞬間の変数78の値を調べることで、ターゲットまでの角度がわかるということです。
単純なポーズの指定による首の回転の場合は、良くて自分の左右どちらにターゲットがあるかが確認できる程度ですが(それでもタイミングを逃す可能性が非常に高いです)、変数演算と繰り返しを用いたこの方法なら、「余計な動きをする必要がない」「関節をちょっとずつ動かしながら確認できるのでターゲットの認識を取りこぼしにくい」「発見次第すぐに次の行動に移ることができ、そのときのターゲットとの角度も調べられる」とかなり高度な動きができます。

ここまでの説明を具体的にプログラムに当てはめると下記のようになります。

首ヨー軸の角度を設定する変数

ここでは、79番の変数をカウンタとして使い、「2step(=2/60秒)停止して78番の変数の値を200ずつ変更する」という動きを30回繰り返しています。
途中でPSDセンサの値(変数146番)を確認し、ターゲットを発見次第、その距離に応じて次の行動にジャンプします。

30回の繰り返しなら片側にせいぜい45度程度までしか動かないので、繰り返し回数を増やしてもっと深い角度まで検索できるようにしたほうがよいです。
これで一方の90度にターゲットが見つからなければ、変数78を0に戻してからつづいて同じようなプログラムを作成し、変数78に先ほどとは符号が逆の値を加算して反対側の検索を行います。

ちなみに、RB2000の自律動作では上記繰り返しを4つ準備して、「相手が右前方45度以内に存在するか」「相手が右前方45度以上に存在するか」「相手が左前方45度以内に存在するか」「相手が左前方45度以上に存在するか」という形で、ターゲットに対する行動を大きく4通りに分けています。
例えばターゲットが左右45度以内に存在した場合、旋回ではなく前進で近づきます。そして左右45度以上の場所にターゲットがいる場合は向きを直します。
このように細かい場合わけをすることで、ロボットの動きが高度になります。

ちなみに、前方180度を検索してターゲットが見つからない場合は、「旋回」や「歩行」などの動作を行なって検索する場所を変えるようにします。

ループブロックは使えない

ここまで大事な点を説明し忘れていました。
自律で使うモーションには、基本的にはループブロックが使えません。
自分で作った自律プログラムで、ターゲットに近づくために「前進」などを組み込んだ人はわかると思いますが、この場合1歩だけ前進してすぐに立ち止まるか、一度歩き出すと止まらなくなるようになります。

これは下記の理由によるものです。
通常、操作マップでループブロックが含まれている場合、そのモーションを呼び出した状態が持続する限りポーズの繰り返しを行います。
例えばボタンを押しっぱなしにすることで歩き続けるのも、これによるものです。
ところが、自律動作で変数の番号でモーションを呼び出された場合、モーションの最初で状態記録変数を初期化すればループが1回で終了し、逆にモーションの最後で初期化するならモーション中にそこまで到達せずにループを永遠に繰り返してしまいます。

このため、RB2000の自律モーション一式では、あえて「1歩前進」や「3歩前進」のように歩数をあらかじめ決めた歩行モーションを作成して、ターゲットとの距離に応じて再生させています。

ちなみに、もう少しプログラムを複雑にして変数を組み合わせると、「任意の変数をカウンタにして、変数に代入した数だけ歩行を繰り返す」というモーションを作成し、ターゲット探査の際にターゲットとの距離に応じて変数に歩数を入れておけば、一つの歩行モーションで柔軟に歩数を調整できます。

Robovie-Xの自律モーションが、ちょうど上記のような方針で行っていますね。
こちらは構造を単純にするため、あえてまったく同じ動作で繰り返し回数のみ変更したモーションを複数用意して対応していますが、考え方を理解できた方は改造に挑戦してみてください。


前のページ
第7回 自律バトルモーションの作成(前編)
コンテンツのトップ 次のページ
第9回 MP3プレイヤーボード「VS-IX009」を使う


検索
Loading
メインメニュー