四足歩行ロボット〜歩行理論〜
タイトル通りですが,四足歩行ロボットを製作中です.
ルーズリーフに計算式書くくらいならブログにした方がいいと思って.
とりあえず,動いている様子.
確実に重心位置が左前にある.
あと,遅い!
歩行パターン
とりあえず歩行
まずは直進について歩行パターンを周期関数にしてみる.
歩行パターンはクローク歩行,静歩行です.
一周期について1/8で脚を上げて,1/8で下げて3/4で元の場所に戻す.
戻している間に他の三脚を動かす.
常に三脚でバランスを取っているので,四脚接地状態での重心移動モーションを含めると
1/12で脚を上げて,1/12で下げて,1/12で四脚全部を接地して重心を前に動かす.3/4で他の脚を動かす.
周期2の関数だとすると
// x_delta:歩幅 x_base:初期位置 z_delta:高さ z_base:初期位置 void walk_base(double x, double x_delta, double x_base, double z_delta, double z_base, double P[]) { x = fmod(x, 2 * M_PI); if (0 <= x && x < M_PI / 6) { // move up P[X] = x_base + x_delta / (M_PI / 3) * x; P[Z] = z_base + z_delta / (M_PI / 6) * x; } else if (M_PI / 6 <= x && x < M_PI / 3) { // move down P[X] = x_base + x_delta / (M_PI / 3) * x; P[Z] = (z_base + z_delta) - z_delta / (M_PI / 6) * (x - M_PI / 6); } else { // shift P[X] = (x_base + x_delta) - x_delta / (5 * M_PI / 3) * (x - M_PI / 3); P[Z] = z_base; } }
クロークなので
右後ー>右前ー>左後ー>左前の順番に動かすのでずつずらせば良いので
// step_speed 1秒に何歩進むか step/s // x 時間 ms void forward(double x) { walk_base(2 * M_PI * step_speed * x / 1000.0 + 3 * M_PI / 2, 80, -80, 50, -100, leg_pos[RIGHT_BACK]); walk_base(2 * M_PI * step_speed * x / 1000.0 + 2 * M_PI / 2, 80, 80, 50, -100, leg_pos[RIGHT_FRONT]); walk_base(2 * M_PI * step_speed * x / 1000.0 + 1 * M_PI / 2, 80, -80, 50, -100, leg_pos[LEFT_BACK]); walk_base(2 * M_PI * step_speed * x / 1000.0 + 0 * M_PI / 2, 80, 80, 50, -100, leg_pos[LEFT_FRONT]); walk_stabilizer(); // 安定化用関数 }
歩行はこれでOKなんだけど,多分転倒するよね w
安定な歩行
安定な歩行にするには重心が支持多角形内部にあればよいので
こんな感じに移動させればよい
1.上げた脚を判定(LEG0)
2.上げた脚の反対の足(LEG3)と支持脚(LEG1 LEG2)を決定
3.不安定か判定ー>上げている脚と重心の間に直線が入っていれば安定
4.現在のbと重心を通る直線のを計算して動かす
計算するのは4くらいかな
なら安定
なら不安定
重心Gについては本来ならZMPから求めるのが良いと思う.
void walk_stabilizer() { int up_leg, support_leg[2]; double gravity_pos[2] = {0, 0}; // 重心 double a; double b_margin, b, b_G, b_up; leg2Global(); // Convert leg cordinate to global if (leg_pos[LEFT_FRONT][Z] == leg_pos[LEFT_BACK][Z] && leg_pos[LEFT_BACK][Z] == leg_pos[RIGHT_FRONT][Z] && leg_pos[RIGHT_FRONT][Z] == leg_pos[RIGHT_BACK][Z]) { up_leg = 4; b = 0; for (int leg = 0; leg < LEG_NUM; leg++) { b += leg_pos_global[leg][Y]; } b /= LEG_NUM; b_G = gravity_pos[Y]; b_up = 0; b_margin = 0; } else { for (int leg = 0 ; leg < LEG_NUM; leg++) { if (leg_pos[leg][Z] > leg_pos[up_leg][Z]) { up_leg = leg; } } if (up_leg == LEFT_FRONT) { support_leg[0] = LEFT_BACK; support_leg[1] = RIGHT_FRONT; b_margin = 10; } else if (up_leg == LEFT_BACK) { support_leg[0] = LEFT_FRONT; support_leg[1] = RIGHT_BACK; b_margin = 10; } else if (up_leg == RIGHT_FRONT) { support_leg[0] = LEFT_FRONT; support_leg[1] = RIGHT_BACK; b_margin = -10; } else if (up_leg == RIGHT_BACK) { support_leg[0] = RIGHT_FRONT; support_leg[1] = LEFT_BACK; b_margin = -10; } a = (leg_pos_global[support_leg[0]][Y] - leg_pos_global[support_leg[1]][Y]) / (leg_pos_global[support_leg[0]][X] - leg_pos_global[support_leg[1]][X]); b = leg_pos_global[support_leg[1]][Y] - a * leg_pos_global[support_leg[1]][X]; b_G = gravity_pos[Y] - a * gravity_pos[X]; b_up = leg_pos_global[up_leg][Y] - a * leg_pos_global[up_leg][X]; } if ((b_up - b) * (b_G - b) > 1) { // Unstable for (int leg = 0 ; leg < LEG_NUM; leg++) { leg_pos[leg][Y] += (b_G + b_margin - b); } } }
ここまで書いてあれなんだけど,今回は安定化の部分を使いませんでした.
いや,動いている間にマイコンボードが動くんだもの.重心動くんだもの.
圧力センサ買いますかぁ,,,