名称 MIRS1202 ソフトウェア詳細設計
番号 MIRS1202-SOFT-0002

最終更新日:2012.11.9

版数 最終更新日 作成 承認 改訂記事
A01 2013.1.28 初版


目次





1.はじめに


本ドキュメントは、MIRS1202のソフトウェア開発詳細設計書である。

2.ファイル構成、状態遷移図、フローチャート

以下にMIRS1202内のファイル構成を示す。
    /MIRS1202
    ├img 画像処理関連のプログラムソースファイル
    |├exit_detect.c
    |├noisecut.c
    |├cv_main.c
    |├threshold.c
    |├labeling.c
    |├select_number.c
    |└DB_knoc.c
    ├main 総合的に扱うプログラムソースファイル(標準プログラムを流用したもの)
    |├initialize.c
    |├introduction.c
    |└correction.c
    ├original 総合的に扱うプログラムソースファイル(新規に作成したもの)
    |├original_main.c
    |├kobeya_control.c
    |├rotary_control.c
    |├judge_state.c
    |├irs_ts_ws_thread.c
    |├timer_thread.c
    |└main (プログラム実行用のシェルスクリプト)
    ├motor モーター制御用のプログラムソースファイル
    |├original_motor_thread.c
    |├mk_motor.c
    |└motor_func.c
    ├talk 音声出力用のプログラムソースファイル
    |├talk.c
    |└talk_main.c
    ├test テスト用のプログラムソースファイル
    ├uss 超音波センサ系のプログラムソースファイル
    |├uss_thread.c
    |├serial_func.c
    |└uss_get.c
    └output ファイル出力用のフォルダ


システム基本設計書のものから改訂を行った状態遷移図を以下に示す。
状態遷移図

主要なプログラムのフローチャートを以下に示していく。
まずはメイン関数。これは、上記の状態遷移図に則ってループを回し、それぞれの関数を実行している。
メインループ

次に、鍵・扉攻略プログラムのフローチャートを示す。
ここでは、鍵の攻略部分のみ掲載したが、扉(1つ曲がり角を見逃す)部分については、鍵の攻略をし終えた時点で、自動的に通路走行中に行われるようになっている。
鍵・扉攻略

最後に、小部屋とロータリー攻略プログラムのフローチャートを示す。
障害物攻略中は、通路走行時と同じくタッチセンサ、白線センサ、超音波センサの監視も行っており、「壁に当たる」「I/Oerror」などのエラーが走行中に起きた場合でも、自動的にメインループ中の修復動作に移行し、修復後はその途中の動作からやり直せるようになっている。
小部屋攻略

ロータリー攻略


3.関数、共有変数の定義

新規で作成した関数を以下の表にまとめる。
ファイル名 関数宣言 概要
/original/original_main.c int original_main(void) メイン関数。switch case文を用いて、14個の状態を状況に応じて遷移させる。
static void straight(void) 通路走行関数。マルチスレッドを用いて、計3つの超音波センサの値とロータリーエンコーダ値を参考にしながら直進走行をする。また、超音波センサに合わせてタッチセンサ、白線センサもスレッドで動かし、状況判断を行う。
static void timer_straight(void) タイマー走行関数。超音波の取得を行わず、タイマースレッド、タッチセンサスレッドを用いて走行する。設定した時間後に停止し通常の通路走行関数へ移行。
static void motor_restart(void) モーター動作中にmotor_restart_flagが"1"(I/Oerror)となった時にこの関数に移行し、現在のロータリーエンコーダー値の保持→motor_restart→1つ前の状態へ移行の順で修復動作を行う。
static void r_restore(void) 右タッチセンサ接触時の修復動作。モーター動作中にr_ts_flagが"1"となった時にこの関数に移行し、現在のロータリーエンコーダー値の保持→数センチ後退→反時計回りに数度回転→correction()→1つ前の状態へ移行の順で修復動作を行う。鍵攻略時は別の動作。
static void l_restore(void) 左タッチセンサ接触時の修復動作。
static void r_turn(void) 曲がり角での右折動作。通路走行中に壁が消えたと判断した時(主に超音波による判断)に、mk_motor関数を用いて、左タイヤのみで右折する。
static void r_return(void) 右折動作のやり直し。r_turn中に左右どちらかのタッチセンサが触れた場合、その時のロータリーエンコーダ値を参考にして、右折前の状態にもどって前進or後退を行った後再び右折動作を行う。
static void l_turn(void) 曲がり角での左折動作。
static void l_return(void) 左折動作のやり直し。
static void db(void) ダイレクションボード読み取り動作。DB_knock関数を用いてダイレクションボードを読み取り、obstに次の障害物の番号が代入される。読み取りが失敗した場合数cm後退する。成功した場合はそれに応じた状態へ移行。
static void key(void) 鍵攻略関数。obst=2のときに前タッチセンサが反応した時実行され、数cm後退して180度回転する。終わった後は、一回だけ曲がり角を見逃すように、uss_thread内の変数を操作する。
static void rotary(void) ロータリー攻略関数。超音波センサ、画像処理の両方によりロータリーに侵入したと判断した時、rotary_control関数を実行する。
static void kobeya(void) 小部屋攻略関数。前方を含めた超音波センサの値により小部屋に侵入したと判断した時、kobeya_control関数を実行する。
static void goal(void) ゴール関数。白線を連続して認識後、前進する。
void fclose_open(char) 各ファイルポインタを閉じてまた開く関数。
/original/kobeya_control.c void kobeya_control(void) 小部屋攻略関数、この中でもswitci case文でstepわけされており、小部屋動作中でもメインループの修復動作への移行が可能。基本超音波センサを用いた左の壁伝いで攻略していく。
/original/rotary_control.c void rotary_control(void) ロータリー攻略関数、この中でもswitci case文でstepわけされており、ロータリー動作中でもメインループの修復動作への移行が可能。画像処理でロータリーの出口を見つけ出し、近いほうに右or左の壁伝いで攻略していく。
/original/judge_state.c void judge_state(void) mainループの通路走行関数を抜けるときに呼び出される状況判断関数、その時に立っていたフラグ、超音波センサ値を参考にして、その次に移行する状態を判定する。
void flag_reset(void) すべてのフラグを"0"にリセットする関数。
/main/initialize.c void initialize(void) 初期化関数。各スレッド、ファイルディスクリプタ、ファイルポインタの初期化を行い、/output 下にある4つのファイルの内容を読み込み、状況変数に代入する。読み込みが失敗すれば、introduction1()を実行し、成功すればintroduction2()を実行する(プログラムが再起動されたかどうかの判断)。
/main/introduction.c void introduction1(void) 通常実行時(シェルスクリプトで/output 下の4つのファイルを消去しての実行時)、走行開始直前に実行する関数。エスケープシーケンスを用いて書かれた文字をコンソール出力し続け、MIRSの前タッチセンサが反応したら関数を抜け、「発進します」の声とともにmain関数の通路走行を開始する。
void introduction2(void) 再起動時、走行開始直前に実行する関数。5秒間待機し、MIRSの前タッチセンサが反応しなければ関数を抜け、「復活」の声とともにmain関数の通路走行を開始する。もしタッチされれば、プログラムを終了する。
/original/irs_ts_ws_thread.c void irs_ts_ws_thread(void); タッチ、白線センサ監視関数。スレッドで実行され、正面、左右側面のタッチセンサ及び白線センサが反応したとき、それに対応したフラグ変数を"1"にする。
/uss/uss_thread.c void *uss_thread(void) 超音波センサ監視関数。スレッドで実行され、左右の壁との距離を繰り返し測定する。壁との距離が急に離れたり、何回か続けて大きな値を取得したときに、そこを曲がり角と判断し左右の壁の状況を表す変数を"0"にする。逆に、壁との距離が近ければ"1"となる。また、測定した超音波の値を用いてのPID制御ができるようにこの関数内で演算し、そのPID制御値を共有変数に代入する。
/original/timer_thread.c void timer_thread(void) 時間監視関数。スレッドで実行され、start_time 設定時刻からの経過時間を秒刻みで共有変数に代入する。
/motor/original_motor_thread.c int motor_stop_thread() モーターの回転を停止させる関数。
void *original_straight_thread(void *arg) 通路走行用モーター制御関数。uss_useによって設定された超音波の値と、ロータリーエンコーダの値を参考にしながらPID制御で直進を行う関数。スレッドで実行され、センサやタイマーの機能を使いたい場合には、そのスレッドを同時に生成する必要がある。引数arg[]の、0番目で走行スピード、4番目でタイマー使用時の制限時間が設定される。
void *const_straight_thread(void *arg) 指定距離直進させる関数。超音波の値を用いず、ロータリーエンコーダの値を参考にして、一定距離直進を行う。スレッドで実行され、センサやタイマーの機能を使いたい場合には、そのスレッドも同時に生成する必要がある。引数arg[]の、0番目で進ませたい距離[mm]("+"で前進"-"で後退)、1番目で走行スピード(13〜122)、4番目でタイマー使用時の制限時間[sec]が設定される。
void *const_rotate_thread(void *arg) 指定角度回転させる関数。ロータリーエンコーダの値を参考にして、一定角度回転を行う。スレッドで実行され、センサやタイマーの機能を使いたい場合には、そのスレッドも同時に生成する必要がある。引数arg[]の、0番目で回転させたい角度[deg]("+"で反時計回り"-"で時計回り)、1番目で回転スピード(13〜122)、4番目でタイマー使用時の制限時間[sec]が設定される。
void *const_circle_thread(void *arg) 指定距離旋回させる関数。ロータリーエンコーダの値を参考にして、一定距離旋回を行う。スレッドで実行され、センサやタイマーの機能を使いたい場合には、そのスレッドも同時に生成する必要がある。引数arg[]の、0番目で旋回させたい角度[deg]、1番目で旋回スピード(13〜122)、2番目で旋回半径[mm]、3番目で旋回方向("1"で反時計回り"0"で時計回り)、4番目でタイマー使用時の制限時間[sec]が設定される。
/motor/mk_motor.c void *mk_right_turn(void *arg) 攻めの右折を行う関数。ロータリーエンコーダの値を参考にして、左のモーターのみを用いて右折を行う。スレッドで実行され、センサやタイマーの機能を使いたい場合には、そのスレッドも同時に生成する必要がある。引数arg[]の、0番目で右折距離[mm]、1番目で右折方向("1"で左モーター前回転"-1"で後ろ回転)、4番目でタイマー使用時の制限時間[sec]が設定される。
void *mk_left_turn(void *arg) 攻めの左折を行う関数。ロータリーエンコーダの値を参考にして、右のモーターのみを用いて左折を行う。スレッドで実行され、センサやタイマーの機能を使いたい場合には、そのスレッドも同時に生成する必要がある。引数arg[]の、0番目で左折距離[mm]、1番目で左折方向("1"で右モーター前回転"-1"で後ろ回転)、4番目でタイマー使用時の制限時間[sec]が設定される。
/main/correction.c int correction(void) 正対補正を行う関数。MIRS左側面の2つの超音波センサの値を用いて、正対補正を行う。演算には三角関数を用いている。戻り値は、正対補正成功時に"0"を、正対補正失敗もしくは超音波センサの値が想定外のものであったときに"-1"を返す。
/img/exit_detect.c int exit_detect(void) ロータリーにおいて出口を画像認識で行う、返り値はミルスの位置を時計の6として3、9、12で表される
/img/noisecut.c viod noisecut(void) 数字認識において迷路の壁より上の不特定な部分を塗りつぶす
/img/cv_main.c int cv_main(void) 数字認識の関数
/img/threshold.c int threshold(void) 2値化する
/img/labeling.c int labeling(void) ラべリングを行う
/img/select_number.c int select_number(void) 数字の判別を行う
/img/DB_knoc.c int DB_knock(void) 数字認識をして優先事項に従って方向を返す。

共有変数一覧
変数名 説明
ws_lock_flag int タッチセンサ、白線センサスレッドの中でも1のときは白線を読まない
ts_exit_flag float タッチセンサスレッドを抜けるフラグ
sp_time int タイマー開始時の時刻から現在の時刻の差が入る変数
r_uss_wall_flag int 右の超音波センサの値をとって壁がなければ0
l_uss_wall_flag int 左の超音波センサの値をとって壁がなければ0
f_ts_flag int 前方のタッチセンサが壁に触れたら1
r_ts_flag int 右のタッチセンサが壁に触れたら1
l_ts_flag int 左のタッチセンサが壁に触れたら1
r_ws_flag int 白線センサが白線を読んだら1
motor_restart_flag int I/Oエラーが出たらモーターリスタートを行う
const_flag int モータースレッドが指定された値通りに動いたら1
time_end_flag int 指定時間経過後1
uss_exit_flag int ussスレッドを抜けるフラグ
timer_exit_flag int タイマースレッドを抜けるフラグ。
obst int 次に来る障害物の数字を示す
step int swich-caseの各動作の段階を示す
r1_def int PD制御に使用する壁との距離を示す
l1_def int PD制御に使用する壁との距離を示す
l2_def int PD制御に使用する壁との距離を示す
kobeya_exit_flag int 小部屋を抜けたら1
uss_use int ussでどの超音波を使用するか指定する
10で左の前、01が右、11が左右と前方、20が左の前後、21がすべてのセンサの値をとる。
x_r_tmp,x_l_tmp,x_r_tmp_keep,x_l_tmp_keep int モータースレッドのロータリーエンコーダ値の引き継ぎ
rotary_center int ロータリーに入った時の真ん中のポールとの角度のずれを示す。
motion_param[5] int モータースレッドで使用するパラメータを決定する
rotary_flag int ロータリーに入ったことを認識する
time_t start_time int タイマー開始時の時刻を示す
uss_pid int PID制御値をモータースレッドに渡す
obst_keep int 障害物の値を保つ

4.プログラム詳細

実際に競技で使用したプログラムを以下に示す。

MIRS1202.zip



沼津工業高等専門学校 電子制御工学科