A sparse MPC solver for walking motion generation (old version).
WMG/WMG.cpp
Go to the documentation of this file.
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 }