RobotIKGuiPlugin.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 ArmarX::
17 * @author Philipp Schmidt
18 * @date 2015
19 * @license http://www.gnu.org/licenses/gpl-2.0.txt
20 * GNU General Public License
21 
22 */
23 
24 #include "RobotIKGuiPlugin.h"
25 
26 #include "RobotViewer.h"
27 
28 /* ArmarX includes */
33 
36 
37 /* Virtual Robot includes */
38 #include <VirtualRobot/RobotNodeSet.h>
39 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
40 #include <VirtualRobot/XML/RobotIO.h>
41 
42 /* Coin includes */
43 #include <QClipboard>
44 
46 
47 #include <Inventor/SbViewportRegion.h>
48 #include <Inventor/actions/SoGetMatrixAction.h>
49 #include <Inventor/actions/SoSearchAction.h>
50 
51 // Gui Includes
52 #include "SetDesiredPoseDialog.h"
53 
54 #define ROBOT_UPDATE_TIMER_MS 33
55 #define TEXTFIELD_UPDATE_TIMER_MS 200
56 #define AUTO_FOLLOW_UPDATE 333
57 #define CARTESIAN_CONTROLLER_LOOP_AMOUNT 100
58 
60 {
61  addWidget<RobotIKWidgetController>();
62 }
63 
65  manipulatorMoved(false), startUpCameraPositioningFlag(true)
66 {
67 
68 
69  //Component names
70  robotStateComponentName = "";
71  robotIKComponentName = "";
72  kinematicUnitComponentName = "";
73 
74  visualization = NULL;
75  robotUpdateSensor = NULL;
76  textFieldUpdateSensor = NULL;
77 }
78 
79 void
81 {
82  ARMARX_INFO << "RobotIKWidgetController on init";
83  QMetaObject::invokeMethod(this, "initWidget");
84  //Prepare proxies
85  usingProxy(robotStateComponentName);
86  usingProxy(robotIKComponentName);
87  usingProxy(kinematicUnitComponentName);
88 }
89 
90 void
92 {
93  //Get all proxies
94  robotStateComponentPrx = getProxy<RobotStateComponentInterfacePrx>(robotStateComponentName);
95  kinematicUnitInterfacePrx = getProxy<KinematicUnitInterfacePrx>(kinematicUnitComponentName);
96  robotIKPrx = getProxy<RobotIKInterfacePrx>(robotIKComponentName);
97 
98  //Load robot
99  robot = loadRobot(getIncludePaths());
100  ARMARX_INFO << VAROUT(robot->getName());
101 
102  if (!robot)
103  {
104  getObjectScheduler()->terminate();
105 
106  if (getWidget()->parentWidget())
107  {
108  getWidget()->parentWidget()->close();
109  }
110 
111  ARMARX_ERROR << "RobotIKPlugin: Unable to load robot file! Terminating." << std::endl;
112  return;
113  }
114 
115  //Add in our visualization for manipulators
116  visualization = new ManipulatorVisualization;
117  this->ui.robotViewer->getRobotViewer()->getRootNode()->addChild((SoNode*)visualization);
118 
119  //Get visualization for our robot and add it to scene graph
120  currentRobotVisualization = robot->getVisualization();
121  this->ui.robotViewer->getRobotViewer()->getRootNode()->addChild(
122  currentRobotVisualization->getCoinVisualization());
123 
124  // Get visualization for preview robot
125  previewRobot = loadRobot(getIncludePaths());
126  previewRobotVisualization = previewRobot->getVisualization();
127 
128  // Setup cartesianControlRobot
129  cartesianControlRobot = previewRobot->clone();
130 
131  //Make a timer update robo pose every time tick
132  SoSensorManager* sensor_mgr = SoDB::getSensorManager();
133  robotUpdateSensor = new SoTimerSensor(robotUpdateTimerCB, this);
134  robotUpdateSensor->setInterval(SbTime(ROBOT_UPDATE_TIMER_MS / 1000.0f));
135  sensor_mgr->insertTimerSensor(robotUpdateSensor);
136 
137  //And a timer to update the labels
138  textFieldUpdateSensor = new SoTimerSensor(textFieldUpdateTimerCB, this);
139  textFieldUpdateSensor->setInterval(SbTime(TEXTFIELD_UPDATE_TIMER_MS / 1000.0f));
140  sensor_mgr->insertTimerSensor(textFieldUpdateSensor);
141 
142  //Get all kinematic chain descriptions and add them to the combo box
143  auto robotNodeSets = robot->getRobotNodeSets();
144 
145  for (VirtualRobot::RobotNodeSetPtr s : robotNodeSets)
146  {
147  this->ui.comboBox->addItem(QString::fromStdString(s->getName()));
148  }
149 
150  //Make sure comboBox is enabled so you can select a kinematic chain
151  this->ui.comboBox->setEnabled(true);
152  this->ui.cartesianselection->clear();
153  //Get all caertesian selections and add them
154  this->ui.cartesianselection->addItem(QString::fromStdString("Orientation and Position"));
155  this->ui.cartesianselection->addItem(QString::fromStdString("Position"));
156  this->ui.cartesianselection->addItem(QString::fromStdString("Orientation"));
157  this->ui.cartesianselection->addItem(QString::fromStdString("X position"));
158  this->ui.cartesianselection->addItem(QString::fromStdString("Y position"));
159  this->ui.cartesianselection->addItem(QString::fromStdString("Z position"));
160 
161  //Make sure it is enabled
162  this->ui.cartesianselection->setEnabled(true);
163  this->ui.cartesianselection->setCurrentIndex(0);
164 
165  connectSlots();
166  enableMainWidgetAsync(true);
167 }
168 
169 void
170 armarx::RobotIKWidgetController::onDisconnect()
171 {
172  //Stop timers
173  SoSensorManager* sensor_mgr = SoDB::getSensorManager();
174  sensor_mgr->removeTimerSensor(textFieldUpdateSensor);
175  sensor_mgr->removeTimerSensor(robotUpdateSensor);
176 
177  //Remove all options in comboBox
178  this->ui.comboBox->clear();
179 
180  //Disable ui controls
181  this->ui.comboBox->setEnabled(false);
182  this->ui.moveTCP->setEnabled(false);
183  this->ui.reachableLabel->setEnabled(false);
184  this->ui.reachableLabel->setText(QString::fromStdString("No kinematic chain selected"));
185  this->ui.reachableLabel->setStyleSheet("QLabel { color : red; }");
186  this->ui.errorValue->setEnabled(false);
187  this->ui.errorValue->setText(QString::fromStdString("Calculated error: 0"));
188  this->ui.errorValue->setEnabled(false);
189  this->ui.pushButton->setEnabled(false);
190  this->ui.checkBox->setChecked(false);
191  this->ui.checkBox->setEnabled(false);
192  this->ui.currentPose->setEnabled(false);
193  this->ui.currentPoseMatrix->setEnabled(false);
194  this->ui.desiredPose->setEnabled(false);
195  this->ui.desiredPoseMatrix->setEnabled(false);
196  this->ui.resetManip->setEnabled(false);
197  this->ui.btnCopyCurrentPoseToClipboard->setEnabled(false);
198  this->ui.pushButton_setDesiredPose->setEnabled(false);
199 
200  //Remove all visualization
201  this->ui.robotViewer->getRobotViewer()->getRootNode()->removeAllChildren();
202 
203  visualization = NULL;
204  robotUpdateSensor = NULL;
205  textFieldUpdateSensor = NULL;
206 }
207 
208 void
210 {
211  QMetaObject::invokeMethod(this, "onDisconnect");
212 }
213 
214 void
216 {
217  // enableMainWidgetAsync(false);
218 }
219 
220 QPointer<QDialog>
222 {
223  if (!dialog)
224  {
225  dialog = new SimpleConfigDialog(parent);
226  dialog->addProxyFinder<RobotStateComponentInterfacePrx>(
227  {"RobotStateComponent", "", "RobotState*"});
228  dialog->addProxyFinder<KinematicUnitInterfacePrx>(
229  {"KinematicUnit", "", "*KinematicUnit|KinematicUnit*"});
230  dialog->addProxyFinder<RobotIKInterfacePrx>({"RobotIK", "", "RobotIK*"});
231  }
232  return qobject_cast<SimpleConfigDialog*>(dialog);
233 }
234 
235 void
237 {
238  robotStateComponentName = settings->value("robotStateComponentName").toString().toStdString();
239  robotIKComponentName = settings->value("robotIKComponentName").toString().toStdString();
240  kinematicUnitComponentName =
241  settings->value("kinematicUnitComponentName").toString().toStdString();
242 }
243 
244 void
246 {
247  settings->setValue("robotStateComponentName", robotStateComponentName.c_str());
248  settings->setValue("robotIKComponentName", robotIKComponentName.c_str());
249  settings->setValue("kinematicUnitComponentName", kinematicUnitComponentName.c_str());
250 }
251 
252 void
254 {
255  robotStateComponentName = dialog->getProxyName("RobotStateComponent");
256  robotIKComponentName = dialog->getProxyName("RobotIK");
257  kinematicUnitComponentName = dialog->getProxyName("KinematicUnit");
258 }
259 
260 void
262 {
263  ARMARX_INFO << "RobotIKWidgetController initWidget";
264  //Initialize Gui
265  ui.setupUi(getWidget());
266  getWidget()->setEnabled(false);
267  //Alignment for ui
268  this->ui.gridLayout->setAlignment(Qt::AlignTop);
269 
270  //Label color can not be set in designer, so we do it here
271  this->ui.reachableLabel->setStyleSheet("QLabel { color : red; }");
272 }
273 
274 void
276 {
277  robotIKPrx->begin_computeExtendedIKGlobalPose(
278  this->ui.comboBox->currentText().toStdString(),
279  new armarx::Pose(visualization->getUserDesiredPose()),
280  convertOption(this->ui.cartesianselection->currentText().toStdString()),
281  Ice::newCallback(this, &RobotIKWidgetController::ikCallbackExecuteMotion));
282 }
283 
284 void
285 armarx::RobotIKWidgetController::ikCallbackExecuteMotion(const Ice::AsyncResultPtr& r)
286 {
287  RobotIKInterfacePrx prx = RobotIKInterfacePrx::uncheckedCast(r->getProxy());
288  ExtendedIKResult solution = prx->end_computeExtendedIKGlobalPose(r);
289  {
290  ScopedLock lock(solutionMutex);
291  currentSolution = improveCurrentSolution(solution);
292  }
293  QMetaObject::invokeMethod(this, "updateSolutionDisplay");
294  QMetaObject::invokeMethod(this, "executeMotion");
295 }
296 
297 void
298 armarx::RobotIKWidgetController::ikCallbackDisplaySolution(const Ice::AsyncResultPtr& r)
299 
300 {
301  RobotIKInterfacePrx prx = RobotIKInterfacePrx::uncheckedCast(r->getProxy());
302  ExtendedIKResult solution = prx->end_computeExtendedIKGlobalPose(r);
303  {
304  ScopedLock lock(solutionMutex);
305  currentSolution = improveCurrentSolution(solution);
306  if (currentSolution.isReachable)
307  {
308  updatePreviewRobot();
309  }
310  }
311  QMetaObject::invokeMethod(this, "updateSolutionDisplay");
312 }
313 
314 void
316 {
317  //An item has been selected, so we can allow the user to use the ui now
318  //The manipulator will be set to the position of the current tcp, so this pose
319  //has to be reachable!
320  this->ui.moveTCP->setEnabled(true);
321  this->ui.reachableLabel->setEnabled(true);
322  this->ui.reachableLabel->setText(QString::fromStdString("Pose reachable!"));
323  this->ui.reachableLabel->setStyleSheet("QLabel { color : green; }");
324  this->ui.errorValue->setText(QString::fromStdString("Calculated error: 0"));
325  this->ui.errorValue->setEnabled(true);
326  this->ui.pushButton->setEnabled(true);
327  this->ui.currentPose->setEnabled(true);
328  this->ui.currentPoseMatrix->setEnabled(true);
329  this->ui.desiredPose->setEnabled(true);
330  this->ui.desiredPoseMatrix->setEnabled(true);
331  this->ui.resetManip->setEnabled(true);
332  this->ui.checkBox->setEnabled(true);
333  this->ui.btnCopyCurrentPoseToClipboard->setEnabled(true);
334  this->ui.pushButton_setDesiredPose->setEnabled(true);
335 
336  //Add visualization
337  if (visualization && robot->hasRobotNodeSet(arg1.toStdString()))
338  {
339  visualization->setVisualization(robot, robot->getRobotNodeSet(arg1.toStdString()));
340  //Add callbacks
341  visualization->addManipFinishCallback(manipFinishCallback, this);
342  visualization->addManipMovedCallback(manipMovedCallback, this);
343  }
344 
345  armarx::RemoteRobot::synchronizeLocalClone(previewRobot, robotStateComponentPrx);
346 }
347 
348 void
350 {
351  //If there is a manip in the scene we pretend it just moved to update color etc.
352  if (visualization->getIsVisualizing())
353  {
354  manipFinishCallback(this, NULL);
355  }
356 }
357 
358 void
360 {
361  //Triggers reset of manipulator in kinematicChainChanged
362  kinematicChainChanged(this->ui.comboBox->currentText());
363 }
364 
365 void
367 {
368  if (getState() != eManagedIceObjectStarted)
369  {
370  return;
371  }
372 
373 
374  ScopedLock lock(solutionMutex);
375 
376  if (currentSolution.isReachable)
377  {
378  //Green
379  ui.reachableLabel->setText(QString::fromStdString("Pose reachable!"));
380  ui.reachableLabel->setStyleSheet("QLabel { color : green; }");
381  visualization->setColor(0, 1, 0);
382  }
383  else
384  {
385  //Red
386  ui.reachableLabel->setText(QString::fromStdString("Pose unreachable!"));
387  ui.reachableLabel->setStyleSheet("QLabel { color : red; }");
388  visualization->setColor(1, 0, 0);
389  }
390 
391  //Display calculated error
392  ui.errorValue->setText(
393  "Calculated error: " + QString::number(currentSolution.errorPosition, 'f', 1) + " mm " +
394  QString::number(currentSolution.errorOrientation * 180 / M_PI, 'f', 2) + " deg");
395 }
396 
397 void
399 {
400  auto visualizationRoot = this->ui.robotViewer->getRobotViewer()->getRootNode();
401  if (checked)
402  {
403  if (visualizationRoot->findChild(currentRobotVisualization->getCoinVisualization()) == -1)
404  {
405  visualizationRoot->addChild(currentRobotVisualization->getCoinVisualization());
406  }
407  }
408  else
409  {
410  if (visualizationRoot->findChild(currentRobotVisualization->getCoinVisualization()) != -1)
411  {
412  visualizationRoot->removeChild(currentRobotVisualization->getCoinVisualization());
413  }
414  }
415 }
416 
417 void
419 {
420  auto visualizationRoot = this->ui.robotViewer->getRobotViewer()->getRootNode();
421  if (checked)
422  {
423  if (visualizationRoot->findChild(previewRobotVisualization->getCoinVisualization()) == -1)
424  {
425  visualizationRoot->addChild(previewRobotVisualization->getCoinVisualization());
426  }
427  }
428  else
429  {
430  if (visualizationRoot->findChild(previewRobotVisualization->getCoinVisualization()) != -1)
431  {
432  visualizationRoot->removeChild(previewRobotVisualization->getCoinVisualization());
433  }
434  }
435 }
436 
437 void
438 armarx::RobotIKWidgetController::connectSlots()
439 {
440  connect(ui.resetManip, SIGNAL(clicked()), this, SLOT(resetManip()), Qt::UniqueConnection);
441  connect(ui.pushButton, SIGNAL(clicked()), this, SLOT(executeMotion()), Qt::UniqueConnection);
442  connect(ui.comboBox,
443  SIGNAL(currentIndexChanged(QString)),
444  this,
445  SLOT(kinematicChainChanged(QString)),
446  Qt::UniqueConnection);
447  connect(ui.cartesianselection,
448  SIGNAL(currentIndexChanged(QString)),
449  this,
450  SLOT(caertesianSelectionChanged(QString)),
451  Qt::UniqueConnection);
452  connect(ui.checkBox,
453  SIGNAL(toggled(bool)),
454  this,
455  SLOT(autoFollowChanged(bool)),
456  Qt::UniqueConnection);
457  connect(ui.btnCopyCurrentPoseToClipboard,
458  SIGNAL(clicked()),
459  this,
460  SLOT(on_btnCopyCurrentPoseToClipboard_clicked()),
461  Qt::UniqueConnection);
462  connect(ui.checkBox_showCurrentRobot,
463  SIGNAL(toggled(bool)),
464  this,
465  SLOT(showCurrentRobotChanged(bool)),
466  Qt::UniqueConnection);
467  connect(ui.checkBox_showPreviewRobot,
468  SIGNAL(toggled(bool)),
469  this,
470  SLOT(showPreviewRobotChanged(bool)),
471  Qt::UniqueConnection);
472  connect(ui.pushButton_setDesiredPose,
473  SIGNAL(clicked()),
474  this,
475  SLOT(on_btnSetDesiredPose_clicked()),
476  Qt::UniqueConnection);
477 }
478 
479 Ice::StringSeq
480 armarx::RobotIKWidgetController::getIncludePaths() const
481 {
482  Ice::StringSeq includePaths;
483 
484  try
485  {
486  Ice::StringSeq packages = robotStateComponentPrx->getArmarXPackages();
487  packages.push_back(Application::GetProjectName());
488 
489  for (const std::string& projectName : packages)
490  {
491  if (projectName.empty())
492  {
493  continue;
494  }
495 
496  CMakePackageFinder project(projectName);
497  auto pathsString = project.getDataDir();
498  Ice::StringSeq projectIncludePaths = armarx::Split(pathsString, ",;", true, true);
499  includePaths.insert(
500  includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
501  }
502  }
503  catch (...)
504  {
505  ARMARX_ERROR << "Unable to retrieve robot filename." << std::endl;
506  }
507 
508  return includePaths;
509 }
510 
512 armarx::RobotIKWidgetController::loadRobot(Ice::StringSeq includePaths)
513 {
514  try
515  {
516  std::string rfile = robotStateComponentPrx->getRobotFilename();
517  ArmarXDataPath::getAbsolutePath(rfile, rfile, includePaths);
518  return VirtualRobot::RobotIO::loadRobot(rfile);
519  }
520  catch (...)
521  {
522  ARMARX_ERROR << "Unable to load robot from file" << std::endl;
523  return VirtualRobot::RobotPtr();
524  }
525 }
526 
527 void
528 armarx::RobotIKWidgetController::manipFinishCallback(void* data, SoDragger* dragger)
529 {
530  RobotIKWidgetController* controller = static_cast<RobotIKWidgetController*>(data);
531  if (controller)
532  {
533  startIKSolving(controller);
534  }
535 }
536 
537 void
538 armarx::RobotIKWidgetController::manipMovedCallback(void* data, SoDragger* dragger)
539 {
540  RobotIKWidgetController* controller = static_cast<RobotIKWidgetController*>(data);
541 
542  if (controller)
543  {
544  controller->manipulatorMoved = true;
545  QMetaObject::invokeMethod(
546  controller, "showPreviewRobotChanged", Qt::QueuedConnection, Q_ARG(bool, false));
547  }
548 }
549 
550 void
551 armarx::RobotIKWidgetController::robotUpdateTimerCB(void* data, SoSensor* sensor)
552 {
553  RobotIKWidgetController* controller = static_cast<RobotIKWidgetController*>(data);
554 
555  if (!controller || !controller->robotStateComponentPrx || !controller->robot)
556  {
557  return;
558  }
559 
560  try
561  {
563  controller->robotStateComponentPrx);
564 
565  if (controller->startUpCameraPositioningFlag)
566  {
567  controller->ui.robotViewer->getRobotViewer()->cameraViewAll();
568  controller->startUpCameraPositioningFlag = false;
569  }
570  }
571  catch (...)
572  {
573  };
574 }
575 
576 void
577 armarx::RobotIKWidgetController::textFieldUpdateTimerCB(void* data, SoSensor* sensor)
578 {
579  RobotIKWidgetController* controller = static_cast<RobotIKWidgetController*>(data);
580 
581  if (!controller)
582  {
583  return;
584  }
585 
586  if (controller->visualization->getIsVisualizing())
587  {
588  Eigen::Matrix4f tcpMatrix =
589  controller->robot->getRobotNodeSet(controller->ui.comboBox->currentText().toStdString())
590  ->getTCP()
591  ->getPoseInRootFrame();
592  FramedPose actualPose(
593  tcpMatrix, controller->robot->getRootNode()->getName(), controller->robot->getName());
594  //Set text label to tcp matrix
595  controller->ui.currentPoseMatrix->setText(QString::fromStdString(actualPose.output()));
596 
597  //Set text label for desired tcp pose
598  FramedPose desired(controller->robot->getRootNode()->toLocalCoordinateSystem(
599  controller->visualization->getUserDesiredPose()),
600  controller->robot->getRootNode()->getName(),
601  controller->robot->getName());
602  controller->ui.desiredPoseMatrix->setText(QString::fromStdString(desired.output()));
603  }
604 }
605 
606 void
607 armarx::RobotIKWidgetController::autoFollowSensorTimerCB(void* data, SoSensor* sensor)
608 {
609  RobotIKWidgetController* controller = static_cast<RobotIKWidgetController*>(data);
610 
611  if (controller && controller->manipulatorMoved)
612  {
613  controller->solveIK();
614  controller->manipulatorMoved = false;
615  }
616 }
617 
618 void
619 armarx::RobotIKWidgetController::startIKSolving(RobotIKWidgetController* controller)
620 {
621  if (controller)
622  {
623  controller->ui.reachableLabel->setText(QString::fromStdString("Calculating..."));
624  controller->ui.reachableLabel->setStyleSheet("QLabel { color : black; }");
625  controller->robotIKPrx->begin_computeExtendedIKGlobalPose(
626  controller->ui.comboBox->currentText().toStdString(),
627  new armarx::Pose(controller->visualization->getUserDesiredPose()),
628  controller->convertOption(
629  controller->ui.cartesianselection->currentText().toStdString()),
630  Ice::newCallback(controller, &RobotIKWidgetController::ikCallbackDisplaySolution));
631  }
632 }
633 
634 armarx::ExtendedIKResult
635 armarx::RobotIKWidgetController::improveCurrentSolution(armarx::ExtendedIKResult& solution)
636 {
637  if (!ui.checkBox_cartesianControl->isChecked())
638  {
639  return solution;
640  }
641 
642  if (!solution.isReachable)
643  {
644  return solution;
645  }
646 
649  convertOption(ui.cartesianselection->currentText().toStdString());
650  if (mode == CartesianSelection::eAll)
651  {
652  vrmode = VirtualRobot::IKSolver::CartesianSelection::All;
653  }
654  else if (mode == CartesianSelection::ePosition)
655  {
657  }
658  else if (mode == CartesianSelection::eOrientation)
659  {
661  }
662  else
663  {
664  return solution;
665  }
666 
667  armarx::RemoteRobot::synchronizeLocalClone(cartesianControlRobot, robotStateComponentPrx);
668  cartesianControlRobot->setJointValues(solution.jointAngles);
669  VirtualRobot::RobotNodeSetPtr kc =
670  cartesianControlRobot->getRobotNodeSet(ui.comboBox->currentText().toStdString());
671  VirtualRobot::RobotNodePtr tcp = kc->getTCP();
672  Eigen::Matrix4f globalTargetTCPPose = visualization->getUserDesiredPose();
673  Eigen::Matrix4f localTarget =
674  cartesianControlRobot->getRootNode()->toLocalCoordinateSystem(globalTargetTCPPose);
675 
676  CartesianPositionControllerPtr cartesianPositionController;
677  cartesianPositionController.reset(new CartesianPositionController(tcp));
678 
679  CartesianVelocityControllerPtr cartesianVelocityController;
680  cartesianVelocityController.reset(
681  new CartesianVelocityController(kc, tcp, VirtualRobot::JacobiProvider::eSVD));
682 
683 
684  float errorOriInitial = cartesianPositionController->getOrientationError(localTarget);
685  float errorPosInitial = cartesianPositionController->getPositionError(localTarget);
686 
687  float stepLength = 0.05f;
688  float eps = 0.001;
689 
690  for (int i = 0; i < CARTESIAN_CONTROLLER_LOOP_AMOUNT; i++)
691  {
692  Eigen::VectorXf tcpVelocities = cartesianPositionController->calculate(localTarget, vrmode);
693  Eigen::VectorXf nullspaceVel =
694  cartesianVelocityController
695  ->calculateJointLimitAvoidance(); // calculateNullspaceVelocity(tcpVelocities, 1.0f, vrmode);
696  float nullspaceLen = nullspaceVel.norm();
697  if (nullspaceLen > stepLength)
698  {
699  nullspaceVel = nullspaceVel / nullspaceLen * stepLength;
700  }
701  Eigen::VectorXf jointVelocities =
702  cartesianVelocityController->calculate(tcpVelocities, nullspaceVel, vrmode);
703 
704  //jointVelocities = jointVelocities * stepLength;
705  float len = jointVelocities.norm();
706  if (len > stepLength)
707  {
708  jointVelocities = jointVelocities / len * stepLength;
709  }
710 
711  for (size_t n = 0; n < kc->getSize(); n++)
712  {
713  kc->getNode(n)->setJointValue(kc->getNode(n)->getJointValue() + jointVelocities(n));
714  }
715  if (len < eps)
716  {
717  break;
718  }
719  }
720 
721  float errorOriAfter = cartesianPositionController->getOrientationError(localTarget);
722  float errorPosAfter = cartesianPositionController->getPositionError(localTarget);
723  if (errorOriAfter < errorOriInitial + 1.f / 180 * M_PI && errorPosAfter < errorPosInitial + 1.f)
724  {
725  solution.jointAngles = kc->getJointValueMap();
726  solution.errorOrientation = errorOriAfter;
727  solution.errorPosition = errorPosAfter;
728  }
729 
730  return solution;
731 }
732 
733 armarx::ExtendedIKResult
734 armarx::RobotIKWidgetController::getIKSolution() const
735 {
736  return ExtendedIKResult();
737 }
738 
740 armarx::RobotIKWidgetController::convertOption(std::string option) const
741 {
742  if (option == "Orientation and Position")
743  {
744  return eAll;
745  }
746  else if (option == "Position")
747  {
748  return ePosition;
749  }
750  else if (option == "Orientation")
751  {
752  return eOrientation;
753  }
754  else if (option == "X position")
755  {
756  return eX;
757  }
758  else if (option == "Y position")
759  {
760  return eY;
761  }
762  else if (option == "Z position")
763  {
764  return eZ;
765  }
766 
767  return eAll;
768 }
769 
770 void
771 armarx::RobotIKWidgetController::updatePreviewRobot()
772 {
773  armarx::RemoteRobot::synchronizeLocalClone(previewRobot, robotStateComponentPrx);
774  previewRobot->setJointValues(currentSolution.jointAngles);
775  showPreviewRobotChanged(ui.checkBox_showPreviewRobot->isChecked());
776 }
777 
778 void
779 armarx::RobotIKWidgetController::on_btnSetDesiredPose_clicked()
780 {
782 
783  if (d.exec() == QDialog::Accepted)
784  {
785  FramedPosePtr newDesiredPose = d.getDesiredPose();
786  if (newDesiredPose->frame.empty())
787  {
788  ARMARX_WARNING << "Frame of a FramedPose cannot be empty!";
789  }
790  else if (newDesiredPose->agent.empty())
791  {
792  ARMARX_WARNING << "Agent of a FramedPose cannot be empty!";
793  }
794  else
795  {
796  try
797  {
798  visualization->setUserDesiredPose(newDesiredPose->toGlobalEigen(robot));
799  startIKSolving(this);
800  }
801  catch (...)
802  {
804  }
805  }
806  }
807 }
808 
809 void
810 armarx::RobotIKWidgetController::executeMotion()
811 {
812  if (currentSolution.isReachable)
813  {
814  //Switch all control modes to ePositionControl
815  std::vector<VirtualRobot::RobotNodePtr> rn =
816  robot->getRobotNodeSet(this->ui.comboBox->currentText().toStdString())
817  ->getAllRobotNodes();
818  NameControlModeMap jointModes;
820 
821  for (unsigned int i = 0; i < rn.size(); i++)
822  {
823  jointModes[rn[i]->getName()] = ePositionControl;
824  jointAngles[rn[i]->getName()] = 0.0f;
825  }
826 
827  kinematicUnitInterfacePrx->switchControlMode(jointModes);
828  kinematicUnitInterfacePrx->setJointAngles(currentSolution.jointAngles);
829  }
830 }
831 
832 void
834 {
835  if (checked)
836  {
837  //Make a timer update robo pose every time tick
838  SoSensorManager* sensor_mgr = SoDB::getSensorManager();
839  autoFollowSensor = new SoTimerSensor(autoFollowSensorTimerCB, this);
840  autoFollowSensor->setInterval(SbTime(AUTO_FOLLOW_UPDATE / 1000.0f));
841  sensor_mgr->insertTimerSensor(autoFollowSensor);
842  }
843  else
844  {
845  SoSensorManager* sensor_mgr = SoDB::getSensorManager();
846  sensor_mgr->removeTimerSensor(autoFollowSensor);
847  }
848 }
849 
850 void
851 armarx::RobotIKWidgetController::on_btnCopyCurrentPoseToClipboard_clicked()
852 {
853 
854  if (visualization->getIsVisualizing())
855  {
856 
857  Eigen::Matrix4f tcpMatrix = robot->getRobotNodeSet(ui.comboBox->currentText().toStdString())
858  ->getTCP()
859  ->getPoseInRootFrame();
860  FramedPosePtr pose =
861  new FramedPose(tcpMatrix, robot->getRootNode()->getName(), robot->getName());
862  JSONObjectPtr obj = new JSONObject();
863  obj->serializeIceObject(pose);
864 
865 
866  QClipboard* clipboard = QApplication::clipboard();
867  clipboard->setText(QString::fromStdString(obj->asString(true)));
868  }
869 }
armarx::RobotIKGuiPlugin::RobotIKGuiPlugin
RobotIKGuiPlugin()
Definition: RobotIKGuiPlugin.cpp:59
armarx::RobotIKWidgetController::showPreviewRobotChanged
void showPreviewRobotChanged(bool checked)
Definition: RobotIKGuiPlugin.cpp:418
armarx::Application::GetProjectName
static const std::string & GetProjectName()
Definition: Application.cpp:879
armarx::RobotIKWidgetController::getConfigDialog
QPointer< QDialog > getConfigDialog(QWidget *parent=0) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
Definition: RobotIKGuiPlugin.cpp:221
armarx::RobotIKWidgetController::RobotIKWidgetController
RobotIKWidgetController()
Definition: RobotIKGuiPlugin.cpp:64
SetDesiredPoseDialog
Definition: SetDesiredPoseDialog.h:15
armarx::RobotIKWidgetController::initWidget
void initWidget()
Definition: RobotIKGuiPlugin.cpp:261
GfxTL::Orientation
ScalarT Orientation(const VectorXD< 2, ScalarT > &p1, const VectorXD< 2, ScalarT > &p2, const VectorXD< 2, ScalarT > &c)
Definition: Orientation.h:10
JSONObject.h
armarx::RobotIKWidgetController::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: RobotIKGuiPlugin.cpp:215
armarx::RemoteRobot::synchronizeLocalClone
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
Definition: RemoteRobot.cpp:522
armarx::VariantType::FramedPose
const VariantTypeId FramedPose
Definition: FramedPose.h:36
GfxTL::Matrix4f
MatrixXX< 4, 4, float > Matrix4f
Definition: MatrixXX.h:650
armarx::JSONObject
The JSONObject class is used to represent and (de)serialize JSON objects.
Definition: JSONObject.h:43
armarx::FramedPosePtr
IceInternal::Handle< FramedPose > FramedPosePtr
Definition: FramedPose.h:272
armarx::Split
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
Definition: StringHelperTemplates.h:36
ROBOT_UPDATE_TIMER_MS
#define ROBOT_UPDATE_TIMER_MS
Definition: RobotIKGuiPlugin.cpp:54
armarx::RobotIKWidgetController::showCurrentRobotChanged
void showCurrentRobotChanged(bool checked)
Definition: RobotIKGuiPlugin.cpp:398
armarx::RobotIKWidgetController::saveSettings
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
Definition: RobotIKGuiPlugin.cpp:245
armarx::NJointTaskSpaceDMPControllerMode::ePosition
@ ePosition
Definition: ControllerInterface.ice:36
armarx::CartesianPositionControllerPtr
std::shared_ptr< CartesianPositionController > CartesianPositionControllerPtr
Definition: CartesianPositionController.h:39
TEXTFIELD_UPDATE_TIMER_MS
#define TEXTFIELD_UPDATE_TIMER_MS
Definition: RobotIKGuiPlugin.cpp:55
armarx::RobotIKWidgetController::caertesianSelectionChanged
void caertesianSelectionChanged(const QString &arg1)
Definition: RobotIKGuiPlugin.cpp:349
armarx::ScopedLock
Mutex::scoped_lock ScopedLock
Definition: Synchronization.h:150
RobotIKGuiPlugin.h
armarx::CartesianVelocityControllerPtr
std::shared_ptr< CartesianVelocityController > CartesianVelocityControllerPtr
Definition: CartesianVelocityController.h:34
armarx::RobotIKWidgetController::kinematicChainChanged
void kinematicChainChanged(const QString &arg1)
Definition: RobotIKGuiPlugin.cpp:315
project
std::string project
Definition: VisualizationRobot.cpp:85
armarx::RobotIKWidgetController::loadSettings
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
Definition: RobotIKGuiPlugin.cpp:236
IceInternal::Handle< FramedPose >
armarx::RobotIKWidgetController::resetManip
void resetManip()
Definition: RobotIKGuiPlugin.cpp:359
controller
Definition: AddOperation.h:39
M_PI
#define M_PI
Definition: MathTools.h:17
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
armarx::NJointTaskSpaceDMPControllerMode::CartesianSelection
CartesianSelection
Definition: ControllerInterface.ice:34
armarx::RobotIKWidgetController::configured
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
Definition: RobotIKGuiPlugin.cpp:253
ArmarXObjectScheduler.h
armarx::channels::KinematicUnitObserver::jointVelocities
const KinematicUnitDatafieldCreator jointVelocities("jointVelocities")
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
SetDesiredPoseDialog::getDesiredPose
armarx::FramedPosePtr getDesiredPose()
Definition: SetDesiredPoseDialog.cpp:34
CARTESIAN_CONTROLLER_LOOP_AMOUNT
#define CARTESIAN_CONTROLLER_LOOP_AMOUNT
Definition: RobotIKGuiPlugin.cpp:57
CartesianVelocityController.h
CartesianPositionController.h
RobotViewer.h
armarx::control::njoint_controller::platform::platform_follower_controller::NameValueMap
std::map< std::string, float > NameValueMap
Definition: PlatformFollowerController.h:88
armarx::channels::KinematicUnitObserver::jointAngles
const KinematicUnitDatafieldCreator jointAngles("jointAngles")
CMakePackageFinder.h
option
#define option(type, fn)
SetDesiredPoseDialog.h
armarx::Pose
The Pose class.
Definition: Pose.h:242
armarx::RobotIKWidgetController::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: RobotIKGuiPlugin.cpp:209
armarx::RobotIKWidgetController::solveIK
void solveIK()
Definition: RobotIKGuiPlugin.cpp:275
armarx::NJointTaskSpaceDMPControllerMode::eAll
@ eAll
Definition: ControllerInterface.ice:38
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::NJointTaskSpaceDMPControllerMode::eOrientation
@ eOrientation
Definition: ControllerInterface.ice:37
IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface >
armarx::ManipulatorVisualization
Definition: ManipulatorVisualization.h:55
armarx::RobotIKWidgetController::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: RobotIKGuiPlugin.cpp:91
armarx::RobotIKWidgetController::autoFollowChanged
void autoFollowChanged(bool checked)
Definition: RobotIKGuiPlugin.cpp:833
armarx::ArmarXDataPath::getAbsolutePath
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
Definition: ArmarXDataPath.cpp:109
armarx::navigation::core::Position
Eigen::Vector3f Position
Definition: basic_types.h:36
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:157
ARMARX_WARNING
#define ARMARX_WARNING
Definition: Logging.h:193
armarx::RobotIKWidgetController::updateSolutionDisplay
void updateSolutionDisplay()
Definition: RobotIKGuiPlugin.cpp:366
ArmarXDataPath.h
AUTO_FOLLOW_UPDATE
#define AUTO_FOLLOW_UPDATE
Definition: RobotIKGuiPlugin.cpp:56
armarx::ctrlutil::s
double s(double t, double s0, double v0, double a0, double j)
Definition: CtrlUtil.h:33
armarx::RobotIKWidgetController::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: RobotIKGuiPlugin.cpp:80
Application.h
VirtualRobot::RobotPtr
std::shared_ptr< class Robot > RobotPtr
Definition: Bus.h:19
armarx::SimpleConfigDialog
A config-dialog containing one (or multiple) proxy finders.
Definition: SimpleConfigDialog.h:84