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
65 manipulatorMoved(false), startUpCameraPositioningFlag(true)
70 robotStateComponentName =
"";
71 robotIKComponentName =
"";
72 kinematicUnitComponentName =
"";
75 robotUpdateSensor = NULL;
76 textFieldUpdateSensor = NULL;
83 QMetaObject::invokeMethod(
this,
"initWidget");
99 robot = loadRobot(getIncludePaths());
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);
170armarx::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";
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));
285armarx::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");
298armarx::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);
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());
438armarx::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);
480armarx::RobotIKWidgetController::getIncludePaths()
const
482 Ice::StringSeq includePaths;
486 Ice::StringSeq packages = robotStateComponentPrx->getArmarXPackages();
489 for (
const std::string& projectName : packages)
491 if (projectName.empty())
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;
512armarx::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;
528armarx::RobotIKWidgetController::manipFinishCallback(
void*
data, SoDragger* dragger)
533 startIKSolving(controller);
538armarx::RobotIKWidgetController::manipMovedCallback(
void*
data, SoDragger* dragger)
544 controller->manipulatorMoved =
true;
545 QMetaObject::invokeMethod(
546 controller,
"showPreviewRobotChanged", Qt::QueuedConnection, Q_ARG(
bool,
false));
551armarx::RobotIKWidgetController::robotUpdateTimerCB(
void*
data, SoSensor* sensor)
555 if (!controller || !controller->robotStateComponentPrx || !controller->robot)
563 controller->robotStateComponentPrx);
565 if (controller->startUpCameraPositioningFlag)
567 controller->ui.robotViewer->getRobotViewer()->cameraViewAll();
568 controller->startUpCameraPositioningFlag =
false;
577armarx::RobotIKWidgetController::textFieldUpdateTimerCB(
void*
data, SoSensor* sensor)
586 if (controller->visualization->getIsVisualizing())
588 Eigen::Matrix4f tcpMatrix =
589 controller->robot->getRobotNodeSet(controller->ui.comboBox->currentText().toStdString())
591 ->getPoseInRootFrame();
593 tcpMatrix, controller->robot->getRootNode()->getName(), controller->robot->getName());
595 controller->ui.currentPoseMatrix->setText(QString::fromStdString(actualPose.output()));
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()));
607armarx::RobotIKWidgetController::autoFollowSensorTimerCB(
void*
data, SoSensor* sensor)
611 if (controller && controller->manipulatorMoved)
613 controller->solveIK();
614 controller->manipulatorMoved =
false;
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));
634armarx::ExtendedIKResult
635armarx::RobotIKWidgetController::improveCurrentSolution(armarx::ExtendedIKResult& solution)
637 if (!ui.checkBox_cartesianControl->isChecked())
642 if (!solution.isReachable)
647 VirtualRobot::IKSolver::CartesianSelection vrmode;
648 armarx::CartesianSelection mode =
649 convertOption(ui.cartesianselection->currentText().toStdString());
650 if (mode == CartesianSelection::eAll)
652 vrmode = VirtualRobot::IKSolver::CartesianSelection::All;
654 else if (mode == CartesianSelection::ePosition)
656 vrmode = VirtualRobot::IKSolver::CartesianSelection::Position;
658 else if (mode == CartesianSelection::eOrientation)
660 vrmode = VirtualRobot::IKSolver::CartesianSelection::Orientation;
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);
680 cartesianVelocityController.reset(
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;
733armarx::ExtendedIKResult
734armarx::RobotIKWidgetController::getIKSolution()
const
736 return ExtendedIKResult();
739armarx::CartesianSelection
740armarx::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")
771armarx::RobotIKWidgetController::updatePreviewRobot()
774 previewRobot->setJointValues(currentSolution.jointAngles);
775 showPreviewRobotChanged(ui.checkBox_showPreviewRobot->isChecked());
779armarx::RobotIKWidgetController::on_btnSetDesiredPose_clicked()
781 SetDesiredPoseDialog d;
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);
810armarx::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);
851armarx::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)));
#define AUTO_FOLLOW_UPDATE
#define CARTESIAN_CONTROLLER_LOOP_AMOUNT
#define TEXTFIELD_UPDATE_TIMER_MS
#define ROBOT_UPDATE_TIMER_MS
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()
The CMakePackageFinder class provides an interface to the CMake Package finder capabilities.
The JSONObject class is used to represent and (de)serialize JSON objects.
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.
static bool synchronizeLocalClone(VirtualRobot::RobotPtr robot, RobotStateComponentInterfacePrx robotStatePrx)
A config-dialog containing one (or multiple) proxy finders.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_ERROR
The logging level for unexpected behaviour, that must be fixed.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
Mutex::scoped_lock ScopedLock
std::shared_ptr< class Robot > RobotPtr
const KinematicUnitDatafieldCreator jointVelocities("jointVelocities")
const KinematicUnitDatafieldCreator jointAngles("jointAngles")
void project(pcl::PointCloud< pcl::PointXYZ > &cloud, wykobi::Polygon polygon)
std::shared_ptr< CartesianVelocityController > CartesianVelocityControllerPtr
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
IceInternal::Handle< JSONObject > JSONObjectPtr
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotStateComponentInterface > RobotStateComponentInterfacePrx
std::shared_ptr< CartesianPositionController > CartesianPositionControllerPtr
IceInternal::Handle< FramedPose > FramedPosePtr
constexpr auto n() noexcept