38 #include <VirtualRobot/RobotNodeSet.h>
39 #include <VirtualRobot/Visualization/CoinVisualization/CoinVisualizationFactory.h>
40 #include <VirtualRobot/XML/RobotIO.h>
47 #include <Inventor/SbViewportRegion.h>
48 #include <Inventor/actions/SoGetMatrixAction.h>
49 #include <Inventor/actions/SoSearchAction.h>
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
61 addWidget<RobotIKWidgetController>();
65 manipulatorMoved(false), startUpCameraPositioningFlag(true)
70 robotStateComponentName =
"";
71 robotIKComponentName =
"";
72 kinematicUnitComponentName =
"";
75 robotUpdateSensor = NULL;
76 textFieldUpdateSensor = NULL;
83 QMetaObject::invokeMethod(
this,
"initWidget");
85 usingProxy(robotStateComponentName);
86 usingProxy(robotIKComponentName);
87 usingProxy(kinematicUnitComponentName);
94 robotStateComponentPrx = getProxy<RobotStateComponentInterfacePrx>(robotStateComponentName);
95 kinematicUnitInterfacePrx = getProxy<KinematicUnitInterfacePrx>(kinematicUnitComponentName);
96 robotIKPrx = getProxy<RobotIKInterfacePrx>(robotIKComponentName);
99 robot = loadRobot(getIncludePaths());
104 getObjectScheduler()->terminate();
106 if (getWidget()->parentWidget())
108 getWidget()->parentWidget()->close();
111 ARMARX_ERROR <<
"RobotIKPlugin: Unable to load robot file! Terminating." << std::endl;
117 this->ui.robotViewer->getRobotViewer()->getRootNode()->addChild((SoNode*)visualization);
120 currentRobotVisualization = robot->getVisualization();
121 this->ui.robotViewer->getRobotViewer()->getRootNode()->addChild(
122 currentRobotVisualization->getCoinVisualization());
125 previewRobot = loadRobot(getIncludePaths());
126 previewRobotVisualization = previewRobot->getVisualization();
129 cartesianControlRobot = previewRobot->clone();
132 SoSensorManager* sensor_mgr = SoDB::getSensorManager();
133 robotUpdateSensor =
new SoTimerSensor(robotUpdateTimerCB,
this);
135 sensor_mgr->insertTimerSensor(robotUpdateSensor);
138 textFieldUpdateSensor =
new SoTimerSensor(textFieldUpdateTimerCB,
this);
140 sensor_mgr->insertTimerSensor(textFieldUpdateSensor);
143 auto robotNodeSets = robot->getRobotNodeSets();
145 for (VirtualRobot::RobotNodeSetPtr
s : robotNodeSets)
147 this->ui.comboBox->addItem(QString::fromStdString(
s->getName()));
151 this->ui.comboBox->setEnabled(
true);
152 this->ui.cartesianselection->clear();
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"));
162 this->ui.cartesianselection->setEnabled(
true);
163 this->ui.cartesianselection->setCurrentIndex(0);
166 enableMainWidgetAsync(
true);
170 armarx::RobotIKWidgetController::onDisconnect()
173 SoSensorManager* sensor_mgr = SoDB::getSensorManager();
174 sensor_mgr->removeTimerSensor(textFieldUpdateSensor);
175 sensor_mgr->removeTimerSensor(robotUpdateSensor);
178 this->ui.comboBox->clear();
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);
201 this->ui.robotViewer->getRobotViewer()->getRootNode()->removeAllChildren();
203 visualization = NULL;
204 robotUpdateSensor = NULL;
205 textFieldUpdateSensor = NULL;
211 QMetaObject::invokeMethod(
this,
"onDisconnect");
227 {
"RobotStateComponent",
"",
"RobotState*"});
228 dialog->addProxyFinder<KinematicUnitInterfacePrx>(
229 {
"KinematicUnit",
"",
"*KinematicUnit|KinematicUnit*"});
230 dialog->addProxyFinder<RobotIKInterfacePrx>({
"RobotIK",
"",
"RobotIK*"});
232 return qobject_cast<SimpleConfigDialog*>(dialog);
238 robotStateComponentName = settings->value(
"robotStateComponentName").toString().toStdString();
239 robotIKComponentName = settings->value(
"robotIKComponentName").toString().toStdString();
240 kinematicUnitComponentName =
241 settings->value(
"kinematicUnitComponentName").toString().toStdString();
247 settings->setValue(
"robotStateComponentName", robotStateComponentName.c_str());
248 settings->setValue(
"robotIKComponentName", robotIKComponentName.c_str());
249 settings->setValue(
"kinematicUnitComponentName", kinematicUnitComponentName.c_str());
255 robotStateComponentName = dialog->getProxyName(
"RobotStateComponent");
256 robotIKComponentName = dialog->getProxyName(
"RobotIK");
257 kinematicUnitComponentName = dialog->getProxyName(
"KinematicUnit");
263 ARMARX_INFO <<
"RobotIKWidgetController initWidget";
265 ui.setupUi(getWidget());
266 getWidget()->setEnabled(
false);
268 this->ui.gridLayout->setAlignment(Qt::AlignTop);
271 this->ui.reachableLabel->setStyleSheet(
"QLabel { color : red; }");
277 robotIKPrx->begin_computeExtendedIKGlobalPose(
278 this->ui.comboBox->currentText().toStdString(),
280 convertOption(this->ui.cartesianselection->currentText().toStdString()),
281 Ice::newCallback(
this, &RobotIKWidgetController::ikCallbackExecuteMotion));
285 armarx::RobotIKWidgetController::ikCallbackExecuteMotion(
const Ice::AsyncResultPtr& r)
287 RobotIKInterfacePrx prx = RobotIKInterfacePrx::uncheckedCast(r->getProxy());
288 ExtendedIKResult solution = prx->end_computeExtendedIKGlobalPose(r);
291 currentSolution = improveCurrentSolution(solution);
293 QMetaObject::invokeMethod(
this,
"updateSolutionDisplay");
294 QMetaObject::invokeMethod(
this,
"executeMotion");
298 armarx::RobotIKWidgetController::ikCallbackDisplaySolution(
const Ice::AsyncResultPtr& r)
301 RobotIKInterfacePrx prx = RobotIKInterfacePrx::uncheckedCast(r->getProxy());
302 ExtendedIKResult solution = prx->end_computeExtendedIKGlobalPose(r);
305 currentSolution = improveCurrentSolution(solution);
306 if (currentSolution.isReachable)
308 updatePreviewRobot();
311 QMetaObject::invokeMethod(
this,
"updateSolutionDisplay");
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);
337 if (visualization && robot->hasRobotNodeSet(arg1.toStdString()))
339 visualization->setVisualization(robot, robot->getRobotNodeSet(arg1.toStdString()));
341 visualization->addManipFinishCallback(manipFinishCallback,
this);
342 visualization->addManipMovedCallback(manipMovedCallback,
this);
352 if (visualization->getIsVisualizing())
354 manipFinishCallback(
this, NULL);
362 kinematicChainChanged(this->ui.comboBox->currentText());
368 if (getState() != eManagedIceObjectStarted)
376 if (currentSolution.isReachable)
379 ui.reachableLabel->setText(QString::fromStdString(
"Pose reachable!"));
380 ui.reachableLabel->setStyleSheet(
"QLabel { color : green; }");
381 visualization->setColor(0, 1, 0);
386 ui.reachableLabel->setText(QString::fromStdString(
"Pose unreachable!"));
387 ui.reachableLabel->setStyleSheet(
"QLabel { color : red; }");
388 visualization->setColor(1, 0, 0);
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");
400 auto visualizationRoot = this->ui.robotViewer->getRobotViewer()->getRootNode();
403 if (visualizationRoot->findChild(currentRobotVisualization->getCoinVisualization()) == -1)
405 visualizationRoot->addChild(currentRobotVisualization->getCoinVisualization());
410 if (visualizationRoot->findChild(currentRobotVisualization->getCoinVisualization()) != -1)
412 visualizationRoot->removeChild(currentRobotVisualization->getCoinVisualization());
420 auto visualizationRoot = this->ui.robotViewer->getRobotViewer()->getRootNode();
423 if (visualizationRoot->findChild(previewRobotVisualization->getCoinVisualization()) == -1)
425 visualizationRoot->addChild(previewRobotVisualization->getCoinVisualization());
430 if (visualizationRoot->findChild(previewRobotVisualization->getCoinVisualization()) != -1)
432 visualizationRoot->removeChild(previewRobotVisualization->getCoinVisualization());
438 armarx::RobotIKWidgetController::connectSlots()
440 connect(ui.resetManip, SIGNAL(clicked()),
this, SLOT(resetManip()), Qt::UniqueConnection);
441 connect(ui.pushButton, SIGNAL(clicked()),
this, SLOT(executeMotion()), Qt::UniqueConnection);
443 SIGNAL(currentIndexChanged(QString)),
445 SLOT(kinematicChainChanged(QString)),
446 Qt::UniqueConnection);
447 connect(ui.cartesianselection,
448 SIGNAL(currentIndexChanged(QString)),
450 SLOT(caertesianSelectionChanged(QString)),
451 Qt::UniqueConnection);
453 SIGNAL(toggled(
bool)),
455 SLOT(autoFollowChanged(
bool)),
456 Qt::UniqueConnection);
457 connect(ui.btnCopyCurrentPoseToClipboard,
460 SLOT(on_btnCopyCurrentPoseToClipboard_clicked()),
461 Qt::UniqueConnection);
462 connect(ui.checkBox_showCurrentRobot,
463 SIGNAL(toggled(
bool)),
465 SLOT(showCurrentRobotChanged(
bool)),
466 Qt::UniqueConnection);
467 connect(ui.checkBox_showPreviewRobot,
468 SIGNAL(toggled(
bool)),
470 SLOT(showPreviewRobotChanged(
bool)),
471 Qt::UniqueConnection);
472 connect(ui.pushButton_setDesiredPose,
475 SLOT(on_btnSetDesiredPose_clicked()),
476 Qt::UniqueConnection);
480 armarx::RobotIKWidgetController::getIncludePaths()
const
482 Ice::StringSeq includePaths;
486 Ice::StringSeq packages = robotStateComponentPrx->getArmarXPackages();
489 for (
const std::string& projectName : packages)
491 if (projectName.empty())
496 CMakePackageFinder
project(projectName);
497 auto pathsString =
project.getDataDir();
498 Ice::StringSeq projectIncludePaths =
armarx::Split(pathsString,
",;",
true,
true);
500 includePaths.end(), projectIncludePaths.begin(), projectIncludePaths.end());
505 ARMARX_ERROR <<
"Unable to retrieve robot filename." << std::endl;
512 armarx::RobotIKWidgetController::loadRobot(Ice::StringSeq includePaths)
516 std::string rfile = robotStateComponentPrx->getRobotFilename();
518 return VirtualRobot::RobotIO::loadRobot(rfile);
522 ARMARX_ERROR <<
"Unable to load robot from file" << std::endl;
528 armarx::RobotIKWidgetController::manipFinishCallback(
void*
data, SoDragger* dragger)
530 RobotIKWidgetController*
controller =
static_cast<RobotIKWidgetController*
>(
data);
538 armarx::RobotIKWidgetController::manipMovedCallback(
void*
data, SoDragger* dragger)
540 RobotIKWidgetController*
controller =
static_cast<RobotIKWidgetController*
>(
data);
545 QMetaObject::invokeMethod(
546 controller,
"showPreviewRobotChanged", Qt::QueuedConnection, Q_ARG(
bool,
false));
551 armarx::RobotIKWidgetController::robotUpdateTimerCB(
void*
data, SoSensor* sensor)
553 RobotIKWidgetController*
controller =
static_cast<RobotIKWidgetController*
>(
data);
567 controller->ui.robotViewer->getRobotViewer()->cameraViewAll();
568 controller->startUpCameraPositioningFlag =
false;
577 armarx::RobotIKWidgetController::textFieldUpdateTimerCB(
void*
data, SoSensor* sensor)
579 RobotIKWidgetController*
controller =
static_cast<RobotIKWidgetController*
>(
data);
586 if (
controller->visualization->getIsVisualizing())
591 ->getPoseInRootFrame();
595 controller->ui.currentPoseMatrix->setText(QString::fromStdString(actualPose.output()));
599 controller->visualization->getUserDesiredPose()),
602 controller->ui.desiredPoseMatrix->setText(QString::fromStdString(desired.output()));
607 armarx::RobotIKWidgetController::autoFollowSensorTimerCB(
void*
data, SoSensor* sensor)
609 RobotIKWidgetController*
controller =
static_cast<RobotIKWidgetController*
>(
data);
619 armarx::RobotIKWidgetController::startIKSolving(RobotIKWidgetController*
controller)
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(),
629 controller->ui.cartesianselection->currentText().toStdString()),
630 Ice::newCallback(
controller, &RobotIKWidgetController::ikCallbackDisplaySolution));
634 armarx::ExtendedIKResult
635 armarx::RobotIKWidgetController::improveCurrentSolution(armarx::ExtendedIKResult& solution)
637 if (!ui.checkBox_cartesianControl->isChecked())
642 if (!solution.isReachable)
649 convertOption(ui.cartesianselection->currentText().toStdString());
652 vrmode = VirtualRobot::IKSolver::CartesianSelection::All;
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();
674 cartesianControlRobot->getRootNode()->toLocalCoordinateSystem(globalTargetTCPPose);
677 cartesianPositionController.reset(
new CartesianPositionController(tcp));
680 cartesianVelocityController.reset(
681 new CartesianVelocityController(kc, tcp, VirtualRobot::JacobiProvider::eSVD));
684 float errorOriInitial = cartesianPositionController->getOrientationError(localTarget);
685 float errorPosInitial = cartesianPositionController->getPositionError(localTarget);
687 float stepLength = 0.05f;
692 Eigen::VectorXf tcpVelocities = cartesianPositionController->calculate(localTarget, vrmode);
693 Eigen::VectorXf nullspaceVel =
694 cartesianVelocityController
695 ->calculateJointLimitAvoidance();
696 float nullspaceLen = nullspaceVel.norm();
697 if (nullspaceLen > stepLength)
699 nullspaceVel = nullspaceVel / nullspaceLen * stepLength;
702 cartesianVelocityController->calculate(tcpVelocities, nullspaceVel, vrmode);
706 if (len > stepLength)
711 for (
size_t n = 0; n < kc->getSize(); n++)
713 kc->getNode(n)->setJointValue(kc->getNode(n)->getJointValue() +
jointVelocities(n));
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)
725 solution.jointAngles = kc->getJointValueMap();
726 solution.errorOrientation = errorOriAfter;
727 solution.errorPosition = errorPosAfter;
733 armarx::ExtendedIKResult
734 armarx::RobotIKWidgetController::getIKSolution()
const
736 return ExtendedIKResult();
740 armarx::RobotIKWidgetController::convertOption(std::string
option)
const
742 if (
option ==
"Orientation and Position")
746 else if (
option ==
"Position")
750 else if (
option ==
"Orientation")
754 else if (
option ==
"X position")
758 else if (
option ==
"Y position")
762 else if (
option ==
"Z position")
771 armarx::RobotIKWidgetController::updatePreviewRobot()
774 previewRobot->setJointValues(currentSolution.jointAngles);
775 showPreviewRobotChanged(ui.checkBox_showPreviewRobot->isChecked());
779 armarx::RobotIKWidgetController::on_btnSetDesiredPose_clicked()
783 if (d.exec() == QDialog::Accepted)
786 if (newDesiredPose->frame.empty())
790 else if (newDesiredPose->agent.empty())
798 visualization->setUserDesiredPose(newDesiredPose->toGlobalEigen(robot));
799 startIKSolving(
this);
810 armarx::RobotIKWidgetController::executeMotion()
812 if (currentSolution.isReachable)
815 std::vector<VirtualRobot::RobotNodePtr> rn =
816 robot->getRobotNodeSet(this->ui.comboBox->currentText().toStdString())
817 ->getAllRobotNodes();
818 NameControlModeMap jointModes;
821 for (
unsigned int i = 0; i < rn.size(); i++)
823 jointModes[rn[i]->getName()] = ePositionControl;
827 kinematicUnitInterfacePrx->switchControlMode(jointModes);
828 kinematicUnitInterfacePrx->setJointAngles(currentSolution.jointAngles);
838 SoSensorManager* sensor_mgr = SoDB::getSensorManager();
839 autoFollowSensor =
new SoTimerSensor(autoFollowSensorTimerCB,
this);
841 sensor_mgr->insertTimerSensor(autoFollowSensor);
845 SoSensorManager* sensor_mgr = SoDB::getSensorManager();
846 sensor_mgr->removeTimerSensor(autoFollowSensor);
851 armarx::RobotIKWidgetController::on_btnCopyCurrentPoseToClipboard_clicked()
854 if (visualization->getIsVisualizing())
857 Eigen::Matrix4f tcpMatrix = robot->getRobotNodeSet(ui.comboBox->currentText().toStdString())
859 ->getPoseInRootFrame();
861 new FramedPose(tcpMatrix, robot->getRootNode()->getName(), robot->getName());
863 obj->serializeIceObject(pose);
866 QClipboard* clipboard = QApplication::clipboard();
867 clipboard->setText(QString::fromStdString(obj->asString(
true)));