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