A sparse MPC solver for walking motion generation.
WMG.cpp
Go to the documentation of this file.
1 
8 #include <stdio.h>
9 #include <math.h> // cos, sin
10 
11 
12 #include "WMG.h"
13 #include "footstep.h"
14 
16  const unsigned int N_,
17  const unsigned int T_,
18  const double step_height_,
19  const double bezier_weight_1_,
20  const double bezier_weight_2_,
21  const double bezier_inclination_1_,
22  const double bezier_inclination_2_,
23  const bool use_fsr_constraints)
24 {
25  step_height = step_height_;
26  N = N_;
27  sampling_period = T_;
28 
29  T_ms = new unsigned int[N];
30  for (unsigned int i = 0; i < N; i++)
31  {
32  T_ms[i] = 0;
33  }
34 
35 
39 
40  if (use_fsr_constraints)
41  {
43  }
44  else
45  {
47  }
48 
49  setFootstepParameters (4, 0, 0);
50 
51  for (int i = 0; i < 4; ++i)
52  {
53  // auto_ds constraints are safer
55  }
56 
57  bezier_weight_1 = bezier_weight_1_;
58  bezier_weight_2 = bezier_weight_2_;
59  bezier_inclination_1 = bezier_inclination_1_;
60  bezier_inclination_2 = bezier_inclination_2_;
61 }
62 
63 
64 
66 {
67  if (T_ms != NULL)
68  {
69  delete T_ms;
70  }
71 }
72 
73 
74 
76  const unsigned int def_periods,
77  const unsigned int ds_periods,
78  const unsigned int ds_number,
79  bool use_user_constraints_)
80 {
82  def_periods * sampling_period,
83  ds_periods * sampling_period,
84  ds_number,
85  use_user_constraints_);
86 }
87 
88 
90  const unsigned int def_time_ms_,
91  const unsigned int ds_time_ms_,
92  const unsigned int ds_number,
93  bool use_user_constraints_)
94 {
95  def_time_ms = def_time_ms_;
96  ds_time_ms = ds_time_ms_;
97  ds_num = ds_number;
98  use_user_constraints = use_user_constraints_;
99 }
100 
101 
103  const double x_relative,
104  const double y_relative,
105  const double angle_relative,
106  fs_type type)
107 {
108  const double *constraints;
109  const double *constraints_auto_ds;
110 
111  // determine type of the step
112  if (type == FS_TYPE_AUTO)
113  {
114  if (FS.size() == 0)
115  {
116  type = FS_TYPE_DS;
117  }
118  else
119  {
120  switch (FS[getPrevSS(FS.size())].type)
121  {
122  case FS_TYPE_SS_R:
123  type = FS_TYPE_SS_L;
124  break;
125  case FS_TYPE_SS_L:
126  case FS_TYPE_DS:
127  default:
128  type = FS_TYPE_SS_R;
129  break;
130  }
131  }
132  }
133 
135  {
136  constraints = user_constraints;
137  constraints_auto_ds = user_constraints_auto_ds;
138  }
139  else
140  {
141  constraints_auto_ds = def_constraints.auto_ds;
142  switch (type)
143  {
144  case FS_TYPE_SS_R:
145  constraints = def_constraints.ss_right;
146  break;
147  case FS_TYPE_SS_L:
148  constraints = def_constraints.ss_left;
149  break;
150  case FS_TYPE_DS:
151  default:
152  constraints = def_constraints.ds;
153  break;
154  }
155  }
156 
157 
158  Transform<double, 3> posture (Translation<double, 3>(x_relative, y_relative, 0.0));
159  Vector3d zref_offset ((constraints[0] - constraints[2])/2, 0.0, 0.0);
160 
161 
162  if (FS.size() == 0)
163  {
164  posture *= AngleAxisd(angle_relative, Vector3d::UnitZ());
165  // offset is the absolute position here.
166  Vector3d zref_abs = posture * zref_offset;
167 
168  FS.push_back(
169  footstep(
170  angle_relative,
171  posture,
172  zref_abs,
173  def_time_ms,
174  type,
175  constraints));
176  }
177  else
178  {
179  // Position of the next step
180  posture = (*FS.back().posture) * posture * AngleAxisd(angle_relative, Vector3d::UnitZ());
181 
182  double prev_a = FS.back().angle;
183  double next_a = prev_a + angle_relative;
184  Vector3d next_zref = posture * zref_offset;
185 
186 
187  // Add double support constraints that lie between the
188  // newly added step and the previous step
189  double theta = (double) 1/(ds_num + 1);
190  double angle_shift = angle_relative * theta;
191  double x_shift = theta*x_relative;
192  double y_shift = theta*y_relative;
193  Vector3d *ds_zref = &FS.back().ZMPref;
194  for (unsigned int i = 0; i < ds_num; i++)
195  {
196  Transform<double, 3> ds_posture = (*FS.back().posture)
197  * Translation<double, 3>(x_shift, y_shift, 0.0)
198  * AngleAxisd(angle_shift, Vector3d::UnitZ());
199 
200  if (i == ds_num / 2)
201  {
202  ds_zref = &next_zref;
203  }
204 
205  FS.push_back(
206  footstep(
207  FS.back().angle + angle_shift,
208  ds_posture,
209  *ds_zref,
210  ds_time_ms,
211  FS_TYPE_DS,
212  constraints_auto_ds));
213  }
214 
215 
216  // add the new step
217  FS.push_back(
218  footstep(
219  next_a,
220  posture,
221  next_zref,
222  def_time_ms,
223  type,
224  constraints));
225  }
226 }
227 
228 
229 
231  const unsigned int shift_from_current_ms,
232  double *left_foot_pos,
233  double *right_foot_pos)
234 {
235  unsigned int support_number = first_preview_step;
236  // formPreviewWindow() have already decremented the time
237  unsigned int step_time_left = FS[support_number].time_left + last_time_decrement;
238  unsigned int shift_ms = shift_from_current_ms;
239 
240 
241  while (shift_ms > step_time_left)
242  {
243  shift_ms -= step_time_left;
244  ++support_number;
245  if (support_number >= FS.size())
246  {
247  return;
248  }
249  step_time_left = FS[support_number].time_left;
250  }
251 
252 
253  if (FS[support_number].type == FS_TYPE_DS)
254  {
255  getDSFeetPositions (support_number, left_foot_pos, right_foot_pos);
256  }
257  else
258  {
259  double theta = (double)
260  ((FS[support_number].time_period - step_time_left) + shift_ms)
261  / FS[support_number].time_period;
262 
264  support_number,
265  theta,
266  left_foot_pos,
267  right_foot_pos);
268  }
269 }
270 
271 
272 
274 {
275  // current_step_number is the number of step, which will
276  // be the first in the preview window, when formPreviewWindow()
277  // is called.
278  if (FS[current_step_number].type == FS_TYPE_DS)
279  {
280  return (false);
281  }
282  else // single support
283  {
284  if (// if we are not in the initial support
285  (current_step_number != 0) &&
286  // this is the first iteration in SS
287  (FS[current_step_number].time_period == FS[current_step_number].time_left) &&
288  // the previous SS was different
290  {
291  return (true);
292  }
293  }
294 
295  return (false);
296 }
297 
298 
299 
300 void WMG::changeNextSSPosition (const double* posture, const bool zero_z_coordinate)
301 {
302  FS[getNextSS(first_preview_step)].changePosture(posture, zero_z_coordinate);
303 }
304 
305 
306 void WMG::repositionFootsteps (const double diff_x, const double diff_y)
307 {
308  int ind = 0;
309  fs_type fixed_fs_type;
310 
311 
312  ind = first_preview_step;
313  if (FS[first_preview_step].type == FS_TYPE_DS)
314  {
315  ind = getNextSS(ind);
316  }
317  fixed_fs_type = FS[ind].type;
318 
319  for (; (ind < (int) FS.size()) && (FS[ind].type != fixed_fs_type); ++ind);
320 
321  Translation<double, 3> diff(diff_x, diff_y, 0.0);
322 
323  for (; ind < (int) FS.size(); ++ind)
324  {
325  *FS[ind].posture = diff * (*FS[ind].posture);
326  FS[ind].rotate_translate(FS[ind].ca, FS[ind].sa, FS[ind].x(), FS[ind].y());
327  }
328 }
329 
330 
332 {
333  WMGret retval = WMG_OK;
334  unsigned int win_step_num = current_step_number;
335  unsigned int step_time_left = FS[win_step_num].time_left;
336 
337 
338  for (unsigned int i = 0; i < N;)
339  {
340  if (step_time_left > 0)
341  {
342  par.angle[i] = FS[win_step_num].angle;
343 
344  par.fp_x[i] = FS[win_step_num].x();
345  par.fp_y[i] = FS[win_step_num].y();
346 
347 
348  // ZMP reference coordinates
349  par.zref_x[i] = FS[win_step_num].ZMPref.x();
350  par.zref_y[i] = FS[win_step_num].ZMPref.y();
351 
352 
353  par.lb[i*2] = -FS[win_step_num].d[2];
354  par.ub[i*2] = FS[win_step_num].d[0];
355 
356  par.lb[i*2 + 1] = -FS[win_step_num].d[3];
357  par.ub[i*2 + 1] = FS[win_step_num].d[1];
358 
359 
360  unsigned int step_len_ms;
361  if (T_ms[i] == 0)
362  {
363  if (sampling_period > step_time_left)
364  {
365  step_len_ms = step_time_left;
366  }
367  else
368  {
369  step_len_ms = sampling_period;
370  }
371  }
372  else
373  {
374  if (T_ms[i] > step_time_left)
375  {
376  retval = WMG_HALT;
377  break;
378  }
379  step_len_ms = T_ms[i];
380  }
381  par.T[i] = (double) step_len_ms / 1000;
382  step_time_left -= step_len_ms;
383 
384  if (i == 0)
385  {
386  last_time_decrement = step_len_ms;
387  }
388  i++;
389  }
390  else
391  {
392  win_step_num++;
393  if (win_step_num == FS.size())
394  {
395  retval = WMG_HALT;
396  break;
397  }
398  step_time_left = FS[win_step_num].time_left;
399  }
400  }
401 
402 
403  if (retval == WMG_OK)
404  {
405  while (FS[current_step_number].time_left == 0)
406  {
408  }
409 
412  if (FS[current_step_number].time_left == 0)
413  {
415  }
416  }
417 
418  return (retval);
419 }
420 
421 
422 
423 void WMG::FS2file(const std::string filename, const bool plot_ds)
424 {
425 
426  FILE *file_op = fopen(filename.c_str(), "w");
427 
428  if(!file_op)
429  {
430  fprintf(stderr, "Cannot open file (for writing)\n");
431  return;
432  }
433 
434  fprintf(file_op,"%%\n%% Footsteps generated using the c++ version of the WMG\n%%\n\n");
435  fprintf(file_op,"cla;\n");
436  fprintf(file_op,"clear FS;\n\n");
437 
438  int i;
439  for (i=0; i< (int) FS.size(); i++ )
440  {
441  if ((plot_ds) || (FS[i].type != FS_TYPE_DS))
442  {
443  fprintf(file_op, "FS(%i).a = %f;\nFS(%i).p = [%f;%f];\nFS(%i).d = [%f;%f;%f;%f];\n",
444  i+1, FS[i].angle,
445  i+1, FS[i].x(), FS[i].y(),
446  i+1, FS[i].d[0], FS[i].d[1], FS[i].d[2], FS[i].d[3]);
447 
448  fprintf(file_op, "FS(%i).D = [%f %f;%f %f;%f %f;%f %f];\n",
449  i+1, FS[i].D[0], FS[i].D[4],
450  FS[i].D[1], FS[i].D[5],
451  FS[i].D[2], FS[i].D[6],
452  FS[i].D[3], FS[i].D[7]);
453 
454  fprintf(file_op, "FS(%i).v = [%f %f; %f %f; %f %f; %f %f; %f %f];\n",
455  i+1, FS[i].vert(0,0), FS[i].vert(0,1),
456  FS[i].vert(1,0), FS[i].vert(1,1),
457  FS[i].vert(2,0), FS[i].vert(2,1),
458  FS[i].vert(3,0), FS[i].vert(3,1),
459  FS[i].vert(0,0), FS[i].vert(0,1));
460 
461  if (FS[i].type == FS_TYPE_DS)
462  {
463  fprintf(file_op, "FS(%i).type = 1;\n\n", i+1);
464  }
465  if ((FS[i].type == FS_TYPE_SS_L) || (FS[i].type == FS_TYPE_SS_R))
466  {
467  fprintf(file_op, "FS(%i).type = 2;\n\n", i+1);
468  }
469  }
470  }
471 
472  fprintf(file_op,"hold on\n");
473  fprintf(file_op,"for i=1:length(FS)\n");
474  fprintf(file_op," if FS(i).type == 1;\n");
475  fprintf(file_op," plot (FS(i).p(1),FS(i).p(2),'gs','MarkerFaceColor','r','MarkerSize',2)\n");
476  fprintf(file_op," plot (FS(i).v(:,1), FS(i).v(:,2), 'c');\n");
477  fprintf(file_op," end\n");
478  fprintf(file_op," if FS(i).type == 2;\n");
479  fprintf(file_op," plot (FS(i).p(1),FS(i).p(2),'gs','MarkerFaceColor','g','MarkerSize',4)\n");
480  fprintf(file_op," plot (FS(i).v(:,1), FS(i).v(:,2), 'r');\n");
481  fprintf(file_op," end\n");
482  fprintf(file_op,"end\n");
483  fprintf(file_op,"grid on; %%axis equal\n");
484  fclose(file_op);
485 }
486 
487 
489  std::vector<double> & x_coord,
490  std::vector<double> & y_coord,
491  std::vector<double> & angle_rot)
492 {
493  for (unsigned int i = 0; i < FS.size(); i++)
494  {
495  if ((FS[i].type == FS_TYPE_SS_L) || (FS[i].type == FS_TYPE_SS_R))
496  {
497  x_coord.push_back(FS[i].x());
498  y_coord.push_back(FS[i].y());
499  angle_rot.push_back(FS[i].angle);
500  }
501  }
502 }
double step_height
The maximum height, that can be reached by a swing foot.
Definition: WMG.h:437
int getPrevSS(const int, const fs_type type=FS_TYPE_AUTO)
Returns index of the previous SS.
Definition: WMG_private.cpp:58
void getDSFeetPositions(const int, double *, double *)
Determine position and orientation of feet in DS.
Definition: WMG_private.cpp:90
void init_FSR()
Definition: WMG.h:178
double * zref_y
N reference coordinates of ZMP.
Definition: WMG.h:105
A container for parameters of the SMPC solver.
Definition: WMG.h:55
WMGret formPreviewWindow(smpc_parameters &)
Forms a preview window.
Definition: WMG.cpp:331
double bezier_weight_2
Definition: WMG.h:471
Definition: WMG.h:39
void init()
Definition: WMG.h:157
void getFootsteps(std::vector< double > &x_coord, std::vector< double > &y_coord, std::vector< double > &angle_rot)
Return coordinates of footstep reference points and rotation angles of footsteps (only for SS).
Definition: WMG.cpp:488
unsigned int * T_ms
Definition: WMG.h:426
defConstraints def_constraints
Default SS and DS constraints.
Definition: WMG.h:441
double bezier_inclination_2
Definition: WMG.h:473
Definition: WMG.h:38
~WMG()
Destructor.
Definition: WMG.cpp:65
void getSSFeetPositionsBezier(const int, const double, double *, double *)
Determine position and orientation of feet (using cubic Bezier curves)
double * zref_x
N reference coordinates of ZMP.
Definition: WMG.h:104
Defines a footstep.
Definition: footstep.h:29
unsigned int last_time_decrement
Definition: WMG.h:487
double * fp_x
Coordinates of N points satisfying constraints,.
Definition: WMG.h:92
Definition: WMG.h:47
int getNextSS(const int, const fs_type type=FS_TYPE_AUTO)
Returns index of the next SS.
Definition: WMG_private.cpp:23
void setFootstepParametersMS(const unsigned int def_time_ms_, const unsigned int ds_time_ms_, const unsigned int ds_number, bool use_user_constraints_=false)
Set default parameters of footsteps.
Definition: WMG.cpp:89
void changeNextSSPosition(const double *posture, const bool zero_z_coordinate)
Changes position of the next SS.
Definition: WMG.cpp:300
double ds[4]
Both feet standing together.
Definition: WMG.h:142
double bezier_weight_1
Definition: WMG.h:470
double * angle
initial h
Definition: WMG.h:88
bool use_user_constraints
Constraints given by the user, initialized to the default values on initialization.
Definition: WMG.h:447
unsigned int N
Number of iterations in a preview window.
Definition: WMG.h:424
double * lb
2*N bounds for coordinates of ZMP position.
Definition: WMG.h:98
void getFeetPositions(const unsigned int shift_from_current_ms, double *left_foot_pos, double *right_foot_pos)
Determine position and orientation of feet.
Definition: WMG.cpp:230
double auto_ds[4]
Automatically added DS.
Definition: WMG.h:145
bool isSupportSwitchNeeded()
Checks if the support foot switch is needed.
Definition: WMG.cpp:273
std::vector< footstep > FS
A vector of footsteps.
Definition: WMG.h:420
double * T
Norm of the acceleration due to gravity.
Definition: WMG.h:82
void FS2file(const std::string filename, const bool plot_ds=true)
Outputs the footsteps in FS to a Matlab/Octave script for plotting.
Definition: WMG.cpp:423
unsigned int def_time_ms
Definition: WMG.h:483
unsigned int sampling_period
Definition: WMG.h:427
double user_constraints_auto_ds[4]
Constraints given by the user, initialized to the default values on initialization.
Definition: WMG.h:446
int first_preview_step
The first step in the current preview window.
Definition: WMG.h:434
double bezier_inclination_1
Definition: WMG.h:472
double ss_right[4]
Definition: WMG.h:139
double user_constraints[4]
Constraints given by the user, initialized to the default values on initialization.
Definition: WMG.h:445
double * ub
2*N bounds for coordinates of ZMP position.
Definition: WMG.h:99
double ss_left[4]
Support constraints with safety margin.
Definition: WMG.h:138
unsigned int ds_time_ms
Definition: WMG.h:484
fs_type
Definition: WMG.h:42
WMG(const unsigned int N_, const unsigned int T_, const double step_height_=0.0135, double bezier_weight_1_=1.0, double bezier_weight_2_=2.0, double bezier_inclination_1_=0.01, double bezier_inclination_2_=0.008, bool use_fsr_constraints=false)
Initializes a WMG object.
Definition: WMG.cpp:15
void setFootstepParameters(const unsigned int def_periods, const unsigned int ds_periods, const unsigned int ds_number, bool use_user_constraints_=false)
Set default parameters of footsteps, a wrapper around not so safe setFootstepParametersMS function.
Definition: WMG.cpp:75
int current_step_number
This is the step in FS that is at the start of the current preview window.
Definition: WMG.h:431
void repositionFootsteps(const double diff_x, const double diff_y)
Reposition all subsequent footsteps that are not fixed at the current moment.
Definition: WMG.cpp:306
void addFootstep(const double, const double, const double, fs_type type=FS_TYPE_AUTO)
Adds a footstep to FS.
Definition: WMG.cpp:102
double * fp_y
Coordinates of N points satisfying constraints,.
Definition: WMG.h:93
WMGret
Definition: WMG.h:36
unsigned int ds_num
Definition: WMG.h:485