MP.cpp
Go to the documentation of this file.
1 #include "MP.h"
2 
3 #include <boost/archive/text_iarchive.hpp>
4 #include <boost/archive/text_oarchive.hpp>
5 #include <boost/archive/xml_iarchive.hpp>
6 #include <boost/archive/xml_oarchive.hpp>
7 
9 
10 #include "../utils.h"
11 #include <mplib/core/SystemState.h>
12 
14 {
15 
16  //MP::MP(const std::string &name, nlohmann::json &userConfig, nlohmann::json &defaultConfig)
17  MP::MP(const MPConfig& c)
18  {
19 
20  cfg = c;
21  mplib::factories::VMPFactory mpfactory;
22  mpfactory.addConfig("kernelSize", c.kernelSize);
23 
24  resetVMPType(c.mpTypeString);
25  // ARMARX_INFO << "Creating mp with name: " << c.name << "\n" << VAROUT(c.className) << "\n" << VAROUT(c.mpTypeString) << "\n" << VAROUT(c.mpMode) << "\n" << VAROUT(c.mpStyle);
26  std::shared_ptr<mplib::representation::AbstractMovementPrimitive> mp =
27  mpfactory.createMP(vmpType);
28  vmp = std::dynamic_pointer_cast<mplib::representation::vmp::PrincipalComponentVMP>(mp);
29 
30  if (cfg.viaPoints.size() > 0)
31  {
32  ARMARX_INFO << "-- adding via points: " << cfg.viaPoints.size();
33  int index = 0;
34  for (const auto& vp : cfg.viaPoints)
35  {
36  ARMARX_INFO << "---- (" << index << ") canonical value: " << vp.canonicalValue
37  << " --- " << common::dVecToString(vp.viaPointValue);
38  ARMARX_CHECK_GREATER_EQUAL(vp.canonicalValue, 0);
39  ARMARX_CHECK_LESS_EQUAL(vp.canonicalValue, 1);
40  userDefinedViaPoints.push_back({vp.canonicalValue, vp.viaPointValue});
41  index++;
42  }
43  }
44  }
45 
46  const std::string&
47  MP::getMPName() const
48  {
49  return cfg.name;
50  }
51 
52  const std::string&
54  {
55  return cfg.className;
56  }
57 
58  const std::string&
60  {
61  return cfg.nodeSetName;
62  }
63 
64  const std::string&
65  MP::getRole() const
66  {
67  return cfg.role;
68  }
69 
70  void
72  {
73  start(std::vector<double>());
74  }
75 
76  void
77  MP::start(const DVec& goals)
78  {
79  start(goals, std::vector<double>());
80  }
81 
82  void
83  MP::start(const DVec& goals, Ice::Double timeDuration)
84  {
85  cfg.durationSec = timeDuration;
86  start(goals);
87  }
88 
89  void
91  {
92  cfg.durationSec = timeDuration;
93  }
94 
95  void
96  MP::start(const DVec& goals, const DVec& starts, Ice::Double timeDuration)
97  {
98  cfg.durationSec = timeDuration;
99  start(goals, starts);
100  }
101 
102  void
103  MP::start(const DVec& goals, const DVec& starts)
104  {
105  ARMARX_INFO << "---- start " << cfg.name;
106  canonicalValue = 1.0;
107  /// parse user defined viapoints from configuration file
108  for (const auto& vp : userDefinedViaPoints)
109  {
110  setViaPoint(vp.first, vp.second);
111  // ARMARX_INFO << "viapoint at " << vp.first << " is " << common::dVecToString(vp.second);
112  }
113 
114  /// overwrite goals and starts if available
115  setStartAndGoal(starts, goals);
116 
117  /// prepare execution
118  LockGuardType guard{mpMutex};
119  vmp->prepareExecution(targetPoseVec, currentState);
120  auto vps = vmp->getViaPoints();
121  ARMARX_INFO << "---- Your MP have: ";
122  int index = 0;
123  for (const auto& v : vps)
124  {
125  ARMARX_INFO << "------ (" << index << ") viapoint at " << v.first << " --- "
127  mplib::core::SystemState::convertStatesToArray(v.second, 0));
128  index++;
129  }
130 
131  /// set flag
132  running.store(true);
133  stopRequested.store(false);
134  resume();
135  ARMARX_INFO << "---- MP started: " << cfg.name;
136  }
137 
138  void
140  {
141  running.store(false);
142  stopRequested.store(false);
143  }
144 
145  void
147  {
148  stopRequested.store(true);
149  }
150 
151  void
153  {
154  paused.store(true);
155  }
156 
157  void
159  {
160  paused.store(false);
161  }
162 
163  void
165  {
166  if (running.load())
167  {
168  ARMARX_INFO << "cannot reset a running mp, please stop it first.";
169  }
170  else
171  {
172  userDefinedViaPoints.clear();
173  targetPoseVec.clear();
174  targetPoseVecInTraj.clear();
175  currentState.clear();
177  goalSetByUser.store(false);
178  mpTrained.store(false);
179  prevViapoint.clear();
180  }
181  }
182 
183  bool
185  {
186  return !running.load();
187  }
188 
189  bool
191  {
192  return running.load();
193  }
194 
195  bool
197  {
198  return firstRun.load();
199  }
200 
201  bool
203  {
204  return stopRequested.load();
205  }
206 
207  MPConfig
209  {
210  return cfg;
211  }
212 
213  void
214  MP::learnFromTraj(const MPTrajs& mpTrajs)
215  {
216  ARMARX_INFO << "-- Train MP '" << cfg.name << "' from trajectories";
217  MPTrajs trajList;
218  if (mpTrajs.empty())
219  {
220  ARMARX_INFO << "---- using default trajectories from the MP configuration";
221  trajList = cfg.trajectoryList;
222  }
223  else
224  {
225  ARMARX_INFO << "---- use user-provided traj";
226  trajList = mpTrajs;
227  }
228 
229  std::vector<mplib::core::SampledTrajectory> trajs;
230  for (const auto& mpTraj : trajList)
231  {
232  std::map<double, std::vector<double>> trajMap;
233  for (int i = 0; i < mpTraj.time.size(); ++i)
234  {
235  auto& row_vector = mpTraj.traj.row(i);
236  std::vector<double> vec(row_vector.data(), row_vector.data() + row_vector.size());
237  trajMap.emplace(mpTraj.time(i), vec);
238  }
239  mplib::core::SampledTrajectory traj(trajMap);
240  trajs.push_back(traj);
241  }
242  ARMARX_TRACE;
243  trainMPFromTraj(trajs);
244  }
245 
246  void
247  MP::learnFromCSV(const Ice::StringSeq& fileNames)
248  {
249  ARMARX_INFO << "-- Train MP '" << cfg.name << "' from csv files";
250  std::vector<std::string> fileList;
251  if (fileNames.empty())
252  {
253  ARMARX_INFO << "---- using default trajectory list: " << cfg.fileList[0];
254  fileList = cfg.fileList;
255  }
256  else
257  {
258  fileList = fileNames;
259  }
260 
261  std::vector<mplib::core::SampledTrajectory> trajs;
262  for (auto& file : fileList)
263  {
264  mplib::core::SampledTrajectory traj;
265  traj.readFromCSVFile(file);
266  trajs.push_back(traj);
267  }
268  trainMPFromTraj(trajs);
269  }
270 
271  void
272  MP::trainMPFromTraj(std::vector<mplib::core::SampledTrajectory>& trajs)
273  {
274  if (cfg.regressionModel == "gpr")
275  {
276  vmp->setBaseFunctionApproximator(
277  std::make_unique<mplib::math::function_approximation::GaussianProcessRegression<
278  mplib::math::kernel::SquaredExponentialCovarianceFunction>>(
279  0.01, 0.1, 0.000001));
280  for (auto& traj : trajs)
281  {
282  traj = mplib::core::SampledTrajectory::downSample(traj, 100);
283  }
284  }
285  ARMARX_TRACE;
286  vmp->learnFromTrajectories(trajs);
287  ARMARX_TRACE;
288 
289  currentState.clear();
290  targetPoseVecInTraj.clear();
291 
292  ARMARX_INFO << "---- Your trajectory has " << VAROUT(trajs[0].dim());
293  for (size_t i = 0; i < trajs[0].dim(); i++)
294  {
295  mplib::representation::MPState state(trajs[0].begin()->getPosition(i),
296  trajs[0].begin()->getDeriv(i, 1));
297  currentState.push_back(state);
298  targetPoseVecInTraj.push_back(trajs[0].rbegin()->getPosition(i));
299  }
300  ARMARX_TRACE;
301  mpTrained.store(true);
302  ARMARX_INFO << "---- MP trained";
303  }
304 
305  void
307  {
308  if (not cfg.fileList.empty())
309  {
310  learnFromCSV();
311  }
312  else if (not cfg.trajectoryList.empty())
313  {
314  learnFromTraj();
315  }
316  else
317  {
319  << cfg.name
320  << ": You don't provide any trajectory files (path on the robot) nor trajectories "
321  "in "
322  "type std::vector<armarx::control::common::mp::arondto::MPTraj> in your "
323  "configuration file. \n"
324  << "If you intended train MPs by providing files or "
325  "trajectories on the fly, consider using \n"
326  << "ctrl.learnFromCSV(Ice::StringSeq& fileNames) or \n"
327  << "ctrl.learnFromCSVlearnFromTrajs(armarx::aron::data::dto::DictPtr& dict)";
328  }
329  }
330 
331  void
332  MP::setGoal(const DVec& goals)
333  {
334  ARMARX_INFO << "---- Reset MP goal: " << common::dVecToString(goals);
335  if (!goals.empty())
336  {
337  goalSetByUser.store(true);
338  targetPoseVec = goals;
339  }
340  else if (!targetPoseVec.empty())
341  {
343  << "---- user specified empty goal, try to use goals in your configuration file:\n"
345  }
346  else if (!targetPoseVecInTraj.empty())
347  {
349  << "---- user specified empty goal, try to use goals learned from trajectory:\n"
352  }
353  else
354  {
355  ARMARX_WARNING << "---- user specified empty goal";
356  }
357  }
358 
359  void
360  MP::setStart(const DVec& starts)
361  {
362  ARMARX_INFO << "---- Reset MP start: " << common::dVecToString(starts);
363  if (!starts.empty())
364  {
365  ARMARX_CHECK_EQUAL(starts.size(), currentState.size())
366  << ": size of starts and learned mp are not consistent";
367  for (size_t i = 0; i < currentState.size(); i++)
368  {
369  currentState[i].pos = starts[i];
370  currentState[i].vel = 0.0;
371  }
372  }
373  else
374  {
375  std::vector<double> learnedStart;
376  for (size_t i = 0; i < currentState.size(); i++)
377  {
378  learnedStart.push_back(currentState[i].pos);
379  }
380  ARMARX_INFO << "---- user doesn't define start point, fall back to start point "
381  "learned from trajectory: "
382  << common::dVecToString(learnedStart);
383  }
384  }
385 
386  std::vector<double>
388  {
389  const auto& startState = vmp->getStartState();
390  std::vector<double> mpStartVec;
391  for (const auto& state : startState)
392  {
393  mpStartVec.push_back(state.pos);
394  }
395  return mpStartVec;
396  }
397 
398  bool
400  {
401  return cfg.startFromPrevTarget;
402  }
403 
404  void
405  MP::setStartAndGoal(const DVec& starts, const DVec& goals)
406  {
407  setStart(starts);
408  setGoal(goals);
409  }
410 
411  void
412  MP::setViaPoint(Ice::Double canVal, const DVec& viapoint)
413  {
414  if (mpTrained.load())
415  {
416  prevViapoint = validateViaPoint(viapoint);
417  ARMARX_INFO << "====> Adding via point " << common::dVecToString(prevViapoint);
418  LockGuardType guard{mpMutex};
419  if (canVal <= vmp->getUmin())
420  {
422  }
423  else if (canVal >= 1.0 - vmp->getUmin())
424  {
426  }
427  else
428  {
429  vmp->setViaPoint(canVal, prevViapoint);
430  }
431  }
432  else
433  {
434  ARMARX_ERROR << " -- mp is not trained yet, potential memory allocation error! "
435  "Please train mp before setting any via points";
436  }
437  }
438 
439  void
441  {
442  LockGuardType guard{mpMutex};
443  vmp->removeViaPoints();
444  }
445 
446  double
448  {
449  return canonicalValue;
450  }
451 
452  /// serialze
453  void
454  MP::setWeight(const DVecVec& weights)
455  {
456  vmp->setWeights(weights);
457  }
458 
459  DVecVec
461  {
462  return vmp->getWeights();
463  }
464 
465  std::string
466  MP::serialize(const std::string& mode)
467  {
468  // std::stringstream ss;
469  // if (mode == "string")
470  // {
471  // boost::archive::text_oarchive oa{ss};
472  // oa << vmp.get();
473  // }
474  // else if (mode == "xml")
475  // {
476  // boost::archive::xml_oarchive oa(ss);
477  // oa << vmp.get();
478  // }
479  // return ss.str();
480  return "";
481  }
482 
483  DVec
484  MP::deserialize(const std::string& mpString, const std::string& mode)
485  {
486  // std::stringstream ss;
487  // ss.str(mpString);
488  // mplib::representation::vmp::PrincipalComponentVMP* dmpPointer;
489  // if (mode == "string")
490  // {
491  // boost::archive::text_iarchive ia{ss};
492  // ia >> dmpPointer;
493  // }
494  // else if (mode == "xml")
495  // {
496  // boost::archive::xml_iarchive ia(ss);
497  // ia >> dmpPointer;
498  // }
499  // else
500  // {
501  // ARMARX_ERROR << VAROUT(mode) << " unsupported! please use 'string' or 'xml' mode";
502  // }
503  // vmp.reset(dmpPointer);
504  return vmp->getGoals();
505  }
506 
507 } // namespace armarx::control::common::mp
armarx::control::common::mp::MP::reset
void reset()
Definition: MP.cpp:164
armarx::control::common::mp::MP::stopRequested
std::atomic_bool stopRequested
Definition: MP.h:157
armarx::control::common::mp::MP::getMPName
const std::string & getMPName() const
Definition: MP.cpp:47
index
uint8_t index
Definition: EtherCATFrame.h:59
armarx::control::common::mp::MP::getWeight
DVecVec getWeight()
Definition: MP.cpp:460
armarx::control::common::mp::MP::canonicalValue
double canonicalValue
Definition: MP.h:158
armarx::control::common::mp::MP::getRole
const std::string & getRole() const
Definition: MP.cpp:65
armarx::control::common::mp::DVecVec
DoubleSeqSeq DVecVec
Definition: MP.h:48
armarx::control::common::mp::MP::trainMPFromTraj
void trainMPFromTraj(std::vector< mplib::core::SampledTrajectory > &trajs)
Definition: MP.cpp:272
armarx::control::common::mp::MP::trainMP
void trainMP()
Definition: MP.cpp:306
armarx::control::common::mp::MP::learnFromCSV
void learnFromCSV(const Ice::StringSeq &fileNames=std::vector< std::string >())
setting
Definition: MP.cpp:247
armarx::control::common::mp::MP::setDurationSec
void setDurationSec(Ice::Double timeDuration)
Definition: MP.cpp:90
armarx::control::common::mp::MP::stop
void stop()
Definition: MP.cpp:139
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::control::common::mp::MP::pause
void pause()
Definition: MP.cpp:152
armarx::control::common::mp::MP::deserialize
DVec deserialize(const std::string &, const std::string &mode="string")
Definition: MP.cpp:484
armarx::control::common::mp::MP::targetPoseVecInTraj
DVec targetPoseVecInTraj
Definition: MP.h:166
armarx::control::common::mp
This file is part of ArmarX.
Definition: aron_conversions.cpp:331
armarx::control::common::mp::MP::getConfig
MPConfig getConfig()
Definition: MP.cpp:208
armarx::control::common::mp::MP::mpTrained
std::atomic_bool mpTrained
Note: if mp is not trained, the dimension is not initialized, thus mp->getDim() is undefined,...
Definition: MP.h:164
armarx::control::common::mp::MP::setStart
void setStart(const DVec &starts)
Definition: MP.cpp:360
armarx::control::common::mp::MP::firstRun
std::atomic_bool firstRun
Definition: MP.h:159
armarx::control::common::mp::MP::MP
MP(const MPConfig &c)
Definition: MP.cpp:17
armarx::control::common::mp::MP::cfg
MPConfig cfg
Definition: MP.h:146
armarx::control::common::mp::LockGuardType
std::lock_guard< std::recursive_mutex > LockGuardType
Definition: MP.h:45
MP.h
armarx::control::common::mp::MP::userDefinedViaPoints
std::vector< std::pair< double, DVec > > userDefinedViaPoints
Definition: MP.h:168
armarx::VariantType::Double
const VariantTypeId Double
Definition: Variant.h:920
armarx::control::common::dVecToString
std::string dVecToString(const mplib::core::DVec &dvec)
Definition: utils.cpp:301
ARMARX_TRACE
#define ARMARX_TRACE
Definition: trace.h:77
armarx::control::common::mp::MP::getStartFromPrevTarget
bool getStartFromPrevTarget()
Definition: MP.cpp:399
armarx::control::common::mp::MP::getCanonicalValue
double getCanonicalValue()
Definition: MP.cpp:447
armarx::control::common::mp::MP::serialize
std::string serialize(const std::string &mode="string")
Definition: MP.cpp:466
armarx::control::common::mp::MP::setGoal
void setGoal(const DVec &goals)
Definition: MP.cpp:332
armarx::control::common::mp::DVec
Ice::DoubleSeq DVec
Definition: MP.h:47
armarx::control::common::mp::MP::goalSetByUser
std::atomic_bool goalSetByUser
Definition: MP.h:161
armarx::control::common::mp::MP::paused
std::atomic_bool paused
Definition: MP.h:156
armarx::control::common::mp::MP::vmp
VMPPtr vmp
Definition: MP.h:151
armarx::control::common::mp::MP::currentState
std::vector< mplib::representation::MPState > currentState
Definition: MP.h:167
armarx::control::common::mp::MP::removeAllViaPoint
void removeAllViaPoint()
Definition: MP.cpp:440
armarx::control::common::mp::MP::isRunning
bool isRunning()
Definition: MP.cpp:190
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::control::common::mp::MP::learnFromTraj
void learnFromTraj(const MPTrajs &trajs=MPTrajs())
Definition: MP.cpp:214
armarx::control::common::mp::MP::prevViapoint
DVec prevViapoint
Definition: MP.h:113
ARMARX_CHECK_GREATER_EQUAL
#define ARMARX_CHECK_GREATER_EQUAL(lhs, rhs)
This macro evaluates whether lhs is greater or equal (>=) rhs and if it turns out to be false it will...
Definition: ExpressionException.h:123
ARMARX_CHECK_LESS_EQUAL
#define ARMARX_CHECK_LESS_EQUAL(lhs, rhs)
This macro evaluates whether lhs is less or equal (<=) rhs and if it turns out to be false it will th...
Definition: ExpressionException.h:109
armarx::control::common::mp::MP::isStopRequested
bool isStopRequested()
Definition: MP.cpp:202
armarx::control::common::mp::MP::getNodeSetName
const std::string & getNodeSetName() const
Definition: MP.cpp:59
ExpressionException.h
armarx::ctrlutil::v
double v(double t, double v0, double a0, double j)
Definition: CtrlUtil.h:39
armarx::control::common::mp::MP::getStartVec
std::vector< double > getStartVec()
Definition: MP.cpp:387
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::control::common::mp::MP::isFirstRun
bool isFirstRun()
Definition: MP.cpp:196
armarx::control::common::mp::MPTrajs
std::vector< MPTraj > MPTrajs
Definition: MP.h:66
armarx::control::common::mp::MP::validateViaPoint
virtual DVec validateViaPoint(const DVec &viapoint)
Definition: MP.h:116
armarx::control::common::mp::MP::start
void start()
control
Definition: MP.cpp:71
armarx::control::common::mp::MP::vmpType
mplib::representation::VMPType vmpType
Definition: MP.h:152
armarx::control::common::mp::MP::setWeight
void setWeight(const DVecVec &weights)
serialze
Definition: MP.cpp:454
ARMARX_CHECK_EQUAL
#define ARMARX_CHECK_EQUAL(lhs, rhs)
This macro evaluates whether lhs is equal (==) rhs and if it turns out to be false it will throw an E...
Definition: ExpressionException.h:130
armarx::control::common::mp::MP::isFinished
bool isFinished()
status
Definition: MP.cpp:184
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::control::common::mp::MP::mpMutex
MutexType mpMutex
Definition: MP.h:150
armarx::control::common::mp::MP::setViaPoint
void setViaPoint(Ice::Double u, const DVec &viapoint)
Definition: MP.cpp:412
httplib::detail::make_unique
std::enable_if<!std::is_array< T >::value, std::unique_ptr< T > >::type make_unique(Args &&...args)
Definition: httplib.h:333
armarx::control::common::mp::MP::getClassName
const std::string & getClassName() const
Definition: MP.cpp:53
armarx::control::common::mp::MP::requestStop
void requestStop()
Definition: MP.cpp:146
armarx::control::common::mp::MP::resume
void resume()
Definition: MP.cpp:158
armarx::control::common::mp::MP::targetPoseVec
DVec targetPoseVec
Definition: MP.h:165
armarx::control::common::mp::MP::running
std::atomic_bool running
Definition: MP.h:154
armarx::control::common::mp::MP::setStartAndGoal
void setStartAndGoal(const DVec &starts, const DVec &goals)
Definition: MP.cpp:405