EmergencyStopWidget.cpp
Go to the documentation of this file.
1
/*
2
* This file is part of ArmarX.
3
*
4
* ArmarX is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License version 2 as
6
* published by the Free Software Foundation.
7
*
8
* ArmarX is distributed in the hope that it will be useful, but
9
* WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
12
*
13
* You should have received a copy of the GNU General Public License
14
* along with this program. If not, see <http://www.gnu.org/licenses/>.
15
*
16
* @package ArmarXCore::ArmarXObjects::EmergencyStop
17
* @author Stefan Reither ( stef dot reither at web dot de )
18
* @date 2016
19
* @copyright http://www.gnu.org/licenses/gpl-2.0.txt
20
* GNU General Public License
21
*/
22
23
#include "
EmergencyStopWidget.h
"
24
25
#include <QGridLayout>
26
#include <QShortcut>
27
#include <QTimer>
28
#include <QToolTip>
29
30
31
#define EMERGENCY_STOP_PROXY "EmergencyStopMaster"
32
#define EMERGENCY_STOP_TOPIC_NAME "EmergencyStop"
33
34
namespace
armarx
35
{
36
37
static
const
std::string ss2_active_tooltip =
38
"Release SS2 emergency stop (only possible after a short cooldown period. Shortcut: "
39
"Shift+Pause or Shift+End."
;
40
static
const
std::string ss2_inactive_tooltip =
41
"Enable SS2 emergency stop. Shortcut: Pause or End."
;
42
43
EmergencyStopWidget::EmergencyStopWidget
(QWidget* parent,
ArmarXMainWindow
* mainWindow) :
44
mainWindow(mainWindow),
45
iconNormal(QPixmap::fromImage(QImage(QString::fromUtf8(
":/icons/emergency-stop.png"
)))),
46
iconDark(QPixmap::fromImage(QImage(QString::fromUtf8(
":/icons/emergency-stop-dark.png"
)))),
47
lastKnownEmergencyStopState(EmergencyStopState::eEmergencyStopInactive),
48
timer(new QTimer(this))
49
{
50
qRegisterMetaType<EmergencyStopState>(
"EmergencyStopState"
);
51
52
// Redundant timer apart from the topic in order to recover from bad states if a topic
53
// message was lost.
54
timer->setInterval(std::chrono::milliseconds(1
'000));
55
connect(timer, &QTimer::timeout, this, &EmergencyStopWidget::updateEmergencyStopState);
56
connect(this,
57
&EmergencyStopWidget::startPeriodicStateUpdate,
58
timer,
59
qOverload<>(&QTimer::start));
60
connect(this, &EmergencyStopWidget::stopPeriodicStateUpdate, timer, &QTimer::stop);
61
QIcon icon;
62
icon.addPixmap(iconNormal, QIcon::Normal, QIcon::Off);
63
icon.addPixmap(iconDark, QIcon::Normal, QIcon::On);
64
65
button = new QToolButton();
66
button->setCheckable(true);
67
button->setIcon(icon);
68
button->setIconSize(QSize(68, 28));
69
button->setToolTip(QString::fromStdString(ss2_active_tooltip));
70
button->setVisible(false);
71
QGridLayout* l = new QGridLayout(this->getWidget());
72
l->setMargin(0);
73
l->setContentsMargins(0, 0, 0, 0);
74
this->getWidget()->setLayout(l);
75
this->getWidget()->layout()->addWidget(button);
76
77
QShortcut* enableSS2Shortcut1 = new QShortcut(this->getWidget());
78
enableSS2Shortcut1->setContext(Qt::ApplicationShortcut);
79
enableSS2Shortcut1->setKey(Qt::Key_Pause);
80
QShortcut* enableSS2Shortcut2 = new QShortcut(this->getWidget());
81
enableSS2Shortcut2->setContext(Qt::ApplicationShortcut);
82
enableSS2Shortcut2->setKey(Qt::Key_End);
83
connect(enableSS2Shortcut1, &QShortcut::activated, this, &EmergencyStopWidget::enableSS2);
84
connect(enableSS2Shortcut2, &QShortcut::activated, this, &EmergencyStopWidget::enableSS2);
85
86
QShortcut* releaseSS2Shortcut1 = new QShortcut(this->getWidget());
87
releaseSS2Shortcut1->setContext(Qt::ApplicationShortcut);
88
releaseSS2Shortcut1->setKey(Qt::SHIFT | Qt::Key_Pause);
89
QShortcut* releaseSS2Shortcut2 = new QShortcut(this->getWidget());
90
releaseSS2Shortcut2->setContext(Qt::ApplicationShortcut);
91
releaseSS2Shortcut2->setKey(Qt::SHIFT | Qt::Key_End);
92
connect(releaseSS2Shortcut1, &QShortcut::activated, this, &EmergencyStopWidget::releaseSS2);
93
connect(releaseSS2Shortcut2, &QShortcut::activated, this, &EmergencyStopWidget::releaseSS2);
94
95
connect(button, &QPushButton::clicked, this, &EmergencyStopWidget::clicked);
96
}
97
98
QWidget*
99
EmergencyStopWidget::getButtonWidget()
100
{
101
return this->getWidget();
102
}
103
104
void
105
EmergencyStopWidget::onInitComponent()
106
{
107
usingProxy(EMERGENCY_STOP_PROXY);
108
usingTopic(EMERGENCY_STOP_TOPIC_NAME);
109
}
110
111
void
112
EmergencyStopWidget::onConnectComponent()
113
{
114
ARMARX_INFO << "SS2 widget connected.";
115
emergencyStopMasterPrx = getProxy<EmergencyStopMasterInterfacePrx>(EMERGENCY_STOP_PROXY);
116
QMetaObject::invokeMethod(button, "setVisible", Qt::QueuedConnection, Q_ARG(bool, true));
117
EmergencyStopState state = EmergencyStopState::eEmergencyStopActive;
118
119
try
120
{
121
state = emergencyStopMasterPrx->getEmergencyStopState();
122
}
123
catch (Ice::Exception const& e)
124
{
125
ARMARX_ERROR << "Could not query SS2 state." << deactivateSpam(2);
126
}
127
128
QMetaObject::invokeMethod(
129
this, "setChecked", Qt::QueuedConnection, Q_ARG(EmergencyStopState, state));
130
131
emit startPeriodicStateUpdate();
132
}
133
134
void
135
EmergencyStopWidget::onDisconnectComponent()
136
{
137
ARMARX_IMPORTANT << "SS2 widget disconnected. This is expected if the earlier connected "
138
"robot unit shut down.";
139
QMetaObject::invokeMethod(button, "setVisible", Qt::QueuedConnection, Q_ARG(bool, false));
140
141
emit stopPeriodicStateUpdate();
142
}
143
144
void
145
EmergencyStopWidget::loadSettings(QSettings* settings)
146
{
147
;
148
}
149
150
void
151
EmergencyStopWidget::saveSettings(QSettings* settings)
152
{
153
;
154
}
155
156
void
157
EmergencyStopWidget::reportEmergencyStopState(EmergencyStopState state, const Ice::Current&)
158
{
159
QMetaObject::invokeMethod(
160
this, "setChecked", Qt::QueuedConnection, Q_ARG(EmergencyStopState, state));
161
}
162
163
void
164
EmergencyStopWidget::enableSS2()
165
{
166
if (emergencyStopMasterPrx)
167
{
168
emergencyStopMasterPrx->setEmergencyStopState(EmergencyStopState::eEmergencyStopActive);
169
170
if (lastKnownEmergencyStopState == EmergencyStopState::eEmergencyStopActive)
171
{
172
std::string const message =
173
"SS2 already active. Press Shift+Pause or Shift+End to release SS2.";
174
175
QPoint globalPos =
176
button->mapToGlobal(QPoint(button->width() / 2, button->height() / 2));
177
QToolTip::showText(globalPos, QString::fromStdString(message), button);
178
ARMARX_INFO << message;
179
}
180
}
181
}
182
183
void
184
EmergencyStopWidget::releaseSS2()
185
{
186
if (emergencyStopMasterPrx)
187
{
188
lastKnownEmergencyStopState = releaseSS2OnMaster();
189
190
if (lastKnownEmergencyStopState == EmergencyStopState::eEmergencyStopActive)
191
{
192
std::string const message = "SS2 cannot be released since it was just activated.";
193
194
QPoint globalPos =
195
button->mapToGlobal(QPoint(button->width() / 2, button->height() / 2));
196
QToolTip::showText(globalPos, QString::fromStdString(message), button);
197
ARMARX_INFO << message;
198
}
199
}
200
}
201
202
void
203
EmergencyStopWidget::clicked(bool checked)
204
{
205
if (not emergencyStopMasterPrx)
206
{
207
return;
208
}
209
210
switch (lastKnownEmergencyStopState)
211
{
212
case EmergencyStopState::eEmergencyStopActive:
213
{
214
// Only release SS2 if the state we received still is "Active". Fail otherwise.
215
lastKnownEmergencyStopState = releaseSS2OnMaster();
216
if (lastKnownEmergencyStopState == EmergencyStopState::eEmergencyStopActive)
217
{
218
ARMARX_INFO << "SS2 cannot be released since it was just activated.";
219
button->setChecked(true);
220
}
221
}
222
break;
223
case EmergencyStopState::eEmergencyStopInactive:
224
// Always enable SS2 without checking.
225
enableSS2();
226
break;
227
}
228
}
229
230
std::string
231
EmergencyStopWidget::getDefaultName() const
232
{
233
return "EmergencyStopGuiWidget" + iceNameUUID;
234
}
235
236
EmergencyStopState
237
EmergencyStopWidget::releaseSS2OnMaster() const
238
{
239
// If emergency stop master is not available, assume that SS2 is still active and cannot
240
// be released.
241
if (not emergencyStopMasterPrx)
242
{
243
return EmergencyStopState::eEmergencyStopActive;
244
}
245
246
try
247
{
248
return emergencyStopMasterPrx->trySetEmergencyStopState(
249
EmergencyStopState::eEmergencyStopInactive);
250
}
251
// This catch is only required as long as the stable robot workspaces are using the old
252
// interface. The changes for the new interface were done in July 2024. It can safely be
253
// removed after a few months.
254
catch (Ice::OperationNotExistException const&)
255
{
256
ARMARX_WARNING << "Cannot safely release SS2. This only happens if your ArmarX GUI "
257
"is using a newer version of the emergency stop interface than the "
258
"emergency stop master or the robot unit provides. Will use a less "
259
"safe fallback interface method now.";
260
emergencyStopMasterPrx->setEmergencyStopState(
261
EmergencyStopState::eEmergencyStopInactive);
262
return emergencyStopMasterPrx->getEmergencyStopState();
263
}
264
}
265
266
void
267
EmergencyStopWidget::setChecked(const EmergencyStopState state)
268
{
269
switch (state)
270
{
271
case EmergencyStopState::eEmergencyStopActive:
272
button->setChecked(true);
273
button->setToolTip(QString::fromStdString(ss2_active_tooltip));
274
break;
275
case EmergencyStopState::eEmergencyStopInactive:
276
default:
277
button->setChecked(false);
278
button->setToolTip(QString::fromStdString(ss2_inactive_tooltip));
279
break;
280
}
281
282
lastKnownEmergencyStopState = state;
283
}
284
285
void
286
EmergencyStopWidget::updateEmergencyStopState()
287
{
288
try
289
{
290
if (emergencyStopMasterPrx)
291
{
292
setChecked(emergencyStopMasterPrx->getEmergencyStopState());
293
}
294
}
295
catch (Ice::Exception const& e)
296
{
297
ARMARX_INFO << "Could not query SS2 state." << deactivateSpam(60);
298
setChecked(EmergencyStopState::eEmergencyStopActive);
299
}
300
}
301
302
} // namespace armarx
armarx::EmergencyStopWidget::EmergencyStopWidget
EmergencyStopWidget(QWidget *parent=0, ArmarXMainWindow *mainWindow=0)
Definition:
EmergencyStopWidget.cpp:43
armarx::ArmarXMainWindow
The ArmarXMainWindow class.
Definition:
ArmarXMainWindow.h:76
EmergencyStopWidget.h
armarx
This file offers overloads of toIce() and fromIce() functions for STL container types.
Definition:
ArmarXTimeserver.cpp:27
ArmarXGui
applications
ArmarXGui
Widgets
EmergencyStopWidget.cpp
Generated on Sat Mar 29 2025 09:17:22 for armarx_documentation by
1.8.17