A sparse MPC solver for walking motion generation (old version).
|
00001 00006 #include <cmath> // sqrt 00007 00008 #include "WMG.h" 00009 #include "footstep.h" 00010 00011 00012 00023 int WMG::getNextSS(const int start_ind, const fs_type type) 00024 { 00025 int index = start_ind + 1; 00026 for (; index < (int) FS.size(); index++) 00027 { 00028 if (FS[index].type != FS_TYPE_DS) 00029 { 00030 if (type == FS_TYPE_AUTO) 00031 { 00032 break; 00033 } 00034 else 00035 { 00036 if (FS[index].type == type) 00037 { 00038 break; 00039 } 00040 } 00041 } 00042 } 00043 return (index); 00044 } 00045 00046 00047 00058 int WMG::getPrevSS(const int start_ind, const fs_type type) 00059 { 00060 int index = start_ind - 1; 00061 for (; index >= 0; index--) 00062 { 00063 if (FS[index].type != FS_TYPE_DS) 00064 { 00065 if (type == FS_TYPE_AUTO) 00066 { 00067 break; 00068 } 00069 else 00070 { 00071 if (FS[index].type == type) 00072 { 00073 break; 00074 } 00075 } 00076 } 00077 } 00078 return (index); 00079 } 00080 00081 00082 00090 void WMG::getDSFeetPositions ( 00091 const int support_number, 00092 double *left_foot_pos, 00093 double *right_foot_pos) 00094 { 00095 int left_ind, right_ind; 00096 00097 left_ind = getNextSS (support_number); 00098 if (FS[left_ind].type == FS_TYPE_SS_L) 00099 { 00100 right_ind = getPrevSS (support_number); 00101 } 00102 else 00103 { 00104 right_ind = left_ind; 00105 left_ind = getPrevSS (support_number); 00106 } 00107 00108 Matrix4d::Map(left_foot_pos) = FS[left_ind].posture->matrix(); 00109 Matrix4d::Map(right_foot_pos) = FS[right_ind].posture->matrix(); 00110 } 00111 00112 00113 00122 void WMG::getSSFeetPositions ( 00123 const int support_number, 00124 const double theta, 00125 double *left_foot_pos, 00126 double *right_foot_pos) 00127 { 00128 double *swing_foot_pos, *ref_foot_pos; 00129 int next_swing_ind, prev_swing_ind; 00130 footstep& current_step = FS[support_number]; 00131 00132 00133 if (current_step.type == FS_TYPE_SS_L) 00134 { 00135 ref_foot_pos = left_foot_pos; 00136 swing_foot_pos = right_foot_pos; 00137 00138 prev_swing_ind = getPrevSS (support_number, FS_TYPE_SS_R); 00139 next_swing_ind = getNextSS (support_number, FS_TYPE_SS_R); 00140 } 00141 else 00142 { 00143 ref_foot_pos = right_foot_pos; 00144 swing_foot_pos = left_foot_pos; 00145 00146 prev_swing_ind = getPrevSS (support_number, FS_TYPE_SS_L); 00147 next_swing_ind = getNextSS (support_number, FS_TYPE_SS_L); 00148 } 00149 00150 Matrix4d::Map(ref_foot_pos) = current_step.posture->matrix(); 00151 00152 00153 double dx = FS[next_swing_ind].x() - FS[prev_swing_ind].x(); 00154 double dy = FS[next_swing_ind].y() - FS[prev_swing_ind].y(); 00155 double l = sqrt(dx*dx + dy*dy); 00156 00157 00158 double x[3] = {0.0, l/2, l}; 00159 double b_coef = - (x[2]*x[2] /*- x[0]*x[0]*/)/(x[2] /*- x[0]*/); 00160 double a = step_height / (x[1]*x[1] /*- x[0]*x[0]*/ + b_coef*(x[1] /*- x[0]*/)); 00161 double b = a * b_coef; 00162 //double c = - a*x[0]*x[0] - b*x[0]; 00163 00164 00165 double dl = /*(1-theta)*x[0] +*/ theta * l; 00166 00167 Matrix4d::Map(swing_foot_pos) = ( 00168 (*FS[prev_swing_ind].posture) 00169 * Translation<double, 3>(theta * dx, theta * dy, a*dl*dl + b*dl) 00170 * AngleAxisd(FS[next_swing_ind].angle - FS[prev_swing_ind].angle, Vector3d::UnitZ()) 00171 ).matrix(); 00172 } 00173 00174 00175 00184 void WMG::getSSFeetPositionsBezier ( 00185 const int support_number, 00186 const double theta, 00187 double *left_foot_pos, 00188 double *right_foot_pos) 00189 { 00190 double *swing_foot_pos, *ref_foot_pos; 00191 int next_swing_ind, prev_swing_ind; 00192 int inclination_sign = 0; 00193 footstep& current_step = FS[support_number]; 00194 00195 00196 if (current_step.type == FS_TYPE_SS_L) 00197 { 00198 inclination_sign = -1; 00199 00200 ref_foot_pos = left_foot_pos; 00201 swing_foot_pos = right_foot_pos; 00202 00203 prev_swing_ind = getPrevSS (support_number, FS_TYPE_SS_R); 00204 next_swing_ind = getNextSS (support_number, FS_TYPE_SS_R); 00205 } 00206 else 00207 { 00208 inclination_sign = 1; 00209 00210 ref_foot_pos = right_foot_pos; 00211 swing_foot_pos = left_foot_pos; 00212 00213 prev_swing_ind = getPrevSS (support_number, FS_TYPE_SS_L); 00214 next_swing_ind = getNextSS (support_number, FS_TYPE_SS_L); 00215 } 00216 00217 Matrix4d::Map(ref_foot_pos) = current_step.posture->matrix(); 00218 00219 00220 00221 Vector4d weighted_binomial_coef; 00222 // first number is the weight 00223 weighted_binomial_coef(0) = 1 * (1-theta)*(1-theta)*(1-theta); 00224 weighted_binomial_coef(1) = bezier_weight_1 * 3*(1-theta)*(1-theta)*theta; 00225 weighted_binomial_coef(2) = bezier_weight_2 * 3*(1-theta)*theta*theta; 00226 weighted_binomial_coef(3) = 1 * theta*theta*theta; 00227 00228 00229 Matrix<double, 3, 4> control_points; 00230 control_points.col(0) = FS[prev_swing_ind].posture->translation(); 00231 control_points.col(3) = FS[next_swing_ind].posture->translation(); 00232 00233 // In order to reach step_height on z axis in the middle of trajectory, 00234 // z coordinates for these two points are derived as follows: 00235 // 00236 // S = sum of weighted binomial coefficients 00237 // 0.5^3 * w0*z0 + 3*0.5^3 * w1*z1 + 3*0.5^3 * w2*z2 + 0.5^3 * w3*z3 = step_height * S 00238 // =0 =0 00239 // 3*0.5^3 * (w1*z1 + w2*z2) = step_height * S 00240 // 00241 // lets take z1=z2=z, then: 00242 // 00243 // z = step_height * S / (3*0.5^3 * (w1+w2)) 00244 00245 // control points in a frame fixed in the reference points of the steps 00246 control_points.col(1).x() = 0.0; 00247 control_points.col(1).y() = inclination_sign * bezier_inclination_1; 00248 control_points.col(1).z() = step_height*weighted_binomial_coef.sum() 00249 / (3*0.5*0.5*0.5 * (bezier_weight_1 + bezier_weight_2)); 00250 control_points.col(2).x() = 0.0; 00251 control_points.col(2).y() = inclination_sign * bezier_inclination_2; 00252 control_points.col(2).z() = control_points.col(1).z(); 00253 00254 // control points in the world frame 00255 control_points.col(1) = (*FS[prev_swing_ind].posture) * control_points.col(1); 00256 control_points.col(2) = (*FS[next_swing_ind].posture) * control_points.col(2); 00257 00258 00259 00260 Transform<double, 3> swing_posture = 00261 Translation<double,3>( 00262 control_points * weighted_binomial_coef / weighted_binomial_coef.sum()) 00263 * 00264 Quaterniond (AngleAxisd (FS[prev_swing_ind].angle,Vector3d::UnitZ())).slerp ( 00265 theta, 00266 Quaterniond (AngleAxisd (FS[next_swing_ind].angle,Vector3d::UnitZ()))); 00267 00268 Matrix4d::Map(swing_foot_pos) = swing_posture.matrix(); 00269 }