NJointJSDMPController.cpp
Go to the documentation of this file.
2 
3 #include <boost/archive/text_iarchive.hpp>
4 #include <boost/archive/text_oarchive.hpp>
5 
8 
9 
11 {
12 
13  NJointControllerRegistration<NJointJSDMPController>
14  registrationControllerNJointJSDMPController("NJointJSDMPController");
15 
16  std::string
17  NJointJSDMPController::getClassName(const Ice::Current&) const
18  {
19  return "NJointJSDMPController";
20  }
21 
23  const armarx::NJointControllerConfigPtr& config,
25  {
26  ARMARX_INFO << "creating joint space dmp controller ... ";
28 
29  cfg = NJointJointSpaceDMPControllerConfigPtr::dynamicCast(config);
30  ARMARX_CHECK_EXPRESSION(cfg) << "Needed type: NJointJointSpaceDMPControllerConfigPtr";
31 
32  for (std::string jointName : cfg->jointNames)
33  {
34  ControlTargetBase* ct = useControlTarget(jointName, ControlModes::Velocity1DoF);
35  const SensorValueBase* sv = useSensorValue(jointName);
36  targets.insert(std::make_pair(jointName, ct->asA<ControlTarget1DoFActuatorVelocity>()));
37  positionSensors.insert(
38  std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorPosition>()));
39  velocitySensors.insert(
40  std::make_pair(jointName, sv->asA<SensorValue1DoFActuatorVelocity>()));
41  }
42  if (cfg->jointNames.size() == 0)
43  {
44  ARMARX_ERROR << "cfg->jointNames.size() == 0";
45  }
46  ARMARX_INFO << "start creating dmpPtr ... "
47  << " baseMode: " << cfg->baseMode;
48 
49  dmpPtr.reset(new DMP::UMIDMP(cfg->kernelSize, 100, cfg->baseMode, 1));
50  timeDuration = cfg->timeDuration;
51  phaseL = cfg->phaseL;
52  phaseK = cfg->phaseK;
53  phaseDist0 = cfg->phaseDist0;
54  phaseDist1 = cfg->phaseDist1;
55  phaseKp = cfg->phaseKp;
56  dimNames = cfg->jointNames;
57  ARMARX_INFO << "created dmpPtr ... ";
58 
59  targetVels.resize(cfg->jointNames.size());
61  initData.targetJointVels.resize(cfg->jointNames.size());
62  for (size_t i = 0; i < cfg->jointNames.size(); ++i)
63  {
64  initData.targetJointVels[i] = 0;
65  targetVels[i] = 0;
66  }
67 
68  reinitTripleBuffer(initData);
69 
70 
71  NJointJSDMPControllerSensorData initSensorData;
72  initSensorData.currentTime = 0;
73  initSensorData.deltaT = 0;
74  initSensorData.currentState.resize(cfg->jointNames.size());
75  controllerSensorData.reinitAllBuffers(initSensorData);
76 
77  deltaT = 0;
78 
79  qpos.resize(dimNames.size());
80  qvel.resize(dimNames.size());
81  }
82 
83  void
85  {
86  if (!started || finished)
87  {
88  for (size_t i = 0; i < dimNames.size(); ++i)
89  {
90  targetVels[i] = 0;
91  }
92  }
93  else
94  {
95  currentState = controllerSensorData.getUpToDateReadBuffer().currentState;
96  double deltaT = controllerSensorData.getUpToDateReadBuffer().deltaT;
97 
98  if (canVal > 1e-8)
99  {
100  double phaseStop = 0;
101  double mpcFactor = 1;
102 
103  std::vector<double> currentPosition;
104  double error = 0;
105  currentPosition.resize(dimNames.size());
106 
107  for (size_t i = 0; i < currentState.size(); i++)
108  {
109  DMP::DMPState currentPos = currentState[i];
110  currentPosition[i] = currentPos.pos;
111  error += pow(currentPos.pos - targetState[i], 2);
112  }
113 
114  if (cfg->isPhaseStop)
115  {
116  double phaseDist;
117 
118  if (isDisturbance)
119  {
120  phaseDist = phaseDist1;
121  }
122  else
123  {
124  phaseDist = phaseDist0;
125  }
126 
127  error = sqrt(error);
128  phaseStop = phaseL / (1 + exp(-phaseK * (error - phaseDist)));
129  mpcFactor = 1 - (phaseStop / phaseL);
130 
131  if (mpcFactor < 0.1)
132  {
133  isDisturbance = true;
134  }
135 
136  if (mpcFactor > 0.9)
137  {
138  isDisturbance = false;
139  }
140  }
141 
142  canVal -= tau * deltaT * 1 / (1 + phaseStop);
143  double dmpDeltaT = deltaT / timeDuration;
144 
145  currentDMPState = dmpPtr->calculateDirectlyVelocity(
146  currentDMPState, canVal / timeDuration, dmpDeltaT, targetState);
147 
148  for (size_t i = 0; i < currentDMPState.size(); ++i)
149  {
150  double vel0 = tau * currentDMPState[i].vel / timeDuration;
151  double vel1 = phaseKp * (targetState[i] - currentPosition[i]);
152  // double vel = mpcFactor * vel0 + (1 - mpcFactor) * vel1;
153  double vel = vel1 + vel0;
154  targetVels[i] = vel;
155  debugOutputData.getWriteBuffer().latestTargetVelocities[dimNames[i]] =
156  (float)vel;
157  debugOutputData.getWriteBuffer().latestTargets[dimNames[i]] =
158  (float)currentDMPState[i].pos;
159  }
160 
161  debugOutputData.getWriteBuffer().currentCanVal = canVal;
162  debugOutputData.getWriteBuffer().mpcFactor = mpcFactor;
163  debugOutputData.commitWrite();
164  }
165  else
166  {
167  finished = true;
168  for (size_t i = 0; i < dimNames.size(); ++i)
169  {
170  targetVels[i] = 0;
171  }
172  }
173  }
174 
176  getWriterControlStruct().targetJointVels = targetVels;
178  }
179 
180  void
181  NJointJSDMPController::rtRun(const IceUtil::Time& sensorValuesTimestamp,
182  const IceUtil::Time& timeSinceLastIteration)
183  {
184  for (size_t i = 0; i < dimNames.size(); i++)
185  {
186  const auto& jointName = dimNames.at(i);
187  DMP::DMPState currentPos;
188  currentPos.pos = (positionSensors.count(jointName) == 1)
189  ? positionSensors[jointName]->position
190  : 0.0f;
191  currentPos.vel = (velocitySensors.count(jointName) == 1)
192  ? velocitySensors[jointName]->velocity
193  : 0.0f;
194  qpos[i] = currentPos.pos;
195  qvel[i] = currentPos.vel;
196  controllerSensorData.getWriteBuffer().currentState[i] = currentPos;
197  }
198  controllerSensorData.getWriteBuffer().deltaT = timeSinceLastIteration.toSecondsDouble();
199  controllerSensorData.getWriteBuffer().currentTime +=
200  timeSinceLastIteration.toSecondsDouble();
201  controllerSensorData.commitWrite();
202 
203 
204  rt2UserData.getWriteBuffer().qpos = qpos;
205  rt2UserData.getWriteBuffer().qvel = qvel;
206  rt2UserData.commitWrite();
207 
208  Eigen::VectorXf targetJointVels = rtGetControlStruct().targetJointVels;
209  // ARMARX_INFO << targetJointVels;
210 
211  for (size_t i = 0; i < dimNames.size(); ++i)
212  {
213 
214  if (fabs(targetJointVels[i]) > cfg->maxJointVel)
215  {
216  targets[dimNames[i]]->velocity =
217  targetJointVels[i] < 0 ? -cfg->maxJointVel : cfg->maxJointVel;
218  }
219  else
220  {
221  targets[dimNames[i]]->velocity = targetJointVels[i];
222  }
223  }
224  }
225 
226  void
227  NJointJSDMPController::learnDMPFromFiles(const Ice::StringSeq& fileNames, const Ice::Current&)
228  {
229  DMP::Vec<DMP::SampledTrajectoryV2> trajs;
230 
231  DMP::DVec ratios;
232  for (size_t i = 0; i < fileNames.size(); ++i)
233  {
234  DMP::SampledTrajectoryV2 traj;
235  traj.readFromCSVFile(fileNames.at(i));
237  trajs.push_back(traj);
238 
239  if (i == 0)
240  {
241  ratios.push_back(1.0);
242  }
243  else
244  {
245  ratios.push_back(0.0);
246  }
247  }
248  dmpPtr->learnFromTrajectories(trajs);
249  dmpPtr->styleParas = dmpPtr->getStyleParasWithRatio(ratios);
250 
251  ARMARX_INFO << "Learned DMP ... ";
252  }
253 
254  void
255  NJointJSDMPController::runDMP(const Ice::DoubleSeq& goals, double times, const Ice::Current&)
256  {
257  while (!rt2UserData.updateReadBuffer())
258  {
259  usleep(100);
260  }
261 
262  targetState.clear();
263  targetState.resize(dimNames.size());
264  currentState.clear();
265  currentState.resize(dimNames.size());
266  currentDMPState.clear();
267  currentDMPState.resize(dimNames.size());
268 
269  std::vector<double> goalVec = goals;
270  for (size_t i = 0; i < dimNames.size(); i++)
271  {
272  DMP::DMPState currentPos;
273  currentPos.pos = rt2UserData.getReadBuffer().qpos[i];
274  currentPos.vel = rt2UserData.getReadBuffer().qvel[i];
275 
276  currentState[i] = currentPos;
277  currentDMPState[i] = currentPos;
278 
279  targetState.push_back(currentPos.pos);
280 
281  if (rtGetRobot()->getRobotNode(dimNames[i])->isLimitless())
282  {
283  double tjv = goalVec[i];
284  double cjv = currentPos.pos;
285  double diff = std::fmod(tjv - cjv, 2 * M_PI);
286  if (fabs(diff) > M_PI)
287  {
288  if (signbit(diff))
289  {
290  diff = -2 * M_PI - diff;
291  }
292  else
293  {
294  diff = 2 * M_PI - diff;
295  }
296  tjv = cjv - diff;
297  }
298  else
299  {
300  tjv = cjv + diff;
301  }
302 
303  goalVec[i] = tjv;
304  ARMARX_INFO << "dim name: " << dimNames[i]
305  << " current state: qpos: " << currentPos.pos
306  << " orig target: " << goals[i] << " current goal: " << tjv;
307  }
308  }
309 
310  dmpPtr->prepareExecution(goalVec, currentDMPState, 1, 1);
311  canVal = timeDuration;
312  finished = false;
313  isDisturbance = false;
314 
315  tau = times;
316  ARMARX_INFO << "run DMP";
317  started = true;
318  }
319 
320  void
322  {
323  }
324 
325  std::string
327  {
328  std::stringstream ss;
329  boost::archive::text_oarchive oa{ss};
330  oa << dmpPtr.get();
331  return ss.str();
332  }
333 
334  std::vector<double>
335  NJointJSDMPController::createDMPFromString(const std::string& dmpString, const Ice::Current&)
336  {
337  std::stringstream ss;
338  ss.str(dmpString);
339  boost::archive::text_iarchive ia{ss};
340  DMP::UMIDMP* newDmpPtr;
341  ia >> newDmpPtr;
342  dmpPtr.reset(newDmpPtr);
343  return dmpPtr->defaultGoal;
344  }
345 
346  void
347  NJointJSDMPController::setViaPoints(Ice::Double u, double viapoint, const Ice::Current&)
348  {
349  LockGuardType guard{controllerMutex};
350  dmpPtr->setViaPoint(u, viapoint);
351  }
352 
353  void
354  NJointJSDMPController::setMPWeights(const DoubleSeqSeq& weights, const Ice::Current&)
355  {
356  dmpPtr->setWeights(weights);
357  }
358 
359  DoubleSeqSeq
361  {
362  DMP::DVec2d res = dmpPtr->getWeights();
363  DoubleSeqSeq resvec;
364  for (size_t i = 0; i < res.size(); ++i)
365  {
366  std::vector<double> cvec;
367  for (size_t j = 0; j < res[i].size(); ++j)
368  {
369  cvec.push_back(res[i][j]);
370  }
371  resvec.push_back(cvec);
372  }
373 
374  return resvec;
375  }
376 
377  void
378  NJointJSDMPController::setSpeed(double times, const Ice::Current&)
379  {
380  LockGuardType guard(controllerMutex);
381  tau = times;
382  }
383 
384  void
386  {
387  }
388 
389  void
391  {
392  }
393 
394  void
397  const DebugObserverInterfacePrx& debugObs)
398  {
399  StringVariantBaseMap datafields;
400  auto values = debugOutputData.getUpToDateReadBuffer().latestTargetVelocities;
401  for (auto& pair : values)
402  {
403  datafields[pair.first] = new Variant(pair.second);
404  }
405 
406  values = debugOutputData.getUpToDateReadBuffer().latestTargets;
407  for (auto& pair : values)
408  {
409  datafields[pair.first + "_pos"] = new Variant(pair.second);
410  }
411 
412  datafields["canVal"] = new Variant(debugOutputData.getUpToDateReadBuffer().currentCanVal);
413  datafields["mpcFactor"] = new Variant(debugOutputData.getUpToDateReadBuffer().mpcFactor);
414  debugObs->setDebugChannel("latestDMPTargetVelocities", datafields);
415  }
416 
417 
418  void
420  {
421  ARMARX_INFO << "init ...";
422  started = false;
423  runTask("NJointJSDMPController",
424  [&]
425  {
426  CycleUtil c(1);
427  getObjectScheduler()->waitForObjectStateMinimum(eManagedIceObjectStarted);
428  while (getState() == eManagedIceObjectStarted)
429  {
430  if (isControllerActive())
431  {
432  controllerRun();
433  }
434  c.waitForCycleDuration();
435  }
436  });
437  }
438 
439  void
441  {
442  }
443 
444 
445 } // namespace armarx::ctrl::njoint_ctrl::dmp
armarx::NJointControllerWithTripleBuffer< NJointJSDMPControllerControlData >::reinitTripleBuffer
void reinitTripleBuffer(const NJointJSDMPControllerControlData &initial)
Definition: NJointControllerWithTripleBuffer.h:68
GfxTL::sqrt
VectorXD< D, T > sqrt(const VectorXD< D, T > &a)
Definition: VectorXD.h:662
armarx::ControlTargetBase::asA
const T * asA() const
Definition: ControlTargetBase.h:76
armarx::Variant
The Variant class is described here: Variants.
Definition: Variant.h:224
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::NJointJSDMPController
NJointJSDMPController(const RobotUnitPtr &robotUnit, const NJointControllerConfigPtr &config, const VirtualRobot::RobotPtr &)
Definition: NJointJSDMPController.cpp:22
armarx::TripleBuffer::getWriteBuffer
T & getWriteBuffer()
Definition: TripleBuffer.h:90
armarx::NJointControllerBase::useSynchronizedRtRobot
const VirtualRobot::RobotPtr & useSynchronizedRtRobot(bool updateCollisionModel=false)
Requests a VirtualRobot for use in rtRun *.
Definition: NJointController.cpp:293
armarx::NJointControllerWithTripleBuffer< NJointJSDMPControllerControlData >::rtGetControlStruct
const NJointJSDMPControllerControlData & rtGetControlStruct() const
Definition: NJointControllerWithTripleBuffer.h:32
armarx::StringVariantBaseMap
std::map< std::string, VariantBasePtr > StringVariantBaseMap
Definition: ManagedIceObject.h:111
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::rtPreActivateController
void rtPreActivateController() override
This function is called before the controller is activated.
Definition: NJointJSDMPController.cpp:385
armarx::SensorValueBase::asA
const T * asA() const
Definition: SensorValueBase.h:82
armarx::SensorValueBase
The SensorValueBase class.
Definition: SensorValueBase.h:40
armarx::ControlTargetBase
Brief description of class JointControlTargetBase.
Definition: ControlTargetBase.h:47
armarx::TripleBuffer::commitWrite
void commitWrite()
Definition: TripleBuffer.h:146
NJointJSDMPController.h
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::rtPostDeactivateController
void rtPostDeactivateController() override
This function is called after the controller is deactivated.
Definition: NJointJSDMPController.cpp:390
armarx::NJointControllerBase::useControlTarget
ControlTargetBase * useControlTarget(const std::string &deviceName, const std::string &controlMode)
Declares to calculate the ControlTarget for the given ControlDevice in the given ControlMode when rtR...
Definition: NJointController.cpp:410
armarx::CycleUtil
This util class helps with keeping a cycle time during a control cycle.
Definition: CycleUtil.h:40
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:725
ProsthesisInterface.values
values
Definition: ProsthesisInterface.py:190
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:43
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::onInitNJointController
void onInitNJointController() override
Definition: NJointJSDMPController.cpp:419
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::createDMPFromString
std::vector< double > createDMPFromString(const std::string &dmpString, const Ice::Current &) override
Definition: NJointJSDMPController.cpp:335
armarx::NJointControllerWithTripleBuffer< NJointJSDMPControllerControlData >::getWriterControlStruct
NJointJSDMPControllerControlData & getWriterControlStruct()
Definition: NJointControllerWithTripleBuffer.h:54
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPControllerControlData
Definition: NJointJSDMPController.h:25
armarx::NJointControllerWithTripleBuffer< NJointJSDMPControllerControlData >::LockGuardType
std::lock_guard< std::recursive_mutex > LockGuardType
Definition: NJointControllerWithTripleBuffer.h:14
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::setSpeed
void setSpeed(double times, const Ice::Current &) override
Definition: NJointJSDMPController.cpp:378
armarx::NJointJointSpaceDMPControllerInterface::getDMPAsString
string getDMPAsString()
armarx::NJointControllerBase::rtGetRobot
const VirtualRobot::RobotPtr & rtGetRobot()
TODO make protected and use attorneys.
Definition: NJointControllerBase.h:845
armarx::detail::ControlThreadOutputBufferEntry
Definition: ControlThreadOutputBuffer.h:177
armarx::VariantType::Double
const VariantTypeId Double
Definition: Variant.h:919
armarx::NJointJointSpaceDMPControllerInterface::showMessages
void showMessages()
normalizeTimestamps
TrajectoryPtr normalizeTimestamps(TrajectoryPtr t, float maxTransVel, float maxRotVel)
Definition: PlayPlatformTrajectory.cpp:76
M_PI
#define M_PI
Definition: MathTools.h:17
armarx::NJointControllerBase::isControllerActive
bool isControllerActive(const Ice::Current &=Ice::emptyCurrent) const final override
Definition: NJointControllerBase.h:777
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::onDisconnectNJointController
void onDisconnectNJointController() override
Definition: NJointJSDMPController.cpp:440
armarx::control::common::mp::DVec
Ice::DoubleSeq DVec
Definition: MP.h:46
armarx::NJointControllerBase::runTask
void runTask(const std::string &taskName, Task &&task)
Executes a given task in a separate thread from the Application ThreadPool.
Definition: NJointControllerBase.h:753
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::learnDMPFromFiles
void learnDMPFromFiles(const Ice::StringSeq &fileNames, const Ice::Current &) override
Definition: NJointJSDMPController.cpp:227
armarx::NJointControllerWithTripleBuffer< NJointJSDMPControllerControlData >::writeControlStruct
void writeControlStruct()
Definition: NJointControllerWithTripleBuffer.h:44
armarx::TripleBuffer::getReadBuffer
const T & getReadBuffer() const
Definition: TripleBuffer.h:102
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::onPublish
virtual void onPublish(const SensorAndControl &, const DebugDrawerInterfacePrx &, const DebugObserverInterfacePrx &) override
Definition: NJointJSDMPController.cpp:395
ArmarXObjectScheduler.h
armarx::control::deprecated_njoint_mp_controller::joint_space
Definition: NJointJointSpaceDMPController.cpp:5
armarx::NJointJointSpaceDMPControllerInterface::getMPWeights
DoubleSeqSeq getMPWeights()
armarx::NJointControllerWithTripleBuffer< NJointJSDMPControllerControlData >::controlDataMutex
MutexType controlDataMutex
Definition: NJointControllerWithTripleBuffer.h:73
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::setViaPoints
void setViaPoints(Ice::Double u, double viapoint, const Ice::Current &) override
Definition: NJointJSDMPController.cpp:347
armarx::armem::Time
armarx::core::time::DateTime Time
Definition: forward_declarations.h:13
armarx::control::deprecated_njoint_mp_controller::joint_space::registrationControllerNJointJSDMPController
NJointControllerRegistration< NJointJSDMPController > registrationControllerNJointJSDMPController("NJointJSDMPController")
CycleUtil.h
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::setMPWeights
void setMPWeights(const DoubleSeqSeq &weights, const Ice::Current &) override
Definition: NJointJSDMPController.cpp:354
ARMARX_CHECK_EXPRESSION
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
Definition: ExpressionException.h:73
float
#define float
Definition: 16_Level.h:22
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::controllerRun
void controllerRun()
Definition: NJointJSDMPController.cpp:84
IceInternal::ProxyHandle<::IceProxy::armarx::DebugDrawerInterface >
armarx::TripleBuffer::getUpToDateReadBuffer
const T & getUpToDateReadBuffer() const
Definition: TripleBuffer.h:108
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::rtRun
void rtRun(const IceUtil::Time &sensorValuesTimestamp, const IceUtil::Time &timeSinceLastIteration) override
TODO make protected and use attorneys.
Definition: NJointJSDMPController.cpp:181
armarx::TripleBuffer::reinitAllBuffers
std::enable_if< std::is_copy_constructible< U >::value >::type reinitAllBuffers(const T &init)
Definition: TripleBuffer.h:153
armarx::ManagedIceObject::getObjectScheduler
ArmarXObjectSchedulerPtr getObjectScheduler() const
Definition: ManagedIceObject.cpp:731
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::runDMP
void runDMP(const Ice::DoubleSeq &goals, double times, const Ice::Current &) override
Definition: NJointJSDMPController.cpp:255
armarx::NJointControllerBase::useSensorValue
const SensorValueBase * useSensorValue(const std::string &sensorDeviceName) const
Get a const ptr to the given SensorDevice's SensorValue.
Definition: NJointController.cpp:383
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:18
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPControllerControlData::targetJointVels
Eigen::VectorXf targetJointVels
Definition: NJointJSDMPController.h:28
armarx::control::deprecated_njoint_mp_controller::joint_space::NJointJSDMPController::getClassName
std::string getClassName(const Ice::Current &) const override
Definition: NJointJSDMPController.cpp:17
armarx::TripleBuffer::updateReadBuffer
bool updateReadBuffer() const
Swaps in the hidden buffer if it contains new data.
Definition: TripleBuffer.h:131