39 static const int OBJECTS_COLUMN_ATTACHMENT = 6;
45 widget.objectsTree->clear();
46 widget.objectsTree->sortItems(0, Qt::SortOrder::AscendingOrder);
47 widget.objectsTree->setContextMenuPolicy(Qt::CustomContextMenu);
49 widget.requestTree->clear();
50 widget.requestTree->sortItems(0, Qt::SortOrder::AscendingOrder);
55 connect(widget.updateButton, &QPushButton::pressed,
this, &This::updateTab);
56 connect(widget.tabWidget, &QTabWidget::currentChanged,
this, &This::updateTab);
57 connect(widget.detchAllButton,
58 &QPushButton::pressed,
60 this->detachAllObjectsFromRobotNodes(
61 widget.detchAllCommitAttachedCheckBox->isChecked());
64 connect(widget.objectsTree,
65 &QTreeWidget::customContextMenuRequested,
67 &This::prepareObjectContextMenu);
69 connect(widget.requestButton, &QPushButton::pressed,
this, &This::requestSelectedObjects);
71 QTimer* timer =
new QTimer(
this);
72 timer->setInterval(500);
73 connect(timer, &QTimer::timeout,
this, &This::updateTab);
74 connect(widget.autoUpdateCheckBox,
109 return "ArMem.ObjectPoseGui";
112 static const std::string CONFIG_KEY_OBJECT_POSE_STORAGE =
"ObjectPoseStorage";
120 configDialog->addProxyFinder<armarx::objpose::ObjectPoseStorageInterfacePrx>(
121 {CONFIG_KEY_OBJECT_POSE_STORAGE,
"Object pose storage",
"Object*"});
123 return qobject_cast<QDialog*>(configDialog);
131 objectPoseStorageName = configDialog->getProxyName(CONFIG_KEY_OBJECT_POSE_STORAGE);
132 if (objectPoseStorageName.empty())
134 objectPoseStorageName =
"ObjectMemory";
142 if (!objectPoseStorageName.empty())
151 if (!objectPoseStorageName.empty())
153 getProxy(ObjectPoseStorage, objectPoseStorageName);
156 this->attachableFrames = ObjectPoseStorage->getAttachableFrames();
157 std::sort(attachableFrames.begin(),
158 attachableFrames.end(),
159 [](
const auto& lhs,
const auto& rhs) { return lhs.agent < rhs.agent; });
160 for (objpose::AgentFrames& frames : attachableFrames)
162 std::sort(frames.frames.begin(), frames.frames.end());
172 ObjectPoseStorage =
nullptr;
178 if (widget.tabWidget->currentWidget() == widget.tabObjects)
182 else if (widget.tabWidget->currentWidget() == widget.tabRequest)
191 if (!ObjectPoseStorage)
198 IceUtil::Time start = IceUtil::Time::now();
200 const objpose::data::ObjectPoseSeq objectPosesIce = ObjectPoseStorage->getObjectPoses();
201 ARMARX_VERBOSE <<
"Got " << objectPosesIce.size() <<
" object poses. "
202 <<
"(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble()
207 std::map<std::string, objpose::ObjectPoseSeq> objectPosesByProvider;
208 for (
const auto& pose : objectPoses)
210 objectPosesByProvider[pose.providerName].push_back(pose);
213 start = IceUtil::Time::now();
215 QTreeWidget* tree = widget.objectsTree;
221 QTreeWidgetItem* item =
new QTreeWidgetItem({QString::fromStdString(provider)});
227 bool expand = item->childCount() == 0;
235 QTreeWidgetItem* item =
new QTreeWidgetItem(QStringList{});
242 item->setText(col++, QString::fromStdString(pose.
objectID.
str()));
243 item->setText(col++, QString::fromStdString(pose.
providerName));
245 QString::fromStdString(
249 std::stringstream ss;
252 static const Eigen::IOFormat iof(5, 0,
"",
" x ",
"",
"",
"",
"");
253 ss << pose.
localOOBB->dimensions().format(iof);
259 item->setText(col++, QString::fromStdString(ss.str()));
261 item->setText(col++, QString::number(
double(pose.
confidence),
'g', 2));
266 std::stringstream ss;
272 item->setText(col++, QString::fromStdString(ss.str()));
281 item->setExpanded(
true);
286 builder.
updateTree(tree, objectPosesByProvider);
289 << (IceUtil::Time::now() - start).toMilliSecondsDouble() <<
" ms.";
295 if (!ObjectPoseStorage)
302 IceUtil::Time start = IceUtil::Time::now();
303 objpose::ProviderInfoMap availableProvidersInfo =
304 ObjectPoseStorage->getAvailableProvidersInfo();
305 ARMARX_VERBOSE <<
"Got infos of " << availableProvidersInfo.size()
306 <<
" object pose providers. "
307 <<
"(Took " << (IceUtil::Time::now() - start).toMilliSecondsDouble()
312 std::map<std::string, std::set<std::pair<std::string, std::string>>>
data;
313 for (
const auto& [providerName, info] : availableProvidersInfo)
315 for (
const auto&
id : info.supportedObjects)
317 data[
id.dataset].insert(std::make_pair(
id.className, providerName));
321 start = IceUtil::Time::now();
323 QTreeWidget* tree = widget.requestTree;
327 [](
const std::string& dataset,
const auto&)
329 QTreeWidgetItem* item =
new QTreeWidgetItem({QString::fromStdString(dataset)});
334 const std::string& dataset,
const auto& datasetData, QTreeWidgetItem* datasetItem)
340 [](
const std::pair<std::string, std::string>& lhs, QTreeWidgetItem* item)
342 auto rhs = std::make_pair(item->text(0).toStdString(),
343 item->text(1).toStdString());
348 return lhs == rhs ? 0 : 1;
351 [](
const std::pair<std::string, std::string>& element)
353 QTreeWidgetItem* item =
354 new QTreeWidgetItem({QString::fromStdString(element.first),
355 QString::fromStdString(element.second)});
359 [tree](
const std::pair<std::string, std::string>& element,
360 QTreeWidgetItem* item)
363 if (!tree->itemWidget(item, 2))
365 QCheckBox* requestCheckBox =
new QCheckBox();
366 tree->setItemWidget(item, 2, requestCheckBox);
377 << (IceUtil::Time::now() - start).toMilliSecondsDouble() <<
" ms.";
383 QTreeWidget* tree = widget.objectsTree;
384 QTreeWidgetItem* item = tree->itemAt(pos);
386 if (item ==
nullptr || item->parent() ==
nullptr)
392 QString providerName = item->parent()->text(0);
393 QString objectID = item->text(0);
395 QMenu* attachMenu =
new QMenu(
"Attach to robot node", tree);
396 for (
const objpose::AgentFrames& agentFrames : attachableFrames)
398 QMenu* agentMenu =
new QMenu(QString::fromStdString(agentFrames.agent), tree);
400 for (
const std::string& frame : agentFrames.frames)
402 QAction* attachAgentAction =
new QAction(QString::fromStdString(frame), tree);
404 connect(attachAgentAction,
408 providerName, objectID, agentFrames.agent, frame);
410 agentMenu->addAction(attachAgentAction);
412 attachMenu->addMenu(agentMenu);
415 QAction* detachAction =
new QAction(tr(
"Detach from to robot node"), tree);
416 detachAction->setEnabled(!item->text(OBJECTS_COLUMN_ATTACHMENT).isEmpty());
417 connect(detachAction,
422 menu.addMenu(attachMenu);
423 menu.addAction(detachAction);
425 menu.exec(tree->mapToGlobal(pos));
431 const std::string& agentName,
432 const std::string& frameName)
434 ARMARX_VERBOSE <<
"Attaching " << objectID <<
" by '" << providerName <<
"' to robot node '"
435 << frameName <<
"' of agent '" << agentName <<
"'.";
437 objpose::AttachObjectToRobotNodeInput input;
438 input.providerName = providerName.toStdString();
440 input.agentName = agentName;
441 input.frameName = frameName;
445 objpose::AttachObjectToRobotNodeOutput output =
446 ObjectPoseStorage->attachObjectToRobotNode(input);
449 catch (
const IceUtil::Exception& e)
451 ARMARX_WARNING <<
"Failed to attach object '" << input.objectID <<
"' to robot node '"
452 << input.frameName <<
"' of agent '" << input.agentName <<
"'."
453 <<
"\nReason: " << e.what();
460 ARMARX_VERBOSE <<
"Detaching " << objectID <<
" by '" << providerName
461 <<
"' from robot node.";
463 objpose::DetachObjectFromRobotNodeInput input;
464 input.providerName = providerName.toStdString();
469 objpose::DetachObjectFromRobotNodeOutput output =
470 ObjectPoseStorage->detachObjectFromRobotNode(input);
473 catch (
const IceUtil::Exception& e)
476 <<
"' from a robot node."
477 <<
"\nReason: " << e.what();
485 objpose::DetachAllObjectsFromRobotNodesInput input;
486 input.commitAttachedPose = commitAttachedPose;
490 objpose::DetachAllObjectsFromRobotNodesOutput output =
491 ObjectPoseStorage->detachAllObjectsFromRobotNodes(input);
492 ARMARX_VERBOSE <<
"Detached " << output.numDetached <<
" objects from robot nodes.";
494 catch (
const IceUtil::Exception& e)
496 ARMARX_WARNING <<
"Failed to detach all objects from robot nodes.";
503 std::map<std::string, objpose::observer::RequestObjectsInput> requestsPerProvider;
505 QTreeWidget* tree = widget.requestTree;
506 for (
int i = 0; i < tree->topLevelItemCount(); ++i)
508 QTreeWidgetItem* datasetItem = tree->topLevelItem(i);
509 for (
int j = 0; j < datasetItem->childCount(); ++j)
511 QTreeWidgetItem* classItem = datasetItem->child(j);
512 QCheckBox* selected =
dynamic_cast<QCheckBox*
>(tree->itemWidget(classItem, 2));
514 if (selected->isChecked())
516 std::string providerName = classItem->text(1).toStdString();
517 objpose::observer::RequestObjectsInput& requests =
518 requestsPerProvider[providerName];
519 data::ObjectID&
id = requests.request.objectIDs.emplace_back();
520 id.dataset = datasetItem->text(0).toStdString();
521 id.className = classItem->text(0).toStdString();
527 if (!widget.requestInfiniteCheckBox->isChecked())
529 timeoutMS = long(widget.requestTimeoutSpinBox->value() * 1000);
532 for (
auto& [providerName, request] : requestsPerProvider)
534 request.provider = providerName;
535 request.request.relativeTimeoutMS = timeoutMS;
537 ARMARX_INFO <<
"Requesting " << request.request.objectIDs.size() <<
" objects for "
538 << request.request.relativeTimeoutMS <<
" ms.";
539 objpose::observer::RequestObjectsOutput output =
540 ObjectPoseStorage->requestObjects(request);
542 for (
const auto& [
id, result] : output.results)
544 successful += int(!result.providerName.empty() && result.result.success);
546 ARMARX_INFO << successful <<
" of " << request.request.objectIDs.size()
547 <<
" object request successful.";
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
A known object ID of the form "Dataset/ClassName" or "Dataset/ClassName/InstanceName".
std::string str() const
Return "dataset/className" or "dataset/className/instanceName".
A config-dialog containing one (or multiple) proxy finders.
std::string toDateTimeString() const
#define ARMARX_CHECK_NOT_NULL(ptr)
This macro evaluates whether ptr is not null and if it turns out to be false it will throw an Express...
#define ARMARX_INFO
The normal logging level.
#define ARMARX_WARNING
The logging level for unexpected behaviour, but not a serious problem.
#define ARMARX_VERBOSE
The logging level for verbose information.
std::vector< ObjectPose > ObjectPoseSeq
void fromIce(const Box &box, simox::OrientedBox< float > &oobb)
const simox::meta::EnumNames< objpose::ObjectType > ObjectTypeNames
This file offers overloads of toIce() and fromIce() functions for STL container types.
void toIce(std::map< IceKeyT, IceValueT > &iceMap, const boost::container::flat_map< CppKeyT, CppValueT > &cppMap)
An object pose as stored by the ObjectPoseStorage.
float confidence
Confidence in [0, 1] (1 = full, 0 = none).
armarx::ObjectID objectID
The object ID, i.e. dataset, class name and instance name.
std::optional< ObjectAttachmentInfo > attachment
Attachment information.
std::string providerName
Name of the providing component.
DateTime timestamp
Source timestamp.
ObjectType objectType
Known or unknown object.
std::optional< simox::OrientedBoxf > localOOBB
Object bounding box in object's local coordinate frame.