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
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
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
79void
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
90void
92{
93 //Get all proxies
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();
167}
168
169void
170armarx::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
208void
210{
211 QMetaObject::invokeMethod(this, "onDisconnect");
212}
213
214void
216{
217 // enableMainWidgetAsync(false);
218}
219
220QPointer<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
235void
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
244void
246{
247 settings->setValue("robotStateComponentName", robotStateComponentName.c_str());
248 settings->setValue("robotIKComponentName", robotIKComponentName.c_str());
249 settings->setValue("kinematicUnitComponentName", kinematicUnitComponentName.c_str());
250}
251
252void
254{
255 robotStateComponentName = dialog->getProxyName("RobotStateComponent");
256 robotIKComponentName = dialog->getProxyName("RobotIK");
257 kinematicUnitComponentName = dialog->getProxyName("KinematicUnit");
258}
259
260void
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
274void
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
284void
285armarx::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
297void
298armarx::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
314void
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
346}
347
348void
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
358void
360{
361 //Triggers reset of manipulator in kinematicChainChanged
362 kinematicChainChanged(this->ui.comboBox->currentText());
363}
364
365void
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
397void
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
417void
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
437void
438armarx::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
479Ice::StringSeq
480armarx::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
512armarx::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
527void
528armarx::RobotIKWidgetController::manipFinishCallback(void* data, SoDragger* dragger)
529{
530 RobotIKWidgetController* controller = static_cast<RobotIKWidgetController*>(data);
531 if (controller)
532 {
533 startIKSolving(controller);
534 }
535}
536
537void
538armarx::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
550void
551armarx::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
576void
577armarx::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
606void
607armarx::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
618void
619armarx::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
634armarx::ExtendedIKResult
635armarx::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
647 VirtualRobot::IKSolver::CartesianSelection vrmode;
648 armarx::CartesianSelection mode =
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 {
656 vrmode = VirtualRobot::IKSolver::CartesianSelection::Position;
657 }
658 else if (mode == CartesianSelection::eOrientation)
659 {
660 vrmode = VirtualRobot::IKSolver::CartesianSelection::Orientation;
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
733armarx::ExtendedIKResult
734armarx::RobotIKWidgetController::getIKSolution() const
735{
736 return ExtendedIKResult();
737}
738
739armarx::CartesianSelection
740armarx::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
770void
771armarx::RobotIKWidgetController::updatePreviewRobot()
772{
773 armarx::RemoteRobot::synchronizeLocalClone(previewRobot, robotStateComponentPrx);
774 previewRobot->setJointValues(currentSolution.jointAngles);
775 showPreviewRobotChanged(ui.checkBox_showPreviewRobot->isChecked());
776}
777
778void
779armarx::RobotIKWidgetController::on_btnSetDesiredPose_clicked()
780{
781 SetDesiredPoseDialog d;
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
809void
810armarx::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
832void
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
850void
851armarx::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}
#define option(type, fn)
#define M_PI
Definition MathTools.h:17
#define AUTO_FOLLOW_UPDATE
#define CARTESIAN_CONTROLLER_LOOP_AMOUNT
#define TEXTFIELD_UPDATE_TIMER_MS
#define ROBOT_UPDATE_TIMER_MS
#define VAROUT(x)
armarx::FramedPosePtr getDesiredPose()
static const std::string & GetProjectName()
static bool getAbsolutePath(const std::string &relativeFilename, std::string &storeAbsoluteFilename, const std::vector< std::string > &additionalSearchPaths={}, bool verbose=true)
std::enable_if<!HasGetWidgetName< ArmarXWidgetType >::value >::type addWidget()
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
void enableMainWidgetAsync(bool enable)
This function enables/disables the main widget asynchronously (if called from a non qt thread).
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
The FramedPose class.
Definition FramedPose.h:281
The JSONObject class is used to represent and (de)serialize JSON objects.
Definition JSONObject.h:44
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
ArmarXObjectSchedulerPtr getObjectScheduler() const
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
int getState() const
Retrieve current state of the ManagedIceObject.
The Pose class.
Definition Pose.h:243
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
void onInitComponent() override
Pure virtual hook for the subclass.
void caertesianSelectionChanged(const QString &arg1)
void onDisconnectComponent() override
Hook for subclass.
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
void kinematicChainChanged(const QString &arg1)
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
QPointer< QDialog > getConfigDialog(QWidget *parent=0) override
getConfigDialog returns a pointer to the a configuration widget of this controller.
void onConnectComponent() override
Pure virtual hook for the subclass.
void configured() override
This function must be implemented by the user, if he supplies a config dialog.
RobotStateComponentInterfacePrx robotStateComponentPrx
void onExitComponent() override
Hook for subclass.
KinematicUnitInterfacePrx kinematicUnitInterfacePrx
A config-dialog containing one (or multiple) proxy finders.
#define ARMARX_INFO
The normal logging level.
Definition Logging.h:181
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
Definition Logging.h:196
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Definition Logging.h:193
Mutex::scoped_lock ScopedLock
std::shared_ptr< class Robot > RobotPtr
Definition Bus.h:19
const KinematicUnitDatafieldCreator jointVelocities("jointVelocities")
const KinematicUnitDatafieldCreator jointAngles("jointAngles")
void project(pcl::PointCloud< pcl::PointXYZ > &cloud, wykobi::Polygon polygon)
std::shared_ptr< CartesianVelocityController > CartesianVelocityControllerPtr
void handleExceptions()
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
IceInternal::Handle< JSONObject > JSONObjectPtr
Definition JSONObject.h:34
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface > RobotStateComponentInterfacePrx
std::shared_ptr< CartesianPositionController > CartesianPositionControllerPtr
IceInternal::Handle< FramedPose > FramedPosePtr
Definition FramedPose.h:272
constexpr auto n() noexcept