KBMComponent.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2012-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package MemoryX::ArmarXObjects::KBMComponent
19  * @author Jonas Rauber ( kit at jonasrauber dot de )
20  * @date 2014
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
25 #include "KBMComponent.h"
26 
27 #include <cmath>
28 #include <fstream>
29 
30 #include <VirtualRobot/Import/RobotImporterFactory.h>
31 #include <VirtualRobot/KinematicChain.h>
32 #include <VirtualRobot/MathTools.h>
33 #include <VirtualRobot/Nodes/RobotNode.h>
34 #include <VirtualRobot/Robot.h>
35 #include <VirtualRobot/RuntimeEnvironment.h>
36 
37 #include <RobotAPI/interface/core/RobotState.h>
39 
42 
43 namespace armarx
44 {
45  void
47  {
48  usingProxy(getProperty<std::string>("LongtermMemoryName").getValue());
49  usingProxy(getProperty<std::string>("RobotStateComponentName").getValue());
50  }
51 
52  void
54  {
55  this->longtermMemoryPrx = getProxy<memoryx::LongtermMemoryInterfacePrx>(
56  getProperty<std::string>("LongtermMemoryName").getValue());
57  this->robotStateComponentPrx = getProxy<armarx::RobotStateComponentInterfacePrx>(
58  getProperty<std::string>("RobotStateComponentName").getValue());
59  }
60 
61  void
63  {
64  }
65 
66  void
68  {
69  }
70 
73  {
76  }
77 
78  /*
79  *
80  *
81  * Helper methods
82  *
83  *
84  */
85 
86  Eigen::Map<const memoryx::KBM::Vector>
88  const std::vector<memoryx::KBM::Real>& position)
89  {
90  VR_ASSERT_MESSAGE((int)(position.size()) == kbm.getNDim(),
91  "position size doesn't match KBM dimensions");
92  return Eigen::Map<const memoryx::KBM::Vector>(position.data(), kbm.getNDim());
93  }
94 
95  Eigen::Map<const memoryx::KBM::Vector>
97  const std::vector<memoryx::KBM::Real>& proprioception)
98  {
99  VR_ASSERT_MESSAGE((int)(proprioception.size()) == kbm.getNDoF(),
100  "proprioception size doesn't match KBM DoF");
101  return Eigen::Map<const memoryx::KBM::Vector>(proprioception.data(), kbm.getNDoF());
102  }
103 
104  Eigen::Map<const memoryx::KBM::Matrix>
106  const std::vector<memoryx::KBM::Real>& position)
107  {
108  int nDim = kbm.getNDim();
109 
110  if (position.size() % nDim != 0)
111  {
112  ARMARX_ERROR << "position has an invalid length";
113  }
114 
115  return mapMatrix(nDim, position);
116  }
117 
118  Eigen::Map<const memoryx::KBM::Matrix>
120  const std::vector<memoryx::KBM::Real>& proprioception)
121  {
122  int nDoF = kbm.getNDoF();
123 
124  if (proprioception.size() % nDoF != 0)
125  {
126  ARMARX_ERROR << "proprioception has an invalid length";
127  }
128 
129  return mapMatrix(nDoF, proprioception);
130  }
131 
132  Eigen::Map<const memoryx::KBM::Matrix>
133  KBMComponent::mapMatrix(int rows, const std::vector<memoryx::KBM::Real>& data)
134  {
135  if (data.size() % rows != 0)
136  {
137  ARMARX_ERROR << "data has an invalid length";
138  }
139 
140  VR_ASSERT(data.size() % rows == 0);
141  int cols = data.size() / rows;
142  return Eigen::Map<const memoryx::KBM::Matrix>(data.data(), rows, cols);
143  }
144 
146  KBMComponent::getKBM(const std::string& name)
147  {
148  auto it = kbms.find(name);
149 
150  if (it == kbms.end())
151  {
152  ARMARX_WARNING << "a KBM with the name '" << name << "' does not exist";
153  return memoryx::KBM::Models::KBM_ptr(); // null pointer
154  }
155 
156  return it->second;
157  }
158 
159  /*
160  *
161  *
162  * KBM Component interface methods
163  *
164  *
165  */
166 
167  void
168  KBMComponent::createKBM(const std::string& name,
169  Ice::Int nDoF,
170  Ice::Int dim,
171  Ice::Float spreadAngle,
172  const Ice::Current& c)
173  {
174  /*
175  * Check if a KBM with the given name already exists
176  */
177  if (kbms.find(name) != kbms.end())
178  {
179  ARMARX_ERROR << "a KBM with the name '" << name << "' already exists";
180  return;
181  }
182 
183  /*
184  * Create the KBM
185  */
186  memoryx::KBM::Models::KBM_ptr kbm(new memoryx::KBM::Models::KBM(nDoF, dim, spreadAngle));
187  kbms[name] = kbm;
188  createdFromVirtualRobot[name] = false;
189  ARMARX_INFO << "created a KBM with the name '" << name << "'";
190  }
191 
192  void
193  KBMComponent::createArmar3KBM(const std::string& name,
194  const Ice::StringSeq& robotNodeNames,
195  const std::vector<memoryx::KBM::Real>& jointValueAverages,
196  const std::vector<memoryx::KBM::Real>& spreadAnglesSequence,
197  const std::string& tcpName,
198  bool useOrientation,
199  const Ice::Current& c)
200  {
201  /*
202  * check parameters
203  */
204  if (robotNodeNames.size() != 7)
205  {
206  ARMARX_WARNING << "createArmar3KBM should only be used with all 7 joints";
207  }
208 
209  if (jointValueAverages.size() != robotNodeNames.size())
210  {
211  ARMARX_INFO << "robotNodeNames: " << robotNodeNames.size();
212  ARMARX_INFO << "jointValueAverages: " << jointValueAverages.size();
213  ARMARX_ERROR << "jointValueAverages should have the same size as robotNodeNames";
214  }
215 
216  if (spreadAnglesSequence.size() != robotNodeNames.size())
217  {
218  ARMARX_INFO << "robotNodeNames: " << robotNodeNames.size();
219  ARMARX_INFO << "spreadAngles: " << spreadAnglesSequence.size();
220  ARMARX_ERROR << "spreadAnglesSequence should have the same size as robotNodeNames";
221  }
222 
223  /*
224  * Check if a KBM with the given name already exists
225  */
226  if (kbms.find(name) != kbms.end())
227  {
228  ARMARX_ERROR << "a KBM with the name '" << name << "' already exists";
229  return;
230  }
231 
232  /*
233  * spread angles
234  */
235  Eigen::Map<const memoryx::KBM::Vector> spreadAngles(spreadAnglesSequence.data(),
236  spreadAnglesSequence.size());
237  ARMARX_IMPORTANT << "spreadAngles: " << spreadAngles.transpose();
238 
239  /*
240  * Save meta data
241  */
242  std::time_t now = std::time(0);
243  std::tm* date = std::localtime(&now);
244  char when[256] = {0};
245  std::strftime(when, sizeof(when), "%Y-%m-%d-%H-%M-%S", date);
246  std::string baseFilename = "data/evaluation/" + std::string(when) + "-" + name;
247 
248  std::ofstream metaFile(baseFilename + "-create.txt", std::ios_base::app);
249  Eigen::Map<const memoryx::KBM::Vector> _jointValueAverages(jointValueAverages.data(),
250  jointValueAverages.size());
251 
252  if (metaFile.is_open())
253  {
254  metaFile << "kbm name: " << name << std::endl;
255  metaFile << "joint offsets: " << _jointValueAverages << std::endl;
256  metaFile << "spread angles: " << spreadAngles << std::endl;
257  }
258 
259  metaFile.close();
260 
261  /*
262  * Load VirtualRobot
263  */
264  VirtualRobot::RobotImporterFactoryPtr importer =
265  VirtualRobot::RobotImporterFactory::fromFileExtension("xml", NULL);
266  std::string filename("robots/ArmarIII/ArmarIII.xml");
267  VirtualRobot::RuntimeEnvironment::getDataFileAbsolute(filename);
268  VirtualRobot::RobotPtr robot =
269  importer->loadFromFile(filename, VirtualRobot::RobotIO::eStructure);
270 
271  if (!robot)
272  {
273  ARMARX_ERROR << "the ArmarIII.xml file could not be loaded";
274  }
275 
276  VR_ASSERT(robot);
277 
278  /*
279  * Create a robot node set with the names of the active joints
280  */
281  //VirtualRobot::RobotNodeSetPtr nodeSet = robot->getRobotNodeSet("TorsoRightArm");
282  VirtualRobot::RobotNodeSetPtr nodeSet = VirtualRobot::RobotNodeSet::createRobotNodeSet(
283  robot, "ToolUseRightArm", robotNodeNames, "Right Arm Base", tcpName, true);
284 
285  if (!nodeSet)
286  {
287  ARMARX_ERROR << "the nodeSet could not be created";
288  }
289 
290  VR_ASSERT(nodeSet);
291 
292  /*
293  * Create a kinematic chain from the robot node set
294  */
295  VirtualRobot::KinematicChainPtr chain;
296  //chain.reset(new VirtualRobot::KinematicChain("TorsoRightArmChain",robot,nodeSet->getAllRobotNodes(),robot->getRobotNode("Wrist 2 R")));
297  chain.reset(new VirtualRobot::KinematicChain("ToolUseRightArmChain",
298  robot,
299  nodeSet->getAllRobotNodes(),
300  robot->getRobotNode(tcpName)));
301 
302  if (!chain)
303  {
304  ARMARX_ERROR << "chain could not be created";
305  }
306 
307  VR_ASSERT(chain);
308 
309  /*
310  * Set joint values to their average position,
311  * so that samples are distributed around zero
312  */
313  ARMARX_IMPORTANT << "TCP GlobalPose before setting averages: "
314  << chain->getTCP()->getGlobalPose();
315  ARMARX_IMPORTANT << "setting averages: " << jointValueAverages;
316  Ice::FloatSeq jointValues;
317 
318  for (auto& value : jointValueAverages)
319  {
320  jointValues.push_back(value);
321  }
322 
323  chain->setJointValues(jointValues);
324  ARMARX_VERBOSE << "node " << chain->getNode(0)->getName()
325  << " is at: " << chain->getNode(0)->getJointValue();
326  ARMARX_IMPORTANT << "TCP GlobalPose after setting averages: "
327  << chain->getTCP()->getGlobalPose();
328 
329  VirtualRobot::RobotNodePtr FoR = chain->getKinematicRoot();
330 
331  VR_ASSERT(FoR);
332 
333  /*
334  * TODO: print warning if not
335  */
336  ARMARX_IMPORTANT << "FoR GlobalPose should be the identity matrix: "
337  << FoR->getGlobalPose();
338 
339  unsigned int nDoF = chain->getSize();
340  ARMARX_IMPORTANT << "degrees of freedom of the VirtualRobot's kinematic chain: " << nDoF;
341 
342  /*
343  * Create the KBM
344  */
346  chain, FoR, spreadAngles, useOrientation));
347  kbms[name] = kbm;
348  createdFromVirtualRobot[name] = true;
349  ARMARX_INFO << "created a KBM with the name '" << name << "'";
350  }
351 
352  void
353  KBMComponent::batch(const std::string& name,
354  const std::vector<memoryx::KBM::Real>& proprioceptionSequence,
355  const std::vector<memoryx::KBM::Real>& positionSequence,
356  Ice::Int method,
357  Ice::Float threshold,
358  const Ice::Current& c)
359  {
361 
362  if (!kbm)
363  {
364  return;
365  }
366 
367  /*
368  * It doesn't make sense to do batch learning on KBMs created from a VirtualRobot.
369  */
370  if (createdFromVirtualRobot[name])
371  {
372  ARMARX_ERROR << "the KBM " << name
373  << " was created from a VirtualRobot, it does not support batch learning";
374  return;
375  }
376 
377  /*
378  * This maps the data column wise.
379  */
380  Eigen::Map<const memoryx::KBM::Matrix> proprioception =
381  mapProprioceptions(*kbm, proprioceptionSequence);
382  Eigen::Map<const memoryx::KBM::Matrix> position = mapPositions(*kbm, positionSequence);
383 
384  if (proprioception.cols() != position.cols())
385  {
386  ARMARX_ERROR << "proprioception and position contain different number of samples";
387  return;
388  }
389 
390  /*
391  * Start batch learning
392  */
393  kbm->batch(
394  proprioception, position, (memoryx::KBM::Models::KBM::Optimization)method, threshold);
395  }
396 
397  void
398  KBMComponent::online(const std::string& name,
399  const std::vector<memoryx::KBM::Real>& proprioceptionSequence,
400  const std::vector<memoryx::KBM::Real>& positionSequence,
401  Ice::Float learningRate,
402  const Ice::Current& c)
403  {
405 
406  if (!kbm)
407  {
408  return;
409  }
410 
411  /*
412  * This maps the data column wise.
413  */
414  Eigen::Map<const memoryx::KBM::Matrix> proprioception =
415  mapProprioceptions(*kbm, proprioceptionSequence);
416  Eigen::Map<const memoryx::KBM::Matrix> position = mapPositions(*kbm, positionSequence);
417 
418  if (proprioception.cols() != position.cols())
419  {
420  ARMARX_ERROR << "proprioception and position contain different number of samples";
421  return;
422  }
423 
424  if (createdFromVirtualRobot[name])
425  {
426  /*
427  * support VirtualRobot KBMs by reversing joint order
428  */
430  << "reversing proprioception order because KBM was created from VirtualRobot";
431  kbm->online(proprioception.colwise().reverse(), position, learningRate);
432  }
433  else
434  {
435  // TODO: why does this work: KBM expects a Matrix and should not be
436  // compatible with a Map of Matrix without additional modifications
437  kbm->online(proprioception, position, learningRate);
438  }
439  }
440 
441  void
443  const std::string& name,
444  const std::vector<memoryx::KBM::Real>& proprioceptionSequence,
445  const std::vector<memoryx::KBM::Real>& positionSequence,
446  Ice::Float learningRate,
447  const std::vector<memoryx::KBM::Real>& evaluationProprioceptionSequence,
448  const std::vector<memoryx::KBM::Real>& evaluationPositionSequence,
449  const Ice::Current& c)
450  {
452 
453  if (!kbm)
454  {
455  return;
456  }
457 
458  /*
459  * This maps the data column wise.
460  */
461  Eigen::Map<const memoryx::KBM::Matrix> _proprioception =
462  mapProprioceptions(*kbm, proprioceptionSequence);
463  Eigen::Map<const memoryx::KBM::Matrix> position = mapPositions(*kbm, positionSequence);
464 
465  Eigen::Map<const memoryx::KBM::Matrix> _evaluationProprioception =
466  mapProprioceptions(*kbm, evaluationProprioceptionSequence);
467  Eigen::Map<const memoryx::KBM::Matrix> evaluationPosition =
468  mapPositions(*kbm, evaluationPositionSequence);
469 
470  if (_proprioception.cols() != position.cols())
471  {
472  ARMARX_ERROR << "proprioception and position contain different number of samples";
473  return;
474  }
475 
476  if (_evaluationProprioception.cols() != evaluationPosition.cols())
477  {
478  ARMARX_ERROR << "evaluation proprioception and evaluation position contain different "
479  "number of samples";
480  return;
481  }
482 
483  memoryx::KBM::Matrix proprioception;
484  memoryx::KBM::Matrix evaluationProprioception;
485 
486  if (createdFromVirtualRobot[name])
487  {
488  /*
489  * support VirtualRobot KBMs by reversing joint order
490  */
492  << "reversing proprioception order because KBM was created from VirtualRobot";
493  proprioception = _proprioception.colwise().reverse();
494  evaluationProprioception = _evaluationProprioception.colwise().reverse();
495  }
496  else
497  {
498  proprioception = _proprioception;
499  evaluationProprioception = _evaluationProprioception;
500  }
501 
502  ARMARX_IMPORTANT << "training samples: " << proprioception.cols();
503  ARMARX_IMPORTANT << "evaluation samples: " << evaluationProprioception.cols();
504 
505  /*
506  * Prepare file
507  */
508 
509  std::time_t now = std::time(0);
510  std::tm* date = std::localtime(&now);
511  char when[256] = {0};
512  std::strftime(when, sizeof(when), "%Y-%m-%d-%H-%M-%S", date);
513  std::string baseFilename = "data/evaluation/" + std::string(when) + "-" + name;
514 
515  std::ofstream metaFile(baseFilename + "-meta.txt", std::ios_base::app);
516  std::string evaluationFilename(baseFilename + "-evaluation.txt");
517  std::ofstream evaluationFile(evaluationFilename, std::ios_base::app);
518  std::string trainingProprioceptionsFilename(baseFilename + "-training-proprioceptions.txt");
519  std::ofstream trainingProprioceptionsFile(trainingProprioceptionsFilename,
520  std::ios_base::app);
521  std::string trainingPositionsFilename(baseFilename + "-training-positions.txt");
522  std::ofstream trainingPositionsFile(trainingPositionsFilename, std::ios_base::app);
523  std::string testProprioceptionsFilename(baseFilename + "-test-proprioceptions.txt");
524  std::ofstream testProprioceptionsFile(testProprioceptionsFilename, std::ios_base::app);
525  std::string testPositionsFilename(baseFilename + "-test-positions.txt");
526  std::ofstream testPositionsFile(testPositionsFilename, std::ios_base::app);
527 
528  if (metaFile.is_open())
529  {
530  metaFile << "kbm name: " << name << std::endl;
531  metaFile << "learning rate: " << learningRate << std::endl;
532  metaFile << "degress of freedom: " << kbm->getNDoF() << std::endl;
533  metaFile << "dimensions: " << kbm->getNDim() << std::endl;
534  metaFile << "training samples: " << proprioception.cols() << std::endl;
535  metaFile << "test samples: " << evaluationProprioception.cols() << std::endl;
536  metaFile << "evaluation columns: mean, std, median, iqr, max" << std::endl;
537  }
538 
539  metaFile.close();
540 
541  if (!trainingProprioceptionsFile.is_open())
542  {
543  ARMARX_ERROR << "file " << trainingProprioceptionsFilename
544  << " could not be opened / created";
545  }
546 
547  if (!trainingPositionsFile.is_open())
548  {
549  ARMARX_ERROR << "file " << trainingPositionsFilename
550  << " could not be opened / created";
551  }
552 
553  if (!testProprioceptionsFile.is_open())
554  {
555  ARMARX_ERROR << "file " << testProprioceptionsFilename
556  << " could not be opened / created";
557  }
558 
559  if (!testPositionsFile.is_open())
560  {
561  ARMARX_ERROR << "file " << testPositionsFilename << " could not be opened / created";
562  }
563 
564  trainingProprioceptionsFile << proprioception.transpose() << std::endl;
565  trainingPositionsFile << position.transpose() << std::endl;
566  testProprioceptionsFile << evaluationProprioception.transpose() << std::endl;
567  testPositionsFile << evaluationPosition.transpose() << std::endl;
568 
569  trainingProprioceptionsFile.close();
570  trainingPositionsFile.close();
571  testProprioceptionsFile.close();
572  testPositionsFile.close();
573 
574  /*
575  * Learn, evaluate and write to file
576  */
577  if (!evaluationFile.is_open())
578  {
579  ARMARX_ERROR << "file " << evaluationFilename << " could not be opened / created";
580  }
581 
583  kbm->getErrors(evaluationProprioception, evaluationPosition);
584  ARMARX_IMPORTANT << "online learning before learning: " << errors;
585  evaluationFile << errors.Mean << ", " << errors.STD << ", " << errors.Median << ", "
586  << errors.IQR << ", " << errors.Max << std::endl;
587 
588  for (int i = 0; i < proprioception.cols(); i++)
589  {
590  kbm->online(proprioception.col(i), position.col(i), learningRate);
591  /*
592  * TODO: maybe use my own error calculation, including standard deviation, etc.
593  */
594  errors = kbm->getErrors(evaluationProprioception, evaluationPosition);
595  ARMARX_IMPORTANT << "online learning error after step " << (i + 1) << ": " << errors;
596  evaluationFile << errors.Mean << ", " << errors.STD << ", " << errors.Median << ", "
597  << errors.IQR << ", " << errors.Max << std::endl;
598  }
599 
600  evaluationFile.close();
601  }
602 
603  std::vector<memoryx::KBM::Real>
604  KBMComponent::predict(const std::string& name,
605  const std::vector<memoryx::KBM::Real>& proprioceptionSequence,
606  const Ice::Current& c)
607  {
609 
610  if (!kbm)
611  {
612  return std::vector<memoryx::KBM::Real>();
613  }
614 
615  Eigen::Map<const memoryx::KBM::Matrix> proprioception =
616  mapProprioceptions(*kbm, proprioceptionSequence);
617 
618  int nDim = kbm->getNDim();
619  int nSamples = proprioception.cols();
620  std::vector<memoryx::KBM::Real> predictionSequence(nDim * nSamples);
621  Eigen::Map<memoryx::KBM::Matrix> prediction(predictionSequence.data(), nDim, nSamples);
622 
623  if (createdFromVirtualRobot[name])
624  {
625  /*
626  * support VirtualRobot KBMs by reversing joint order
627  */
628  prediction = kbm->predict(proprioception.colwise().reverse());
629  }
630  else
631  {
632  prediction = kbm->predict(proprioception);
633  }
634 
635  ARMARX_INFO << "KBM '" << name << "' predicted: " << prediction.transpose();
636  return predictionSequence;
637  }
638 
639  void
640  KBMComponent::printErrors(const std::string& name,
641  const std::vector<memoryx::KBM::Real>& proprioceptionSequence,
642  const std::vector<memoryx::KBM::Real>& positionSequence,
643  const Ice::Current& c)
644  {
646 
647  if (!kbm)
648  {
649  return;
650  }
651 
652  /*
653  * This maps the data column wise.
654  */
655  Eigen::Map<const memoryx::KBM::Matrix> proprioception =
656  mapProprioceptions(*kbm, proprioceptionSequence);
657  Eigen::Map<const memoryx::KBM::Matrix> position = mapPositions(*kbm, positionSequence);
658 
659  if (proprioception.cols() != position.cols())
660  {
661  ARMARX_ERROR << "proprioception and position contain different number of samples";
662  return;
663  }
664 
665  ARMARX_IMPORTANT << "samples: " << proprioception.cols();
666 
668 
669  if (createdFromVirtualRobot[name])
670  {
671  /*
672  * support VirtualRobot KBMs by reversing joint order
673  */
674  errors = kbm->getErrors(proprioception.colwise().reverse(), position);
675  }
676  else
677  {
678  errors = kbm->getErrors(proprioception, position);
679  }
680 
681  ARMARX_IMPORTANT << "KBM '" << name << "' error: " << errors;
682  }
683 
684  void
685  KBMComponent::printAccumulatorStatistics(int nDim, int nDoF, const Ice::Current& c)
686  {
687  Eigen::Map<const memoryx::KBM::Matrix> proprioception =
688  mapMatrix(nDoF, proprioceptionAccumulator);
689  Eigen::Map<const memoryx::KBM::Matrix> position = mapMatrix(nDim, positionAccumulator);
690 
691  ARMARX_VERBOSE << "proprioception samples: " << proprioception.cols();
692  ARMARX_VERBOSE << "position samples: " << position.cols();
693 
694  ARMARX_VERBOSE << "proprioception minima: "
695  << proprioception.rowwise().minCoeff().transpose();
696  ARMARX_VERBOSE << "proprioception maxima: "
697  << proprioception.rowwise().maxCoeff().transpose();
698  ARMARX_VERBOSE << "proprioception average: " << proprioception.rowwise().mean().transpose();
699  ARMARX_VERBOSE << "position minima: " << position.rowwise().minCoeff().transpose();
700  ARMARX_VERBOSE << "position maxima: " << position.rowwise().maxCoeff().transpose();
701  ARMARX_VERBOSE << "position average: " << position.rowwise().mean().transpose();
702  }
703 
704  Ice::DoubleSeq
705  KBMComponent::getRawJointValuesAverages(int nDoF, const Ice::Current& c)
706  {
707  Eigen::Map<const memoryx::KBM::Matrix> rawJointValues =
708  mapMatrix(nDoF, rawJointValuesAccumulator);
709 
710  ARMARX_VERBOSE << "raw jointValue samples: " << rawJointValues.cols();
711 
712  std::vector<memoryx::KBM::Real> result(nDoF);
713  Eigen::Map<memoryx::KBM::Vector> averages(result.data(), nDoF);
714  averages = rawJointValues.rowwise().mean();
715 
716  Ice::DoubleSeq resultFloat(result.begin(), result.end());
717  return resultFloat;
718  }
719 
720  Ice::DoubleSeq
721  KBMComponent::getSpreadAngles(int nDoF, const Ice::Current& c)
722  {
723  Eigen::Map<const memoryx::KBM::Matrix> proprioceptions =
724  mapMatrix(nDoF, proprioceptionAccumulator);
725 
726  ARMARX_VERBOSE << "proprioception samples: " << proprioceptions.cols();
727 
728  std::vector<memoryx::KBM::Real> result(nDoF);
729  Eigen::Map<memoryx::KBM::Vector> spreadAngles(result.data(), nDoF);
730 
731  memoryx::KBM::Vector leftSpreadAngles = proprioceptions.rowwise().minCoeff();
732  memoryx::KBM::Vector rightSpreadAngles = proprioceptions.rowwise().maxCoeff();
733  ARMARX_VERBOSE << "leftSpreadAngles: " << leftSpreadAngles;
734  ARMARX_VERBOSE << "rightSpreadAngles: " << rightSpreadAngles;
735 
736  for (int i = 0; i < nDoF; i++)
737  {
738  spreadAngles[i] = fmin(fabs(leftSpreadAngles[i]), fabs(rightSpreadAngles[i]));
739  }
740 
741  ARMARX_VERBOSE << "data spreadAngles: " << spreadAngles;
742 
743  Ice::DoubleSeq resultFloat(result.begin(), result.end());
744  return resultFloat;
745  }
746 
747  void
749  const std::vector<memoryx::KBM::Real>& rawJointValuesAverages,
750  const Ice::Current& c)
751  {
752  if (proprioceptionAccumulator.size() != 0)
753  {
754  ARMARX_ERROR << "proprioception accumulator should be empty, when using setting it "
755  "from raw joint accumulator";
756  }
757 
758  if (rawJointValuesAccumulator.size() % rawJointValuesAverages.size() != 0)
759  {
760  ARMARX_ERROR << "rawJointValuesAverages size is incompatible to accumulator size";
761  }
762 
763  ARMARX_INFO << "rawJointValuesAccumualtor: " << rawJointValuesAccumulator;
764  std::vector<memoryx::KBM::Real> proprioceptionsFromRawJointAccumulator;
765  unsigned int i = 0;
766 
767  for (auto jointValue : rawJointValuesAccumulator)
768  {
769  if (i == rawJointValuesAverages.size())
770  {
771  i = 0;
772  }
773 
774  float offset = rawJointValuesAverages[i];
775  i++;
776 
777  /*
778  * Convert to proprioception
779  */
780  proprioceptionsFromRawJointAccumulator.push_back(jointValue - offset);
781  }
782 
783  ARMARX_INFO << "proprioceptionsFromRawJointAccumulator: "
784  << proprioceptionsFromRawJointAccumulator;
785  proprioceptionAccumulator = proprioceptionsFromRawJointAccumulator;
786 
787  /*
788  * TODO: move to separate method
789  */
790  }
791 
792  void
793  KBMComponent::setPositionLimits(int nDim, const Ice::Current& c)
794  {
795  Eigen::Map<const memoryx::KBM::Matrix> positions = mapMatrix(nDim, positionAccumulator);
796  minima = positions.rowwise().minCoeff();
797  maxima = positions.rowwise().maxCoeff();
798  ARMARX_IMPORTANT << "setting position minima: " << minima.transpose();
799  ARMARX_IMPORTANT << "setting position maxima: " << maxima.transpose();
800  }
801 
802  void
803  KBMComponent::onlineAccumulator(const std::string& name,
804  Ice::Float learningRate,
805  const Ice::Current& c)
806  {
807  online(name, proprioceptionAccumulator, positionAccumulator, learningRate, c);
808  }
809 
810  void
811  KBMComponent::onlineAccumulatorVerbose(const std::string& name,
812  Ice::Float learningRate,
813  const Ice::Current& c)
814  {
815  onlineVerbose(name,
816  proprioceptionAccumulator,
817  positionAccumulator,
818  learningRate,
819  evaluationProprioceptionAccumulator,
820  evaluationPositionAccumulator,
821  c);
822  }
823 
824  void
825  KBMComponent::batchAccumulator(const std::string& name,
826  Ice::Int method,
827  Ice::Float threshold,
828  const Ice::Current& c)
829  {
830  batch(name, proprioceptionAccumulator, positionAccumulator, method, threshold, c);
831  }
832 
833  void
834  KBMComponent::printErrorsAccumulator(const std::string& name, const Ice::Current& c)
835  {
836  printErrors(name, proprioceptionAccumulator, positionAccumulator, c);
837  }
838 
839  void
840  KBMComponent::predictAccumulator(const std::string& name, const Ice::Current& c)
841  {
842  predict(name, proprioceptionAccumulator, c);
843  }
844 
845  /*
846  *
847  *
848  * The following methods should alredady have orientation support
849  *
850  *
851  */
852 
853  void
854  KBMComponent::accumulatePositions(const std::vector<memoryx::KBM::Real>& position,
855  const Ice::Current& c)
856  {
857  /*
858  * accumulate positions
859  */
860  positionAccumulator.insert(positionAccumulator.end(), position.begin(), position.end());
861 
862  //ARMARX_VERBOSE << "Positions Accumulator: " << positionAccumulator;
863  }
864 
865  void
866  KBMComponent::accumulateProprioceptions(const std::vector<memoryx::KBM::Real>& proprioception,
867  const Ice::Current& c)
868  {
869  /*
870  * accumulate proprioceptions
871  */
872  proprioceptionAccumulator.insert(
873  proprioceptionAccumulator.end(), proprioception.begin(), proprioception.end());
874 
875  //ARMARX_VERBOSE << "Proprioception Accumulator: " << proprioceptionAccumulator;
876  }
877 
878  void
880  const std::vector<memoryx::KBM::Real>& rawJointValuesSequence,
881  const Ice::Current& c)
882  {
883  /*
884  * accumulate raw joint values
885  */
886  rawJointValuesAccumulator.insert(rawJointValuesAccumulator.end(),
887  rawJointValuesSequence.begin(),
888  rawJointValuesSequence.end());
889 
890  //ARMARX_VERBOSE << "Raw Joint Values Accumulator: " << rawJointValuesAccumulator;
891  }
892 
893  void
894  KBMComponent::accumulateEvaluationPositions(const std::vector<memoryx::KBM::Real>& position,
895  const Ice::Current& c)
896  {
897  /*
898  * accumulate positions
899  */
900  evaluationPositionAccumulator.insert(
901  evaluationPositionAccumulator.end(), position.begin(), position.end());
902 
903  //ARMARX_VERBOSE << "Positions Accumulator: " << positionAccumulator;
904  }
905 
906  void
908  const std::vector<memoryx::KBM::Real>& proprioception,
909  const Ice::Current& c)
910  {
911  /*
912  * accumulate proprioceptions
913  */
914  evaluationProprioceptionAccumulator.insert(evaluationProprioceptionAccumulator.end(),
915  proprioception.begin(),
916  proprioception.end());
917 
918  //ARMARX_VERBOSE << "Proprioception Accumulator: " << proprioceptionAccumulator;
919  }
920 
921  std::vector<memoryx::KBM::Real>
922  KBMComponent::solveGlobalIK(const std::string& name,
923  const std::vector<memoryx::KBM::Real>& targetPosition,
924  const Ice::Current& c)
925  {
926  /*
927  * Check input variables
928  */
930 
931  if (!kbm)
932  {
933  ARMARX_WARNING << "returning empty solution";
934  return std::vector<memoryx::KBM::Real>();
935  }
936 
937  Eigen::Map<const memoryx::KBM::Vector> target(mapPosition(*kbm, targetPosition));
938 
939  /*
940  * Create output variables
941  */
942  std::vector<memoryx::KBM::Real> result(kbm->getNDoF());
943  Eigen::Map<memoryx::KBM::Vector> solution(result.data(), kbm->getNDoF());
944 
945  /*
946  * Solve Global IK
947  */
950  ARMARX_IMPORTANT << "Global IK found " << solutions.size() << " solutions";
951 
952  for (unsigned int i = 0; i < solutions.size(); ++i)
953  {
954  memoryx::KBM::Inverse::Solution solution = solutions[i];
955  ARMARX_IMPORTANT << i << ". solution: " << solution.spreadAngles;
956  }
957 
958  // TODO: support VirtualRobot KBMs by switching proprioceptions
959  if (createdFromVirtualRobot[name])
960  {
961  ARMARX_ERROR << "solveGlobalIK does not yet support KBMs created from Virtual Robot!";
962  }
963 
964  return result; // TODO: currently always 0
965  }
966 
967  std::vector<memoryx::KBM::Real>
969  const std::string& name,
970  const std::vector<memoryx::KBM::Real>& targetPosition,
971  const std::vector<memoryx::KBM::Real>& currentPosition,
972  const std::vector<memoryx::KBM::Real>& currentProprioception,
973  const std::vector<memoryx::KBM::Real>& lowerProprioceptionLimitsSequence,
974  const std::vector<memoryx::KBM::Real>& upperProprioceptionLimitsSequence,
975  const Ice::Current& c)
976  {
977  /*
978  * Check input variables
979  */
981 
982  if (!kbm)
983  {
984  ARMARX_WARNING << "returning empty solution";
985  return std::vector<memoryx::KBM::Real>();
986  }
987 
988  Eigen::Map<const memoryx::KBM::Vector> target(mapPosition(*kbm, targetPosition));
989  Eigen::Map<const memoryx::KBM::Vector> current(mapPosition(*kbm, currentPosition));
990  Eigen::Map<const memoryx::KBM::Vector> proprioception(
991  mapProprioception(*kbm, currentProprioception));
992  Eigen::Map<const memoryx::KBM::Vector> lowerProprioceptionLimits(
993  mapProprioception(*kbm, lowerProprioceptionLimitsSequence));
994  Eigen::Map<const memoryx::KBM::Vector> upperProprioceptionLimits(
995  mapProprioception(*kbm, upperProprioceptionLimitsSequence));
996 
997  /*
998  * Check position limits
999  */
1000  if (minima.size() != target.size())
1001  {
1002  ARMARX_ERROR << "minima and target have different size";
1003  return std::vector<memoryx::KBM::Real>();
1004  }
1005 
1006  if (maxima.size() != target.size())
1007  {
1008 
1009  ARMARX_ERROR << "maxima and target have different size";
1010  return std::vector<memoryx::KBM::Real>();
1011  }
1012 
1013  for (int i = 0; i < kbm->getNDim(); i++)
1014  {
1015  if (target[i] < minima[i] - 90)
1016  {
1017  ARMARX_ERROR << "target[" << i << "] = " << target[i] << " is smaller than minima "
1018  << minima[i];
1019  return std::vector<memoryx::KBM::Real>();
1020  }
1021 
1022  if (target[i] > maxima[i] + 90)
1023  {
1024  ARMARX_ERROR << "target[" << i << "] = " << target[i] << " is greater than maxima "
1025  << maxima[i];
1026  return std::vector<memoryx::KBM::Real>();
1027  }
1028  }
1029 
1030  /*
1031  * Create output variables
1032  */
1033  std::vector<memoryx::KBM::Real> result(kbm->getNDoF());
1034  Eigen::Map<memoryx::KBM::Vector> solution(result.data(), kbm->getNDoF());
1035 
1036  /*
1037  * Solve Differential IK
1038  */
1039  bool solved;
1040 
1041  if (createdFromVirtualRobot[name])
1042  {
1043  /*
1044  * support VirtualRobot KBMs by reversing joint order
1045  */
1046  ARMARX_IMPORTANT << "reversing proprioception and limits order because KBM was created "
1047  "from VirtualRobot";
1048  solved = KBMDifferentialIK::solveMany(*kbm,
1049  target,
1050  current,
1051  proprioception.reverse(),
1052  lowerProprioceptionLimits.reverse(),
1053  upperProprioceptionLimits.reverse(),
1054  solution);
1055  }
1056  else
1057  {
1058  solved = KBMDifferentialIK::solveMany(*kbm,
1059  target,
1060  current,
1061  proprioception,
1062  lowerProprioceptionLimits,
1063  upperProprioceptionLimits,
1064  solution);
1065  }
1066 
1067  if (createdFromVirtualRobot[name])
1068  {
1069  /*
1070  * support VirtualRobot KBMs by reversing joint order
1071  */
1072  ARMARX_IMPORTANT << "solution before reverse: " << solution.transpose();
1073  solution = solution.colwise().reverse();
1074  ARMARX_IMPORTANT << "solution after reverse: " << solution.transpose();
1075  }
1076 
1077  /*
1078  * Output
1079  */
1080  ARMARX_IMPORTANT << "solved = " << solved;
1081  ARMARX_IMPORTANT << "solution = " << solution;
1082  ARMARX_IMPORTANT << "result (check if equal to solution!) = " << result;
1083 
1084  return result;
1085  }
1086 
1087  /*
1088  *
1089  *
1090  * KBM Differential Inverse Kinematics
1091  *
1092  *
1093  */
1094 
1095  float
1097  {
1098  return LO + static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / (HI - LO)));
1099  }
1100 
1104  const memoryx::KBM::Vector& position,
1105  const memoryx::KBM::Vector& proprioception,
1106  float stepSizeFactor,
1107  float maxStepSize)
1108  {
1109 
1110  /*
1111  * Calculate postion deltas
1112  */
1113  memoryx::KBM::Vector positionDeltas = stepSizeFactor * (target - position);
1114 
1115  if (positionDeltas.norm() > maxStepSize)
1116  {
1117  positionDeltas *= maxStepSize / positionDeltas.norm();
1118  }
1119 
1120  /*
1121  * Calcualte the jacobian matrix
1122  */
1123  memoryx::KBM::Matrix jacobian = kbm.getJacobian(proprioception);
1124 
1125  /*
1126  * Calculate pseudo inverse using function from simox
1127  * simox uses an algorithm that is numerically stable
1128  */
1129 #ifdef KBM_USE_DOUBLE_PRECISION
1130  memoryx::KBM::Matrix pseudoInverse = VirtualRobot::MathTools::getPseudoInverseD(jacobian);
1131 #else
1132  memoryx::KBM::Matrix pseudoInverse = VirtualRobot::MathTools::getPseudoInverse(jacobian);
1133 #endif
1134 
1135  /*
1136  * Calculate joint deltas
1137  */
1138  memoryx::KBM::Vector jointDeltas = pseudoInverse * positionDeltas;
1139  return jointDeltas;
1140  }
1141 
1144  const memoryx::KBM::Vector& upperProprioceptionLimits)
1145  {
1146  if (lowerProprioceptionLimits.size() != upperProprioceptionLimits.size())
1147  {
1148  ARMARX_ERROR_S << "limits must have same length";
1149  }
1150 
1151  int n = lowerProprioceptionLimits.size();
1152  memoryx::KBM::Vector result(n);
1153 
1154  for (int i = 0; i < n; i++)
1155  {
1156  float l = lowerProprioceptionLimits(i);
1157  float u = upperProprioceptionLimits(i);
1158  result(i) = randomFloat(l, u);
1159  }
1160 
1161  return result;
1162  }
1163 
1164  bool
1166  const memoryx::KBM::Vector& solution,
1167  const memoryx::KBM::Vector& lowerProprioceptionLimits,
1168  const memoryx::KBM::Vector& upperProprioceptionLimits)
1169  {
1170  /*
1171  * Check parameters
1172  */
1173  int n = solution.size();
1174 
1175  if (lowerProprioceptionLimits.size() != n)
1176  {
1177  ARMARX_ERROR_S << "lower proprioception limits have wrong length: "
1178  << lowerProprioceptionLimits.size() << ", should be " << n;
1179  }
1180 
1181  if (upperProprioceptionLimits.size() != n)
1182  {
1183  ARMARX_ERROR_S << "upper proprioception limits have wrong length: "
1184  << upperProprioceptionLimits.size() << ", should be " << n;
1185  }
1186 
1187  /*
1188  * Check limits
1189  */
1190  for (int i = 0; i < n; i++)
1191  {
1192  if ((solution(i) < lowerProprioceptionLimits(i)) ||
1193  (solution(i) > upperProprioceptionLimits(i)))
1194  {
1195  return false;
1196  }
1197  }
1198 
1199  return true;
1200  }
1201 
1202  bool
1204  Eigen::Map<memoryx::KBM::Vector>& solution,
1205  const memoryx::KBM::Vector& lowerProprioceptionLimits,
1206  const memoryx::KBM::Vector& upperProprioceptionLimits)
1207  {
1208  /*
1209  * Check parameters
1210  */
1211  int n = solution.size();
1212 
1213  if (lowerProprioceptionLimits.size() != n)
1214  {
1215  ARMARX_ERROR_S << "lower proprioception limits have wrong length: "
1216  << lowerProprioceptionLimits.size() << ", should be " << n;
1217  }
1218 
1219  if (upperProprioceptionLimits.size() != n)
1220  {
1221  ARMARX_ERROR_S << "upper proprioception limits have wrong length: "
1222  << upperProprioceptionLimits.size() << ", should be " << n;
1223  }
1224 
1225  /*
1226  * Check limits
1227  */
1228  bool inLimits = true;
1229 
1230  for (int i = 0; i < n; i++)
1231  {
1232  if (solution(i) < lowerProprioceptionLimits(i))
1233  {
1234  solution(i) = lowerProprioceptionLimits(i);
1235  inLimits = false;
1236  }
1237 
1238  if (solution(i) > upperProprioceptionLimits(i))
1239  {
1240  solution(i) = upperProprioceptionLimits(i);
1241  inLimits = false;
1242  }
1243  }
1244 
1245  return inLimits;
1246  }
1247 
1248  bool
1250  const memoryx::KBM::Vector& targetPosition,
1251  const memoryx::KBM::Vector& currentPosition,
1252  const memoryx::KBM::Vector& currentProprioception,
1253  const memoryx::KBM::Vector& lowerProprioceptionLimits,
1254  const memoryx::KBM::Vector& upperProprioceptionLimits,
1255  Eigen::Map<memoryx::KBM::Vector>& solution,
1256  bool applyLimits,
1257  int maxSolves,
1258  float positionTolerance,
1259  float minimumDelta,
1260  bool requireImprovment,
1261  int maxSteps,
1262  float stepSizeFactor,
1263  float maxStepSize)
1264  {
1265 
1266  float bestDistance = FLT_MAX;
1267  bool inLimits = false;
1268 
1269  std::vector<memoryx::KBM::Real> newSolutionSequence(kbm.getNDoF());
1270  Eigen::Map<memoryx::KBM::Vector> newSolution(newSolutionSequence.data(), kbm.getNDoF());
1271 
1272  for (int i = 0; i < maxSolves; i++)
1273  {
1274  memoryx::KBM::Vector startProprioception;
1275 
1276  if (i == 0)
1277  {
1278  startProprioception = currentProprioception;
1279  }
1280  else
1281  {
1282  startProprioception =
1283  randomProprioception(lowerProprioceptionLimits, upperProprioceptionLimits);
1284  }
1285 
1286  ARMARX_IMPORTANT_S << "iteration " << (i + 1)
1287  << " proprioception: " << startProprioception.transpose();
1288  memoryx::KBM::Vector startPosition = kbm.predict(startProprioception);
1289 
1290  /*
1291  * TODO: it's probably much more efficient, to use the limits
1292  * in the solve method itself and consider the limits right away.
1293  */
1295  targetPosition,
1296  startPosition,
1297  startProprioception,
1298  newSolution,
1299  positionTolerance,
1300  minimumDelta,
1301  requireImprovment,
1302  maxSteps,
1303  stepSizeFactor,
1304  maxStepSize);
1305 
1306  /*
1307  * When using applyLimits, all solutions will be in limits, but solutions
1308  * that were outside the limits will probably get worse.
1309  *
1310  * Note: when using this option, the following limits check and solution ignoring
1311  * doesn't have any effect.
1312  */
1313  if (applyLimits)
1314  {
1315  /*
1316  * distance before enforcing limits
1317  */
1318  memoryx::KBM::Vector testPosition = kbm.predict(newSolution);
1319  float distance = (targetPosition - testPosition).norm();
1320  ARMARX_INFO_S << "distance before enforcing limits: " << distance;
1321 
1322  /*
1323  * modify the solution to be within the limits
1324  */
1325  ARMARX_VERBOSE_S << "solution before apply limits: " << newSolution;
1326  bool wasInLimits = applyProprioceptionLimits(
1327  newSolution, lowerProprioceptionLimits, upperProprioceptionLimits);
1328  ARMARX_VERBOSE_S << "solution after apply limits: " << newSolution;
1329 
1330  if (!wasInLimits)
1331  {
1333  << "solution was not within limits, but enforced limits so now it is";
1334  }
1335 
1336  /*
1337  * distance after enforcing limits
1338  */
1339  testPosition = kbm.predict(newSolution);
1340  distance = (targetPosition - testPosition).norm();
1341  ARMARX_INFO_S << "distance after enforcing limits: " << distance;
1342  }
1343 
1344  /*
1345  * If we already found a solution in joint limits,
1346  * only accept other solutions in joint limits.
1347  */
1348  bool currentInLimits = checkProprioceptionLimits(
1349  newSolution, lowerProprioceptionLimits, upperProprioceptionLimits);
1350  ARMARX_INFO_S << "is in limits: " << currentInLimits;
1351 
1352  if (applyLimits && !currentInLimits)
1353  {
1354  ARMARX_ERROR_S << "this should not be possible";
1355  ARMARX_ERROR_S << "problematic solution: " << newSolution;
1356  ARMARX_ERROR_S << "lower proprioception limits: " << lowerProprioceptionLimits;
1357  ARMARX_ERROR_S << "upper proprioception limits: " << upperProprioceptionLimits;
1358  }
1359 
1360  if (inLimits && !currentInLimits)
1361  {
1363  << "ignoring solution because we already found one that is within the limits";
1364  continue;
1365  }
1366 
1367  memoryx::KBM::Vector newPosition = kbm.predict(newSolution);
1368  float distance = (targetPosition - newPosition).norm();
1369 
1370  ARMARX_INFO_S << "distance to target: " << distance << ", best known distance "
1371  << bestDistance;
1372 
1373  if ((distance < bestDistance) || (currentInLimits && !inLimits))
1374  {
1375  bestDistance = distance;
1376  inLimits = currentInLimits;
1377  solution = newSolution;
1378  ARMARX_IMPORTANT_S << "found new solution: " << solution.transpose();
1379 
1380  if (inLimits && (bestDistance < positionTolerance))
1381  {
1382  ARMARX_IMPORTANT_S << "found a solution within the limits with small distance, "
1383  "aborting search";
1384  break;
1385  }
1386  }
1387  }
1388 
1389  ARMARX_IMPORTANT_S << "final distance: " << bestDistance << ", in limits: " << inLimits;
1390 
1391  if (bestDistance < positionTolerance)
1392  {
1393  return true;
1394  }
1395  else
1396  {
1397  return false;
1398  }
1399  }
1400 
1401  bool
1403  const memoryx::KBM::Vector& targetPosition,
1404  const memoryx::KBM::Vector& currentPosition,
1405  const memoryx::KBM::Vector& currentProprioception,
1406  Eigen::Map<memoryx::KBM::Vector>& solution,
1407  float positionTolerance,
1408  float minimumDelta,
1409  bool requireImprovment,
1410  int maxSteps,
1411  float stepSizeFactor,
1412  float maxStepSize)
1413  {
1414 
1415  assert(targetPosition.size() == kbm.getNDim());
1416  assert(currentPosition.size() == kbm.getNDim());
1417  assert(currentProprioception.size() == kbm.getNDoF());
1418  assert(solution.size() == kbm.getNDoF());
1419 
1420  /*
1421  * In the beginning, our best guess it the current proprioception
1422  */
1423  solution = currentProprioception;
1424 
1425  /*
1426  * The best known distance
1427  */
1428  float bestDistance = (targetPosition - currentPosition).norm();
1429 
1430  /*
1431  * Check if the initial position is already a solution
1432  */
1433  if (bestDistance <= positionTolerance)
1434  {
1435  return true;
1436  }
1437 
1438  /*
1439  * Current joint values
1440  */
1441  memoryx::KBM::Vector simulatedProprioception(currentProprioception);
1442 
1443  /*
1444  * Current position
1445  */
1446  memoryx::KBM::Vector predictedPosition(currentPosition);
1447 
1448  /*
1449  * Compare this to the predicted position
1450  */
1451  ARMARX_IMPORTANT_S << "current predicted position: " << kbm.predict(currentProprioception);
1452 
1453  for (int step = 0; step < maxSteps; ++step)
1454  {
1455  /*
1456  * Calculate joint deltas
1457  */
1459  targetPosition,
1460  predictedPosition,
1461  simulatedProprioception,
1462  stepSizeFactor,
1463  maxStepSize);
1464 
1465  /*
1466  * Calculate new joint values
1467  */
1468  simulatedProprioception += deltas;
1469 
1470  /*
1471  * Predict new position
1472  */
1473  predictedPosition = kbm.predict(simulatedProprioception);
1474  ARMARX_IMPORTANT_S << "predicted position: " << predictedPosition;
1475 
1476  /*
1477  * Check if the predicted position is a solution
1478  */
1479  float distance = (targetPosition - predictedPosition).norm();
1480  ARMARX_IMPORTANT_S << "distance to target: " << distance;
1481 
1482  if (distance <= positionTolerance)
1483  {
1484  solution = simulatedProprioception;
1485  return true;
1486  }
1487 
1488  /*
1489  * Stop calculation if result doesn't get better in each iteration
1490  */
1491  if (requireImprovment && (distance >= bestDistance))
1492  {
1493  return false;
1494  }
1495 
1496  /*
1497  * If the new solution is better than the best known solution,
1498  * set it as the new solution!
1499  */
1500  if (distance < bestDistance)
1501  {
1502  solution = simulatedProprioception;
1503  bestDistance = distance;
1504  }
1505 
1506  /*
1507  * Stop calculation if deltas are small
1508  */
1509  if (deltas.norm() < minimumDelta)
1510  {
1511  return false;
1512  }
1513  }
1514 
1515  return false;
1516  }
1517 
1518  Ice::StringSeq
1519  KBMComponent::kbmNames(const Ice::Current& c)
1520  {
1521  std::vector<std::string> kbmKeys;
1522 
1523  for (auto it : kbms)
1524  {
1525  kbmKeys.push_back(it.first);
1526  }
1527 
1528  return kbmKeys;
1529  }
1530 
1531  void
1532  KBMComponent::clearAccumulators(const Ice::Current& c)
1533  {
1534  positionAccumulator.clear();
1535  proprioceptionAccumulator.clear();
1536  rawJointValuesAccumulator.clear();
1537  }
1538 
1539  void
1540  KBMComponent::storeToMemory(const std::string& kbmName,
1541  const std::string& nodeSetName,
1542  const std::string& referenceFrameName,
1543  const std::string& robotName,
1544  const Ice::Current& c)
1545  {
1546  memoryx::KBM::Models::KBM_ptr kbm = kbms[kbmName];
1547  if (kbm)
1548  {
1549  // get KBM segment from longterm memory
1550  auto kbmSeg = this->longtermMemoryPrx->getKBMSegment();
1551 
1552  if (kbmSeg)
1553  {
1555  new memoryx::KBMData(new armarx::MatrixVariant(kbm->getControlNet()),
1556  nodeSetName,
1557  referenceFrameName,
1558  robotName));
1559  kbmSeg->addEntity(kbmData);
1560  }
1561  }
1562  else
1563  {
1564  ARMARX_WARNING << "Could not store KBM! No KBM segment in longterm memory!";
1565  }
1566 
1567  return;
1568  }
1569 
1570  void
1571  KBMComponent::restoreFromMemory(const std::string& kbmName,
1572  const std::string& nodeSetName,
1573  const std::string& referenceFrameName,
1574  const std::string& robotName,
1575  const Ice::Current& c)
1576  {
1577 
1578  auto kbmSeg = this->longtermMemoryPrx->getKBMSegment();
1579  std::string kbmEntityName = robotName + "_" + referenceFrameName + "_" + nodeSetName;
1580 
1581  if (kbmSeg && kbmSeg->hasEntityByName(kbmEntityName))
1582  {
1583  auto entity = kbmSeg->getEntityByName(kbmEntityName);
1584  memoryx::KBMDataPtr kbmData = memoryx::KBMDataPtr::dynamicCast(entity);
1585 
1586  if (kbmData)
1587  {
1588  VirtualRobot::RobotPtr robot =
1589  armarx::RemoteRobot::createLocalClone(this->robotStateComponentPrx);
1590  int nDoF = robot->getRobotNodeSet(nodeSetName)->getSize();
1591 
1592  armarx::MatrixVariantPtr controlNet =
1593  armarx::MatrixVariantPtr::dynamicCast(kbmData->getControlNet());
1594 
1595  kbms[kbmName] = memoryx::KBM::Models::KBM::createKBM(
1596  nDoF,
1597  controlNet->rows,
1598  Eigen::VectorXd::Zero(nDoF),
1599  Eigen::VectorXd::Constant(nDoF, M_PI / 4.0f),
1600  controlNet->toEigen().cast<double>());
1601  createdFromVirtualRobot[kbmName] =
1602  false; //hacky, because also KBMs created from VirtualRobot could be stored to the longterm memory
1603  }
1604  else
1605  {
1606  ARMARX_WARNING << "Could not restore KBM entity specified by: " << kbmEntityName;
1607  }
1608  }
1609 
1610  return;
1611  }
1612 
1613  bool
1614  KBMComponent::isInMemory(const std::string& nodeSetName,
1615  const std::string& referenceFrameName,
1616  const std::string& robotName,
1617  const Ice::Current& c)
1618  {
1619  std::string kbmEntityName = robotName + "_" + referenceFrameName + "_" + nodeSetName;
1620 
1621  return (this->longtermMemoryPrx->getKBMSegment() &&
1622  this->longtermMemoryPrx->getKBMSegment()->hasEntityByName(kbmEntityName));
1623  }
1624 } // namespace armarx
armarx::KBMComponent::createArmar3KBM
void createArmar3KBM(const std::string &name, const Ice::StringSeq &robotNodeNames, const std::vector< memoryx::KBM::Real > &jointValueAverages, const std::vector< memoryx::KBM::Real > &spreadAnglesSequence, const std::string &tcpName, bool useOrientation, const Ice::Current &c=Ice::emptyCurrent) override
createArmar3KBM creates a KBM from a VirtualRobot model
Definition: KBMComponent.cpp:193
RemoteRobot.h
armarx::KBMComponent::onExitComponent
void onExitComponent() override
Definition: KBMComponent.cpp:67
armarx::KBMComponent::getKBM
memoryx::KBM::Models::KBM_ptr getKBM(const std::string &name)
returns a pointer to the KBM with the given name if it exists or a nullptr if it doesn't
Definition: KBMComponent.cpp:146
ARMARX_VERBOSE
#define ARMARX_VERBOSE
Definition: Logging.h:187
ARMARX_IMPORTANT_S
#define ARMARX_IMPORTANT_S
Definition: Logging.h:210
armarx::KBMComponent::storeToMemory
void storeToMemory(const std::string &, const std::string &, const std::string &, const std::string &, const Ice::Current &) override
Definition: KBMComponent.cpp:1540
armarx::MatrixDouble
The MatrixDouble class.
Definition: MatrixVariant.h:126
armarx::VariantType::Float
const VariantTypeId Float
Definition: Variant.h:919
memoryx::KBM::Models::KBM_ptr
std::shared_ptr< KBM > KBM_ptr
Definition: kbm.h:71
memoryx::KBM::Models::KBM::predict
Matrix predict(const Matrix &proprioception, int dim=0) const
Predicts a value of the FK given a set of joint angles.
Definition: kbm.cpp:343
armarx::KBMComponent::accumulateProprioceptions
void accumulateProprioceptions(const std::vector< memoryx::KBM::Real > &proprioceptions, const Ice::Current &c=Ice::emptyCurrent) override
accumualteProprioceptions accumulates proprioceptions
Definition: KBMComponent.cpp:866
memoryx::KBMDataPtr
IceInternal::Handle< KBMData > KBMDataPtr
Definition: KBMData.h:83
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
memoryx::KBM::Models::KBM::getNDim
int getNDim() const
Definition: kbm.cpp:443
memoryx::KBM::Matrix
Eigen::MatrixXd Matrix
Definition: kbm.h:40
armarx::KBMDifferentialIK::solve
bool solve(const memoryx::KBM::Models::KBM &kbm, const memoryx::KBM::Vector &targetPosition, const memoryx::KBM::Vector &currentPostion, const memoryx::KBM::Vector &currentProprioception, Eigen::Map< memoryx::KBM::Vector > &solution, float positionTolerance=5.0f, float minimumDelta=0.0f, bool requireImprovment=false, int maxSteps=50, float stepSizeFactor=0.2f, float maxStepSize=FLT_MAX)
solves the inverse kinematics
Definition: KBMComponent.cpp:1402
armarx::KBMComponent::onInitComponent
void onInitComponent() override
Definition: KBMComponent.cpp:46
armarx::KBMComponent::onlineVerbose
void onlineVerbose(const std::string &name, const std::vector< memoryx::KBM::Real > &proprioceptionSequence, const std::vector< memoryx::KBM::Real > &positionSequence, Ice::Float learningRate, const std::vector< memoryx::KBM::Real > &evaluationProprioceptionSequence, const std::vector< memoryx::KBM::Real > &evaluationPositionSequence, const Ice::Current &c=Ice::emptyCurrent) override
same as online, but evaluates after each learning iteration
Definition: KBMComponent.cpp:442
armarx::KBMComponent::onlineAccumulatorVerbose
void onlineAccumulatorVerbose(const std::string &name, Ice::Float learningRate, const Ice::Current &c=Ice::emptyCurrent) override
onlineAccumulatorVerbose same as onlineAccumulator, but evaluates after each learning step
Definition: KBMComponent.cpp:811
armarx::KBMComponent::mapProprioceptions
Eigen::Map< const memoryx::KBM::Matrix > mapProprioceptions(const memoryx::KBM::Models::KBM &kbm, const std::vector< memoryx::KBM::Real > &proprioception)
mapProprioceptions converts the proprioception sequence into an Eigen::Map of a Matrix
Definition: KBMComponent.cpp:119
armarx::KBMComponent::batchAccumulator
void batchAccumulator(const std::string &name, Ice::Int method, Ice::Float threshold, const Ice::Current &c=Ice::emptyCurrent) override
the same as batch but with the data from the accumulator
Definition: KBMComponent.cpp:825
memoryx::KBM::Inverse::Solution
Definition: kbm.h:415
armarx::KBMComponent::online
void online(const std::string &name, const std::vector< memoryx::KBM::Real > &proprioceptionSequence, const std::vector< memoryx::KBM::Real > &positionSequence, Ice::Float learningRate, const Ice::Current &c=Ice::emptyCurrent) override
online learning of n training samples
Definition: KBMComponent.cpp:398
armarx::KBMComponent::clearAccumulators
void clearAccumulators(const Ice::Current &c) override
Clears the accumulators.
Definition: KBMComponent.cpp:1532
boost::target
Vertex target(const detail::edge_base< Directed, Vertex > &e, const PCG &)
Definition: point_cloud_graph.h:668
memoryx::KBM::Models::KBM::ErrorValuesType::Mean
Real Mean
Mean error.
Definition: kbm.h:111
armarx::KBMDifferentialIK::randomProprioception
memoryx::KBM::Vector randomProprioception(const memoryx::KBM::Vector &lowerProprioceptionLimits, const memoryx::KBM::Vector &upperProprioceptionLimits)
Creates a vector of random values between the limits.
Definition: KBMComponent.cpp:1143
memoryx::KBM::Models::KBM::getJacobian
Matrix getJacobian(const Vector &proprioception) const
Computes the partial derivative with respect to a configuration.
Definition: kbm.cpp:412
armarx::KBMComponent::printAccumulatorStatistics
void printAccumulatorStatistics(int nDim, int nDoF, const Ice::Current &c=Ice::emptyCurrent) override
printAccumulatorStatistics prints information about the values in the accumulators
Definition: KBMComponent.cpp:685
c
constexpr T c
Definition: UnscentedKalmanFilterTest.cpp:46
armarx::KBMComponent::onDisconnectComponent
void onDisconnectComponent() override
Definition: KBMComponent.cpp:62
armarx::KBMComponent::printErrorsAccumulator
void printErrorsAccumulator(const std::string &name, const Ice::Current &c=Ice::emptyCurrent) override
the same as printErrors but with the data from the accumulator
Definition: KBMComponent.cpp:834
armarx::KBMComponent::mapPositions
Eigen::Map< const memoryx::KBM::Matrix > mapPositions(const memoryx::KBM::Models::KBM &kbm, const std::vector< memoryx::KBM::Real > &position)
mapPositions converts the position sequence into an Eigen::Map of a Matrix
Definition: KBMComponent.cpp:105
memoryx::KBM::Vector
Eigen::VectorXd Vector
Definition: kbm.h:41
memoryx::KBM::Models::KBM::ErrorValuesType
Return type of the evaluation (KBM::getErrors()) function providing insight in the statistics of the ...
Definition: kbm.h:108
armarx::KBMComponent::createPropertyDefinitions
armarx::PropertyDefinitionsPtr createPropertyDefinitions() override
Definition: KBMComponent.cpp:72
armarx::KBMComponent::getRawJointValuesAverages
Ice::DoubleSeq getRawJointValuesAverages(int nDoF, const Ice::Current &c=Ice::emptyCurrent) override
getRawJointValuesAverages calculates the average raw joint values for each joint from the data stored...
Definition: KBMComponent.cpp:705
armarx::KBMComponent::getSpreadAngles
Ice::DoubleSeq getSpreadAngles(int nDoF, const Ice::Current &c=Ice::emptyCurrent) override
getSpreadAngles returns the spreadAngles calculated using the data in the proprioceptionAccumulator
Definition: KBMComponent.cpp:721
memoryx::KBM::Models::KBM::createFromVirtualRobot
static KBM_ptr createFromVirtualRobot(VirtualRobot::KinematicChainPtr chain, VirtualRobot::SceneObjectPtr FoR, const Vector &spreadAngles, bool useOrientation=false)
Definition: kbm.cpp:494
armarx::KBMComponent::accumulateEvaluationProprioceptions
void accumulateEvaluationProprioceptions(const std::vector< memoryx::KBM::Real > &proprioceptions, const Ice::Current &c=Ice::emptyCurrent) override
accumualteProprioceptions accumulates proprioceptions in the evaluate accumulator
Definition: KBMComponent.cpp:907
IceInternal::Handle
Definition: forward_declarations.h:8
armarx::KBMDifferentialIK::solveMany
bool solveMany(const memoryx::KBM::Models::KBM &kbm, const memoryx::KBM::Vector &targetPosition, const memoryx::KBM::Vector &currentPosition, const memoryx::KBM::Vector &currentProprioception, const memoryx::KBM::Vector &lowerProprioceptionLimits, const memoryx::KBM::Vector &upperProprioceptionLimits, Eigen::Map< memoryx::KBM::Vector > &solution, bool applyLimits=true, int maxSolves=25, float positionTolerance=5.0f, float minimumDelta=0.0f, bool requireImprovment=false, int maxSteps=50, float stepSizeFactor=0.2f, float maxStepSize=FLT_MAX)
KBMDifferentialIK::solveMany runs solve many times.
Definition: KBMComponent.cpp:1249
armarx::KBMComponent::accumulatePositions
void accumulatePositions(const std::vector< memoryx::KBM::Real > &positionSequence, const Ice::Current &c=Ice::emptyCurrent) override
accumulate adds the given position to the accumulator to use it later
Definition: KBMComponent.cpp:854
armarx::KBMComponent::setProprioceptionAccumulatorFromRawJointAccumulator
void setProprioceptionAccumulatorFromRawJointAccumulator(const std::vector< memoryx::KBM::Real > &rawJointValuesAverages, const Ice::Current &c=Ice::emptyCurrent) override
setProprioceptionAccumulatorFromRawJointAccumulator updates the proprioception accumulator
Definition: KBMComponent.cpp:748
cxxopts::value
std::shared_ptr< Value > value()
Definition: cxxopts.hpp:855
armarx::KBMComponent::accumulateEvaluationPositions
void accumulateEvaluationPositions(const std::vector< memoryx::KBM::Real > &positionSequence, const Ice::Current &c=Ice::emptyCurrent) override
accumulates the given position in the evaluation accumulator
Definition: KBMComponent.cpp:894
armarx::KBMComponent::batch
void batch(const std::string &name, const std::vector< memoryx::KBM::Real > &proprioceptionSequence, const std::vector< memoryx::KBM::Real > &positionSequence, Ice::Int method, Ice::Float threshold, const Ice::Current &c=Ice::emptyCurrent) override
batch learning of n training samples
Definition: KBMComponent.cpp:353
armarx::KBMComponent::printErrors
void printErrors(const std::string &name, const std::vector< memoryx::KBM::Real > &proprioceptionSequence, const std::vector< memoryx::KBM::Real > &positionSequence, const Ice::Current &c=Ice::emptyCurrent) override
calls getErrors on the KBM and prints the result
Definition: KBMComponent.cpp:640
armarx::KBMComponent::isInMemory
bool isInMemory(const std::string &nodeSetName, const std::string &referenceFrameName, const std::string &robotName, const Ice::Current &c) override
Definition: KBMComponent.cpp:1614
M_PI
#define M_PI
Definition: MathTools.h:17
EntityAttribute.h
memoryx::KBM::Models::KBM::createKBM
static KBM_ptr createKBM(int nDoF, int dim, const Vector &center, const Vector &spreadAngles, const Matrix &controlNet)
Factory methods.
Definition: kbm.cpp:455
armarx::KBMComponent::accumulateRawJointValues
void accumulateRawJointValues(const std::vector< memoryx::KBM::Real > &rawJointValuesSequence, const Ice::Current &c=Ice::emptyCurrent) override
accumualteRawJointValues accumulates raw joint values that will be transformed to proprioceptions lat...
Definition: KBMComponent.cpp:879
memoryx::KBM::Models::KBM::getNDoF
int getNDoF() const
Get the number of degrees of freedom (DoF).
Definition: kbm.cpp:437
armarx::KBMComponent::restoreFromMemory
void restoreFromMemory(const std::string &, const std::string &, const std::string &, const std::string &, const Ice::Current &) override
Definition: KBMComponent.cpp:1571
ARMARX_ERROR_S
#define ARMARX_ERROR_S
Definition: Logging.h:216
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::KBMDifferentialIK::randomFloat
float randomFloat(float LO, float HI)
randomFloat creates a random float between LO and HI
Definition: KBMComponent.cpp:1096
armarx::KBMComponent::mapProprioception
Eigen::Map< const memoryx::KBM::Vector > mapProprioception(const memoryx::KBM::Models::KBM &kbm, const std::vector< memoryx::KBM::Real > &proprioception)
mapProprioception converts the proprioception sequence into an Eigen::Map of a Vector
Definition: KBMComponent.cpp:96
KBMData.h
filename
std::string filename
Definition: VisualizationRobot.cpp:86
armarx::KBMComponentPropertyDefinitions
Definition: KBMComponent.h:50
armarx::KBMComponent::solveGlobalIK
std::vector< memoryx::KBM::Real > solveGlobalIK(const std::string &name, const std::vector< memoryx::KBM::Real > &targetPosition, const Ice::Current &c=Ice::emptyCurrent) override
solveGlobalIK solves the global inverse kinematics for the given position
Definition: KBMComponent.cpp:922
armarx::KBMComponent::setPositionLimits
void setPositionLimits(int nDim, const Ice::Current &c=Ice::emptyCurrent) override
setPositionLimits sets the position limits using the data in the position accumulator
Definition: KBMComponent.cpp:793
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
armarx::KBMComponent::createKBM
void createKBM(const std::string &name, Ice::Int nDoF, Ice::Int dim, Ice::Float spreadAngle, const Ice::Current &c=Ice::emptyCurrent) override
createKBM creates a new KBM and makes it available under the given name
Definition: KBMComponent.cpp:168
memoryx::KBM::Models::KBM::Optimization
Optimization
Enum for the preferred optimization method during batch learning.
Definition: kbm.h:85
armarx::deltas
Definition: BasicControllers.h:57
armarx::KBMDifferentialIK::checkProprioceptionLimits
bool checkProprioceptionLimits(const memoryx::KBM::Vector &solution, const memoryx::KBM::Vector &lowerProprioceptionLimits, const memoryx::KBM::Vector &upperProprioceptionLimits)
check if solution is within the limits
Definition: KBMComponent.cpp:1165
armarx::KBMComponent::onConnectComponent
void onConnectComponent() override
Definition: KBMComponent.cpp:53
memoryx::KBM::Inverse::Solution::spreadAngles
Vector spreadAngles
Definition: kbm.h:427
memoryx::KBM::Inverse::solveGlobalIK
void solveGlobalIK(unsigned int recursion, int side, SolutionSet &solutionSet, Models::KBM_ptr kbm, const Vector &lower, const Vector &upper, Real resolution, Vector spreadAngles, Vector center)
Definition: inverse.cpp:365
armarx::Component::getConfigIdentifier
std::string getConfigIdentifier()
Retrieve config identifier for this component as set in constructor.
Definition: Component.cpp:79
armarx::KBMComponent::mapPosition
Eigen::Map< const memoryx::KBM::Vector > mapPosition(const memoryx::KBM::Models::KBM &kbm, const std::vector< memoryx::KBM::Real > &position)
mapPosition converts the position sequence into an Eigen::Map of a Vector
Definition: KBMComponent.cpp:87
memoryx::KBMData
Definition: KBMData.h:47
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
armarx::RemoteRobot::createLocalClone
VirtualRobot::RobotPtr createLocalClone()
Clones the structure of this remote robot to a local instance.
Definition: RemoteRobot.cpp:381
pseudoInverse
Eigen::MatrixXd pseudoInverse(const Eigen::MatrixXd &a, double epsilon=std::numeric_limits< double >::epsilon())
Definition: pinv.hh:6
IceUtil::Handle< class PropertyDefinitionContainer >
armarx::KBMComponent::onlineAccumulator
void onlineAccumulator(const std::string &name, Ice::Float learningRate, const Ice::Current &c=Ice::emptyCurrent) override
onlineAccumulator calls online after transforming the raw joint accumulator to proprioceptions
Definition: KBMComponent.cpp:803
armarx::KBMComponent::kbmNames
Ice::StringSeq kbmNames(const Ice::Current &c) override
Returns the names of the existing KBMs.
Definition: KBMComponent.cpp:1519
memoryx::KBM::Models::KBM
The Kinematic B\'ezier Maps.
Definition: kbm.h:81
armarx::VariantType::Int
const VariantTypeId Int
Definition: Variant.h:917
ARMARX_VERBOSE_S
#define ARMARX_VERBOSE_S
Definition: Logging.h:207
armarx::KBMComponent::predictAccumulator
void predictAccumulator(const std::string &name, const Ice::Current &c=Ice::emptyCurrent) override
the same as predict but with the data from the accumulator, however the results are currently just pr...
Definition: KBMComponent.cpp:840
armarx::KBMComponent::solveDifferentialIK
std::vector< memoryx::KBM::Real > solveDifferentialIK(const std::string &name, const std::vector< memoryx::KBM::Real > &targetPosition, const std::vector< memoryx::KBM::Real > &currentPosition, const std::vector< memoryx::KBM::Real > &proprioceptionSequence, const std::vector< memoryx::KBM::Real > &lowerProprioceptionLimitsSequence, const std::vector< memoryx::KBM::Real > &upperProprioceptionLimitsSequence, const Ice::Current &c=Ice::emptyCurrent) override
solveDifferentialIK solves the differential inverse kinematics for the given position
Definition: KBMComponent.cpp:968
distance
double distance(const Point &a, const Point &b)
Definition: point.hpp:95
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:202
armarx::KBMComponent::mapMatrix
Eigen::Map< const memoryx::KBM::Matrix > mapMatrix(int rows, const std::vector< memoryx::KBM::Real > &data)
maps a sequence to an Eigen::Map
Definition: KBMComponent.cpp:133
KBMComponent.h
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::PropertyDefinitionsPtr
IceUtil::Handle< class PropertyDefinitionContainer > PropertyDefinitionsPtr
PropertyDefinitions smart pointer type.
Definition: forward_declarations.h:35
armarx::KBMDifferentialIK::applyProprioceptionLimits
bool applyProprioceptionLimits(Eigen::Map< memoryx::KBM::Vector > &solution, const memoryx::KBM::Vector &lowerProprioceptionLimits, const memoryx::KBM::Vector &upperProprioceptionLimits)
apply limits to solution and return true, if solution has been changed = solution was not in limits
Definition: KBMComponent.cpp:1203
armarx::KBMDifferentialIK::calculateJointDeltas
memoryx::KBM::Vector calculateJointDeltas(const memoryx::KBM::Models::KBM &kbm, const memoryx::KBM::Vector &target, const memoryx::KBM::Vector &position, const memoryx::KBM::Vector &proprioception, float stepSizeFactor, float maxStepSize)
calculateJointDeltas is in internal function called by solve
Definition: KBMComponent.cpp:1102
memoryx::KBM::Inverse::SolutionSet
std::vector< Solution > SolutionSet
Return type of the global inverse kinematics solvers.
Definition: kbm.h:434
armarx::ManagedIceObject::usingProxy
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Definition: ManagedIceObject.cpp:154
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:19
armarx::KBMComponent::predict
std::vector< memoryx::KBM::Real > predict(const std::string &name, const std::vector< memoryx::KBM::Real > &proprioceptionSequence, const Ice::Current &c=Ice::emptyCurrent) override
predict the position for n samples of proprioception (forward kinematics)
Definition: KBMComponent.cpp:604
norm
double norm(const Point &a)
Definition: point.hpp:102