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&
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&
66 {
67 return cfg.role;
68 }
69
70 std::string
72 {
73 return cfg.group.toString();
74 }
75
76 const arondto::MPGroup&
78 {
79 return cfg.group;
80 }
81
82 bool
84 {
85 return cfg.role == "taskspace" or cfg.role == "object";
86 }
87
88 void
90 {
91 start(std::vector<double>());
92 }
93
94 void
95 MP::start(const DVec& goals)
96 {
97 start(goals, std::vector<double>());
98 }
99
100 void
101 MP::start(const DVec& goals, Ice::Double timeDuration)
102 {
103 cfg.durationSec = timeDuration;
104 start(goals);
105 }
106
107 void
108 MP::setDurationSec(Ice::Double timeDuration)
109 {
110 cfg.durationSec = timeDuration;
111 }
112
113 void
114 MP::start(const DVec& goals, const DVec& starts, Ice::Double timeDuration)
115 {
116 cfg.durationSec = timeDuration;
117 start(goals, starts);
118 }
119
120 void
121 MP::start(const DVec& goals, const DVec& starts)
122 {
123 ARMARX_INFO << "---- start " << cfg.name;
124 canonicalValue = 1.0;
125 /// parse user defined viapoints from configuration file
126 for (const auto& vp : userDefinedViaPoints)
127 {
128 setViaPoint(vp.first, vp.second);
129 // ARMARX_INFO << "viapoint at " << vp.first << " is " << common::dVecToString(vp.second);
130 }
131
132 /// overwrite goals and starts if available
133 setStartAndGoal(starts, goals);
134
135 /// prepare execution
136 LockGuardType guard{mpMutex};
137 vmp->prepareExecution(targetPoseVec, currentState);
138 auto vps = vmp->getViaPoints();
139 ARMARX_INFO << "---- Your MP have: ";
140 int index = 0;
141 for (const auto& v : vps)
142 {
143 ARMARX_INFO << "------ (" << index << ") viapoint at " << v.first << " --- "
145 mplib::core::SystemState::convertStatesToArray(v.second, 0));
146 index++;
147 }
148
149 /// set flag
150 running.store(true);
151 stopRequested.store(false);
152 resume();
153 ARMARX_INFO << "---- MP started: " << cfg.name;
154 }
155
156 void
158 {
159 running.store(false);
160 stopRequested.store(false);
161 }
162
163 void
165 {
166 stopRequested.store(true);
167 }
168
169 void
171 {
172 paused.store(true);
173 }
174
175 void
177 {
178 paused.store(false);
179 }
180
181 void
183 {
184 if (running.load())
185 {
186 ARMARX_INFO << "cannot reset a running mp, please stop it first.";
187 }
188 else
189 {
190 userDefinedViaPoints.clear();
191 targetPoseVec.clear();
192 targetPoseVecInTraj.clear();
193 currentState.clear();
195 goalSetByUser.store(false);
196 mpTrained.store(false);
197 prevViapoint.clear();
198 }
199 }
200
201 bool
203 {
204 return !running.load();
205 }
206
207 bool
209 {
210 return running.load();
211 }
212
213 bool
215 {
216 return firstRun.load();
217 }
218
219 bool
221 {
222 return stopRequested.load();
223 }
224
225 MPConfig
227 {
228 return cfg;
229 }
230
231 void
233 {
234 ARMARX_INFO << "-- Train MP '" << cfg.name << "' from trajectories";
235 MPTrajs trajList;
236 if (mpTrajs.empty())
237 {
238 ARMARX_INFO << "---- using default trajectories from the MP configuration";
239 trajList = cfg.trajectoryList;
240 }
241 else
242 {
243 ARMARX_INFO << "---- use user-provided traj";
244 trajList = mpTrajs;
245 }
246
247 std::vector<mplib::core::SampledTrajectory> trajs;
248 for (const auto& mpTraj : trajList)
249 {
250 std::map<double, std::vector<double>> trajMap;
251 for (int i = 0; i < mpTraj.time.size(); ++i)
252 {
253 auto& row_vector = mpTraj.traj.row(i);
254 std::vector<double> vec(row_vector.data(), row_vector.data() + row_vector.size());
255 trajMap.emplace(mpTraj.time(i), vec);
256 }
257 mplib::core::SampledTrajectory traj(trajMap);
258 trajs.push_back(traj);
259 }
261 trainMPFromTraj(trajs);
262 }
263
264 void
265 MP::learnFromCSV(const Ice::StringSeq& fileNames)
266 {
267 ARMARX_INFO << "-- Train MP '" << cfg.name << "' from csv files";
268 std::vector<std::string> fileList;
269 if (fileNames.empty())
270 {
271 ARMARX_INFO << "---- using default trajectory list: " << cfg.fileList[0];
272 fileList = cfg.fileList;
273 }
274 else
275 {
276 fileList = fileNames;
277 }
278
279 std::vector<mplib::core::SampledTrajectory> trajs;
280 for (auto& file : fileList)
281 {
282 mplib::core::SampledTrajectory traj;
283 traj.readFromCSVFile(file);
284 trajs.push_back(traj);
285 }
286 trainMPFromTraj(trajs);
287 }
288
289 void
290 MP::trainMPFromTraj(std::vector<mplib::core::SampledTrajectory>& trajs)
291 {
292 if (cfg.regressionModel == "gpr")
293 {
294 vmp->setBaseFunctionApproximator(
295 std::make_unique<mplib::math::function_approximation::GaussianProcessRegression<
296 mplib::math::kernel::SquaredExponentialCovarianceFunction>>(
297 0.01, 0.1, 0.000001));
298 for (auto& traj : trajs)
299 {
300 traj = mplib::core::SampledTrajectory::downSample(traj, 100);
301 }
302 }
304 vmp->learnFromTrajectories(trajs);
306
307 currentState.clear();
308 targetPoseVecInTraj.clear();
309
310 ARMARX_INFO << "---- Your trajectory has " << VAROUT(trajs[0].dim());
311 for (size_t i = 0; i < trajs[0].dim(); i++)
312 {
313 mplib::representation::MPState state(trajs[0].begin()->getPosition(i),
314 trajs[0].begin()->getDeriv(i, 1));
315 currentState.push_back(state);
316 targetPoseVecInTraj.push_back(trajs[0].rbegin()->getPosition(i));
317 }
319 mpTrained.store(true);
320 ARMARX_INFO << "---- MP trained";
321 }
322
323 void
325 {
326 if (not cfg.fileList.empty())
327 {
328 learnFromCSV();
329 }
330 else if (not cfg.trajectoryList.empty())
331 {
333 }
334 else
335 {
337 << cfg.name
338 << ": You don't provide any trajectory files (path on the robot) nor trajectories "
339 "in "
340 "type std::vector<armarx::control::common::mp::arondto::MPTraj> in your "
341 "configuration file. \n"
342 << "If you intended train MPs by providing files or "
343 "trajectories on the fly, consider using \n"
344 << "ctrl.learnFromCSV(Ice::StringSeq& fileNames) or \n"
345 << "ctrl.learnFromCSVlearnFromTrajs(armarx::aron::data::dto::DictPtr& dict)";
346 }
347 }
348
349 void
350 MP::setGoal(const DVec& goals)
351 {
352 ARMARX_INFO << "---- Reset MP goal: " << common::dVecToString(goals);
353 if (!goals.empty())
354 {
355 goalSetByUser.store(true);
356 targetPoseVec = goals;
357 }
358 else if (!targetPoseVec.empty())
359 {
361 << "---- user specified empty goal, try to use goals in your configuration file:\n"
363 }
364 else if (!targetPoseVecInTraj.empty())
365 {
367 << "---- user specified empty goal, try to use goals learned from trajectory:\n"
370 }
371 else
372 {
373 ARMARX_WARNING << "---- user specified empty goal";
374 }
375 }
376
377 void
378 MP::setStart(const DVec& starts)
379 {
380 ARMARX_INFO << "---- Reset MP start: " << common::dVecToString(starts);
381 if (!starts.empty())
382 {
383 ARMARX_CHECK_EQUAL(starts.size(), currentState.size())
384 << ": size of starts and learned mp are not consistent";
385 for (size_t i = 0; i < currentState.size(); i++)
386 {
387 currentState[i].pos = starts[i];
388 currentState[i].vel = 0.0;
389 }
390 }
391 else
392 {
393 std::vector<double> learnedStart;
394 for (size_t i = 0; i < currentState.size(); i++)
395 {
396 learnedStart.push_back(currentState[i].pos);
397 }
398 ARMARX_INFO << "---- user doesn't define start point, fall back to start point "
399 "learned from trajectory: "
400 << common::dVecToString(learnedStart);
401 }
402 }
403
404 std::vector<double>
406 {
407 const auto& startState = vmp->getStartState();
408 std::vector<double> mpStartVec;
409 for (const auto& state : startState)
410 {
411 mpStartVec.push_back(state.pos);
412 }
413 return mpStartVec;
414 }
415
416 bool
418 {
419 return cfg.startFromPrevTarget;
420 }
421
422 void
423 MP::setStartAndGoal(const DVec& starts, const DVec& goals)
424 {
425 setStart(starts);
426 setGoal(goals);
427 }
428
429 void
430 MP::setViaPoint(Ice::Double canVal, const DVec& viapoint)
431 {
432 if (mpTrained.load())
433 {
434 prevViapoint = validateViaPoint(viapoint);
435 ARMARX_INFO << "====> Adding via point " << common::dVecToString(prevViapoint);
436 LockGuardType guard{mpMutex};
437 if (canVal <= vmp->getUmin())
438 {
440 }
441 else if (canVal >= 1.0 - vmp->getUmin())
442 {
444 }
445 else
446 {
447 vmp->setViaPoint(canVal, prevViapoint);
448 }
449 }
450 else
451 {
452 ARMARX_ERROR << " -- mp is not trained yet, potential memory allocation error! "
453 "Please train mp before setting any via points";
454 }
455 }
456
457 void
459 {
460 LockGuardType guard{mpMutex};
461 vmp->removeViaPoints();
462 }
463
464 double
466 {
467 return canonicalValue;
468 }
469
470 /// serialze
471 void
472 MP::setWeight(const DVecVec& weights)
473 {
474 vmp->setWeights(weights);
475 }
476
477 DVecVec
479 {
480 return vmp->getWeights();
481 }
482
483 std::string
484 MP::serialize(const std::string& mode)
485 {
486 // std::stringstream ss;
487 // if (mode == "string")
488 // {
489 // boost::archive::text_oarchive oa{ss};
490 // oa << vmp.get();
491 // }
492 // else if (mode == "xml")
493 // {
494 // boost::archive::xml_oarchive oa(ss);
495 // oa << vmp.get();
496 // }
497 // return ss.str();
498 return "";
499 }
500
501 DVec
502 MP::deserialize(const std::string& mpString, const std::string& mode)
503 {
504 // std::stringstream ss;
505 // ss.str(mpString);
506 // mplib::representation::vmp::PrincipalComponentVMP* dmpPointer;
507 // if (mode == "string")
508 // {
509 // boost::archive::text_iarchive ia{ss};
510 // ia >> dmpPointer;
511 // }
512 // else if (mode == "xml")
513 // {
514 // boost::archive::xml_iarchive ia(ss);
515 // ia >> dmpPointer;
516 // }
517 // else
518 // {
519 // ARMARX_ERROR << VAROUT(mode) << " unsupported! please use 'string' or 'xml' mode";
520 // }
521 // vmp.reset(dmpPointer);
522 return vmp->getGoals();
523 }
524
525} // namespace armarx::control::common::mp
uint8_t index
#define VAROUT(x)
constexpr T c
MP(const MPConfig &c)
Definition MP.cpp:17
std::vector< double > getStartVec()
Definition MP.cpp:405
std::atomic_bool stopRequested
Definition MP.h:170
std::atomic_bool running
Definition MP.h:167
std::string getGroupName() const
Definition MP.cpp:71
void setDurationSec(Ice::Double timeDuration)
Definition MP.cpp:108
const std::string & getClassName() const
Definition MP.cpp:53
void setStartAndGoal(const DVec &starts, const DVec &goals)
Definition MP.cpp:423
const std::string & getNodeSetName() const
Definition MP.cpp:59
void setViaPoint(Ice::Double u, const DVec &viapoint)
Definition MP.cpp:430
virtual DVec validateViaPoint(const DVec &viapoint)
Definition MP.h:125
std::vector< std::pair< double, DVec > > userDefinedViaPoints
Definition MP.h:181
void setWeight(const DVecVec &weights)
serialze
Definition MP.cpp:472
bool isTaskSpaceMP() const
Definition MP.cpp:83
std::atomic_bool goalSetByUser
Definition MP.h:174
DVec deserialize(const std::string &, const std::string &mode="string")
Definition MP.cpp:502
std::string serialize(const std::string &mode="string")
Definition MP.cpp:484
std::vector< mplib::representation::MPState > currentState
Definition MP.h:180
const arondto::MPGroup & getGroup() const
Definition MP.cpp:77
std::atomic_bool mpTrained
Note: if mp is not trained, the dimension is not initialized, thus mp->getDim() is undefined,...
Definition MP.h:177
void trainMPFromTraj(std::vector< mplib::core::SampledTrajectory > &trajs)
Definition MP.cpp:290
void learnFromCSV(const Ice::StringSeq &fileNames=std::vector< std::string >())
setting
Definition MP.cpp:265
std::atomic_bool firstRun
Definition MP.h:172
const std::string & getMPName() const
Definition MP.cpp:47
void setStart(const DVec &starts)
Definition MP.cpp:378
const std::string & getRole() const
Definition MP.cpp:65
mplib::representation::VMPType vmpType
Definition MP.h:165
void setGoal(const DVec &goals)
Definition MP.cpp:350
void learnFromTraj(const MPTrajs &trajs=MPTrajs())
Definition MP.cpp:232
std::atomic_bool paused
Definition MP.h:169
#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...
#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...
#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...
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
This file is part of ArmarX.
std::vector< MPTraj > MPTrajs
Definition MP.h:72
Ice::DoubleSeq DVec
Definition MP.h:53
std::lock_guard< std::recursive_mutex > LockGuardType
Definition MP.h:45
DoubleSeqSeq DVecVec
Definition MP.h:54
std::string dVecToString(const DVec &dvec)
Definition utils.cpp:408
#define ARMARX_TRACE
Definition trace.h:77