DMPInstance.cpp
Go to the documentation of this file.
1/*
2 * This file is part of ArmarX.
3 *
4 * ArmarX is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * ArmarX is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 *
16 * @package RobotAPI::ArmarXObjects::DMPComponent
17 * @author Mirko Waechter ( mirko dot waechter at kit dot edu )
18 * @date 2015
19 * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 */
22
23
24#include "DMPInstance.h"
25
26#include <Ice/ObjectAdapter.h>
27
28#include <dmp/io/MMMConverter.h>
29
30using namespace armarx;
31
32// tool functions
33DMP::Vec<DMP::DMPState>
34getDMPStateFromcStateVec(const cStateVec& state)
35{
36 DMP::Vec<DMP::DMPState> res;
37 res.resize(state.size());
38
39 for (size_t i = 0; i < state.size(); i++)
40 {
41 res[i].pos = state[i].pos;
42 res[i].vel = state[i].vel;
43 }
44
45 return res;
46}
47
48DMP::DVec2d
49getDVec2dStateFromcStateVec(const cStateVec& state)
50{
51 DMP::DVec2d res;
52 res.resize(state.size());
53 for (size_t i = 0; i < state.size(); i++)
54 {
55 res[i].push_back(state[i].pos);
56 res[i].push_back(state[i].vel);
57 }
58
59 return res;
60}
61
62armarx::cStateVec
63getcStateVec(const DMP::Vec<DMP::DMPState>& dmpstate)
64{
65 armarx::cStateVec sv;
66 sv.resize(dmpstate.size());
67
68 for (size_t i = 0; i < dmpstate.size(); i++)
69 {
70 sv[i].pos = dmpstate[i].pos;
71 sv[i].vel = dmpstate[i].vel;
72 }
73
74 return sv;
75}
76
77armarx::cStateVec
78getcStateVec(const DMP::DVec2d& dmpstate)
79{
80 armarx::cStateVec sv;
81 sv.resize(dmpstate.size());
82
83 for (size_t i = 0; i < dmpstate.size(); i++)
84 {
85 sv[i].pos = dmpstate[i].at(0);
86 sv[i].vel = dmpstate[i].at(1);
87 }
88
89 return sv;
90}
91
92DMPInstance::DMPInstance(DMP::DMPInterfacePtr dmpInter, std::string DMPType)
93{
94 dmp = dmpInter;
95 dmpType = DMPType;
96 ctime = 0;
97 timestep = 0.001;
98}
99
100// state calculation
101
102cStateVec
103DMPInstance::getNextState(const cStateVec& states, const Ice::Current&)
104{
105 if (canonicalValues.size() == 0)
106 {
107 ARMARX_WARNING << "Canonical value is not specified. It will be set 1.0.";
108 canonicalValues.push_back(1.0);
109 }
110
111 DMP::DVec2d currentDMPState = getDVec2dStateFromcStateVec(states);
112 if (currentDMPState.size() == 0)
113 {
114 ARMARX_ERROR << "The current state is not available. Please specify current state with "
115 "setDMPState().";
116 }
117
118 DMP::DVec goal = dmp->getGoals();
119
120
121 ARMARX_INFO << "CanonicalValues: " << canonicalValues[0] << " ctime: " << ctime
122 << " Timestep: " << timestep;
123 double temporalFactor = dmp->getTemporalFactor();
124 currentDMPState = dmp->calculateTrajectoryPointBase(
125 ctime + timestep, goal, ctime, currentDMPState, canonicalValues, temporalFactor);
126
127 ctime += timestep;
128 cStateVec nextState = getcStateVec(currentDMPState);
129 setDMPState(nextState);
130 ARMARX_INFO << "Got next state";
131
132 return nextState;
133}
134
135armarx::nStateValues
137 const Ice::DoubleSeq& goal,
138 double currentT,
139 const Vec2D& currentStates,
140 const Ice::DoubleSeq& canonicalValues,
141 double temporalFactor,
142 const ::Ice::Current&)
143{
144 if (canonicalValues.size() == 0)
145 {
146 ARMARX_ERROR << "Canonical value is not specified.";
147 // canonicalValues.push_back(1.0);
148 }
149
150 if (currentStates.size() == 0)
151 {
152 ARMARX_ERROR << "Current DMP State has to be specified";
153 }
154
155 DMP::DVec goal_v = DMP::DVec(goal);
156
157 if (goal.size() == 0)
158 {
159 ARMARX_WARNING << "Using goal specified in configs";
160 goal_v = getGoal();
161 }
162
163 DMP::DVec2d curStates;
164
165 for (std::size_t i = 0; i < currentStates.size(); ++i)
166 {
167 curStates.emplace_back(DMP::DVec(currentStates.at(i)));
168 }
169
170 DMP::DVec canValues = DMP::DVec(canonicalValues);
171 ARMARX_INFO_S << VAROUT(temporalFactor);
172 DMP::DVec2d tmp_result = dmp->calculateTrajectoryPointBase(
173 t, goal_v, currentT, curStates, canValues, temporalFactor);
174
175 Ice::DoubleSeq tmpCanVal;
176 for (std::size_t i = 0; i < canValues.size(); i++)
177 {
178 tmpCanVal.emplace_back(canValues.at(i));
179 }
180
181 nStateValues result;
182
183 result.canonicalValues = tmpCanVal;
184
185 Vec2D nState;
186 for (std::size_t i = 0; i < tmp_result.size(); ++i)
187 {
188 ::Ice::DoubleSeq dblseq = ::Ice::DoubleSeq(tmp_result.at(i));
189
190 nState.emplace_back(dblseq);
191 }
192
193 result.nextState = nState;
194
195 return result;
196}
197
198armarx::nStateValues
200 double currentT,
201 const Vec2D& currentStates,
202 const Ice::DoubleSeq& canonicalValues,
203 const Ice::Current&)
204{
205 DMP::DVec goal = getGoal();
206 double temporalFactor = getTemporalFactor();
207 return calcNextState(t, goal, currentT, currentStates, canonicalValues, temporalFactor);
208}
209
210// configuration & parameters
211void
212DMPInstance::setConfigurationMap(const DMPConfigMap& conf, const Ice::Current&)
213{
214 std::map<std::string, paraType> configMap;
215 for (::std::map<::std::string, ::Ice::DoubleSeq>::const_iterator it = conf.begin();
216 it != conf.end();
217 ++it)
218 {
219 configMap[it->first] = (DMP::DVec)it->second;
220 dmp->setConfiguration(it->first, it->second);
221 }
222
224}
225
227DMPInstance::createConfigMap(DMP::Vec<std::string> paraIDs, DMP::Vec<paraType> paraVals)
228{
229 if (paraIDs.size() != paraVals.size())
230 {
231 ARMARX_WARNING << "ID list and value list have different sizes, which may cause error.";
232 }
233
235 for (size_t i = 0; i < paraIDs.size(); i++)
236 {
237 if (configs.find(paraIDs[i]) == configs.end())
238 {
239 configs.insert(configPair(paraIDs[i], paraVals[i]));
240 }
241 else
242 {
243 configs[paraIDs[i]] = paraVals[i];
244 }
245 }
246
247 return configs;
248}
249
250void
251DMPInstance::setParameter(const std::string& paraID,
252 const Ice::DoubleSeq& value,
253 const ::Ice::Current&)
254{
255 if (configs.find(paraID) == configs.end())
256 {
257 configs.insert(configPair(paraID, value));
258 }
259 else
260 {
261 configs[paraID] = value;
262 }
263 dmp->setConfiguration(paraID, DMP::DVec(value));
264}
265
266// setter functions
267
268void
269DMPInstance::setCanonicalValues(const Ice::DoubleSeq& value, const Ice::Current&)
270{
271 canonicalValues = value;
272}
273
274void
275DMPInstance::setAmpl(int dim, double value, const Ice::Current&)
276{
277 dmp->setAmpl(dim, value);
278}
279
280void
281DMPInstance::setTemporalFactor(double value, const Ice::Current&)
282{
283 dmp->setTemporalFactor(value);
284}
285
286void
287DMPInstance::setGoal(const Ice::DoubleSeq& value, const Ice::Current&)
288{
289 if (configs.find(DMP::Goal) == configs.end())
290 {
291 configs.insert(configPair(DMP::Goal, DMP::DVec(value)));
292 }
293 else
294 {
295 configs[DMP::Goal] = DMP::DVec(value);
296 }
297 dmp->setConfiguration(DMP::Goal, DMP::DVec(value));
298}
299
300void
301DMPInstance::setStartPosition(const Ice::DoubleSeq& value, const Ice::Current&)
302{
303 if (configs.find(DMP::StartPosition) == configs.end())
304 {
305 configs.insert(configPair(DMP::StartPosition, DMP::DVec(value)));
306 }
307 else
308 {
309 configs[DMP::StartPosition] = DMP::DVec(value);
310 }
311 dmp->setConfiguration(DMP::StartPosition, DMP::DVec(value));
312}
313
314void
315DMPInstance::setDMPState(const cStateVec& state, const Ice::Current&)
316{
317 dmpState = state;
318}
319
320// getter function
321
322double
323DMPInstance::getAmpl(int dim, const Ice::Current&)
324{
325 return dmp->getAmpl(dim);
326}
327
328double
330{
331 return dmp->getTemporalFactor();
332}
333
334double
335DMPInstance::getForceTerm(const Ice::DoubleSeq& canVal, int dim, const Ice::Current&)
336{
337 return dmp->_getPerturbationForce(dim, canVal[0]);
338}
339
340Ice::DoubleSeq
341DMPInstance::getGoal(const Ice::Current&)
342{
343 DMP::DVec goals = dmp->getGoals();
344 Ice::DoubleSeq res;
345
346 for (size_t i = 0; i < goals.size(); ++i)
347 {
348 res.push_back(goals.at(i));
349 }
350
351 return res;
352}
353
354// trajectory related
355
356Ice::DoubleSeq
357DMPInstance::getTrajGoal(const ::Ice::Current&)
358{
359 Ice::DoubleSeq trajGoal;
360 for (size_t i = 0; i < trajs[0].dim(); i++)
361 {
362 trajGoal.push_back(trajs[0].rbegin()->getPosition(i));
363 }
364
365 return trajGoal;
366}
367
368cStateVec
369DMPInstance::getTrajStartState(const ::Ice::Current&)
370{
371 cStateVec startState;
372
373 for (size_t i = 0; i < trajs[0].dim(); i++)
374 {
375 cState state;
376 state.pos = trajs[0].begin()->getPosition(i);
377 state.vel = trajs[0].begin()->getDeriv(i, 1);
378 state.acc = trajs[0].begin()->getDeriv(i, 2);
379
380 startState.push_back(state);
381 }
382
383 return startState;
384}
385
386void
387DMPInstance::readTrajectoryFromFile(const std::string& file, double times, const Ice::Current&)
388{
389 std::string ext = file.rfind(".") == file.npos ? file : file.substr(file.rfind(".") + 1);
390
391 if (ext == "xml")
392 {
393
394
395 ARMARX_INFO << "xml file loaded";
396 }
397 else if (ext == "csv")
398 {
399 DMP::SampledTrajectoryV2 traj;
400 traj.readFromCSVFile(file);
401 traj.gaussianFilter(0.01);
402
403 double startTime = 0;
404 double endTime = times;
405 traj = DMP::SampledTrajectoryV2::normalizeTimestamps(traj, startTime, endTime);
406
407
408 trajs.push_back(traj);
409 dmp->setDim(traj.dim());
410
411 ARMARX_INFO << "csv file loaded";
412 }
413 else if (ext == "vsg")
414 {
415 }
416 else
417 {
418 ARMARX_ERROR << "Error: The file is not valid ";
419 }
420}
421
422// DMP Trainer
423void
424DMPInstance::trainDMP(const Ice::Current&)
425{
426 dmp->learnFromTrajectories(trajs);
427}
428
429Vec2D
431 double timeStep,
432 double endTime,
433 const ::Ice::DoubleSeq& goal,
434 const cStateVec& states,
435 const ::Ice::DoubleSeq& canonicalValues,
436 double temporalFactor,
437 const Ice::Current&)
438{
439 setDMPState(states);
440 setGoal(goal);
442 setTemporalFactor(temporalFactor);
443 setCurrentTime(startTime);
444 setTimeStep(timeStep);
445
446 Vec2D resultingTrajectory;
447
448 cStateVec nextStates = states;
449 while (ctime < endTime)
450 {
451 nextStates = getNextState(nextStates);
452 ::Ice::DoubleSeq positions;
453
454 positions.push_back(ctime);
455 for (unsigned int d = 0; d < states.size(); d++)
456 {
457 positions.push_back(nextStates.at(d).pos);
458 }
459
460 resultingTrajectory.push_back(positions);
461 }
462
464
465 return resultingTrajectory;
466}
467
468Vec2D
469DMPInstance::calcTrajectoryV2(const Ice::DoubleSeq& timestamps,
470 const Ice::DoubleSeq& goal,
471 const Vec2D& initStates,
472 const Ice::DoubleSeq& canonicalValues,
473 double temporalFactor,
474 const Ice::Current&)
475{
476 DMP::DVec timestampsLocal = timestamps;
477
478 if (timestampsLocal.size() == 0)
479 {
480 ARMARX_ERROR << "No Timestamps specified";
481 }
482
483 DMP::DVec::const_iterator it = timestamps.begin();
484 Vec2D previousState = initStates;
485 Vec2D resultingTrajectory;
486 // std::map<double, DMP::DVec > resultingSystemStatesMap;
487
488 //DMP::DVec canonicalValues = initialCanonicalValues;
489 double prevTimestamp = *it;
490
491 Ice::DoubleSeq canValues = canonicalValues;
492
493 for (; it != timestamps.end(); it++)
494 {
495 nStateValues nState =
496 calcNextState(*it, goal, prevTimestamp, previousState, canValues, temporalFactor);
497 canValues = nState.canonicalValues;
498 previousState = nState.nextState;
499
500 prevTimestamp = *it;
501 ::Ice::DoubleSeq positions;
502 for (unsigned int d = 0; d < previousState.size(); d++)
503 {
504 positions.push_back(previousState.at(d)[0]);
505 }
506 resultingTrajectory.push_back(positions);
507 }
508
509 return resultingTrajectory;
510}
511
512Vec2D
513DMPInstance::calcTrajectoryFromConfig(const Ice::DoubleSeq& timestamps,
514 const Vec2D& initStates,
515 const Ice::DoubleSeq& canonicalValues,
516 const Ice::Current&)
517{
518 DMP::DVec goal = getGoal();
519 double temporalFactor = getTemporalFactor();
520 return calcTrajectoryV2(timestamps, goal, initStates, canonicalValues, temporalFactor);
521}
DMP::DVec2d getDVec2dStateFromcStateVec(const cStateVec &state)
DMP::Vec< DMP::DMPState > getDMPStateFromcStateVec(const cStateVec &state)
armarx::cStateVec getcStateVec(const DMP::Vec< DMP::DMPState > &dmpstate)
#define VAROUT(x)
void trainDMP(const ::Ice::Current &=Ice::emptyCurrent) override
void setAmpl(int dim, double value, const ::Ice::Current &=Ice::emptyCurrent) override
setAmpl: set amplitude for dmp
Vec2D calcTrajectoryFromConfig(const Ice::DoubleSeq &timestamps, const Vec2D &initStates, const Ice::DoubleSeq &canonicalValues, const Ice::Current &=Ice::emptyCurrent) override
void setTimeStep(double ts)
void setConfigurationMap(const DMPConfigMap &value, const ::Ice::Current &=Ice::emptyCurrent) override
setConfigurationMap set dmp configurations using configMap
Ice::DoubleSeq getGoal(const Ice::Current &=Ice::emptyCurrent)
void setDMPState(const cStateVec &state, const ::Ice::Current &=Ice::emptyCurrent) override
setDMPState set current state for dmp
double getAmpl(int dim, const ::Ice::Current &=Ice::emptyCurrent) override
getAmpl: get current amplitude of a dimension
Ice::DoubleSeq getTrajGoal(const ::Ice::Current &=Ice::emptyCurrent) override
getTrajGoal: get the goal of the training trajectory
void setParameter(const std::string &paraId, const Ice::DoubleSeq &value, const ::Ice::Current &=Ice::emptyCurrent) override
setParameter set parameters for
void setCanonicalValues(const Ice::DoubleSeq &value, const ::Ice::Current &=Ice::emptyCurrent) override
setCanonicalValues: set dmp canonicalValues to control the dmp's state
double getForceTerm(const Ice::DoubleSeq &canVal, int dim, const ::Ice::Current &=Ice::emptyCurrent) override
getForceTerm: get force termf for one dimension at a specified canonical values
Vec2D calcTrajectory(double startTime, double timestep, double endTime, const ::Ice::DoubleSeq &goal, const cStateVec &initStates, const ::Ice::DoubleSeq &canonicalValues, double temporalFactor, const Ice::Current &=Ice::emptyCurrent) override
calcTrajectory solves the DMP for all Timesteps
nStateValues calcNextStateFromConfig(double t, double currentT, const Vec2D &currentStates, const Ice::DoubleSeq &canonicalValues, const Ice::Current &=Ice::emptyCurrent) override
void setCurrentTime(double t)
Vec2D calcTrajectoryV2(const Ice::DoubleSeq &timestamps, const Ice::DoubleSeq &goal, const Vec2D &initStates, const Ice::DoubleSeq &canonicalValues, double temporalFactor, const Ice::Current &=Ice::emptyCurrent) override
void setGoal(const Ice::DoubleSeq &value, const ::Ice::Current &=Ice::emptyCurrent) override
setGoal set the goal for dmp
cStateVec getTrajStartState(const ::Ice::Current &=Ice::emptyCurrent) override
getTrajStartState: get the start state of the training trajectory
nStateValues calcNextState(double t, const Ice::DoubleSeq &goal, double currentT, const Vec2D &currentStates, const Ice::DoubleSeq &canonicalValues, double temporalFactor, const ::Ice::Current &=Ice::emptyCurrent) override
void setTemporalFactor(double value, const ::Ice::Current &=Ice::emptyCurrent) override
setTemporalFactor: set dmp temporal factor
configMap createConfigMap(DMP::Vec< std::string > paraIDs, DMP::Vec< paraType > paraVals)
DMP::DMPInterfacePtr dmp
void setStartPosition(const Ice::DoubleSeq &value, const ::Ice::Current &=Ice::emptyCurrent) override
setStartPosition set the start position for dmp
DMPInstance()
DMPInstance constructs an empty instance of a basicDMP.
Definition DMPInstance.h:87
std::string dmpType
double getTemporalFactor(const ::Ice::Current &=Ice::emptyCurrent) override
getTemporalFactor: get current temporal factor
cStateVec getNextState(const cStateVec &states, const ::Ice::Current &=Ice::emptyCurrent) override
getNextState: get next state according to the state given
DMP::DVec canonicalValues
void readTrajectoryFromFile(const std::string &file, double times=1, const ::Ice::Current &=Ice::emptyCurrent) override
#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_INFO_S
Definition Logging.h:202
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
This file offers overloads of toIce() and fromIce() functions for STL container types.
std::pair< std::string, paraType > configPair
Definition DMPInstance.h:68
std::map< std::string, paraType > configMap
Definition DMPInstance.h:67