こんにちは。
ペットの魚の名前がまだ決まらない松崎です。
名づけってものがどうも苦手で困ります。
中2病っぽい名前にしたいですw
さて、金沢草の根大会の興奮冷めやらぬ今日は、のり先生からさらに壁切れ制御について教わります。
今日興味深かったのはこれです。
まず、
Pi:Co Classicの探索方法のひとつである足立法のサンプルプログラムを見てみてください。
void search_adachi(int gx, int gy) { //引数gx,gyに向かって足立法で迷路を探索する t_direction glob_nextdir; //次に向かう方向を記録する変数 max_speed = SEARCH_SPEED; //探索の速度を指定 accel=SEARCH_ACCEL; switch(get_nextdir(gx,gy,MASK_SEARCH,&glob_nextdir)) //次に行く方向を戻り値とする関数を呼ぶ { case front: straight(HALF_SECTION,SEARCH_SPEED); //一区画進む break; case right: rotate(right,1); //左に曲がって straight(HALF_SECTION,SEARCH_SPEED); //半区画進む break; case left: rotate(left,1); //左に曲がって straight(HALF_SECTION,SEARCH_SPEED); //半区画進む break; case rear: rotate(left,2); //左に曲がって straight(HALF_SECTION,SEARCH_SPEED); //半区画進む break; } accel=SEARCH_ACCEL; r_accel=SEARCH_ACCEL; //加速度を設定 con_wall.enable = true; //壁制御を有効にする MOT_CWCCW_R = MOT_CWCCW_L = MOT_FORWARD; //前方に進む step_r = step_l = 0; //進んだ距離カウント用変数をリセット MTU2.TSTR.BIT.CST3 = MTU2.TSTR.BIT.CST4 = 1; //カウントスタート mypos.dir = glob_nextdir; //方向を更新 //向いた方向によって自分の座標を更新する switch(mypos.dir) { case north: mypos.y++; //北を向いた時はY座標を増やす break; case east: mypos.x++; //東を向いた時はX座標を増やす break; case south: mypos.y--; //南を向いた時はY座標を減らす break; case west: mypos.x--; //西を向いたときはX座標を減らす break; } while((mypos.x != gx) || (mypos.y != gy)){ //ゴールするまで繰り返す set_wall(mypos.x,mypos.y); //壁をセット switch(get_nextdir(gx,gy,MASK_SEARCH,&glob_nextdir)) //次に行く方向を戻り値とする関数を呼ぶ { case front: straight_for_search(SECTION,SEARCH_SPEED); //一区画進む break; case right: straight_for_search(HALF_SECTION,0); //半区画進んで rotate(right,1); //左に曲がって straight(HALF_SECTION,SEARCH_SPEED); //半区画進む break; case left: straight_for_search(HALF_SECTION,0); //半区画進んで rotate(left,1); //左に曲がって straight(HALF_SECTION,SEARCH_SPEED); //半区画進む break; case rear: straight_for_search(HALF_SECTION,0); //半区画進んで rotate(left,2); //左に曲がって straight(HALF_SECTION,SEARCH_SPEED); //半区画進む break; } accel = SEARCH_ACCEL; r_accel = SEARCH_ACCEL; //加速度(後で指定方法を変更すること) con_wall.enable = true; //壁制御を有効にする MOT_CWCCW_R = MOT_CWCCW_L = MOT_FORWARD; //前方に進む step_r = step_l = 0; //進んだ距離をカウントする変数をリセット MTU2.TSTR.BIT.CST3 = MTU2.TSTR.BIT.CST4 = 1; //カウントスタート mypos.dir = glob_nextdir; //方向を更新 //向いた方向によって自分の座標を更新する switch(mypos.dir) { case north: mypos.y++; //北を向いた時はY座標を増やす break; case east: mypos.x++; //東を向いた時はX座標を増やす break; case south: mypos.y--; //南を向いた時はY座標を減らす break; case west: mypos.x--; //西を向いたときはX座標を減らす break; } } set_wall(mypos.x,mypos.y); //壁をセット straight_for_search(HALF_SECTION,0); //ゴール.半区画進む }
いままであまりGenieちゃんが考え込んで立ち止まる(何らかの形で観測できるレベルに計算に時間を費やす)というところを見たことがなかったのでつい忘れていましたが、
Genieちゃんでも、計算に時間がかかる分、走行に誤差がでることがあるそうです。
今日見たのは足立法での探索走行時。
get_nextdir(gx,gy,MASK_SEARCH,&glob_nextdir))という部分 の計算に時間がかかるので、
計算を開始したA地点(下図参照)から、実際に計算結果を走行として出力する瞬間B地点で、
Genieちゃんのいる位置に誤差ができるそうです。
これをクリアしているのが、「step_r = step_l = 0;」という一行です。
これにより、計算を開始した時点を必ず「0」とし、誤差が出た分を加味して走行しています。
このたった一行で、そんなヤバイ誤差をクリアしているんですね…。
そんなことに感心していたら、
金沢草の根大会で頂いたアドバイスを思い出しました。
プログラムのたった一行が原因で壁制御の仕組みがおかしくなってしまい、やっとでミスに気付いてほっとしてお話ししていたときにぽっと教わった、
「誤作動を起こすのは一行あれば十分」
という言葉。
なるほど、たった一行がもたらす影響は大きいのだなあ!!
なまじコンパイルが成功するだけに気付き辛い不都合ですが、
きちんと仕組みを知ってミスに気付けるようになりたいと思いました。
そんなこんなで今日は壁切れ補正の方向性が決まりました!
当初私は曲がることが多く走行時間も長い探索にこそ壁切れ制御を入れたいと思っていました。
(曲がれば曲がるほど姿勢を補正できるというのに魅力を感じていたのです~)
ですが、探索走行では、すべての壁切れを読んで走ることになるので、
すべての壁切れを読むタイミングでの、ちょっとした姿勢制御のズレが壁切れ補正のズレにつながり、
走行がガチャガチャになってしまう可能性があるのです…!
それは避けたい!せめて完走はしたいよー!!
と、いうことで、
最短走行のみに壁切れ補正を実装することになりました!
今日は、straight関数をまるまるコピペして名前を変えて各所にペーストし、
壁切れ補正入りの最短走行プログラムに書き換える土壌まで作りまし…
のり先生「はい、じゃあがんばって~~^^」
松崎「!?!?」
松崎は今「どこに書くか」「どういうイメージか」しかわかりませんっっ!!!
「どう書けばいいか」←これがわかりませんっ!のり先生~~~!!!!!!!
to be continued…