StatechartViewerController.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of ArmarX.
3  *
4  * Copyright (C) 2011-2016, High Performance Humanoid Technologies (H2T), Karlsruhe Institute of Technology (KIT), all rights reserved.
5  *
6  * ArmarX is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  * ArmarX is distributed in the hope that it will be useful, but
11  * WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  *
18  * @package
19  * @author
20  * @date
21  * @copyright http://www.gnu.org/licenses/gpl-2.0.txt
22  * GNU General Public License
23  */
24 
26 
27 #include <queue>
28 
29 #include <QMenu>
30 #include <QToolBar>
31 
32 #include <IceUtil/UUID.h>
33 
36 #include <ArmarXCore/interface/statechart/RemoteStateOffererIce.h> //RemoteStateOffererInterfacePrx
40 
43 #include <ArmarXGui/gui-plugins/StatechartViewerPlugin/ui_StatechartViewer.h>
46 
47 #include "model/State.h"
50 #include "view/StatechartView.h"
51 
52 namespace armarx
53 {
54 
56  {
57  setlocale(LC_ALL, "C");
58 
59  ui = new Ui::StatechartViewer();
60  connect(this, SIGNAL(componentConnected()), this, SLOT(connectToIce()));
61 
62  qRegisterMetaType<LockableGraphPtr>("LockableGraphPtr");
63  qRegisterMetaType<MediatorPtr>("MediatorPtr");
64  qRegisterMetaType<size_t>("size_t");
65  qRegisterMetaType<IceStateConverterPtr>("IceStateConverterPtr");
66  qRegisterMetaType<StateIceBasePtr>("StateIceBasePtr");
67 
68  ui->setupUi(getWidget());
70  ui->gridLayout_2->addWidget(proxyFinder, 0, 0, 2, 1);
71  proxyFinder->setSearchMask("*RemoteStateOfferer");
72  follower = new ActiveStateFollower(nullptr, getWidget());
73  connect(ui->btnRefreshStateInstances, SIGNAL(clicked()), this, SLOT(updateStateComboBox()));
74  connect(ui->tabWidget, SIGNAL(currentChanged(int)), this, SLOT(updateStateFollower()));
75  connect(ui->tabWidget, SIGNAL(tabCloseRequested(int)), this, SLOT(removeTab(int)));
76  connect(ui->btnAddViewer, SIGNAL(clicked()), this, SLOT(addNewStateView()));
77  connect(proxyFinder->getProxyNameComboBox(),
78  SIGNAL(currentIndexChanged(QString)),
79  this,
80  SLOT(updateStateComboBox()),
81  Qt::UniqueConnection);
82  }
83 
85  {
86  shutdown = true;
87  std::unique_lock lock(mutex); // wait for network functions to finish
88  }
89 
90  void
92  {
94  this,
96  1000,
97  false,
98  "StatechartViewerRefetch");
99  }
100 
101  void
103  {
104  qRegisterMetaType<statechartmodel::TransitionCPtr>("statechartmodel::TransitionCPtr");
105  qRegisterMetaType<statechartmodel::SignalType>("statechartmodel::SignalType");
106  watcher = new StateWatcher;
107  getArmarXManager()->addObject(watcher, false, "StateWatcher" + IceUtil::generateUUID());
108  updateTask->start();
109  emit componentConnected();
110  proxyFinder->setIceManager(getIceManager());
111  }
112 
113  void
115  {
116 
117  updateTask->stop();
118  getArmarXManager()->removeObjectNonBlocking(watcher->getName());
119  }
120 
121  void
123  {
124  }
125 
126  void
128  {
129  int size = settings->beginReadArray("StatechartViewers");
130  for (int i = 0; i < size; ++i)
131  {
132  settings->setArrayIndex(i);
133  QString proxyName = settings->value("proxyName").toString();
134  QString globalStateName = settings->value("globalStateName").toString();
135  delayedConverterAdding.push_back(qMakePair(proxyName, globalStateName));
136  }
137  settings->endArray();
138  }
139 
140  void
142  {
143  settings->beginWriteArray("StatechartViewers");
144  int i = 0;
145  for (RemoteStateData& data : converters)
146  {
147  settings->setArrayIndex(i);
148  settings->setValue("globalStateName", data.globalStateName);
149  settings->setValue("proxyName", data.proxyName);
150  i++;
151  }
152  settings->endArray();
153  }
154 
155  void
156  StatechartViewerController::connectToIce()
157  {
158  for (QPair<QString, QString>& pair : delayedConverterAdding)
159  {
160  addNewStateView(pair.first, pair.second);
161  }
162  if (!ui->tabWidget->currentStateview())
163  {
164  addNewStateView("RobotControlStateOfferer", "RobotStatechart->RobotControl");
165  }
166 
167  ui->tabWidget->currentStateview()->viewAll();
168  }
169 
170  void
171  StatechartViewerController::updateStatechartView(StateIceBasePtr stateptr,
172  IceStateConverterPtr converter)
173  {
174  std::unique_lock lock(mutex);
175  auto start = IceUtil::Time::now();
176  converter->convert(stateptr);
177  ARMARX_DEBUG << deactivateSpam(3) << "converting instance took : "
178  << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms";
179  }
180 
181  void
183  {
184  if (shutdown)
185  {
186  return;
187  }
188  QMap<QPointer<StatechartView>, RemoteStateData> tempConverters;
189  {
190  std::unique_lock lock(mutex);
191  tempConverters = converters;
192  }
193  for (RemoteStateData& stateData : tempConverters)
194  {
195  RemoteStateOffererInterfacePrx statechartHandler;
196  try
197  {
198  statechartHandler = getProxy<RemoteStateOffererInterfacePrx>(
199  stateData.proxyName.toStdString(), false, "", false);
200  if (!statechartHandler)
201  {
202  continue;
203  }
204  auto start = IceUtil::Time::now();
205 
206 
207  start = IceUtil::Time::now();
208 
209  auto asyncResult = statechartHandler->begin_getStatechartInstanceByGlobalIdStr(
210  stateData.globalStateName.toStdString());
211  while (!asyncResult->isCompleted())
212  {
213  if (shutdown)
214  {
215  return;
216  }
217  usleep(100);
218  // qApp->processEvents();
219  }
220  armarx::StateIceBasePtr stateptr =
221  statechartHandler->end_getStatechartInstanceByGlobalIdStr(asyncResult);
222  if (!stateptr)
223  {
224  ARMARX_WARNING_S << "Could not find state with name "
225  << stateData.globalStateName.toStdString();
226  continue;
227  }
228  // armarx::StateIceBasePtr stateptr = m_statechartHandler->getStatechartInstance(stateMap.begin()->first);
230  << " took : " << (IceUtil::Time::now() - start).toMilliSecondsDouble()
231  << " ms";
232  QMetaObject::invokeMethod(this,
233  "updateStatechartView",
234  Q_ARG(StateIceBasePtr, stateptr),
235  Q_ARG(IceStateConverterPtr, stateData.converter));
236  // stateData.converter.convert(stateptr);
237  }
238  catch (Ice::NotRegisteredException&)
239  {
240  getIceManager()->removeProxyFromCache(statechartHandler);
242  << "No ice ID 'RobotControlStateOfferer' registered";
243  }
244  catch (...)
245  {
247  }
248  }
249  }
250 
251  void
252  StatechartViewerController::displayParameters(
253  statechartmodel::StateInstancePtr selectedStateInstance)
254  {
255  try
256  {
257  QList<QTreeWidgetItem*> items;
258  if (selectedStateInstance && watcher)
259  {
260  auto paramContainerTypes = {
261  "inputParameters", "localParameters", "outputParameters"};
262  ui->paramView->clear();
263 
264 
265  for (auto& type : paramContainerTypes)
266  {
267  QTreeWidgetItem* item = new QTreeWidgetItem();
268  item->setText(0, type);
269  StateParameterMap map;
270  try
271  {
272  map = watcher->getStateParameterMap(selectedStateInstance->getStateClass(),
273  type);
274  }
275  catch (...)
276  {
278  continue;
279  }
280 
281 
282  for (auto& elem : map)
283  {
284  QTreeWidgetItem* subItem = new QTreeWidgetItem();
285  StateParameterIceBasePtr param = elem.second;
286  subItem->setText(0, elem.first.c_str());
287  subItem->setText(1, param->value->output().c_str());
288  item->addChild(subItem);
289  }
290  items.push_back(item);
291  // inputParamsJson->setVariant(type, var);
292  }
293  ui->paramView->addTopLevelItems(items);
294  for (auto& item : items)
295  {
296  ui->paramView->expandItem(item);
297  }
298  }
299  else
300  {
301  ARMARX_INFO << "no state instance!";
302  }
303  if (items.size() == 0)
304  {
305  QTreeWidgetItem* item = new QTreeWidgetItem();
306  item->setText(0, "No data available yet");
307  ui->paramView->addTopLevelItem(item);
308  }
309  }
310  catch (...)
311  {
312  QTreeWidgetItem* item = new QTreeWidgetItem();
313  item->setText(0, "No data available yet");
314  ui->paramView->addTopLevelItem(item);
316  }
317  }
318 
319  void
320  StatechartViewerController::addNewStateView(QString proxyName, QString stateName)
321  {
322  auto view = ui->tabWidget->addEmptyStateTab();
323  if (!view)
324  {
325  return;
326  }
327  connect(view,
328  SIGNAL(selectedStateChanged(statechartmodel::StateInstancePtr)),
329  this,
330  SLOT(displayParameters(statechartmodel::StateInstancePtr)));
331  converters[view].converter.reset(new IceStateConverter());
332  converters[view].converter->setStateWatcher(watcher);
333  view->setState(converters[view].converter->getTopState()->getStateClass());
334  converters[view].proxyName = proxyName;
335  converters[view].globalStateName = stateName;
336  QString instanceName;
337  if (stateName.lastIndexOf("->") >= 0)
338  {
339  instanceName = stateName.right(stateName.size() - stateName.lastIndexOf("->") - 2);
340  }
341  else
342  {
343  instanceName = stateName;
344  }
345  ui->tabWidget->setTabText(ui->tabWidget->currentIndex(), instanceName);
346 
347  view->getLayoutController().enableLayouting();
349  connectToStateTab(ui->tabWidget->currentIndex());
350  }
351 
352  void
353  StatechartViewerController::addNewStateView()
354  {
355  addNewStateView(proxyFinder->getSelectedProxyName(),
356  ui->comboBoxStateInstances->currentText());
357  }
358 
359  void
360  StatechartViewerController::followActiveState()
361  {
362  auto view = ui->tabWidget->currentStateview();
363  if (!view)
364  {
365  return;
366  }
367  follower->setStatechartView(view);
368  }
369 
370  void
371  StatechartViewerController::updateStateComboBox()
372  {
373  if (proxyFinder->getSelectedProxyName().isEmpty())
374  {
375  return;
376  }
377  if (getState() < eManagedIceObjectStarting)
378  {
379  return;
380  }
381  auto proxy = getProxy<RemoteStateOffererInterfacePrx>(
382  proxyFinder->getSelectedProxyName().toStdString(), false, "", false);
383 
384  ui->comboBoxStateInstances->clear();
385  if (proxy)
386  {
387  QStringList stateInstances;
388  for (auto& elem : proxy->getAvailableStateInstances())
389  {
390  stateInstances << (elem.second.c_str());
391  }
392  stateInstances.removeDuplicates();
393  ui->comboBoxStateInstances->addItems(stateInstances);
394  }
395  ui->btnAddViewer->setEnabled(ui->comboBoxStateInstances->count() > 0);
396  }
397 
398  void
399  StatechartViewerController::updateStateFollower()
400  {
401  auto view = ui->tabWidget->currentStateview();
402  if (!view)
403  {
404  return;
405  }
406  follower->setStatechartView(view);
407  }
408 
409  void
410  StatechartViewerController::removeTab(int index)
411  {
412  QPointer<StatechartView> view = qobject_cast<StatechartView*>(ui->tabWidget->widget(index));
413  if (view)
414  {
415  converters.remove(view);
416  }
417  else
418  {
419  ARMARX_INFO_S << "View already NULL";
420  }
421  }
422 
423  QPointer<QWidget>
425  {
426  if (customToolbar)
427  {
428  if (parent != customToolbar->parent())
429  {
430  customToolbar->setParent(parent);
431  }
432 
433  return qobject_cast<QToolBar*>(customToolbar);
434  }
435 
436  customToolbar = new QToolBar(parent);
437  customToolbar->setIconSize(QSize(16, 16));
438  autoFollowAction = customToolbar->addAction(QIcon(":/icons/magic-wand-icon.png"),
439  "Auto follow active state");
440  autoFollowAction->setCheckable(true);
441  autoFollowAction->setChecked(true);
442  follower->startFollowing();
443  connect(autoFollowAction, SIGNAL(toggled(bool)), follower, SLOT(toggle(bool)));
444 
445  centerActiveStateAction = customToolbar->addAction(QIcon(":/icons/zoom-original-2.png"),
446  "Center on active state");
447  connect(centerActiveStateAction,
448  SIGNAL(triggered(bool)),
449  follower,
450  SLOT(centerOnCurrentState(bool)));
451  return qobject_cast<QToolBar*>(customToolbar);
452  }
453 
454  void
456  {
457  ARMARX_INFO << "Trying to connect to " << index;
458  if (index != -1 && ui->tabWidget->currentStateview() &&
459  ui->tabWidget->currentStateview()->getScene())
460  {
461  connect(
462  ui->tabWidget->currentStateview()->getScene(),
463  SIGNAL(transitionContextMenuRequested(
465  this,
468  Qt::UniqueConnection);
469  }
470  }
471 
472  void
476  QPoint mouseScreenPos,
477  QPointF mouseItemPos)
478  {
479  ARMARX_DEBUG_S << "pos: " << mouseItemPos;
480  QMenu menu;
481  QAction* triggerTransition = menu.addAction("Trigger Transition " + transition->eventName);
482  if (transition->sourceState != state->getActiveSubstate())
483  {
484  triggerTransition->setEnabled(false);
485  }
486 
487 
488  QAction* result = menu.exec(mouseScreenPos);
489 
490 
491  if (result == triggerTransition)
492  {
493  std::unique_lock lock(mutex);
494 
495  for (RemoteStateData& data : converters)
496  {
497  std::set<std::string> proxyNames;
498  std::string globalId;
499  auto states = data.converter->getCompleteStateMap();
500  for (auto& statepair : states)
501  {
502  proxyNames.insert(data.proxyName.toStdString());
503  if (state == statepair.second.first->getStateClass())
504  {
505  globalId = statepair.first;
506  ARMARX_DEBUG << "Found state " << statepair.first;
507  }
508  StateIceBasePtr iceState = statepair.second.second;
509  RemoteStateIceBasePtr remoteState =
510  RemoteStateIceBasePtr::dynamicCast(iceState);
511  if (remoteState)
512  {
513  proxyNames.insert(remoteState->proxyName);
514  }
515  }
516  if (!globalId.empty())
517  {
518  RemoteStateOffererInterfacePrx correctOffererproxy;
520  << VAROUT(Ice::StringSeq(proxyNames.begin(), proxyNames.end()));
521  std::map<RemoteStateOffererInterfacePrx, Ice::AsyncResultPtr> proxyResultPtrs;
522  for (auto proxyName : proxyNames)
523  {
524  RemoteStateOffererInterfacePrx proxy;
525  try
526  {
527  proxy = getProxy<RemoteStateOffererInterfacePrx>(
528  proxyName, false, "", false);
529  if (proxy)
530  {
531  proxyResultPtrs[proxy] =
532  proxy->begin_isHostOfStateByGlobalIdStr(globalId);
533  }
534  }
535  catch (...)
536  {
537  getArmarXManager()->getIceManager()->removeProxyFromCache(proxy);
538  }
539  }
540  for (auto& proxyPair : proxyResultPtrs)
541  {
542  RemoteStateOffererInterfacePrx proxy;
543  try
544  {
545  proxy = proxyPair.first;
546  if (proxy->end_isHostOfStateByGlobalIdStr(proxyPair.second))
547  {
548  correctOffererproxy = proxy;
549  break;
550  }
551  }
552  catch (...)
553  {
554  getArmarXManager()->getIceManager()->removeProxyFromCache(proxy);
555  }
556  }
557 
558  if (correctOffererproxy)
559  {
560  ARMARX_INFO << "Sending event " << transition->eventName << " to "
561  << transition->sourceState->getInstanceName();
562  correctOffererproxy->begin_issueEventWithGlobalIdStr(
563  globalId,
564  new Event(transition->sourceState->getInstanceName().toStdString(),
565  transition->eventName.toStdString()));
566  }
567  }
568  }
569  }
570  }
571 
572 } // namespace armarx
armarx::StatechartViewerController::showTransitionContextMenu
void showTransitionContextMenu(statechartmodel::TransitionCPtr transition, statechartmodel::StatePtr state, QPoint mouseScreenPos, QPointF mouseItemPos)
Definition: StatechartViewerController.cpp:473
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:366
armarx::StatechartViewerController::loadSettings
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
Definition: StatechartViewerController.cpp:127
StatechartView.h
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:190
armarx::StatechartViewerController::updateStatechart
void updateStatechart()
Definition: StatechartViewerController.cpp:182
JSONObject.h
index
uint8_t index
Definition: EtherCATFrame.h:59
ArmarXManager.h
armarx::StatechartViewerController::saveSettings
void saveSettings(QSettings *settings) override
Implement to save the settings as part of the GUI configuration.
Definition: StatechartViewerController.cpp:141
armarx::StatechartViewerController::connectToStateTab
void connectToStateTab(int index)
Definition: StatechartViewerController.cpp:455
armarx::StatechartViewerController::componentConnected
void componentConnected()
armarx::ManagedIceObject::getArmarXManager
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Definition: ManagedIceObject.cpp:360
armarx::StatechartViewerController::~StatechartViewerController
~StatechartViewerController() override
Definition: StatechartViewerController.cpp:84
StateItem.h
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:769
armarx::StatechartViewerController::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: StatechartViewerController.cpp:91
armarx::StateWatcher
Definition: StateWatcher.h:36
StateUtilFunctions.h
armarx::statechartmodel::StateInstancePtr
std::shared_ptr< StateInstance > StateInstancePtr
Definition: StateInstance.h:146
armarx::StatechartViewerController::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: StatechartViewerController.cpp:102
StringValueMap.h
armarx::Event
An Event is used to communicate between e.g. condition handlers and statecharts.
Definition: Event.h:50
ARMARX_DEBUG_S
#define ARMARX_DEBUG_S
Definition: Logging.h:205
StatechartViewerController.h
ManagedIceObject.h
armarx::statechartmodel::StateParameterMap
QMap< QString, StateParameterPtr > StateParameterMap
Definition: StateParameter.h:46
data
uint8_t data[1]
Definition: EtherCATFrame.h:68
ARMARX_DEBUG
#define ARMARX_DEBUG
Definition: Logging.h:184
RemoteState.h
IceProxyFinder.h
LocalState.h
armarx::StatechartViewerController::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: StatechartViewerController.cpp:114
armarx::ActiveStateFollower
Definition: ActiveStateFollower.h:33
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:196
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:213
StateInstance.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:181
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:198
armarx::StatechartViewerController::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: StatechartViewerController.cpp:122
armarx::ActiveStateFollower::startFollowing
void startFollowing()
Definition: ActiveStateFollower.cpp:52
armarx::IceProxyFinder< RemoteStateOffererInterfacePrx >
armarx::statechartmodel::TransitionCPtr
std::shared_ptr< const Transition > TransitionCPtr
Definition: Transition.h:91
armarx::statechartmodel::StatePtr
std::shared_ptr< State > StatePtr
Definition: State.h:48
armarx::Logging::deactivateSpam
SpamFilterDataPtr deactivateSpam(float deactivationDurationSec=10.0f, const std::string &identifier="", bool deactivate=true) const
disables the logging for the current line for the given amount of seconds.
Definition: Logging.cpp:99
armarx::ArmarXWidgetController::getWidget
virtual QPointer< QWidget > getWidget()
getWidget returns a pointer to the a widget of this controller.
Definition: ArmarXWidgetController.cpp:54
armarx::StatechartViewerController::StatechartViewerController
StatechartViewerController()
Definition: StatechartViewerController.cpp:55
ARMARX_INFO_S
#define ARMARX_INFO_S
Definition: Logging.h:202
armarx::PeriodicTask
Definition: ArmarXManager.h:70
armarx::StatechartViewerController::getCustomTitlebarWidget
QPointer< QWidget > getCustomTitlebarWidget(QWidget *parent) override
getTitleToolbar returns a pointer to the a toolbar widget of this controller.
Definition: StatechartViewerController.cpp:424
State.h
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:157
armarx::ActiveStateFollower::setStatechartView
void setStatechartView(StatechartView *value)
Definition: ActiveStateFollower.cpp:139
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:27
armarx::IceStateConverterPtr
std::shared_ptr< IceStateConverter > IceStateConverterPtr
Definition: IceStateConverter.h:220
DynamicRemoteState.h