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 
25 #include <ArmarXCore/interface/statechart/RemoteStateOffererIce.h> //RemoteStateOffererInterfacePrx
26 
28 #include "model/State.h"
31 #include "view/StatechartView.h"
32 #include <ArmarXGui/gui-plugins/StatechartViewerPlugin/ui_StatechartViewer.h>
33 
35 
40 
43 
46 #include <IceUtil/UUID.h>
47 #include <queue>
48 
49 #include <QMenu>
50 #include <QToolBar>
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(), SIGNAL(currentIndexChanged(QString)), this, SLOT(updateStateComboBox()), Qt::UniqueConnection);
78 
79  }
80 
82  {
83  shutdown = true;
84  std::unique_lock lock(mutex);// wait for network functions to finish
85 
86  }
87 
89  {
90  updateTask = new PeriodicTask<StatechartViewerController>(this, &StatechartViewerController::updateStatechart, 1000, false, "StatechartViewerRefetch");
91 
92  }
93 
95  {
96  qRegisterMetaType<statechartmodel::TransitionCPtr>("statechartmodel::TransitionCPtr");
97  qRegisterMetaType<statechartmodel::SignalType>("statechartmodel::SignalType");
98  watcher = new StateWatcher;
99  getArmarXManager()->addObject(watcher, false, "StateWatcher" + IceUtil::generateUUID());
100  updateTask->start();
101  emit componentConnected();
102  proxyFinder->setIceManager(getIceManager());
103  }
104 
106  {
107 
108  updateTask->stop();
109  getArmarXManager()->removeObjectNonBlocking(watcher->getName());
110  }
111 
113  {
114  }
115 
117  {
118  int size = settings->beginReadArray("StatechartViewers");
119  for (int i = 0; i < size; ++i)
120  {
121  settings->setArrayIndex(i);
122  QString proxyName = settings->value("proxyName").toString();
123  QString globalStateName = settings->value("globalStateName").toString();
124  delayedConverterAdding.push_back(qMakePair(proxyName, globalStateName));
125  }
126  settings->endArray();
127  }
128 
130  {
131  settings->beginWriteArray("StatechartViewers");
132  int i = 0;
133  for (RemoteStateData& data : converters)
134  {
135  settings->setArrayIndex(i);
136  settings->setValue("globalStateName", data.globalStateName);
137  settings->setValue("proxyName", data.proxyName);
138  i++;
139  }
140  settings->endArray();
141  }
142 
143  void StatechartViewerController::connectToIce()
144  {
145  for (QPair<QString, QString>& pair : delayedConverterAdding)
146  {
147  addNewStateView(pair.first, pair.second);
148  }
149  if (!ui->tabWidget->currentStateview())
150  {
151  addNewStateView("RobotControlStateOfferer", "RobotStatechart->RobotControl");
152  }
153 
154  ui->tabWidget->currentStateview()->viewAll();
155  }
156 
157  void StatechartViewerController::updateStatechartView(StateIceBasePtr stateptr, IceStateConverterPtr converter)
158  {
159  std::unique_lock lock(mutex);
160  auto start = IceUtil::Time::now();
161  converter->convert(stateptr);
162  ARMARX_DEBUG << deactivateSpam(3) << "converting instance took : " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms";
163  }
164 
166  {
167  if (shutdown)
168  {
169  return;
170  }
171  QMap<QPointer<StatechartView>, RemoteStateData> tempConverters;
172  {
173  std::unique_lock lock(mutex);
174  tempConverters = converters;
175  }
176  for (RemoteStateData& stateData : tempConverters)
177  {
178  RemoteStateOffererInterfacePrx statechartHandler;
179  try
180  {
181  statechartHandler = getProxy<RemoteStateOffererInterfacePrx>(stateData.proxyName.toStdString(), false, "", false);
182  if (!statechartHandler)
183  {
184  continue;
185  }
186  auto start = IceUtil::Time::now();
187 
188 
189  start = IceUtil::Time::now();
190 
191  auto asyncResult = statechartHandler->begin_getStatechartInstanceByGlobalIdStr(stateData.globalStateName.toStdString());
192  while (!asyncResult->isCompleted())
193  {
194  if (shutdown)
195  {
196  return;
197  }
198  usleep(100);
199  // qApp->processEvents();
200  }
201  armarx::StateIceBasePtr stateptr = statechartHandler->end_getStatechartInstanceByGlobalIdStr(asyncResult);
202  if (!stateptr)
203  {
204  ARMARX_WARNING_S << "Could not find state with name " << stateData.globalStateName.toStdString();
205  continue;
206  }
207  // armarx::StateIceBasePtr stateptr = m_statechartHandler->getStatechartInstance(stateMap.begin()->first);
208  ARMARX_DEBUG << deactivateSpam(3) << " took : " << (IceUtil::Time::now() - start).toMilliSecondsDouble() << " ms";
209  QMetaObject::invokeMethod(this, "updateStatechartView", Q_ARG(StateIceBasePtr, stateptr), Q_ARG(IceStateConverterPtr, stateData.converter));
210  // stateData.converter.convert(stateptr);
211 
212  }
213  catch (Ice::NotRegisteredException&)
214  {
215  getIceManager()->removeProxyFromCache(statechartHandler);
216  ARMARX_ERROR << deactivateSpam(10) << "No ice ID 'RobotControlStateOfferer' registered";
217  }
218  catch (...)
219  {
221  }
222  }
223  }
224 
225  void StatechartViewerController::displayParameters(statechartmodel::StateInstancePtr selectedStateInstance)
226  {
227  try
228  {
229  QList<QTreeWidgetItem*> items;
230  if (selectedStateInstance && watcher)
231  {
232  auto paramContainerTypes = {"inputParameters", "localParameters", "outputParameters"};
233  ui->paramView->clear();
234 
235 
236  for (auto& type : paramContainerTypes)
237  {
238  QTreeWidgetItem* item = new QTreeWidgetItem();
239  item->setText(0, type);
240  StateParameterMap map;
241  try
242  {
243  map = watcher->getStateParameterMap(selectedStateInstance->getStateClass(), type);
244  }
245  catch (...)
246  {
248  continue;
249  }
250 
251 
252 
253  for (auto& elem : map)
254  {
255  QTreeWidgetItem* subItem = new QTreeWidgetItem();
256  StateParameterIceBasePtr param = elem.second;
257  subItem->setText(0, elem.first.c_str());
258  subItem->setText(1, param->value->output().c_str());
259  item->addChild(subItem);
260 
261  }
262  items.push_back(item);
263  // inputParamsJson->setVariant(type, var);
264 
265  }
266  ui->paramView->addTopLevelItems(items);
267  for (auto& item : items)
268  {
269  ui->paramView->expandItem(item);
270  }
271  }
272  else
273  {
274  ARMARX_INFO << "no state instance!";
275  }
276  if (items.size() == 0)
277  {
278  QTreeWidgetItem* item = new QTreeWidgetItem();
279  item->setText(0, "No data available yet");
280  ui->paramView->addTopLevelItem(item);
281  }
282 
283  }
284  catch (...)
285  {
286  QTreeWidgetItem* item = new QTreeWidgetItem();
287  item->setText(0, "No data available yet");
288  ui->paramView->addTopLevelItem(item);
290  }
291  }
292 
293  void StatechartViewerController::addNewStateView(QString proxyName, QString stateName)
294  {
295  auto view = ui->tabWidget->addEmptyStateTab();
296  if (!view)
297  {
298  return;
299  }
300  connect(view, SIGNAL(selectedStateChanged(statechartmodel::StateInstancePtr)), this, SLOT(displayParameters(statechartmodel::StateInstancePtr)));
301  converters[view].converter.reset(new IceStateConverter());
302  converters[view].converter->setStateWatcher(watcher);
303  view->setState(converters[view].converter->getTopState()->getStateClass());
304  converters[view].proxyName = proxyName;
305  converters[view].globalStateName = stateName;
306  QString instanceName;
307  if (stateName.lastIndexOf("->") >= 0)
308  {
309  instanceName = stateName.right(stateName.size() - stateName.lastIndexOf("->") - 2);
310  }
311  else
312  {
313  instanceName = stateName;
314  }
315  ui->tabWidget->setTabText(ui->tabWidget->currentIndex(), instanceName);
316 
317  view->getLayoutController().enableLayouting();
319  connectToStateTab(ui->tabWidget->currentIndex());
320 
321  }
322 
323  void StatechartViewerController::addNewStateView()
324  {
325  addNewStateView(proxyFinder->getSelectedProxyName(), ui->comboBoxStateInstances->currentText());
326  }
327 
328  void StatechartViewerController::followActiveState()
329  {
330  auto view = ui->tabWidget->currentStateview();
331  if (!view)
332  {
333  return;
334  }
335  follower->setStatechartView(view);
336  }
337 
338  void StatechartViewerController::updateStateComboBox()
339  {
340  if (proxyFinder->getSelectedProxyName().isEmpty())
341  {
342  return;
343  }
344  if (getState() < eManagedIceObjectStarting)
345  {
346  return;
347  }
348  auto proxy = getProxy<RemoteStateOffererInterfacePrx>(proxyFinder->getSelectedProxyName().toStdString(), false, "", false);
349 
350  ui->comboBoxStateInstances->clear();
351  if (proxy)
352  {
353  QStringList stateInstances;
354  for (auto& elem : proxy->getAvailableStateInstances())
355  {
356  stateInstances << (elem.second.c_str());
357  }
358  stateInstances.removeDuplicates();
359  ui->comboBoxStateInstances->addItems(stateInstances);
360  }
361  ui->btnAddViewer->setEnabled(ui->comboBoxStateInstances->count() > 0);
362  }
363 
364  void StatechartViewerController::updateStateFollower()
365  {
366  auto view = ui->tabWidget->currentStateview();
367  if (!view)
368  {
369  return;
370  }
371  follower->setStatechartView(view);
372  }
373 
374  void StatechartViewerController::removeTab(int index)
375  {
376  QPointer<StatechartView> view = qobject_cast<StatechartView*>(ui->tabWidget->widget(index));
377  if (view)
378  {
379  converters.remove(view);
380  }
381  else
382  {
383  ARMARX_INFO_S << "View already NULL";
384  }
385  }
386 
387  QPointer<QWidget> StatechartViewerController::getCustomTitlebarWidget(QWidget* parent)
388  {
389  if (customToolbar)
390  {
391  if (parent != customToolbar->parent())
392  {
393  customToolbar->setParent(parent);
394  }
395 
396  return qobject_cast<QToolBar*>(customToolbar);
397  }
398 
399  customToolbar = new QToolBar(parent);
400  customToolbar->setIconSize(QSize(16, 16));
401  autoFollowAction = customToolbar->addAction(QIcon(":/icons/magic-wand-icon.png"), "Auto follow active state");
402  autoFollowAction->setCheckable(true);
403  autoFollowAction->setChecked(true);
404  follower->startFollowing();
405  connect(autoFollowAction, SIGNAL(toggled(bool)), follower, SLOT(toggle(bool)));
406 
407  centerActiveStateAction = customToolbar->addAction(QIcon(":/icons/zoom-original-2.png"), "Center on active state");
408  connect(centerActiveStateAction, SIGNAL(triggered(bool)), follower, SLOT(centerOnCurrentState(bool)));
409  return qobject_cast<QToolBar*>(customToolbar);
410  }
411 
413  {
414  ARMARX_INFO << "Trying to connect to " << index;
415  if (index != -1 && ui->tabWidget->currentStateview() && ui->tabWidget->currentStateview()->getScene())
416  {
417  connect(ui->tabWidget->currentStateview()->getScene(), SIGNAL(transitionContextMenuRequested(statechartmodel::TransitionCPtr, statechartmodel::StatePtr, QPoint, QPointF)),
418  this, SLOT(showTransitionContextMenu(statechartmodel::TransitionCPtr, statechartmodel::StatePtr, QPoint, QPointF)), Qt::UniqueConnection);
419  }
420  }
421 
423  {
424  ARMARX_DEBUG_S << "pos: " << mouseItemPos;
425  QMenu menu;
426  QAction* triggerTransition = menu.addAction("Trigger Transition " + transition->eventName);
427  if (transition->sourceState != state->getActiveSubstate())
428  {
429  triggerTransition->setEnabled(false);
430  }
431 
432 
433  QAction* result = menu.exec(mouseScreenPos);
434 
435 
436 
437 
438  if (result == triggerTransition)
439  {
440  std::unique_lock lock(mutex);
441 
442  for (RemoteStateData& data : converters)
443  {
444  std::set<std::string> proxyNames;
445  std::string globalId;
446  auto states = data.converter->getCompleteStateMap();
447  for (auto& statepair : states)
448  {
449  proxyNames.insert(data.proxyName.toStdString());
450  if (state == statepair.second.first->getStateClass())
451  {
452  globalId = statepair.first;
453  ARMARX_DEBUG << "Found state " << statepair.first;
454  }
455  StateIceBasePtr iceState = statepair.second.second;
456  RemoteStateIceBasePtr remoteState = RemoteStateIceBasePtr::dynamicCast(iceState);
457  if (remoteState)
458  {
459  proxyNames.insert(remoteState->proxyName);
460  }
461  }
462  if (!globalId.empty())
463  {
464  RemoteStateOffererInterfacePrx correctOffererproxy;
465  ARMARX_IMPORTANT << VAROUT(Ice::StringSeq(proxyNames.begin(), proxyNames.end()));
466  std::map<RemoteStateOffererInterfacePrx, Ice::AsyncResultPtr> proxyResultPtrs;
467  for (auto proxyName : proxyNames)
468  {
469  RemoteStateOffererInterfacePrx proxy;
470  try
471  {
472  proxy = getProxy<RemoteStateOffererInterfacePrx>(proxyName, false, "", false);
473  if (proxy)
474  {
475  proxyResultPtrs[proxy] = proxy->begin_isHostOfStateByGlobalIdStr(globalId);
476  }
477  }
478  catch (...)
479  {
480  getArmarXManager()->getIceManager()->removeProxyFromCache(proxy);
481  }
482  }
483  for (auto& proxyPair : proxyResultPtrs)
484  {
485  RemoteStateOffererInterfacePrx proxy;
486  try
487  {
488  proxy = proxyPair.first;
489  if (proxy->end_isHostOfStateByGlobalIdStr(proxyPair.second))
490  {
491  correctOffererproxy = proxy;
492  break;
493  }
494 
495  }
496  catch (...)
497  {
498  getArmarXManager()->getIceManager()->removeProxyFromCache(proxy);
499  }
500  }
501 
502  if (correctOffererproxy)
503  {
504  ARMARX_INFO << "Sending event " << transition->eventName << " to " << transition->sourceState->getInstanceName();
505  correctOffererproxy->begin_issueEventWithGlobalIdStr(globalId, new Event(transition->sourceState->getInstanceName().toStdString(), transition->eventName.toStdString()));
506  }
507  }
508  }
509  }
510 
511  }
512 
513 }
armarx::StatechartViewerController::showTransitionContextMenu
void showTransitionContextMenu(statechartmodel::TransitionCPtr transition, statechartmodel::StatePtr state, QPoint mouseScreenPos, QPointF mouseItemPos)
Definition: StatechartViewerController.cpp:422
armarx::ManagedIceObject::getIceManager
IceManagerPtr getIceManager() const
Returns the IceManager.
Definition: ManagedIceObject.cpp:353
armarx::StatechartViewerController::loadSettings
void loadSettings(QSettings *settings) override
Implement to load the settings that are part of the GUI configuration.
Definition: StatechartViewerController.cpp:116
StatechartView.h
ARMARX_IMPORTANT
#define ARMARX_IMPORTANT
Definition: Logging.h:183
armarx::StatechartViewerController::updateStatechart
void updateStatechart()
Definition: StatechartViewerController.cpp:165
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:129
armarx::StatechartViewerController::connectToStateTab
void connectToStateTab(int index)
Definition: StatechartViewerController.cpp:412
armarx::StatechartViewerController::componentConnected
void componentConnected()
armarx::ManagedIceObject::getArmarXManager
ArmarXManagerPtr getArmarXManager() const
Returns the ArmarX manager used to add and remove components.
Definition: ManagedIceObject.cpp:348
armarx::StatechartViewerController::~StatechartViewerController
~StatechartViewerController() override
Definition: StatechartViewerController.cpp:81
StateItem.h
armarx::ManagedIceObject::getState
int getState() const
Retrieve current state of the ManagedIceObject.
Definition: ManagedIceObject.cpp:725
armarx::StatechartViewerController::onInitComponent
void onInitComponent() override
Pure virtual hook for the subclass.
Definition: StatechartViewerController.cpp:88
armarx::StateWatcher
Definition: StateWatcher.h:36
StateUtilFunctions.h
armarx::statechartmodel::StateInstancePtr
std::shared_ptr< StateInstance > StateInstancePtr
Definition: StateInstance.h:138
armarx::StatechartViewerController::onConnectComponent
void onConnectComponent() override
Pure virtual hook for the subclass.
Definition: StatechartViewerController.cpp:94
StringValueMap.h
armarx::Event
An Event is used to communicate between e.g. condition handlers and statecharts.
Definition: Event.h:52
ARMARX_DEBUG_S
#define ARMARX_DEBUG_S
Definition: Logging.h:198
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:177
RemoteState.h
IceProxyFinder.h
LocalState.h
armarx::StatechartViewerController::onDisconnectComponent
void onDisconnectComponent() override
Hook for subclass.
Definition: StatechartViewerController.cpp:105
armarx::ActiveStateFollower
Definition: ActiveStateFollower.h:35
ARMARX_ERROR
#define ARMARX_ERROR
Definition: Logging.h:189
ARMARX_WARNING_S
#define ARMARX_WARNING_S
Definition: Logging.h:206
StateInstance.h
ARMARX_INFO
#define ARMARX_INFO
Definition: Logging.h:174
VAROUT
#define VAROUT(x)
Definition: StringHelpers.h:182
armarx::StatechartViewerController::onExitComponent
void onExitComponent() override
Hook for subclass.
Definition: StatechartViewerController.cpp:112
armarx::ActiveStateFollower::startFollowing
void startFollowing()
Definition: ActiveStateFollower.cpp:51
armarx::IceProxyFinder< RemoteStateOffererInterfacePrx >
armarx::statechartmodel::TransitionCPtr
std::shared_ptr< const Transition > TransitionCPtr
Definition: Transition.h:94
armarx::statechartmodel::StatePtr
std::shared_ptr< State > StatePtr
Definition: State.h:46
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:92
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:195
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:387
State.h
armarx::handleExceptions
void handleExceptions()
Definition: Exception.cpp:141
armarx::ActiveStateFollower::setStatechartView
void setStatechartView(StatechartView *value)
Definition: ActiveStateFollower.cpp:128
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition: ArmarXTimeserver.cpp:28
armarx::IceStateConverterPtr
std::shared_ptr< IceStateConverter > IceStateConverterPtr
Definition: IceStateConverter.h:206
DynamicRemoteState.h