知能ロボットコンテスト’99 ロボット製作資料No1 – R.U.R.

知能ロボットコンテスト’99 ロボット製作資料

作成 de JM4LFA 99.5.27


FOR628.C または T98.C 等のソースファイルで使用されている関数について簡単な解説

関数解説










arm() アーム制御関数です。引数は、ARM_UP,ARM_DOWN,OPEN,CLOSE,STOP_ARM
の5つです。アームはハードウエアでリミットスイッチを用いた、ドライブ回路なので、ソフトウエアで、地面に接地したかどうか判断できませんので、十分に時間を取って待ちましょう。
wait() unsigned int型を用いたソフトウエアループによるウエイト関数です。よって引数は、正の数で、最大65535です。
pokeV25reg() 割り込み関数をつかうことを許可するときに使用します。ロボットスタート時に呼び出します。
ppi_init() 8255を初期化します。プログラムの最初あたりにこの関数を呼び出すだけでOKです。引数はなし。
timer_init() これは割り込みのサンプリングレートを変えたいとき意外は、しらなくていい関数です。スタート時あたりに引数なしで呼び出すだけでOKです。なにも変更しなければ、1秒間に20回、sampling()関数が呼び出され、位置計算等が行われます。
sampling() ソフトウエア割り込みによって、1秒間に20回呼び出される関数です。標準の機能は、ロータリーエンコーダーを読みとり、その値を用いて、iti()関数により、現在位置を計算させます。位置計算された結果は、グローバル変数にセットされます。そこでプログラマは、その値をもとに、目標速度を表す、グローバル変数に目標速度(1/20秒ごとのロータリーエンコーダーのカウント値)をセットさせる関数を自作し、このsampling()関数から呼び出してください。その後、speed_control()関数によって、目標速度に追従するPI制御計算され、モーターへの操作量がグローバル変数にセットされ、motor()関数によって、モータがPWM速度制御され、ロボットが動きます。詳しい説明は、後述してます。
speed_control() 引数は、そのときのロータリーエンコーダーのカウント値です。PI速度制御によりモーター操作量を目標速度(iTargetVelo_r、iTargetVelo_l)をもとに計算し、グローバル変数 iMotorOut_r、iMotorOut_lにセットします。とくにこの関数については、変更の必要はないと思います。
motor() 引数はint型で、-416から+416までです。マイナスならモータは逆回転します。PWM速度制御です。第1引数が左モータ、第2が右です。通常は、PI制御計算された操作量をしようするので、motor(iMotorOut_l,iMotorOut_r);のままでOKです。
iti() 現在位置計算関数です。引数は、ロータリーエンコーダーカウント値です。計算結果は、グローバル変数 x,y,arg に代入されます。座標系は、スタート時のロボット位置のロータリーエンコーダー軸の中心点が(0,0)で、角度は、最初が0ラジアンです。詳しいことは現在不明。後ほど報告します。

なにをかんがえればいいか?

ロボットは20分の1秒ごとの現在位置、向き(多少の誤差あり)がわかっているので、それをもとに左右のモーターの目標速度を設定するだけです。(この場合、その変数に数値を代入するだけで、勝手にPI制御関数が追従してくれる)

具体的には、ある目標地点にたいして、どのようにして近づくか?です。

たとえば、目標地点と現在の位置がずれていて、まず、ロボットの角度を修正して、あとは、直進とか。(この場合、近付くにつれ、角度の誤差が拡大されるし、近付けば近付くほど、角度の修正は難しくなります。)


参考までに昨年の方法をかいておくと、ロボットがほぼ直線で数メートルすすめることを仮定して、目標地点との距離を√(x*x + y*y)でなくて、この場合なら y  として、(x方向にある範囲からはみ出なければ、)、yの値を係数倍したものを左右のモーターの目標速度として、与えています。制御の言葉で言うと比例制御、P制御というのかな? で、横方向は無視できないほどはみでちゃった場合は、はみでてすぐなら、1cmくらいしかはみでてないので、はみでたほうのモーターを多めにまわすとか。(ここは、どうしてたか覚えてないです)


がんばれーーーー!! (^ ^)/


知能ロボットコンテスト98ロボット「つみたて君」のプログラムの

フローチャートみたいな。

まずは、main()関数から追っかけていくとしよう。(割り込み起動関数は後回し)

  1. 各種関数初期化
  2. アームを持ち上げて。(あげるまでの間しばらく待つ)
  3. 後ろのドアを閉じて。(しまるまでちょっとまつ)
  4. PI制御の係数を初期化
  5. ホストコンピュータの画面を改行しまくって、きれいにして、Start OK と表示
  6. コンピュータBoxの蓋にある、ロータリースイッチが1になるまで待つ(0以外になるとロボットスタート)
  7.   ロボットが完全に静止するまで待つ(人間によって動かされている間はとまっとけ ということ)
  8. 割り込みを許可する
  9. 無限ループ(この後にも、かいてあるけど、たぶん実行されることはない)

main()関数で割り込みを許可したけど、どうなるの?

うーん、それはね、main()で初期化した関数で timer_init() って関数があるでしょ。それが、20分の1(変更可能だよ)秒ごとに、 sampling() って関数を呼び出す仕組みになってるんだ。

じゃあ、以下に sampling() 関数の流れ図(?)を示そう。4~8は重要なので、表示を変えてあります。

  1. ロータリーエンコーダーの値を保存する変数を宣言
  2. ロータリーエンコーダーのカウント値を読みとって、変数に代入
  3. そのカウント値をもとに、現在位置を計算する。 iti() 関数がそれ。現在位置は、グローバル変数に保存されてるよん。






4. 行動命令実行可能状態 process==0 なら、(ちなみに命令実行中ならprocess==1だ)

次のロボット行動命令を読み込む(administ()関数) 以下の5から8は読み込んだ命令を実行、処理する
5. その場回転しろ という命令だったならば

回転する
6. 「止まれ」命令なら

ロボットが完全に静止するまで待つ(正確には、瞬間速度が、0であればOKってこと)
7. 「アームを動かせ」命令実行中なら、 time_count変数が200になるまで

アームを動かす
8. 上記の3つの条件分岐(5,6,7)のどれにも当てはまらなかった場合

ロボットの位置が目標位置となるよう、position_control()
関数を呼び出す。END_PHASEとなったら(目標位置に到達したら)

process変数を命令受け入れ可能状態の0を代入、phaseを1つすすめる。
  • 9.PI制御スピードコントロール関数 speed_control() を呼び出し、目標速度(グローバル変数)と、引数の現在の速度(エンコーダー読みとり値)から、モーター入力値を求める。
  • 10.計算された入力値をもとに、モータを駆動する。
  • 11.割り込み関数終了関数 fint() を呼び出して、割り込み関数を終了させる。

肝心の位置(x、y)の制御は?

寝る。またこんど。できれば、つくりなおしてほしいし。


回転の制御は? rotation_control()   その場回転だ。

  1. 変数宣言だ。
  2. 目標角度が180度方向か、それ以外で分岐



    目標角度が180度の場合

    (特別扱いが必要なため)
    目標角度を代入する。

    目標角度と現在の角度の差を取る(偏差)
    それ以外の場合 目標角度を代入

    偏差を取る

3.偏差が許容値以内なら、ロボットを停止させ、回転制御関数を抜ける。(戻り値は END_PHASE)

4.偏差の50倍を操作量とする。

5.回転最高速を越えていたら、設定最高速にする。

6.操作量を左右のモーターの目標速度に代入。


アーム操作関数 arm() は?

アームをそのときの引数に従って、動かす信号をだすだけ。ハードウエアでリミットスイッチをもっているので、アームが停止位置にきたら、勝手に、止まってくれます。 ただ、それだけ。



詳しく質問したい場合は 明官先生か、JM4LFAまで



経過、結果報告ページへ戻る

© RUR 1999.
Do not copy without permission.