名称 MIRS1303 ソフトウェア詳細設計書
番号 MIRS1303-SOFT-0001

最終更新日:2014.02.03

版数 最終更新日 作成 承認 改訂記事
A01 2013.02.03 飯塚・野村・杉山春樹 初版

目次




1.はじめに

本ドキュメントは、MIRS1303ソフトウェアの詳細設計について記したドキュメントである。

2.状態遷移図

プログラム全体の状態遷移図を図1に示す。
状態遷移の各要素は関数として作成し、条件を満たしたときに呼び出して使うようにした。

図1 状態遷移図

3.フローチャート

主要な関数の説明を以下に示す。


  • 巡回(宝の確認)
     宝の位置はあらかじめわかっているため、まず宝の位置まで直進と回転をして向かう。宝の有無を画像処理で確認した後、宝固有の番号をvoid capture_image(void)で読み取る。宝をひとつ確認するごとに座標を修正しながらすべての宝を確認する。

    図2 巡回(宝の確認)



  • 怪盗機の捜索
     あらかじめ設定した捜索コースを回る。
    その途中で赤外線センサが反応した場合、怪盗機を発見したと判断し、「怪盗機の追跡」に移行する。
    また、巡回中に別スレッドで前方の画像を取得していき、視界内に怪盗機がいた場合も「怪盗機の追跡」に移行する。
    途中で宝の盗難情報が更新された場合は、「盗難現場へ移動」に移行する。
     画像を取得する場所:
  • 小部屋の入り口
  • 機体が回転した後
  • 視界の開けている場所
  • 長い直線の途中


  • 図3 怪盗機の捜索



  • 怪盗機の追跡
     怪盗機を発見してから見失ってしまうまでずっと怪盗機を追跡する。
    怪盗機が近い場合は赤外線センサが反応する。赤外線の情報により怪盗機のいる方向を判断して、その方向に前進する。
    怪盗機が遠い場合は別スレッドの画像処理で得た進行方向へ向き、怪盗機が居るか判断する。
    ここで怪盗機が居る場合は「怪盗機の追跡」を続行し、追跡に失敗した場合は「捜索コースに復帰」に移行する。


    図4 怪盗機の追跡



  • 盗難現場へ移動
     まず盗まれた宝の位置を判断し、捜索コースを使って盗難現場の近くまで向かう。既に逃げられている可能性が高いため、周囲の画像を取得し、怪盗機を探す。
    怪盗機を発見した場合は「怪盗機の追跡」に移行する。現場到着までに発見できなかった場合は、「座標修正」を行った後、「捜索コースに復帰」に移行する。

    図5 盗難現場へ移動



  • 捜索コースに復帰
     現在位置から捜索コースに向かい回転と直進を繰り返す。捜索コースに合流した後、「怪盗機の捜索」に移行する。

    図6 捜索コースに復帰



  • 座標修正
     機体の正面と右側の壁を利用して、超音波の測定により座標を修正する。
    このとき、壁から本体までの距離が長い状態で補正をしても精度は得られないと思われるため、壁との距離が2マス以内の状態でのみ補正を行う。
    測定できない場合はエラーを返し、補正が完了しなかったことを知らせる。
    補正できる場合は、正面と右側の超音波センサを使って壁との距離を測定し、座標(current_x,current_y)を更新する。

    図7 座標修正



  • 画像処理
     走行中、常に前方の赤(もしくは青)、すなわち怪盗を検知できるようにするため、用意したスレッド(ball_find_thread)内で無限ループさせる。

    図8 画像処理



  • 4.関数一覧

    MIRS競技用に新しく作成する関数の一覧とその概要を以下に記す。
    表1 新規作成する関数一覧
    ファイル名 関数宣言 概要
    mirs.c int main(void) 各種スレッドの作成とドライバオープンを行う関数。
    junkai.c void junkai(void) 宝の確認を行うプログラム。競技前半の動作はこの関数に記述する。
    chase.c void chase(void) 怪盗機の捜索、追跡を行うプログラム。競技後半の動作はこの関数に記述する。
    run.c float run_straight_to(float x,float max_speed,double angle_ref,RunStatus* st) 直進走行時に呼び出す関数。
    ロータリーエンコーダと電子コンパスの値を用いてPID制御を行う。
    目標距離[mm],直進速度,指定角度[deg]、現在の走行状態を引数、走行距離[mm]を返り値に持つ。
    この関数を目標値に達するまで繰り返し呼び出す。
    float run_rotate_to(float angle_ref,float max_angle_speed,RunStatus* st) その場回転時に呼び出す関数。
    ロータリーエンコーダと電子コンパスの値を用いてPID制御を行う。
    指定角度[deg],回転速度、現在の走行状態を引数、回転角度[deg]を返り値に持つ。
    この関数を目標値に達するまで繰り返し呼び出す。
    coordinates.c void coordinates_correct(float current_x,float current_y) 自己位置の修正が必要になった時に呼び出す関数。
    角度の正対補正をした後超音波センサの値を用いて座標修正を行う。
    float型の推定位置座標(x,y)[mm]を引数に持つ。
    自己位置を修正する前後で座標推定を一時中断させる。
    void coordinates_guess(void) 自己位置の推定を行う関数。スレッドで常に呼び出す。
    ロータリーエンコーダで移動した距離、電子コンパスで現在の角度を読み取り、移動距離を推定する。
    センサスレッドで繰り返して呼び出し、一定時間ごとに現在位置を更新する。
    なお、現在位置は機体の中心を基準にして推定する。
    void coordinates_touch_center(float speed,float dir) 走行中に前方のタッチセンサが反応した場合に動作を行う関数。
    直前の走行の速度、指定角度を引数に持つ。
    怪盗機が前方に居る場合はこの関数は呼び出さない。
    void coordinates_touch_side(float speed,float dir,int side) 走行中に左右のタッチセンサが反応した場合に動作を行う関数。
    壁に当たらない程度に後退して、指定角度に回転する。
    直前の走行の速度、指定角度、反応したタッチセンサの番号(右、左)を引数に持つ。
    distance.c int distance(float x,float y,int dir) 指定したマス目の指定した方向の壁までの距離を調べる関数。
    測定可能な壁と指定したマスが何マス離れているかを返す。
    dirはスタートの向きを0、右側を1、後ろ側を2、左側を3として、4方向を指定する。
    mail.c void send_mail(int status) イベント発生時にメールを送る関数。
    発生したパターンごとに送る内容を変更する予定。
    compass.c float compass(void) 電子コンパスの値を受け取る関数。スレッドで常に呼び出す。
    float型(0から359.9[deg])の方位(スタートからの回転角度)を返り値に持つ。
    角度はスタート時正面を0[deg]基準にして、時計回りに正とする。
    mapping.c int mapping(void) コース情報を配列に渡すための関数。
    course.csvからデータ情報を読み取り、配列squareに値を代入する。
    stolen_thread.c void stolen_thread(void) サーバに接続して盗難情報を受け取るスレッド。
    盗難情報が更新されると、盗まれた宝の番号を更新する。
    capture_image.c void capture_image(void) コマンド"uvccapture"を実行するための関数。
    Webカメラで静止画像を一枚撮影し、保存する。
    ball_find_thread.c int ball_find_thread(void) 赤いボール、もしくは青いボールを認識するためのスレッド。
    撮影した画像を2値化し、赤もしくは青を検知する。
    入力画像を縦に4分割し、検出されたピクセルがどの領域に一番多いかの判断からボールの方角を決める。

    また、電子コンパスの通信用のプログラムは
    MIRS1301,1303,1304 I2Cマスターボード詳細設計書内4.3「プログラム」からダウンロードできるプログラムを用いる。

    5.共有変数一覧

    MIRS競技中に使用する共有変数の一覧を示す。
    表2 主な共有変数の一覧
    変数宣言 概要
    int uss[4] 超音波センサの値[cm]を保持する。
    char io_data[12] タッチセンサ、赤外線センサの値を保持する。
    RunStatus* st 走行状態を保持する変数。直進・回転開始前に初期化する。
    float angle 電子コンパスの値[degree]を受け取り保持する。
    float init_angle スタート時の電子コンパスの値[degree]を保持する。
    float current_x 現在のx座標[mm]を保持する。現在の座標は機体の中心を表す。
    原点は競技場の角を仮定している。
    float current_y 現在のy座標[mm]を保持する。現在の座標は機体の中心を表す。
    原点は競技場の角を仮定している。
    int stolen_num 最後に盗難された宝の番号を保持する。
    int square[i][j][data] コース情報から、各マス目[i,j]の情報を保持する配列。初期値はdata.csvに入力されている。
    data = [0-3]:各マス目の壁の有無情報
    data = [4]:宝に関する情報
    data = [5-8]:怪盗機捜索コースの方向、距離情報(2パターン)
    int direction 画像認識で取得した怪盗(ボール)の方向を示す値を保持する。
    direction = [1-4]:ボールの位置 (このときの1〜4を図9を用いて示す。)
    direction = [0]:ボール無し


    なお、画像処理(ボール)で判定するdirectionの範囲は以下に示す通りで、最も白が多い(色が識別されている)部分を怪盗の居る方向とみなす。

    図9 画像認識プログラムが返す"1〜4"の値の範囲



    実際の競技会に使用したプログラムを以下に示す。ただし、この詳細設計書とは異なる部分(実装できなかった、多少の仕様変更など)がいくつもあるため要注意。
    そして、走行系に関しては期待通りに動作する保障がない。

    MIRSAK.zip
    MIRS1303ドキュメント管理台帳