A sparse MPC solver for walking motion generation (old version).
|
00001 00008 #include <stdio.h> 00009 #include <math.h> // cos, sin 00010 00011 00012 #include "WMG.h" 00013 #include "footstep.h" 00014 00015 00027 WMG::WMG ( 00028 const unsigned int N_, 00029 const unsigned int T_, 00030 const double step_height_, 00031 const double bezier_weight_1_, 00032 const double bezier_weight_2_, 00033 const double bezier_inclination_1_, 00034 const double bezier_inclination_2_) 00035 { 00036 step_height = step_height_; 00037 N = N_; 00038 sampling_period = T_; 00039 00040 T_ms = new unsigned int[N]; 00041 for (unsigned int i = 0; i < N; i++) 00042 { 00043 T_ms[i] = 0; 00044 } 00045 00046 00047 current_step_number = 0; 00048 last_time_decrement = 0; 00049 first_preview_step = current_step_number; 00050 00051 00053 def_ss_constraint[0] = 0.09; 00054 def_ss_constraint[1] = 0.025; 00055 def_ss_constraint[2] = 0.03; 00056 def_ss_constraint[3] = 0.025; 00057 00058 def_auto_ds_constraint[0] = 0.07; 00059 def_auto_ds_constraint[1] = 0.025; 00060 def_auto_ds_constraint[2] = 0.025; 00061 def_auto_ds_constraint[3] = 0.025; 00062 00063 addstep_constraint[0] = def_ss_constraint[0]; 00064 addstep_constraint[1] = def_ss_constraint[1]; 00065 addstep_constraint[2] = def_ss_constraint[2]; 00066 addstep_constraint[3] = def_ss_constraint[3]; 00067 00068 def_time_ms = 400; 00069 ds_time_ms = 0; 00070 00071 bezier_weight_1 = bezier_weight_1_; 00072 bezier_weight_2 = bezier_weight_2_; 00073 bezier_inclination_1 = bezier_inclination_1_; 00074 bezier_inclination_2 = bezier_inclination_2_; 00075 } 00076 00077 00079 WMG::~WMG() 00080 { 00081 if (T_ms != NULL) 00082 { 00083 delete T_ms; 00084 } 00085 } 00086 00087 00088 00098 void WMG::setFootstepDefaults( 00099 const unsigned int def_num_, 00100 const unsigned int ds_num_, 00101 const double *constraints) 00102 { 00103 if (constraints != NULL) 00104 { 00105 addstep_constraint[0] = constraints[0]; 00106 addstep_constraint[1] = constraints[1]; 00107 addstep_constraint[2] = constraints[2]; 00108 addstep_constraint[3] = constraints[3]; 00109 } 00110 00111 def_time_ms = def_num_ * sampling_period; 00112 ds_time_ms = sampling_period; 00113 ds_num = ds_num_; 00114 } 00115 00116 00117 00126 void WMG::setFootstepDefaults( 00127 const unsigned int def_time_ms_, 00128 const unsigned int ds_time_ms_, 00129 const unsigned int ds_num_, 00130 const double *constraints) 00131 { 00132 if (constraints != NULL) 00133 { 00134 addstep_constraint[0] = constraints[0]; 00135 addstep_constraint[1] = constraints[1]; 00136 addstep_constraint[2] = constraints[2]; 00137 addstep_constraint[3] = constraints[3]; 00138 } 00139 00140 def_time_ms = def_time_ms_; 00141 ds_time_ms = ds_time_ms_; 00142 ds_num = ds_num_; 00143 } 00144 00145 00146 00157 void WMG::addFootstep( 00158 const double x_relative, 00159 const double y_relative, 00160 const double angle_relative, 00161 fs_type type) 00162 { 00163 Transform<double, 3> posture (Translation<double, 3>(x_relative, y_relative, 0.0)); 00164 Vector3d zref_offset ((addstep_constraint[0] - addstep_constraint[2])/2, 0.0, 0.0); 00165 00166 00167 if (FS.size() == 0) 00168 { 00169 // this is the first ("virtual") step. 00170 if (type == FS_TYPE_AUTO) 00171 { 00172 type = FS_TYPE_DS; 00173 } 00174 00175 posture *= AngleAxisd(angle_relative, Vector3d::UnitZ()); 00176 // offset is the absolute position here. 00177 Vector3d zref_abs = posture * zref_offset; 00178 00179 FS.push_back( 00180 footstep( 00181 angle_relative, 00182 posture, 00183 zref_abs, 00184 def_time_ms, 00185 type, 00186 addstep_constraint)); 00187 } 00188 else 00189 { 00190 // determine type of the step 00191 if (type == FS_TYPE_AUTO) 00192 { 00193 switch (FS[getPrevSS(FS.size())].type) 00194 { 00195 case FS_TYPE_SS_L: 00196 type = FS_TYPE_SS_R; 00197 break; 00198 case FS_TYPE_SS_R: 00199 type = FS_TYPE_SS_L; 00200 break; 00201 case FS_TYPE_DS: 00202 default: 00203 type = FS_TYPE_SS_R; 00204 break; 00205 } 00206 } 00207 00208 // Position of the next step 00209 posture = (*FS.back().posture) * posture * AngleAxisd(angle_relative, Vector3d::UnitZ()); 00210 00211 double prev_a = FS.back().angle; 00212 double next_a = prev_a + angle_relative; 00213 Vector3d next_zref = posture * zref_offset; 00214 00215 00216 // Add double support constraints that lie between the 00217 // newly added step and the previous step 00218 double theta = (double) 1/(ds_num + 1); 00219 double angle_shift = angle_relative * theta; 00220 double x_shift = theta*x_relative; 00221 double y_shift = theta*y_relative; 00222 Vector3d *ds_zref = &FS.back().ZMPref; 00223 for (unsigned int i = 0; i < ds_num; i++) 00224 { 00225 Transform<double, 3> ds_posture = (*FS.back().posture) 00226 * Translation<double, 3>(x_shift, y_shift, 0.0) 00227 * AngleAxisd(angle_shift, Vector3d::UnitZ()); 00228 00229 if (i == ds_num / 2) 00230 { 00231 ds_zref = &next_zref; 00232 } 00233 00234 FS.push_back( 00235 footstep( 00236 FS.back().angle + angle_shift, 00237 ds_posture, 00238 *ds_zref, 00239 ds_time_ms, 00240 FS_TYPE_DS, 00241 def_auto_ds_constraint)); 00242 } 00243 00244 00245 // add the new step 00246 FS.push_back( 00247 footstep( 00248 next_a, 00249 posture, 00250 next_zref, 00251 def_time_ms, 00252 type, 00253 addstep_constraint)); 00254 } 00255 } 00256 00257 00258 00273 void WMG::getFeetPositions ( 00274 const unsigned int shift_from_current_ms, 00275 double *left_foot_pos, 00276 double *right_foot_pos) 00277 { 00278 unsigned int support_number = first_preview_step; 00279 // formPreviewWindow() have already decremented the time 00280 unsigned int step_time_left = FS[support_number].time_left + last_time_decrement; 00281 unsigned int shift_ms = shift_from_current_ms; 00282 00283 00284 while (shift_ms > step_time_left) 00285 { 00286 shift_ms -= step_time_left; 00287 ++support_number; 00288 if (support_number >= FS.size()) 00289 { 00290 return; 00291 } 00292 step_time_left = FS[support_number].time_left; 00293 } 00294 00295 00296 if (FS[support_number].type == FS_TYPE_DS) 00297 { 00298 getDSFeetPositions (support_number, left_foot_pos, right_foot_pos); 00299 } 00300 else 00301 { 00302 double theta = (double) 00303 ((FS[support_number].time_period - step_time_left) + shift_ms) 00304 / FS[support_number].time_period; 00305 00306 getSSFeetPositionsBezier ( 00307 support_number, 00308 theta, 00309 left_foot_pos, 00310 right_foot_pos); 00311 } 00312 } 00313 00314 00315 00321 bool WMG::isSupportSwitchNeeded () 00322 { 00323 // current_step_number is the number of step, which will 00324 // be the first in the preview window, when formPreviewWindow() 00325 // is called. 00326 if (FS[current_step_number].type == FS_TYPE_DS) 00327 { 00328 return (false); 00329 } 00330 else // single support 00331 { 00332 if (// if we are not in the initial support 00333 (current_step_number != 0) && 00334 // this is the first iteration in SS 00335 (FS[current_step_number].time_period == FS[current_step_number].time_left) && 00336 // the previous SS was different 00337 (FS[getPrevSS(first_preview_step)].type != FS[current_step_number].type)) 00338 { 00339 return (true); 00340 } 00341 } 00342 00343 return (false); 00344 } 00345 00346 00347 00356 void WMG::changeNextSSPosition (const double* posture, const bool zero_z_coordinate) 00357 { 00358 FS[getNextSS(first_preview_step)].changePosture(posture, zero_z_coordinate); 00359 } 00360 00361 00362 00368 WMGret WMG::formPreviewWindow(smpc_parameters & par) 00369 { 00370 WMGret retval = WMG_OK; 00371 unsigned int win_step_num = current_step_number; 00372 unsigned int step_time_left = FS[win_step_num].time_left; 00373 00374 00375 for (unsigned int i = 0; i < N;) 00376 { 00377 if (step_time_left > 0) 00378 { 00379 par.angle[i] = FS[win_step_num].angle; 00380 00381 par.fp_x[i] = FS[win_step_num].x(); 00382 par.fp_y[i] = FS[win_step_num].y(); 00383 00384 00385 // ZMP reference coordinates 00386 par.zref_x[i] = FS[win_step_num].ZMPref.x(); 00387 par.zref_y[i] = FS[win_step_num].ZMPref.y(); 00388 00389 00390 par.lb[i*2] = -FS[win_step_num].d[2]; 00391 par.ub[i*2] = FS[win_step_num].d[0]; 00392 00393 par.lb[i*2 + 1] = -FS[win_step_num].d[3]; 00394 par.ub[i*2 + 1] = FS[win_step_num].d[1]; 00395 00396 00397 unsigned int step_len_ms; 00398 if (T_ms[i] == 0) 00399 { 00400 if (sampling_period > step_time_left) 00401 { 00402 step_len_ms = step_time_left; 00403 } 00404 else 00405 { 00406 step_len_ms = sampling_period; 00407 } 00408 } 00409 else 00410 { 00411 if (T_ms[i] > step_time_left) 00412 { 00413 retval = WMG_HALT; 00414 break; 00415 } 00416 step_len_ms = T_ms[i]; 00417 } 00418 par.T[i] = (double) step_len_ms / 1000; 00419 step_time_left -= step_len_ms; 00420 00421 if (i == 0) 00422 { 00423 last_time_decrement = step_len_ms; 00424 } 00425 i++; 00426 } 00427 else 00428 { 00429 win_step_num++; 00430 if (win_step_num == FS.size()) 00431 { 00432 retval = WMG_HALT; 00433 break; 00434 } 00435 step_time_left = FS[win_step_num].time_left; 00436 } 00437 } 00438 00439 00440 if (retval == WMG_OK) 00441 { 00442 while (FS[current_step_number].time_left == 0) 00443 { 00444 current_step_number++; 00445 } 00446 00447 first_preview_step = current_step_number; 00448 FS[current_step_number].time_left -= last_time_decrement; 00449 if (FS[current_step_number].time_left == 0) 00450 { 00451 current_step_number++; 00452 } 00453 } 00454 00455 return (retval); 00456 } 00457 00458 00459 00467 void WMG::FS2file(const std::string filename, const bool plot_ds) 00468 { 00469 00470 FILE *file_op = fopen(filename.c_str(), "w"); 00471 00472 if(!file_op) 00473 { 00474 fprintf(stderr, "Cannot open file (for writing)\n"); 00475 return; 00476 } 00477 00478 fprintf(file_op,"%%\n%% Footsteps generated using the c++ version of the WMG\n%%\n\n"); 00479 fprintf(file_op,"cla;\n"); 00480 fprintf(file_op,"clear FS;\n\n"); 00481 00482 int i; 00483 for (i=0; i< (int) FS.size(); i++ ) 00484 { 00485 if ((plot_ds) || (FS[i].type != FS_TYPE_DS)) 00486 { 00487 fprintf(file_op, "FS(%i).a = %f;\nFS(%i).p = [%f;%f];\nFS(%i).d = [%f;%f;%f;%f];\n", 00488 i+1, FS[i].angle, 00489 i+1, FS[i].x(), FS[i].y(), 00490 i+1, FS[i].d[0], FS[i].d[1], FS[i].d[2], FS[i].d[3]); 00491 00492 fprintf(file_op, "FS(%i).D = [%f %f;%f %f;%f %f;%f %f];\n", 00493 i+1, FS[i].D[0], FS[i].D[4], 00494 FS[i].D[1], FS[i].D[5], 00495 FS[i].D[2], FS[i].D[6], 00496 FS[i].D[3], FS[i].D[7]); 00497 00498 fprintf(file_op, "FS(%i).v = [%f %f; %f %f; %f %f; %f %f; %f %f];\n", 00499 i+1, FS[i].vert(0,0), FS[i].vert(0,1), 00500 FS[i].vert(1,0), FS[i].vert(1,1), 00501 FS[i].vert(2,0), FS[i].vert(2,1), 00502 FS[i].vert(3,0), FS[i].vert(3,1), 00503 FS[i].vert(0,0), FS[i].vert(0,1)); 00504 00505 if (FS[i].type == FS_TYPE_DS) 00506 { 00507 fprintf(file_op, "FS(%i).type = 1;\n\n", i+1); 00508 } 00509 if ((FS[i].type == FS_TYPE_SS_L) || (FS[i].type == FS_TYPE_SS_R)) 00510 { 00511 fprintf(file_op, "FS(%i).type = 2;\n\n", i+1); 00512 } 00513 } 00514 } 00515 00516 fprintf(file_op,"hold on\n"); 00517 fprintf(file_op,"for i=1:length(FS)\n"); 00518 fprintf(file_op," if FS(i).type == 1;\n"); 00519 fprintf(file_op," plot (FS(i).p(1),FS(i).p(2),'gs','MarkerFaceColor','r','MarkerSize',2)\n"); 00520 fprintf(file_op," plot (FS(i).v(:,1), FS(i).v(:,2), 'c');\n"); 00521 fprintf(file_op," end\n"); 00522 fprintf(file_op," if FS(i).type == 2;\n"); 00523 fprintf(file_op," plot (FS(i).p(1),FS(i).p(2),'gs','MarkerFaceColor','g','MarkerSize',4)\n"); 00524 fprintf(file_op," plot (FS(i).v(:,1), FS(i).v(:,2), 'r');\n"); 00525 fprintf(file_op," end\n"); 00526 fprintf(file_op,"end\n"); 00527 fprintf(file_op,"grid on; %%axis equal\n"); 00528 fclose(file_op); 00529 } 00530 00531 00540 void WMG::getFootsteps( 00541 std::vector<double> & x_coord, 00542 std::vector<double> & y_coord, 00543 std::vector<double> & angle_rot) 00544 { 00545 for (unsigned int i = 0; i < FS.size(); i++) 00546 { 00547 if ((FS[i].type == FS_TYPE_SS_L) || (FS[i].type == FS_TYPE_SS_R)) 00548 { 00549 x_coord.push_back(FS[i].x()); 00550 y_coord.push_back(FS[i].y()); 00551 angle_rot.push_back(FS[i].angle); 00552 } 00553 } 00554 }