* 想定するロボットシミュレータ [#oe85417b]
- グリッパ(ロボットの手)により物体を掴んでその位置を移動させるガントリー(直行)型ロボット
- 物体把持に失敗することもある.
- 物体の位置・形状・色を読み取る視覚センサ(ノイズを含む)
- 把持中の物体の重さを計測する重量センサ(ノイズを含む)
- 物体の位置・形状・色を読み取る視覚センサ
- 把持中の物体の重さを計測する重量センサ
- 基本動作・センシングのライブラリ

* ロボットプログラミング [#x9a96992]
** 基本構造と設計手法 [#yffe3161]
知能ロボットは常に環境の情報を受け取りながら適切な行動を決定し,実行します.そのため,常に
- ロボット自身と環境情報の取得
- 取得した情報に基づく行動決定
- 行動の実行と制御

のループを短い周期で定期的に実行するプログラムを書く必要があります.

具体的には,while文などで無限ループを構成し,システムに用意されたsleep関数やwait関数を用いて次の処理を開始するまでプロセスを停止する方法があります.

~
ロボットプログラムは大規模となることが多く,また,ロボットが人や環境に危害を加えないことが条件となるため,見通しの良い,バグの少ないプログラム開発が望まれます.

~
そこで,よく使われる設計手法である構造化プログラミングと状態遷移を紹介します.

** 構造化プログラミングと状態遷移 [#a4b96087]
構造化プログラミング:全体の処理を排他的なモジュールに分割し,組み合わせて構築することで,見通しの良いプログラムを目指す考え方

~
このモジュールを状態とみなし,それらの状態の遷移として課題を表現します.

~
例として,以下の状態遷移を考えます.
+状態Aの処理が終了したら状態Bへ
+状態Bの処理が終了したときにvalueが0より大きければ終了
+状態Bの処理が終了したときにvalueが0以下ならば状態Cへ
+状態Cの処理が終了したら状態Bへ

この[[状態遷移を図に表す>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2016/example_transition.pdf]]ことで,プログラムの整理ができ,共同での設計や議論がしやすくなります.
この[[状態遷移を図に表す>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2017/example_transition.pdf]]ことで,プログラムの整理ができ,共同での設計や議論がしやすくなります.
達成したい課題があるとき,まずは状態を定義して,状態遷移図を描いてから,プログラミングに取り掛かるように心がけましょう.

ロボットによる物体操作の場合,次のように状態を定義できます.
- 状態A:アームを物体へ接近する行動
- 状態B:物体を掴む行動
- 状態C:掴み損ねて物体を落としたときに再準備する行動
- value:物体を掴んでいれば0より大きな値を示すセンサ値

*X Window System [#lba16761]
スタートメニュー -> Devel -> Xmingをクリックしてください.~
右下のツールバーにXのアイコンが表示されればOKです.

これはX Window SystemというUNIX/LinuxでGUIを使うときに必要になるウィンドウシステムです.~
この操作は今後もPCを立ち上げたときに実行してください.

*プログラムの基本構造 [#i91c434a]
[[サンプルプログラム>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2016/sample_code.zip]]をダウンロードしてください.
[[サンプルプログラム>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2017/sample.zip]]をダウンロードしてください.

** コンパイルと実行 [#wa538208]
main_1-1.cのあるフォルダに移動して,
 gcc main1.c -o main1 -L. -lrobo -lm -lpthread -lGL -lglut
main1.cのあるフォルダに移動して,
 gcc main1.c -o main1 -L. -lrobo -lm -lpthread -lGL -lglut -lGLU
でコンパイルします.
(glu**関数関連のエラーが出るときは,コマンドの後ろに -lGLU を追加してみてください)

~
そして,
 ./main1
で実行します.

a:左,d:右,w:拡大,s:縮小
~
q:終了

端末上でCtrl + Cで実行終了.

** ロボットライブラリ [#b81e9d85]
コンパイルコマンドの「-l{ライブラリ名}」はプログラム中に使用するライブラリを指定しています.
~
例えば,mは算術演算ライブラリで,GLとglut,GLUは3Dグラフィックのライブラリです.

例えば,mは算術演算ライブラリで,GLとglutは3Dグラフィックのライブラリです.

roboライブラリ(librobo.a)は独自に開発したロボットライブラリで,同じフォルダ内にあります.

~
L. は同じフォルダ内にライブラリがあることを示します.
~
このロボットライブラリはロボットの駆動やセンシングに関する関数や構造体を定義しています.

~
なお,このライブラリ自体を変更することはできません.
(ソースコードがあればライブラリの変更・構築が可能ですが,この授業の範囲外とします.ライブラリの構築については,四年生の授業「アドバンスドプログラミング演習(C言語)」で扱います.)

(ソースコードがあればライブラリの変更が可能ですが,この授業の範囲外とします.
~
ライブラリの構築については,四年生の授業「アドバンスドプログラミング演習(C言語)」で扱います.)

librobo2.aは第2回の課題で使います.

** ヘッダファイル [#f8a7749d]
ロボットライブラリの関数と構造体,列挙型はヘッダファイルrobot_simulator.hで説明されています.

~
例えば,位置を表すPosition構造体にはxとyの座標が定義されています.
 struct Position_{
     double x;
     double y;
 };
 typedef struct Position_ Position;

また,色を表すColorRGB構造体にはr(赤),g(緑),b(青)の各色の変数が定義されています.
 struct ColorRGB_{
      int r;
      int g;
      int b;
 };
 typedef struct ColorRGB_ ColorRGB;

例えば,関数
 bool set_command_move_arm_to( Position target_position );
へPosition構造体を渡すことで,アームがその座標まで移動します.

~
bool型(論理型)関数はtrue(真)かfalse(偽)を返します.
~
この関数の場合,ARM_STATE_HANDLING_OBJECTのとき,あるいは,指定した座標が可動範囲外であるときにfalseを返し,それ以外だとtrueを返します.

このARM_STATE_HANDLING_OBJECTはenum型(列挙型)で定義されています.
 enum ARM_STATE{
      ARM_STATE_STOP,
      ARM_STATE_MOVING,
      ARM_STATE_HANDLING_OBJECT,
 };
 typedef enum ARM_STATE ArmState
 typedef enum ARM_STATE ArmState;

列挙型は一般に,選択肢を表す整数の定数を定義するときに用いられます.
 enum タグ名{
      列挙変数1,
      列挙変数2,
      列挙変数3, ...
 };
で定義すると,列挙変数には自動的に先頭から0, 1, 2, ...と整数が割り当てられます.

Arm_State列挙型はアームの状態を表し,各列挙変数はそれぞれ,アームが止まっている,動いている,物体を把持してるを意味しています.

今アームがどの状態にあるかは,関数
 ArmState get_arm_state_str ( );
で取得できます.この関数はアームの状態に応じたArmState型を返します.すなわち,ARM_STATE_STOP,ARM_STATE_MOVING,および,ARM_STATE_HANDLING_OBJECTのいずれかを返します.

で取得できます.
~
この関数はアームの状態に応じたArmState型を返します.
~
すなわち,ARM_STATE_STOP,ARM_STATE_MOVING,および,ARM_STATE_HANDLING_OBJECTのいずれかを返します.
~
この関数がARM_STATE_HANDLING_OBJECT(つまり,2)を返せば,アームが物体を把持していることになります.

set_command_move_arm_to関数では,このアーム状態の情報を用いて,返り値を決めています.
~
ただし,上記の処理はライブラリのソースコードに書かれており,ライブラリユーザには見えません.

このヘッダファイルには,この他にも課題の遂行に必要な関数・列挙型が説明されています.
~
プログラミングを始める前に,各自で読んでおいてください.

** アームの駆動 [#z89c051b]
main1.cを解説します.ヘッダファイル中のコメントと併せて見てください.

~
まず,
 #include "robot_simulator.h"
で,ヘッダファイルを読み込みます.

 #define OBJECT_NUM 10
で,物体の数を指定しています.

main関数の中ですが,まず,
 initialize_robot(OBJECT_NUM);
でシミュレーション環境を初期化しています.
でOBJECT_NUM個の物体のあるシミュレーション環境を初期化しています.
~
この関数は初期化に失敗するとfalseを返すので,以降で,その場合のエラー処理をしています.

もし,エラー(!is_initialized)なら,
 finalize_robot();
でシミュレーションを終了します.

次に,
 Position pos = {0.2, 0.1};
で,Position構造体にアームの目標座標を代入しています.

ここから,ロボットシミュレーションの実行になります.
 while(update_robot()){***}
によって,update_robot関数がfalseを返すまで処理***をループさせます.

このupdate_robot関数により,シミュレーションを実行します.1回の関数呼び出し(1回のwhileループ)で,シミュレーションの実行時間ステップが1増加します.
現在の実行時間ステップ数はget_update_robot_step関数で取得でき,
 update_step = get_update_robot_step();
で格納しています.
このupdate_robot関数により,シミュレーションを実行します.
~
1回の関数呼び出し(1回のwhileループ)で,シミュレーションの実行時間ステップが1増加します.
~
現在の実行時間ステップ数は関数
 int get_update_robot_step();
で取得できます.

今回,ロボットが動き始める前に,100ステップ待つことにします.
~
その処理は,
 if(update_step == 100) set_command_move_arm_to(pos);
 if(get_update_robot_step() == 100) set_command_move_arm_to(pos);
の条件文に反映されています.
~
ここで,関数
 bool set_command_move_arm_to(Position target_position);
は,アームを目標座標 (target_position) まで移動させるものです.

set_command_move_arm_to(pos)関数で,アームを目標座標まで移動させます.


* 練習:ロボットを動かしてみよう [#m3d26cb4]
(x, y) = (0.2, 0.1) と (x, y) = (0.3, 0.6) を往復し続けるプログラムを作成してください.
* 練習1 [#m3d26cb4]
(x, y) = (0.6, -0.3) と (x, y) = (-0.1, 0.2) を往復し続けるプログラムを作成してください.
~
また,このときの状態遷移図を描いてください.

**ヒント [#j80b8554]
アームの状態はget_arm_state関数で取得でき,アームが停止していれば,その関数はARM_STATE_STOPを返します.
**ヒント1 [#ba47a5ce]
例えば,(0.6, -0.3) への移動を状態A,(-0.1, 0.2) への移動を状態Bと定義して,それらの状態間を遷移するようにしましょう.

* 課題 [#n6351693]
アームが[[長方形軌道>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2016/movement_square.pdf]]を3周描いて,停止するプログラムを作成してください.
**ヒント2 [#y8c8fe0d]
set_command_move_arm_to(pos)は,posを中心としたある範囲にアームが入るまでアームを移動させます.~
したがって,アームがposの位置ぴったりまで移動しないことがあります.

**ヒント3 [#j80b8554]
アームの状態は関数
 ArmState get_arm_state();
で取得でき,アームが停止していれば,この関数はARM_STATE_STOPを返します.

* 練習2 [#n6351693]
アームが[[長方形軌道>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2017/movement_square.pdf]]を2周描いて,停止するプログラムを作成してください.
~
図中のAとCの座標を,プログラム実行後にキーボード入力できるようにしてください.
~
フィールド外の座標が指定された場合はエラーを表示して,実行を終了するようにしてください.

また,このときのアームの駆動の状態遷移図を描いてください.上記の座標指定や指定時のエラー処理の状態遷移を考慮する必要はありません.

状態と状態遷移を明示的に定義して図にし,それに基づいてプログラムを作成するといった手順を踏んでください.

適宜コメントを入れたり,関数化したりして,他人にもわかりやすいプログラムになるように心がけてください.全くコメントのないものは減点します.

**ヒント [#s50808fe]
範囲外の座標を指定されたとき,set_command_move_arm_to関数はfalseを返します.
範囲外の座標を指定されたとき,関数
 bool set_command_move_arm_to(Position target_position);
はfalseを返します.

** 提出物 [#k17aaedc]
提出物一式を入れるファイルの名前は学生番号にしてください.
- プログラムファイル(TAがUSBメモリで回収)
- 状態遷移図(手書きでもプリントアウトでもOK)

** 提出日 [#lc267e66]
次の授業中に提出してもらいます.
そのときに提出プログラムが正しく実行できていることをTAが直接確認します.

- 1・2組:1/6
- 3・4組:12/26


トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS