41 static const int OBJECTS_COLUMN_ATTACHMENT = 6;
47 widget.objectsTree->clear();
48 widget.objectsTree->sortItems(0, Qt::SortOrder::AscendingOrder);
49 widget.objectsTree->setContextMenuPolicy(Qt::CustomContextMenu);
51 widget.requestTree->clear();
52 widget.requestTree->sortItems(0, Qt::SortOrder::AscendingOrder);
57 connect(widget.updateButton, &QPushButton::pressed,
this, &This::updateTab);
58 connect(widget.tabWidget, &QTabWidget::currentChanged,
this, &This::updateTab);
60 connect(widget.objectsTree, &QTreeWidget::customContextMenuRequested,
61 this, &This::prepareObjectContextMenu);
63 connect(widget.requestButton, &QPushButton::pressed,
this, &This::requestSelectedObjects);
65 QTimer* timer =
new QTimer(
this);
66 timer->setInterval(500);
67 connect(timer, &QTimer::timeout,
this, &This::updateTab);
68 connect(widget.autoUpdateCheckBox, &QCheckBox::toggled,
this, [timer](
bool checked)
82 ObjectPoseGuiWidgetController::~ObjectPoseGuiWidgetController()
87 void ObjectPoseGuiWidgetController::loadSettings(QSettings* settings)
92 void ObjectPoseGuiWidgetController::saveSettings(QSettings* settings)
97 QString ObjectPoseGuiWidgetController::GetWidgetName()
99 return "MemoryX.ObjectPoseGui";
102 static const std::string CONFIG_KEY_OBJECT_POSE_OBSERVER =
"ObjectPoseStorage";
104 QPointer<QDialog> ObjectPoseGuiWidgetController::getConfigDialog(QWidget* parent)
109 configDialog->addProxyFinder<armarx::objpose::ObjectPoseStorageInterfacePrx>({CONFIG_KEY_OBJECT_POSE_OBSERVER,
"Object pose observer.",
"*"});
111 return qobject_cast<QDialog*>(configDialog);
114 void ObjectPoseGuiWidgetController::configured()
118 ObjectPoseStorageName = configDialog->getProxyName(CONFIG_KEY_OBJECT_POSE_OBSERVER);
122 void ObjectPoseGuiWidgetController::onInitComponent()
124 if (!ObjectPoseStorageName.empty())
126 usingProxy(ObjectPoseStorageName);
130 void ObjectPoseGuiWidgetController::onConnectComponent()
132 if (!ObjectPoseStorageName.empty())
134 getProxy(ObjectPoseStorage, ObjectPoseStorageName);
137 this->attachableFrames = ObjectPoseStorage->getAttachableFrames();
138 std::sort(attachableFrames.begin(), attachableFrames.end(), [](
const auto & lhs,
const auto & rhs)
140 return lhs.agent < rhs.agent;
142 for (objpose::AgentFrames& frames : attachableFrames)
144 std::sort(frames.frames.begin(), frames.frames.end());
148 void ObjectPoseGuiWidgetController::onDisconnectComponent()
150 ObjectPoseStorage =
nullptr;
153 void ObjectPoseGuiWidgetController::updateTab()
155 if (widget.tabWidget->currentWidget() == widget.tabObjects)
159 else if (widget.tabWidget->currentWidget() == widget.tabRequest)
167 void ObjectPoseGuiWidgetController::updateObjectsTab()
169 if (!ObjectPoseStorage)
179 ARMARX_VERBOSE <<
"Got " << objectPosesIce.size() <<
" object poses. "
180 <<
"(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() <<
" ms.)";
184 std::map<std::string, objpose::ObjectPoseSeq> objectPosesByProvider;
185 for (
const auto& pose : objectPoses)
187 objectPosesByProvider[pose.providerName].push_back(pose);
190 start = IceUtil::Time::now();
192 QTreeWidget* tree = widget.objectsTree;
197 QTreeWidgetItem* item =
new QTreeWidgetItem({QString::fromStdString(provider)});
202 bool expand = item->childCount() == 0;
211 QTreeWidgetItem* item =
new QTreeWidgetItem(QStringList{});
217 item->setText(col++, QString::fromStdString(pose.
objectID.
str()));
218 item->setText(col++, QString::fromStdString(pose.
providerName));
222 std::stringstream ss;
225 static const Eigen::IOFormat iof(5, 0,
"",
" x ",
"",
"",
"",
"");
226 ss << pose.
localOOBB->dimensions().format(iof);
232 item->setText(col++, QString::fromStdString(ss.str()));
234 item->setText(col++, QString::number(
double(pose.
confidence),
'g', 2));
238 std::stringstream ss;
243 item->setText(col++, QString::fromStdString(ss.str()));
252 item->setExpanded(
true);
257 builder.
updateTree(tree, objectPosesByProvider);
259 ARMARX_VERBOSE <<
"Gui update took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() <<
" ms.";
263 void ObjectPoseGuiWidgetController::updateRequestTab()
265 if (!ObjectPoseStorage)
273 objpose::ProviderInfoMap availableProvidersInfo = ObjectPoseStorage->getAvailableProvidersInfo();
274 ARMARX_VERBOSE <<
"Got infos of " << availableProvidersInfo.size() <<
" object pose providers. "
275 <<
"(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() <<
" ms.)";
279 std::map<std::string, std::set<std::pair<std::string, std::string>>> data;
280 for (
const auto& [providerName, info] : availableProvidersInfo)
282 for (
const auto&
id : info.supportedObjects)
284 data[
id.dataset].insert(std::make_pair(
id.className, providerName));
288 start = IceUtil::Time::now();
290 QTreeWidget* tree = widget.requestTree;
293 builder.
setMakeItemFn([](
const std::string & dataset,
const auto&)
295 QTreeWidgetItem* item =
new QTreeWidgetItem({QString::fromStdString(dataset)});
298 builder.
setUpdateItemFn([tree](
const std::string & dataset,
const auto & datasetData, QTreeWidgetItem * datasetItem)
303 builder.
setCompareFn([](
const std::pair<std::string, std::string>& lhs, QTreeWidgetItem * item)
305 auto rhs = std::make_pair(item->text(0).toStdString(), item->text(1).toStdString());
310 return lhs == rhs ? 0 : 1;
312 builder.
setMakeItemFn([](
const std::pair<std::string, std::string>& element)
314 QTreeWidgetItem* item =
new QTreeWidgetItem({ QString::fromStdString(element.first), QString::fromStdString(element.second)});
317 builder.
setUpdateItemFn([tree](
const std::pair<std::string, std::string>& element, QTreeWidgetItem * item)
320 if (!tree->itemWidget(item, 2))
322 QCheckBox* requestCheckBox =
new QCheckBox();
323 tree->setItemWidget(item, 2, requestCheckBox);
333 ARMARX_VERBOSE <<
"Gui update took " << (IceUtil::Time::now() - start).toMilliSecondsDouble() <<
" ms.";
336 void ObjectPoseGuiWidgetController::prepareObjectContextMenu(
const QPoint& pos)
338 QTreeWidget* tree = widget.objectsTree;
339 QTreeWidgetItem* item = tree->itemAt(pos);
341 if (item ==
nullptr || item->parent() ==
nullptr)
347 QString providerName = item->parent()->text(0);
348 QString objectID = item->text(0);
350 QMenu* attachMenu =
new QMenu(
"Attach to robot node", tree);
351 for (
const objpose::AgentFrames& agentFrames : attachableFrames)
353 QMenu* agentMenu =
new QMenu(QString::fromStdString(agentFrames.agent), tree);
355 for (
const std::string& frame : agentFrames.frames)
357 QAction* attachAgentAction =
new QAction(QString::fromStdString(frame), tree);
359 connect(attachAgentAction, &QAction::triggered,
362 this->attachObjectToRobotNode(providerName, objectID, agentFrames.agent, frame);
364 agentMenu->addAction(attachAgentAction);
366 attachMenu->addMenu(agentMenu);
369 QAction* detachAction =
new QAction(tr(
"Detach from to robot node"), tree);
370 detachAction->setEnabled(!item->text(OBJECTS_COLUMN_ATTACHMENT).isEmpty());
371 connect(detachAction, &QAction::triggered, [ =,
this ]()
373 this->detachObjectFromRobotNode(providerName, objectID);
377 menu.addMenu(attachMenu);
378 menu.addAction(detachAction);
380 menu.exec(tree->mapToGlobal(pos));
383 void ObjectPoseGuiWidgetController::attachObjectToRobotNode(
384 QString providerName, QString objectID,
385 const std::string& agentName,
const std::string& frameName)
387 ARMARX_VERBOSE <<
"Attaching " << objectID <<
" by '" << providerName <<
"' to robot node '"
388 << frameName <<
"' of agent '" << agentName <<
"'.";
390 objpose::AttachObjectToRobotNodeInput
input;
391 input.providerName = providerName.toStdString();
393 input.agentName = agentName;
394 input.frameName = frameName;
398 objpose::AttachObjectToRobotNodeOutput output = ObjectPoseStorage->attachObjectToRobotNode(
input);
401 catch (
const IceUtil::Exception& e)
404 <<
input.frameName <<
"' of agent '" <<
input.agentName <<
"'."
405 <<
"\nReason: " << e.what();
409 void ObjectPoseGuiWidgetController::detachObjectFromRobotNode(QString providerName, QString objectID)
411 ARMARX_VERBOSE <<
"Detaching " << objectID <<
" by '" << providerName <<
"' from robot node.";
413 objpose::DetachObjectFromRobotNodeInput
input;
414 input.providerName = providerName.toStdString();
419 objpose::DetachObjectFromRobotNodeOutput output = ObjectPoseStorage->detachObjectFromRobotNode(
input);
422 catch (
const IceUtil::Exception& e)
425 <<
"\nReason: " << e.what();
429 void ObjectPoseGuiWidgetController::requestSelectedObjects()
431 std::map<std::string, objpose::observer::RequestObjectsInput> requestsPerProvider;
433 QTreeWidget* tree = widget.requestTree;
434 for (
int i = 0; i < tree->topLevelItemCount(); ++i)
436 QTreeWidgetItem* datasetItem = tree->topLevelItem(i);
437 for (
int j = 0; j < datasetItem->childCount(); ++j)
439 QTreeWidgetItem* classItem = datasetItem->child(j);
440 QCheckBox* selected =
dynamic_cast<QCheckBox*
>(tree->itemWidget(classItem, 2));
442 if (selected->isChecked())
444 std::string providerName = classItem->text(1).toStdString();
445 objpose::observer::RequestObjectsInput& requests = requestsPerProvider[providerName];
447 id.dataset = datasetItem->text(0).toStdString();
448 id.className = classItem->text(0).toStdString();
454 if (!widget.requestInfiniteCheckBox->isChecked())
456 timeoutMS = long(widget.requestTimeoutSpinBox->value() * 1000);
459 for (
auto& [providerName, request] : requestsPerProvider)
461 request.provider = providerName;
462 request.request.relativeTimeoutMS = timeoutMS;
464 ARMARX_INFO <<
"Requesting " << request.request.objectIDs.size() <<
" objects for "
465 << request.request.relativeTimeoutMS <<
" ms.";
466 objpose::observer::RequestObjectsOutput output = ObjectPoseStorage->requestObjects(request);
468 for (
const auto& [
id, result] : output.results)
470 successful += int(!result.providerName.empty() && result.result.success);
472 ARMARX_INFO << successful <<
" of " << request.request.objectIDs.size() <<
" object request successful.";