* 想定するロボットシミュレータ [#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]]ことで,プログラムの整理ができ,共同での設計や議論がしやすくなります. 達成したい課題があるとき,まずは状態を定義して,状態遷移図を描いてから,プログラミングに取り掛かるように心がけましょう. ロボットによる物体操作の場合,次のように状態を定義できます. - 状態A:アームを物体へ接近する行動 - 状態B:物体を掴む行動 - 状態C:掴み損ねて物体を落としたときに再準備する行動 - value:物体を掴んでいれば0より大きな値を示すセンサ *プログラムの基本構造 [#i91c434a] [[サンプルプログラム>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2016/sample_code.zip]]をダウンロードしてください. ** コンパイルと実行 [#wa538208] main_1-1.cのあるフォルダに移動して, gcc main1.c -o main1 -L. -lrobo -lm -lpthread -lGL -lglut でコンパイルします. (glu**関数関連のエラーが出るときは,コマンドの後ろに -lGLU を追加してみてください) そして, ./main1 で実行します. a:左,d:右,w:拡大,s:縮小 端末上でCtrl + Cで実行終了. ** ロボットライブラリ [#b81e9d85] コンパイルコマンドの「-l{ライブラリ名}」はプログラム中に使用するライブラリを指定しています. 例えば,GLやglutは3Dグラフィックのライブラリです. roboライブラリ(librobo.a)は独自に開発したロボットライブラリで,同じフォルダ内にあります. このライブラリはロボットの駆動やセンシングに関する関数や構造体が定義されています. なお,このライブラリ自体を変更することはできません. (ソースコードがあればライブラリの変更・構築が可能ですが,この授業の範囲外とします.ライブラリの構築については,四年生の授業「アドバンスドプログラミング演習(C言語)」で扱います.) ** ヘッダファイル [#f8a7749d] ロボットライブラリの関数と構造体,列挙型はヘッダファイルrobot_simulator.hで説明されています. 例えば,位置を表すPosition構造体にはxとyの座標が定義されています. struct Position_{ double x; double y; }; また,色を表すColorRGB構造体にはr(赤),g(緑),b(青)の各色の変数が定義されています. struct ColorRGB_{ int r; int g; int b; }; 例えば,関数 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, }; 列挙型は一般に,選択肢を表す整数の定数を定義するときに用いられます. enum タグ名{ 列挙変数1, 列挙変数2, 列挙変数3, ... }; で定義すると,列挙変数には自動的に先頭から0, 1, 2, ...と整数が割り当てられます. ARM_STATE列挙型はアームの状態を表し,各列挙変数はそれぞれ,アームが止まっている,動いている,物体を把持してるを意味しています. 今アームがどの状態にあるかは,関数 const char* get_arm_state_str ( ArmState status ); で取得できます. この関数が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); でシミュレーション環境を初期化しています. この関数は初期化に失敗すると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(); で格納しています. 今回,ロボットが動き始める前に,100ステップ待つことにします. その処理は, if(update_step == 100) set_command_move_arm_to(pos); の条件文に反映されています. set_command_move_arm_to(pos)関数で,アームを目標座標まで移動させます. * 練習:ロボットを動かしてみよう [#m3d26cb4] (x, y) = (0.2, 0.1) と (x, y) = (0.3, 0.6) を往復し続けるプログラムを作成してください. また,このときの状態遷移図を描いてください. **ヒント [#j80b8554] アームの状態はget_arm_state関数で取得でき,アームが停止していれば,その関数はARM_STATE_STOPを返します. * 課題 [#n6351693] アームが[[長方形軌道>http://www.er.ams.eng.osaka-u.ac.jp/kawai/CP2016/movement_square.pdf]]を3回描くプログラムを作成してください. 図中のAとCの座標を,プログラム実行後にキーボード入力できるようにしてください. フィールド外の座標が指定された場合はエラーを表示して,実行を終了するようにしてください. また,このときのアームの駆動の状態遷移図を描いてください.上記の座標指定や指定時のエラー処理の状態遷移を考慮する必要はありません. 状態と状態遷移を明示的に定義して図にし,それに基づいてプログラムを作成するといった手順を踏んでください. 適宜コメントを入れたり,関数化したりして,他人にもわかりやすいプログラムになるように心がけてください.全くコメントのないものは減点します. ** 提出物 [#k17aaedc] 提出物一式を入れるファイルの名前は学生番号にしてください. - プログラムファイル(TAがUSBメモリで回収) - 状態遷移図(手書きでもプリントアウトでもOK) ** 提出日 [#lc267e66] 次の授業中に提出してもらいます. そのときに提出プログラムが正しく実行できていることをTAが直接確認します. - 1・2組:1/6 - 3・4組:12/26