25#include <RobotAPI/gui-plugins/RobotUnitPlugin/ui_RobotUnitPluginWidget.h>
33#include <QSortFilterProxyModel>
47 widget = std::make_unique<Ui::RobotUnitPluginWidget>();
53 widget->groupBoxCDev->layout()->addWidget(controlDevices);
55 controlDevices->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
56 controlDevices->setVisible(
false);
61 widget->groupBoxSDev->layout()->addWidget(sensorDevices);
63 sensorDevices->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
64 sensorDevices->setVisible(
false);
69 widget->groupBoxNJointCtrl->layout()->addWidget(nJointControllers);
71 nJointControllers->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Expanding);
72 nJointControllers->setVisible(
true);
77 widget->groupBoxNJointCtrlClasses->layout()->addWidget(nJointControllerClasses);
78 widget->groupBoxNJointCtrlClasses->
setVisible(
false);
79 nJointControllerClasses->setSizePolicy(QSizePolicy::MinimumExpanding,
80 QSizePolicy::Expanding);
81 nJointControllerClasses->setVisible(
false);
85 widget->groupBoxLogging->setVisible(
false);
86 widget->groupBoxLogging->setSizePolicy(QSizePolicy::MinimumExpanding,
87 QSizePolicy::Expanding);
89 connect(widget->pushButtonLoggingStart,
92 SLOT(on_pushButtonLoggingStart_clicked()));
93 connect(widget->pushButtonLoggingStop,
96 SLOT(on_pushButtonLoggingStop_clicked()));
97 connect(widget->pushButtonLoggingMark1,
100 SLOT(on_pushButtonLoggingMark1_clicked()));
101 connect(widget->pushButtonLoggingMark2,
104 SLOT(on_pushButtonLoggingMark2_clicked()));
105 connect(widget->pushButtonLoggingMark3,
108 SLOT(on_pushButtonLoggingMark3_clicked()));
109 connect(widget->lineEditLoggingFilter,
110 SIGNAL(textChanged(
const QString&)),
112 SLOT(on_lineEditLoggingFilter_textChanged(
const QString&)));
113 connect(widget->treeWidgetLoggingNames,
114 SIGNAL(itemChanged(QTreeWidgetItem*,
int)),
116 SLOT(on_treeWidgetLoggingNames_itemChanged(QTreeWidgetItem*,
int)));
118 updateToolBarActionCheckedState();
125 settings->value(
"robotUnitProxyName", QString::fromStdString(robotUnitProxyName))
128 nJointControllerClasses->loadSettings(settings);
129 nJointControllers->loadSettings(settings);
130 controlDevices->loadSettings(settings);
131 sensorDevices->loadSettings(settings);
132 widget->groupBoxCDev->setVisible(settings->value(
"cdevVisible",
false).toBool());
133 widget->groupBoxSDev->setVisible(settings->value(
"sdevVisible",
false).toBool());
134 widget->groupBoxNJointCtrl->setVisible(settings->value(
"ctrlVisible",
true).toBool());
135 widget->groupBoxNJointCtrlClasses->setVisible(settings->value(
"classVisible",
false).toBool());
136 updateToolBarActionCheckedState();
142 settings->setValue(
"robotUnitProxyName", QString::fromStdString(robotUnitProxyName));
143 nJointControllerClasses->saveSettings(settings);
144 nJointControllers->saveSettings(settings);
145 controlDevices->saveSettings(settings);
146 sensorDevices->saveSettings(settings);
147 settings->setValue(
"cdevVisible", widget->groupBoxCDev->isVisible());
148 settings->setValue(
"sdevVisible", widget->groupBoxSDev->isVisible());
149 settings->setValue(
"ctrlVisible", widget->groupBoxNJointCtrl->isVisible());
150 settings->setValue(
"classVisible", widget->groupBoxNJointCtrlClasses->isVisible());
157 ARMARX_INFO <<
"RobotUnitPluginWidgetController::onInitComponent()" << std::flush;
158 QMetaObject::invokeMethod(
this,
"startOnConnectTimer", Qt::QueuedConnection);
164 QMetaObject::invokeMethod(
this,
"stopOnConnectTimer", Qt::QueuedConnection);
170 std::lock_guard guard{robotUnitPrxMutex};
172 listenerTopicName = robotUnitPrx->getRobotUnitListenerTopicName();
174 updateToolBarActionCheckedState();
175 timerLastIterationRuWasRunning =
false;
181 std::lock_guard guard{robotUnitPrxMutex};
183 robotUnitPrx =
nullptr;
184 QMetaObject::invokeMethod(
this,
"refreshNJointControllersClicked", Qt::QueuedConnection);
185 QMetaObject::invokeMethod(
this,
"refreshNJointControllerClassesClicked", Qt::QueuedConnection);
186 QMetaObject::invokeMethod(
this,
"refreshControlDevicesClicked", Qt::QueuedConnection);
187 QMetaObject::invokeMethod(
this,
"refreshSensorDevicesClicked", Qt::QueuedConnection);
198 return qobject_cast<SimpleConfigDialog*>(dialog);
204 robotUnitProxyName = dialog->getProxyName(
"RobotUnit");
212 customToolbar->setParent(parent);
216 customToolbar =
new QToolBar(parent);
217 customToolbar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
218 customToolbar->setIconSize(QSize(16, 16));
221 QIcon(
":/icons/view-refresh-7.png"),
"",
this, SLOT(refreshControlDevicesClicked()))
222 ->setToolTip(
"Update the list of Control Devices");
223 showCDevs =
new QAction{
"Control Devices", customToolbar};
224 showCDevs->setCheckable(
true);
225 showCDevs->setToolTip(
"Hide/Show the list of Control Devices");
226 connect(showCDevs, SIGNAL(toggled(
bool)), widget->groupBoxCDev, SLOT(setVisible(
bool)));
227 connect(showCDevs, SIGNAL(toggled(
bool)), controlDevices, SLOT(setVisible(
bool)));
228 customToolbar->addAction(showCDevs);
229 customToolbar->addSeparator();
233 QIcon(
":/icons/view-refresh-7.png"),
"",
this, SLOT(refreshSensorDevicesClicked()))
234 ->setToolTip(
"Update the list of Sensor Devices");
235 showSDevs =
new QAction{
"Sensor Devices", customToolbar};
236 showSDevs->setCheckable(
true);
237 showSDevs->setToolTip(
"Hide/Show the list of Sensor Devices");
238 connect(showSDevs, SIGNAL(toggled(
bool)), widget->groupBoxSDev, SLOT(setVisible(
bool)));
239 connect(showSDevs, SIGNAL(toggled(
bool)), sensorDevices, SLOT(setVisible(
bool)));
240 customToolbar->addAction(showSDevs);
241 customToolbar->addSeparator();
244 ->addAction(QIcon(
":/icons/view-refresh-7.png"),
247 SLOT(refreshNJointControllersClicked()))
248 ->setToolTip(
"Update the list of NJointControllers");
249 showNJoint =
new QAction{
"NJointControllers", customToolbar};
250 showNJoint->setCheckable(
true);
251 showNJoint->setToolTip(
"Hide/Show the list of NJointControllers");
253 showNJoint, SIGNAL(toggled(
bool)), widget->groupBoxNJointCtrl, SLOT(setVisible(
bool)));
254 connect(showNJoint, SIGNAL(toggled(
bool)), nJointControllers, SLOT(setVisible(
bool)));
255 customToolbar->addAction(showNJoint);
256 customToolbar->addSeparator();
259 ->addAction(QIcon(
":/icons/view-refresh-7.png"),
262 SLOT(refreshNJointControllerClassesClicked()))
263 ->setToolTip(
"Update the list of NJointController Classes");
264 showNJointClasses =
new QAction{
"NJointController Classes", customToolbar};
265 showNJointClasses->setCheckable(
true);
266 showNJointClasses->setToolTip(
"Hide/Show the list of NJointControllers Classes");
267 connect(showNJointClasses,
268 SIGNAL(toggled(
bool)),
269 widget->groupBoxNJointCtrlClasses,
270 SLOT(setVisible(
bool)));
271 connect(showNJointClasses,
272 SIGNAL(toggled(
bool)),
273 nJointControllerClasses,
274 SLOT(setVisible(
bool)));
275 customToolbar->addAction(showNJointClasses);
276 customToolbar->addSeparator();
278 customToolbar->addAction(
279 QIcon(
":/icons/view-refresh-7.png"),
"",
this, SLOT(refreshLogging()));
280 showLogging =
new QAction{
"Logging", customToolbar};
281 showLogging->setCheckable(
true);
282 showLogging->setToolTip(
"Hide/Show the logging pane");
283 connect(showLogging, SIGNAL(toggled(
bool)), widget->groupBoxLogging, SLOT(setVisible(
bool)));
284 customToolbar->addAction(showLogging);
285 customToolbar->addSeparator();
288 ->addAction(QIcon(
":/icons/document-save.svg"),
292 std::lock_guard guard{robotUnitPrxMutex};
293 robotUnitPrx->writeRecentIterationsToFile(
294 "/tmp/RobotUnitLog-{DateTime}");
296 ->setToolTip(
"Writes the log to /tmp/");
298 updateToolBarActionCheckedState();
299 return customToolbar.data();
304 const NJointControllerStatusSeq&
status,
307 nJointControllers->nJointControllerStatusChanged(
status);
314 controlDevices->controlDeviceStatusChanged(
status);
321 sensorDevices->sensorDeviceStatusChanged(
status);
328 nJointControllerClasses->nJointControllerClassAdded(name);
335 nJointControllers->nJointControllerCreated(name);
342 nJointControllers->nJointControllerDeleted(name);
346RobotUnitPluginWidgetController::refreshNJointControllersClicked()
348 std::lock_guard guard{robotUnitPrxMutex};
349 nJointControllers->
reset(robotUnitPrx);
353RobotUnitPluginWidgetController::refreshNJointControllerClassesClicked()
355 std::lock_guard guard{robotUnitPrxMutex};
356 nJointControllerClasses->reset(robotUnitPrx);
360RobotUnitPluginWidgetController::refreshControlDevicesClicked()
362 std::lock_guard guard{robotUnitPrxMutex};
363 controlDevices->reset(robotUnitPrx);
367RobotUnitPluginWidgetController::refreshSensorDevicesClicked()
369 std::lock_guard guard{robotUnitPrxMutex};
370 sensorDevices->reset(robotUnitPrx);
374RobotUnitPluginWidgetController::startOnConnectTimer()
378 timerId = startTimer(100);
383RobotUnitPluginWidgetController::stopOnConnectTimer()
393RobotUnitPluginWidgetController::updateToolBarActionCheckedState()
397 showCDevs->setChecked(widget->groupBoxCDev->isVisible());
398 showSDevs->setChecked(widget->groupBoxSDev->isVisible());
399 showNJoint->setChecked(widget->groupBoxNJointCtrl->isVisible());
400 showNJointClasses->setChecked(widget->groupBoxNJointCtrlClasses->isVisible());
405armarx::RobotUnitPluginWidgetController::timerEvent(QTimerEvent*)
407 std::lock_guard guard{robotUnitPrxMutex};
408 if (robotUnitPrx && robotUnitPrx->isRunning())
411 if (!timerLastIterationRuWasRunning)
413 refreshNJointControllersClicked();
414 refreshNJointControllerClassesClicked();
415 refreshControlDevicesClicked();
416 refreshSensorDevicesClicked();
421 loggingData.localLogging();
423 timerLastIterationRuWasRunning =
true;
427 timerLastIterationRuWasRunning =
false;
433armarx::RobotUnitPluginWidgetController::refreshLogging()
435 std::lock_guard guard{robotUnitPrxMutex};
436 on_pushButtonLoggingStop_clicked();
438 widget->treeWidgetLoggingNames->clear();
439 loggingData.allItems.clear();
441 const auto allLoggingNames = robotUnitPrx->getLoggingNames();
443 std::map<std::string, QTreeWidgetItem*> separators;
444 auto add = [&](
const std::string& name,
const std::string& display,
auto parent)
446 QTreeWidgetItem* i =
new QTreeWidgetItem(parent);
447 i->setText(0, QString::fromStdString(display) +
"*");
448 i->setData(0, Qt::ToolTipRole, QString::fromStdString(name));
449 separators[name] = i;
450 loggingData.allItems.emplace_back(i);
451 i->setCheckState(0, Qt::Unchecked);
453 add(
"",
"", widget->treeWidgetLoggingNames);
454 loggingData.top = loggingData.allItems.front();
456 for (
const auto& name : allLoggingNames)
458 const auto parts =
Split(name,
".",
true,
true);
459 std::string reassembled;
460 for (
const auto& p : parts)
463 auto parent = separators.at(reassembled);
464 reassembled += (reassembled.empty() ? p :
"." + p);
465 if (!separators.count(reassembled))
467 add(reassembled, p, parent);
470 loggingData.allItems.back()->setText(0, QString::fromStdString(parts.back()));
475armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingStart_clicked()
477 std::lock_guard guard{robotUnitPrxMutex};
478 if (!robotUnitPrx || loggingData.handle || loggingData.streamingHandler)
482 std::vector<std::string> loggingNames;
483 std::function<void(QTreeWidgetItem*)> recurseChildren = [&](
auto it)
485 switch (it->checkState(0))
488 if (it->childCount() == 0)
490 loggingNames.emplace_back(
491 it->data(0, Qt::ToolTipRole).toString().toStdString());
495 for (
int i = 0; i < it->childCount(); ++i)
497 recurseChildren(it->child(i));
503 case Qt::PartiallyChecked:
504 for (
int i = 0; i < it->childCount(); ++i)
506 recurseChildren(it->child(i));
511 recurseChildren(loggingData.top);
512 const std::string saveFormatString = widget->lineEditLoggingPath->text().toStdString();
513 if (widget->checkBoxLoggingStream->isChecked())
516 RobotUnitDataStreaming::Config cfg;
517 cfg.loggingNames = loggingNames;
518 loggingData.streamingHandler =
522 loggingData.logStream.open(pb.getPath());
523 loggingData.logStream <<
";iteration;timestamp;TimeSinceLastIteration";
524 const auto&
entries = loggingData.streamingHandler->getDataDescription().entries;
525 std::stringstream
str;
526 str <<
"stream " <<
entries.size() <<
" values\n";
527 for (
const auto& [name, desc] : entries)
529 loggingData.logStream <<
';' << name;
530 str <<
" " << name <<
" -> type " << desc.type <<
", index " << desc.index <<
'\n';
532 loggingData.logStream << std::endl;
538 loggingData.handle = robotUnitPrx->startRtLogging(saveFormatString, loggingNames);
539 widget->pushButtonLoggingMark1->setEnabled(
true);
540 widget->pushButtonLoggingMark2->setEnabled(
true);
541 widget->pushButtonLoggingMark3->setEnabled(
true);
543 widget->pushButtonLoggingStart->setEnabled(
false);
544 widget->pushButtonLoggingStop->setEnabled(
true);
548armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingStop_clicked()
550 std::lock_guard guard{robotUnitPrxMutex};
551 widget->pushButtonLoggingStart->setEnabled(
true);
552 widget->pushButtonLoggingStop->setEnabled(
false);
553 widget->pushButtonLoggingMark1->setEnabled(
false);
554 widget->pushButtonLoggingMark2->setEnabled(
false);
555 widget->pushButtonLoggingMark3->setEnabled(
false);
556 if (loggingData.handle)
558 robotUnitPrx->stopRtLogging(loggingData.handle);
560 if (loggingData.logStream.is_open())
562 loggingData.logStream.close();
564 loggingData.handle =
nullptr;
565 loggingData.streamingHandler =
nullptr;
569armarx::RobotUnitPluginWidgetController::on_lineEditLoggingFilter_textChanged(
const QString& arg1)
574 reg = std::regex{arg1.toStdString()};
579 widget->lineEditLoggingFilter->setStyleSheet(
580 "QLineEdit { background: rgb(255, 150, 150); selection-background-color: rgb(255, 0, "
584 widget->lineEditLoggingFilter->setStyleSheet(
"QLineEdit {}");
586 std::function<void(QTreeWidgetItem * item)> setVisible = [&](
auto it)
588 it->setHidden(
false);
589 auto parent = it->parent();
597 for (
auto item : loggingData.allItems)
599 item->setHidden(
true);
601 for (
auto item : loggingData.allItems)
603 const auto str = item->data(0, Qt::ToolTipRole).toString().toStdString();
605 if (std::regex_search(
str, match, reg))
610 widget->treeWidgetLoggingNames->blockSignals(
true);
612 for (
auto iter = loggingData.allItems.rbegin(); iter != loggingData.allItems.rend(); ++iter)
614 QTreeWidgetItem* item = *iter;
615 loggingData.updateCheckStateUpward(item,
false);
617 widget->treeWidgetLoggingNames->blockSignals(
false);
621armarx::RobotUnitPluginWidgetController::on_treeWidgetLoggingNames_itemChanged(
622 QTreeWidgetItem* item,
625 widget->treeWidgetLoggingNames->blockSignals(
true);
626 loggingData.updateCheckStateDownward(item, item->checkState(0),
true);
627 loggingData.updateCheckStateUpward(item->parent(),
true);
628 widget->treeWidgetLoggingNames->blockSignals(
false);
632armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingMark1_clicked()
634 if (!loggingData.handle)
638 const auto mark = widget->lineEditLoggingMark1->text().toStdString();
640 robotUnitPrx->addMarkerToRtLog(loggingData.handle, mark);
644armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingMark2_clicked()
646 if (!loggingData.handle)
650 const auto mark = widget->lineEditLoggingMark2->text().toStdString();
652 robotUnitPrx->addMarkerToRtLog(loggingData.handle, mark);
656armarx::RobotUnitPluginWidgetController::on_pushButtonLoggingMark3_clicked()
658 if (!loggingData.handle)
662 const auto mark = widget->lineEditLoggingMark3->text().toStdString();
664 robotUnitPrx->addMarkerToRtLog(loggingData.handle, mark);
668RobotUnitPluginWidgetController::LoggingData::updateCheckStateUpward(QTreeWidgetItem* item,
672 for (; item; item = recurseParents ? item->parent() :
nullptr)
674 if (item->isHidden())
678 bool anyChecked =
false;
679 bool anyUnchecked =
false;
681 for (
int i = 0; i < item->childCount(); ++i)
683 auto c = item->child(i);
688 switch (
c->checkState(0))
696 case Qt::PartiallyChecked:
700 if (anyChecked + anyUnchecked + anyTri > 1 || anyTri)
702 item->setCheckState(0, Qt::PartiallyChecked);
706 item->setCheckState(0, Qt::Checked);
708 else if (anyUnchecked)
710 item->setCheckState(0, Qt::Unchecked);
718RobotUnitPluginWidgetController::LoggingData::updateCheckStateDownward(QTreeWidgetItem* item,
719 Qt::CheckState state,
720 bool recurseChildren)
722 if (item->isHidden())
726 item->setCheckState(0, state);
728 if (!recurseChildren)
732 for (
int i = 0; i < item->childCount(); ++i)
734 auto c = item->child(i);
739 c->setCheckState(0, state);
740 updateCheckStateDownward(
c, state,
true);
745RobotUnitPluginWidgetController::LoggingData::localLogging()
747 if (!streamingHandler)
753 auto&
data = streamingHandler->getDataBuffer();
760 const auto& descr = streamingHandler->getDataDescription();
761 for (
const auto& step : data)
763 for (
const auto& [name, desc] : descr.entries)
765 logStream <<
';' << step.iterationId <<
';' << step.timestampUSec <<
';'
766 << step.timesSinceLastIterationUSec;
767 using enum_t = RobotUnitDataStreaming::DataEntryType;
770 case enum_t::NodeTypeBool:
771 logStream <<
';' << step.bools.at(desc.index);
773 case enum_t::NodeTypeByte:
774 logStream <<
';' << step.bytes.at(desc.index);
776 case enum_t::NodeTypeShort:
777 logStream <<
';' << step.shorts.at(desc.index);
779 case enum_t::NodeTypeInt:
780 logStream <<
';' << step.ints.at(desc.index);
782 case enum_t::NodeTypeLong:
783 logStream <<
';' << step.longs.at(desc.index);
785 case enum_t::NodeTypeFloat:
786 logStream <<
';' << step.floats.at(desc.index);
788 case enum_t::NodeTypeDouble:
789 logStream <<
';' << step.doubles.at(desc.index);
793 logStream << std::endl;
SpamFilterDataPtr deactivateSpam(SpamFilterDataPtr const &spamFilter, float deactivationDurationSec, const std::string &identifier, bool deactivate)
bool unsubscribeFromTopic(const std::string &name)
Unsubscribe from a topic.
bool usingProxy(const std::string &name, const std::string &endpoints="")
Registers a proxy for retrieval after initialization and adds it to the dependency list.
void usingTopic(const std::string &name, bool orderedPublishing=false)
Registers a proxy for subscription after initialization.
Ice::ObjectPrx getProxy(long timeoutMs=0, bool waitForScheduler=true) const
Returns the proxy of this object (optionally it waits for the proxy)
A config-dialog containing one (or multiple) proxy finders.
#define ARMARX_CHECK_EXPRESSION(expression)
This macro evaluates the expression and if it turns out to be false it will throw an ExpressionExcept...
#define ARMARX_DEBUG_S
The logging level for output that is only interesting while debugging.
#define ARMARX_INFO
The normal logging level.
#define ARMARX_DEBUG
The logging level for output that is only interesting while debugging.
This file offers overloads of toIce() and fromIce() functions for STL container types.
::IceInternal::ProxyHandle<::IceProxy::armarx::RobotUnitInterface > RobotUnitInterfacePrx
auto make_shared(Args &&... args)
std::vector< std::string > Split(const std::string &source, const std::string &splitBy, bool trimElements=false, bool removeEmptyElements=false)
constexpr auto entries(std::index_sequence< I... >) noexcept
Helps to build a path via format strings: All format strings are of the form '{[^{}...