GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: src/seqplay.cc Lines: 0 513 0.0 %
Date: 2023-01-29 11:05:01 Branches: 0 1166 0.0 %

Line Branch Exec Source
1
//
2
// Copyright (C) 2012, 2013 LAAS-CNRS
3
//
4
// Author: Florent Lamiraux, Mehdi Benallegue
5
//
6
7
#include "sot/tools/seqplay.hh"
8
9
#include <dynamic-graph/command-bind.h>
10
11
#include <boost/tokenizer.hpp>
12
#include <iostream>
13
#include <stdexcept>
14
#include <vector>
15
16
namespace dynamicgraph {
17
namespace sot {
18
namespace tools {
19
using dynamicgraph::Entity;
20
using dynamicgraph::command::docCommandVoid0;
21
using dynamicgraph::command::docCommandVoid1;
22
using dynamicgraph::command::makeCommandVoid0;
23
using dynamicgraph::command::makeCommandVoid1;
24
25
Seqplay::Seqplay(const std::string& name)
26
    : Entity(name),
27
      postureSOUT_("Seqplay(" + name + ")::output(vector)::posture"),
28
      leftAnkleSOUT_("Seqplay(" + name + ")::output(MatrixHomo)::leftAnkle"),
29
      rightAnkleSOUT_("Seqplay(" + name + ")::output(MatrixHomo)::rightAnkle"),
30
      leftAnkleVelSOUT_("Seqplay(" + name + ")::output(Vector)::leftAnkleVel"),
31
      rightAnkleVelSOUT_("Seqplay(" + name +
32
                         ")::output(Vector)::rightAnkleVel"),
33
      comSOUT_("Seqplay(" + name + ")::output(vector)::com"),
34
      comdotSOUT_("Seqplay(" + name + ")::output(vector)::comdot"),
35
      comddotSOUT_("Seqplay(" + name + ")::output(vector)::comddot"),
36
      forceLeftFootSOUT_("Seqplay(" + name +
37
                         ")::output(vector)::forceLeftFoot"),
38
      forceRightFootSOUT_("Seqplay(" + name +
39
                          ")::output(vector)::forceRightFoot"),
40
      zmpSOUT_("Seqplay(" + name + ")::output(vector)::zmp"),
41
      state_(0),
42
      startTime_(0),
43
      posture_(),
44
      leftAnkle_(),
45
      rightAnkle_(),
46
      com_(),
47
      time_(),
48
      R0_(),
49
      R0t_(),
50
      R1_(),
51
      R1R0t_() {
52
  signalRegistration(postureSOUT_ << leftAnkleSOUT_ << rightAnkleSOUT_
53
                                  << leftAnkleVelSOUT_ << rightAnkleVelSOUT_
54
                                  << comSOUT_ << comdotSOUT_ << comddotSOUT_
55
                                  << forceLeftFootSOUT_ << forceRightFootSOUT_
56
                                  << zmpSOUT_);
57
  postureSOUT_.setFunction(boost::bind(&Seqplay::computePosture, this, _1, _2));
58
  comSOUT_.setFunction(boost::bind(&Seqplay::computeCom, this, _1, _2));
59
  leftAnkleSOUT_.setFunction(
60
      boost::bind(&Seqplay::computeLeftAnkle, this, _1, _2));
61
  rightAnkleSOUT_.setFunction(
62
      boost::bind(&Seqplay::computeRightAnkle, this, _1, _2));
63
  leftAnkleVelSOUT_.setFunction(
64
      boost::bind(&Seqplay::computeLeftAnkleVel, this, _1, _2));
65
  rightAnkleVelSOUT_.setFunction(
66
      boost::bind(&Seqplay::computeRightAnkleVel, this, _1, _2));
67
  comdotSOUT_.setFunction(boost::bind(&Seqplay::computeComdot, this, _1, _2));
68
  comddotSOUT_.setFunction(boost::bind(&Seqplay::computeComddot, this, _1, _2));
69
70
  zmpSOUT_.setFunction(boost::bind(&Seqplay::computeZMP, this, _1, _2));
71
72
  forceLeftFootSOUT_.setFunction(
73
      boost::bind(&Seqplay::computeForceLeftFoot, this, _1, _2));
74
  forceRightFootSOUT_.setFunction(
75
      boost::bind(&Seqplay::computeForceRightFoot, this, _1, _2));
76
77
  std::string docstring =
78
      "Load files describing a whole-body motion as reference feature "
79
      "trajectories\n"
80
      "\n"
81
      "  Input:\n"
82
      "    - string filename without extension\n"
83
      "\n"
84
      "  Data is read from the following files:\n"
85
      "    - posture from file \"filename.posture\",\n"
86
      "    - left ankle task from \"filename.la\",\n"
87
      "    - right ankle task from \"filename.ra\",\n"
88
      "    - center of mass task from \"filename.com\",\n"
89
      "    - force and moment in left foot from \"filename.fl\",\n"
90
      "    - force and moment in right foot from \"filename.fr\".\n"
91
      "  Each file should contain one column for time and as many columns as"
92
      " required\n"
93
      "  depending on data-type, i.e.:\n"
94
      "    - 17 for homogeneous matrices,\n"
95
      "    -  4 for center of mass.\n"
96
      "\n";
97
  addCommand("load", makeCommandVoid1(*this, &Seqplay::load, docstring));
98
99
  addCommand("start", makeCommandVoid0(*this, &Seqplay::start,
100
                                       docCommandVoid0("Start motion")));
101
  for (size_t i = 0; i < 7; ++i) {
102
    facultativeFound_[i] = false;
103
  }
104
}
105
106
void Seqplay::load(const std::string& filename) {
107
  using boost::escaped_list_separator;
108
  typedef boost::tokenizer<escaped_list_separator<char> > tokenizer_t;
109
  std::string line;
110
  std::string fn[4];
111
  std::string facultativefn[7];
112
113
  std::ifstream file[4];
114
  std::ifstream facultativeFile[7];
115
  unsigned int lineNumber = 0;
116
  int postureSize = -2;
117
118
  fn[0] = filename + ".posture";
119
  fn[1] = filename + ".la";
120
  fn[2] = filename + ".ra";
121
  fn[3] = filename + ".com";
122
123
  // Open files
124
  for (std::size_t i = 0; i < 4; i++) {
125
    file[i].open(fn[i].c_str());
126
    if (!file[i].is_open()) {
127
      throw std::runtime_error(std::string("Failed to open file ") + fn[i]);
128
    }
129
  }
130
131
  facultativefn[0] = filename + ".fl";
132
  facultativefn[1] = filename + ".fr";
133
  facultativefn[2] = filename + ".comdot";
134
  facultativefn[3] = filename + ".comddot";
135
  facultativefn[4] = filename + ".zmp";
136
  facultativefn[5] = filename + ".ladot";
137
  facultativefn[6] = filename + ".radot";
138
139
  // Open facultative files
140
  for (std::size_t i = 0; i < 7; i++) {
141
    facultativeFile[i].open(facultativefn[i].c_str());
142
    if (facultativeFile[i].is_open()) {
143
      facultativeFound_[i] = true;
144
    } else {
145
      facultativeFound_[i] = false;
146
    }
147
  }
148
149
  // both feet forces must be defined together
150
  if (facultativeFound_[0] != facultativeFound_[1]) {
151
    throw std::runtime_error(
152
        std::string("File ") +
153
        (facultativeFound_[0] ? facultativefn[1] : facultativefn[0]) +
154
        " failed to open");
155
  }
156
157
  // both ankle velocity must be defined together
158
  if (facultativeFound_[5] != facultativeFound_[6]) {
159
    throw std::runtime_error(
160
        std::string("File ") +
161
        (facultativeFound_[5] ? facultativefn[6] : facultativefn[5]) +
162
        " failed to open");
163
  }
164
165
  posture_.clear();
166
  leftAnkle_.clear();
167
  rightAnkle_.clear();
168
  com_.clear();
169
  comdot_.clear();
170
  comddot_.clear();
171
  zmp_.clear();
172
  leftAnkleDot_.clear();
173
  rightAnkleDot_.clear();
174
175
  forceLeftFoot_.clear();
176
  forceRightFoot_.clear();
177
178
  // Read posture
179
  while (file[0].good()) {
180
    std::getline(file[0], line);
181
    ++lineNumber;
182
    tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
183
    std::vector<double> components;
184
    for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
185
      components.push_back(atof(it->c_str()));
186
    }
187
    if (components.size() == 0) {
188
      break;
189
    }
190
    if (postureSize == -2) {
191
      postureSize = static_cast<int>(components.size() - 1);
192
    } else {
193
      if (postureSize != static_cast<int>(components.size()) - 1) {
194
        std::ostringstream oss;
195
        oss << fn[0] << ", line " << lineNumber << ": config of size "
196
            << components.size() - 1 << ". Expecting " << postureSize << ".";
197
        throw std::runtime_error(oss.str());
198
      }
199
    }
200
    Vector config(static_cast<unsigned>(components.size() - 1));
201
    for (unsigned i = 1; i < components.size(); ++i) {
202
      config(i - 1) = components[i];
203
    }
204
    posture_.push_back(config);
205
  }
206
  file[0].close();
207
208
  readAnkleFile(file[1], leftAnkle_, fn[1]);
209
  readAnkleFile(file[2], rightAnkle_, fn[2]);
210
211
  // Read com
212
  lineNumber = 0;
213
  while (file[3].good()) {
214
    std::getline(file[3], line);
215
    ++lineNumber;
216
    tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
217
    std::vector<double> components;
218
    for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
219
      components.push_back(atof(it->c_str()));
220
    }
221
    if (components.size() == 0) break;
222
    Vector com(3);
223
    if (components.size() != 4) {
224
      std::ostringstream oss;
225
      oss << fn[3] << ", line " << lineNumber << ": expecting 4 numbers.";
226
      throw std::runtime_error(oss.str());
227
    }
228
    time_.push_back(components[0]);
229
    for (unsigned i = 1; i < 4; ++i) {
230
      com(i - 1) = components[i];
231
    }
232
    com_.push_back(com);
233
  }
234
  file[3].close();
235
236
  // Read forces
237
  if (facultativeFound_[0]) {
238
    readForceFile(facultativeFile[0], forceLeftFoot_, facultativefn[4]);
239
    readForceFile(facultativeFile[1], forceRightFoot_, facultativefn[5]);
240
  }
241
242
  // Read com velocity
243
  if (facultativeFound_[2]) {
244
    lineNumber = 0;
245
    while (facultativeFile[2].good()) {
246
      std::getline(facultativeFile[2], line);
247
      ++lineNumber;
248
      tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
249
      std::vector<double> components;
250
      for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
251
        components.push_back(atof(it->c_str()));
252
      }
253
      if (components.size() == 0) break;
254
      Vector comdot(3);
255
      if (components.size() != 4) {
256
        std::ostringstream oss;
257
        oss << facultativefn[2] << ", line " << lineNumber
258
            << ": expecting 4 numbers.";
259
        throw std::runtime_error(oss.str());
260
      }
261
262
      for (unsigned i = 1; i < 4; ++i) {
263
        comdot(i - 1) = components[i];
264
      }
265
      comdot_.push_back(comdot);
266
    }
267
    facultativeFile[2].close();
268
  }
269
270
  // Read com acceleration
271
  if (facultativeFound_[3]) {
272
    lineNumber = 0;
273
    while (facultativeFile[3].good()) {
274
      std::getline(facultativeFile[3], line);
275
      ++lineNumber;
276
      tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
277
      std::vector<double> components;
278
      for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
279
        components.push_back(atof(it->c_str()));
280
      }
281
      if (components.size() == 0) break;
282
      Vector comddot(3);
283
      if (components.size() != 4) {
284
        std::ostringstream oss;
285
        oss << facultativefn[3] << ", line " << lineNumber
286
            << ": expecting 4 numbers.";
287
        throw std::runtime_error(oss.str());
288
      }
289
290
      for (unsigned i = 1; i < 4; ++i) {
291
        comddot(i - 1) = components[i];
292
      }
293
      comddot_.push_back(comddot);
294
    }
295
    facultativeFile[3].close();
296
  }
297
298
  // left ankle velocity
299
  if (facultativeFound_[5]) {
300
    lineNumber = 0;
301
    while (facultativeFile[5].good()) {
302
      std::getline(facultativeFile[5], line);
303
      ++lineNumber;
304
      tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
305
      std::vector<double> components;
306
      for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
307
        components.push_back(atof(it->c_str()));
308
      }
309
      if (components.size() == 0) break;
310
      Vector ankledot(7);
311
      if (components.size() != 7) {
312
        std::ostringstream oss;
313
        oss << facultativefn[5] << ", line " << lineNumber
314
            << ": expecting 7 numbers.";
315
        throw std::runtime_error(oss.str());
316
      }
317
318
      for (unsigned i = 1; i < 7; ++i) {
319
        ankledot(i - 1) = components[i];
320
      }
321
      leftAnkleDot_.push_back(ankledot);
322
    }
323
    facultativeFile[5].close();
324
  }
325
326
  // right ankle velocity
327
  if (facultativeFound_[6]) {
328
    lineNumber = 0;
329
    while (facultativeFile[6].good()) {
330
      std::getline(facultativeFile[6], line);
331
      ++lineNumber;
332
      tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
333
      std::vector<double> components;
334
      for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
335
        components.push_back(atof(it->c_str()));
336
      }
337
      if (components.size() == 0) break;
338
      Vector ankledot(7);
339
      if (components.size() != 7) {
340
        std::ostringstream oss;
341
        oss << facultativefn[6] << ", line " << lineNumber
342
            << ": expecting 7 numbers.";
343
        throw std::runtime_error(oss.str());
344
      }
345
346
      for (unsigned i = 1; i < 7; ++i) {
347
        ankledot(i - 1) = components[i];
348
      }
349
      rightAnkleDot_.push_back(ankledot);
350
    }
351
    facultativeFile[6].close();
352
  }
353
354
  // Read zmp
355
  if (facultativeFound_[4]) {
356
    lineNumber = 0;
357
    while (facultativeFile[4].good()) {
358
      std::getline(facultativeFile[4], line);
359
      ++lineNumber;
360
      tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
361
      std::vector<double> components;
362
      for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
363
        components.push_back(atof(it->c_str()));
364
      }
365
      if (components.size() == 0) break;
366
      Vector zmp(3);
367
      if (components.size() != 4) {
368
        std::ostringstream oss;
369
        oss << facultativefn[3] << ", line " << lineNumber
370
            << ": expecting 4 numbers.";
371
        throw std::runtime_error(oss.str());
372
      }
373
374
      for (unsigned i = 1; i < 4; ++i) {
375
        zmp(i - 1) = components[i];
376
      }
377
      zmp_.push_back(zmp);
378
    }
379
    facultativeFile[4].close();
380
  }
381
382
  // Check that size of files is the same
383
  if (posture_.size() != leftAnkle_.size() ||
384
      posture_.size() != rightAnkle_.size() || posture_.size() != com_.size() ||
385
      (facultativeFound_[0] && posture_.size() != forceLeftFoot_.size()) ||
386
      (facultativeFound_[1] && posture_.size() != forceRightFoot_.size()) ||
387
      (facultativeFound_[2] && posture_.size() != comdot_.size()) ||
388
      (facultativeFound_[3] && posture_.size() != comddot_.size()) ||
389
      (facultativeFound_[4] && posture_.size() != zmp_.size()) ||
390
      (facultativeFound_[5] && posture_.size() != leftAnkleDot_.size()) ||
391
      (facultativeFound_[6] && posture_.size() != rightAnkleDot_.size())) {
392
    std::ostringstream oss;
393
    oss << "Seqplay: Files should have the same number of lines. Read"
394
        << std::endl;
395
    oss << "  " << posture_.size() << " lines from " << filename << ".posture,"
396
        << std::endl;
397
    oss << "  " << leftAnkle_.size() << " lines from " << filename << ".la,"
398
        << std::endl;
399
    oss << "  " << rightAnkle_.size() << " lines from " << filename << ".ra,"
400
        << std::endl;
401
    oss << "  " << com_.size() << " lines from " << filename << ".com,"
402
        << std::endl;
403
    if (facultativeFound_[0]) {
404
      oss << "  " << forceLeftFoot_.size() << " lines from " << filename
405
          << ".fl" << std::endl;
406
      oss << "  " << forceRightFoot_.size() << " lines from " << filename
407
          << ".fr" << std::endl;
408
    }
409
410
    if (facultativeFound_[2]) {
411
      oss << "  " << comdot_.size() << " lines from " << filename << ".comdot"
412
          << std::endl;
413
    }
414
415
    if (facultativeFound_[3]) {
416
      oss << "  " << comddot_.size() << " lines from " << filename << ".comddot"
417
          << std::endl;
418
    }
419
420
    if (facultativeFound_[4]) {
421
      oss << "  " << zmp_.size() << " lines from " << filename << ".zmp"
422
          << std::endl;
423
    }
424
425
    if (facultativeFound_[5]) {
426
      oss << "  " << leftAnkleDot_.size() << " lines from " << filename
427
          << ".ladot" << std::endl;
428
      oss << "  " << leftAnkleDot_.size() << " lines from " << filename
429
          << ".radot" << std::endl;
430
    }
431
432
    throw std::runtime_error(oss.str());
433
  }
434
  state_ = 0;
435
}
436
437
void Seqplay::start() {
438
  if (state_ == 0) {
439
    state_ = 1;
440
    startTime_ =
441
        std::max(std::max(comSOUT_.getTime(), comdotSOUT_.getTime()),
442
                 std::max(leftAnkleSOUT_.getTime(), rightAnkleSOUT_.getTime()));
443
    startTime_ = std::max(startTime_, postureSOUT_.getTime());
444
  }
445
}
446
447
Vector& Seqplay::computePosture(Vector& pos, const int& t) {
448
  if (posture_.size() == 0) {
449
    throw std::runtime_error(
450
        "Seqplay posture: Signals not initialized. read files first.");
451
  }
452
  std::size_t configId;
453
  if (state_ == 0) {
454
    configId = 0;
455
  } else if (state_ == 1) {
456
    configId = t - startTime_;
457
    if (configId == posture_.size() - 1) {
458
      state_ = 2;
459
    }
460
  } else {
461
    configId = posture_.size() - 1;
462
  }
463
  pos = posture_[configId];
464
  return pos;
465
}
466
467
MatrixHomogeneous& Seqplay::computeLeftAnkle(MatrixHomogeneous& la,
468
                                             const int& t) {
469
  if (leftAnkle_.size() == 0) {
470
    throw std::runtime_error(
471
        "Seqplay leftAnkle: Signals not initialized. read files first.");
472
  }
473
  std::size_t configId;
474
  if (state_ == 0) {
475
    configId = 0;
476
  } else if (state_ == 1) {
477
    configId = t - startTime_;
478
    if (configId == posture_.size() - 1) {
479
      state_ = 2;
480
    }
481
  } else {
482
    configId = posture_.size() - 1;
483
  }
484
  la = leftAnkle_[configId];
485
  return la;
486
}
487
488
MatrixHomogeneous& Seqplay::computeRightAnkle(MatrixHomogeneous& ra,
489
                                              const int& t) {
490
  if (rightAnkle_.size() == 0) {
491
    throw std::runtime_error(
492
        "Seqplay rightAnkle: Signals not initialized. read files first.");
493
  }
494
  std::size_t configId;
495
  if (state_ == 0) {
496
    configId = 0;
497
  } else if (state_ == 1) {
498
    configId = t - startTime_;
499
    if (configId == posture_.size() - 1) {
500
      state_ = 2;
501
    }
502
  } else {
503
    configId = posture_.size() - 1;
504
  }
505
  ra = rightAnkle_[configId];
506
  return ra;
507
}
508
509
Vector& Seqplay::computeAnkleVelocity(
510
    Vector& velocity, const std::vector<MatrixHomogeneous>& ankleVector,
511
    const int& t) {
512
  velocity.resize(6);
513
  velocity.setZero();
514
  std::size_t configId;
515
  if (state_ == 0) {
516
    configId = 0;
517
  } else if (state_ == 1) {
518
    configId = t - startTime_;
519
    if (configId == com_.size() - 1) {
520
      state_ = 2;
521
    }
522
  } else {
523
    configId = posture_.size() - 1;
524
  }
525
526
  if (configId > 0 && configId < com_.size() - 1) {
527
    const MatrixHomogeneous& M1 = ankleVector[configId + 1];
528
    const MatrixHomogeneous& M0 = ankleVector[configId];
529
    double dt = 1 / (time_[configId + 1] - time_[configId]);
530
    for (unsigned i = 0; i < 3; ++i) {
531
      velocity(i) = (M1(i, 3) - M0(i, 3)) * dt;
532
    }
533
    R1_ = M1.linear();
534
    R0_ = M0.linear();
535
    R0t_ = R0_.transpose();
536
    R1R0t_ = R1_ * R0t_;
537
    velocity(3) = (R1R0t_(2, 1)) * dt;
538
    velocity(4) = (R1R0t_(0, 2)) * dt;
539
    velocity(5) = (R1R0t_(1, 0)) * dt;
540
  }
541
542
  return velocity;
543
}
544
545
Vector& Seqplay::computeLeftAnkleVel(Vector& velocity, const int& t) {
546
  // if there is no file, the velocity is computed using finite differences
547
  if (!facultativeFound_[5]) {
548
    return computeAnkleVelocity(velocity, leftAnkle_, t);
549
  } else {
550
    std::size_t configId;
551
    if (state_ == 0) {
552
      configId = 0;
553
    } else if (state_ == 1) {
554
      configId = t - startTime_;
555
      if (configId == posture_.size() - 1) {
556
        state_ = 2;
557
      }
558
    } else {
559
      configId = posture_.size() - 1;
560
    }
561
    velocity = leftAnkleDot_[configId];
562
    return velocity;
563
  }
564
}
565
566
Vector& Seqplay::computeRightAnkleVel(Vector& velocity, const int& t) {
567
  if (!facultativeFound_[6]) {
568
    return computeAnkleVelocity(velocity, rightAnkle_, t);
569
  } else {
570
    std::size_t configId;
571
    if (state_ == 0) {
572
      configId = 0;
573
    } else if (state_ == 1) {
574
      configId = t - startTime_;
575
      if (configId == posture_.size() - 1) {
576
        state_ = 2;
577
      }
578
    } else {
579
      configId = posture_.size() - 1;
580
    }
581
    velocity = rightAnkleDot_[configId];
582
    return velocity;
583
  }
584
}
585
586
Vector& Seqplay::computeCom(Vector& com, const int& t) {
587
  if (com_.size() == 0) {
588
    throw std::runtime_error(
589
        "Seqplay com: Signals not initialized. read files first.");
590
  }
591
  std::size_t configId;
592
  if (state_ == 0) {
593
    configId = 0;
594
  } else if (state_ == 1) {
595
    configId = t - startTime_;
596
    if (configId == com_.size() - 1) {
597
      state_ = 2;
598
    }
599
  } else {
600
    configId = posture_.size() - 1;
601
  }
602
  com = com_[configId];
603
  return com;
604
}
605
606
Vector& Seqplay::computeZMP(Vector& zmp, const int& t) {
607
  if (zmp_.size() == 0) {
608
    throw std::runtime_error("Seqplay zmp: Signals not initialized.");
609
  }
610
  std::size_t configId;
611
  if (state_ == 0) {
612
    configId = 0;
613
  } else if (state_ == 1) {
614
    configId = t - startTime_;
615
    if (configId == com_.size() - 1) {
616
      state_ = 2;
617
    }
618
  } else {
619
    configId = posture_.size() - 1;
620
  }
621
  zmp = zmp_[configId];
622
  return zmp;
623
}
624
625
Vector& Seqplay::computeComdot(Vector& comdot, const int& t) {
626
  if (facultativeFound_[2]) {
627
    std::size_t configId;
628
    if (state_ == 0) {
629
      configId = 0;
630
    } else if (state_ == 1) {
631
      configId = t - startTime_;
632
      if (configId == posture_.size() - 1) {
633
        state_ = 2;
634
      }
635
    } else {
636
      configId = posture_.size() - 1;
637
    }
638
    comdot = comdot_[configId];
639
    return comdot;
640
  } else {
641
    // finite differences
642
643
    if (com_.size() == 0) {
644
      throw std::runtime_error(
645
          "Seqplay comdot: Signals not initialized. read files first.");
646
    }
647
    std::size_t configId;
648
    if (state_ == 0) {
649
      configId = 0;
650
    } else if (state_ == 1) {
651
      configId = t - startTime_;
652
      if (configId == com_.size() - 1) {
653
        state_ = 2;
654
      }
655
    } else {
656
      configId = posture_.size() - 1;
657
    }
658
    comdot.resize(com_[0].size());
659
    comdot.setZero();
660
    if (configId > 0 && configId < com_.size() - 1) {
661
      const Vector& q_1 = com_[configId + 1];
662
      const Vector& q_0 = com_[configId];
663
      double dt = 1 / (time_[configId + 1] - time_[configId]);
664
      comdot = (q_1 - q_0) * dt;
665
    }
666
    return comdot;
667
  }
668
}
669
670
Vector& Seqplay::computeComddot(Vector& comddot, const int& t) {
671
  if (facultativeFound_[3]) {
672
    std::size_t configId;
673
    if (state_ == 0) {
674
      configId = 0;
675
    } else if (state_ == 1) {
676
      configId = t - startTime_;
677
      if (configId == posture_.size() - 1) {
678
        state_ = 2;
679
      }
680
    } else {
681
      configId = posture_.size() - 1;
682
    }
683
    comddot = comddot_[configId];
684
    return comddot;
685
  } else {
686
    // finite differences
687
    if (com_.size() == 0) {
688
      throw std::runtime_error(
689
          "Seqplay comddot: Signals not initialized. read files first.");
690
    }
691
    std::size_t configId;
692
    if (state_ == 0) {
693
      configId = 0;
694
    } else if (state_ == 1) {
695
      configId = t - startTime_;
696
      if (configId == com_.size() - 1) {
697
        state_ = 2;
698
      }
699
    } else {
700
      configId = posture_.size() - 1;
701
    }
702
    comddot.resize(com_[0].size());
703
    comddot.setZero();
704
    if (configId > 0 && configId < com_.size() - 2) {
705
      Vector qdot_1;
706
      Vector qdot_0;
707
708
      double dt_0 = 1 / (time_[configId + 1] - time_[configId]);
709
710
      if (facultativeFound_[2]) {
711
        qdot_1 = comdot_[configId + 1];
712
        qdot_0 = comdot_[configId];
713
      } else {
714
        const Vector& q_2 = com_[configId + 2];
715
        const Vector& q_1 = com_[configId + 1];
716
        const Vector& q_0 = com_[configId];
717
        double dt_1 = 1 / (time_[configId + 2] - time_[configId + 1]);
718
719
        qdot_1 = (q_2 - q_1) * dt_1;
720
        qdot_0 = (q_1 - q_0) * dt_0;
721
      }
722
723
      for (int i = 0; i < comddot.size(); ++i) {
724
        comddot(i) = (qdot_1(i) - qdot_0(i)) * dt_0;
725
      }
726
    }
727
    return comddot;
728
  }
729
}
730
731
Vector& Seqplay::computeForceFoot(Vector& force,
732
                                  const std::vector<Vector>& forceVector,
733
                                  const int& t) {
734
  if (forceVector.size() == 0) {
735
    throw std::runtime_error(
736
        "Seqplay foot force: Force signals not initialized.");
737
  }
738
  std::size_t configId;
739
  if (state_ == 0) {
740
    configId = 0;
741
  } else if (state_ == 1) {
742
    configId = t - startTime_;
743
    if (configId == forceVector.size() - 1) {
744
      state_ = 2;
745
    }
746
  } else {
747
    configId = posture_.size() - 1;
748
  }
749
  force = forceVector[configId];
750
  return force;
751
}
752
753
Vector& Seqplay::computeForceLeftFoot(Vector& force, const int& t) {
754
  return computeForceFoot(force, forceLeftFoot_, t);
755
}
756
757
Vector& Seqplay::computeForceRightFoot(Vector& force, const int& t) {
758
  return computeForceFoot(force, forceRightFoot_, t);
759
}
760
761
std::string Seqplay::getDocString() const {
762
  return "Provide task references for a whole-body motion\n"
763
         "\n"
764
         "  The reference trajectories of the following features is loaded "
765
         "from files\n"
766
         "  using command load:\n"
767
         "    - posture,\n"
768
         "    - left ankle,\n"
769
         "    - right ankle, and\n"
770
         "    - center of mass.\n"
771
         "\n"
772
         "  To use this entity,\n"
773
         "    1. call method load,\n"
774
         "    2. plug reference signals into robot signals and\n"
775
         "    3. call method start.\n"
776
         "  Warning: pluging signals before loading trajectories will fail.\n";
777
}
778
779
void Seqplay::readAnkleFile(std::ifstream& file,
780
                            std::vector<MatrixHomogeneous>& data,
781
                            const std::string& filename) {
782
  using boost::escaped_list_separator;
783
  typedef boost::tokenizer<escaped_list_separator<char> > tokenizer_t;
784
  unsigned int lineNumber = 0;
785
  std::string line;
786
787
  while (file.good()) {
788
    std::getline(file, line);
789
    ++lineNumber;
790
    tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
791
    std::vector<double> components;
792
    for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
793
      components.push_back(atof(it->c_str()));
794
    }
795
    if (components.size() == 0) break;
796
    if (components.size() != 17) {
797
      std::ostringstream oss;
798
      oss << filename << ", line " << lineNumber
799
          << ": expecting 17 numbers, got " << components.size() << ".";
800
      throw std::runtime_error(oss.str());
801
    }
802
    MatrixHomogeneous la;
803
    std::size_t i = 1;
804
    for (unsigned row = 0; row < 4; ++row) {
805
      for (unsigned col = 0; col < 4; ++col) {
806
        la(row, col) = components[i];
807
        ++i;
808
      }
809
    }
810
    data.push_back(la);
811
  }
812
  file.close();
813
}
814
815
void Seqplay::readForceFile(std::ifstream& file, std::vector<Vector>& data,
816
                            const std::string& filename) {
817
  using boost::escaped_list_separator;
818
  typedef boost::tokenizer<escaped_list_separator<char> > tokenizer_t;
819
  unsigned int lineNumber = 0;
820
  std::string line;
821
822
  while (file.good()) {
823
    std::getline(file, line);
824
    ++lineNumber;
825
    tokenizer_t tok(line, escaped_list_separator<char>('\\', '\t', '\"'));
826
    std::vector<double> components;
827
    for (tokenizer_t::iterator it = tok.begin(); it != tok.end(); ++it) {
828
      components.push_back(atof(it->c_str()));
829
    }
830
    if (components.size() == 0) break;
831
    if (components.size() != 7) {
832
      std::ostringstream oss;
833
      oss << filename << ", line " << lineNumber
834
          << ": expecting 7 numbers, got " << components.size() << ".";
835
      throw std::runtime_error(oss.str());
836
    }
837
    Vector force(6);
838
    for (unsigned i = 1; i < 7; ++i) {
839
      force(i - 1) = components[i];
840
    }
841
    data.push_back(force);
842
  }
843
  file.close();
844
}
845
846
DYNAMICGRAPH_FACTORY_ENTITY_PLUGIN(Seqplay, "Seqplay");
847
}  // namespace tools
848
}  // namespace sot
849
}  // namespace dynamicgraph