Skip to content

Commit f99b37c

Browse files
committed
Add Reload button to reload current namespace
1 parent 9260e59 commit f99b37c

File tree

6 files changed

+58
-7
lines changed

6 files changed

+58
-7
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ __pycache__
22
*doc/html
33
*egg-info
44
*.md.html
5+
**.vscode

py_trees_ros_viewer/backend.py

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ def __init__(
9595

9696
self.topic_name = None
9797
self.subscriber = None
98+
self.connected = False
9899

99100
self.services = {
100101
'open': None,
@@ -119,6 +120,8 @@ def __init__(
119120
}
120121
# create service clients
121122
self.services["open"] = self.create_service_client(key="open")
123+
if self.services["open"] is None:
124+
return # Prevent from waiting more time for other services and exit earlier.
122125
self.services["close"] = self.create_service_client(key="close")
123126
self.services["reconfigure"] = self.create_service_client(key="reconfigure")
124127

@@ -160,15 +163,23 @@ def _connect_on_init(self, timeout_sec=1.0):
160163
request.parameters.snapshot_period = self.parameters.snapshot_period
161164
console.logdebug("establishing a snapshot stream connection [{}][backend]".format(self.namespace))
162165
future = self.services["open"].call_async(request)
163-
rclpy.spin_until_future_complete(self.node, future)
166+
start_time = time.monotonic()
167+
while not future.done():
168+
elapsed_time = time.monotonic() - start_time
169+
if elapsed_time > timeout_sec:
170+
console.logerror(f"Timed out waiting to open a connection")
171+
return
172+
rclpy.spin_once(self.node, timeout_sec=0.1)
164173
response = future.result()
165174
self.topic_name = response.topic_name
166175
# connect to a snapshot stream
167176
start_time = time.monotonic()
168177
while True:
169178
elapsed_time = time.monotonic() - start_time
170179
if elapsed_time > timeout_sec:
171-
raise exceptions.TimedOutError("timed out waiting for a snapshot stream publisher [{}]".format(self.topic_name))
180+
console.logerror(f"Timed out waiting for a snapshot stream publisher [{self.topic_name}]")
181+
self.connected = False
182+
return
172183
if self.node.count_publishers(self.topic_name) > 0:
173184
break
174185
time.sleep(0.1)
@@ -178,6 +189,7 @@ def _connect_on_init(self, timeout_sec=1.0):
178189
callback=self.callback,
179190
qos_profile=utilities.qos_profile_latched()
180191
)
192+
self.connected = True
181193
console.logdebug(" ...ok [backend]")
182194

183195
def shutdown(self):
@@ -197,6 +209,9 @@ def create_service_client(self, key: str):
197209
198210
Args:
199211
key: one of 'open', 'close'.
212+
213+
Returns:
214+
A client if successful, else None.
200215
201216
Raises:
202217
:class:`~py_trees_ros.exceptions.NotReadyError`: if setup() wasn't called to identify the relevant services to connect to.
@@ -213,9 +228,8 @@ def create_service_client(self, key: str):
213228
)
214229
# hardcoding timeouts will get us into trouble
215230
if not client.wait_for_service(timeout_sec=3.0):
216-
raise exceptions.TimedOutError(
217-
"timed out waiting for {}".format(self.service_names['close'])
218-
)
231+
console.logdebug(f"Timed out waiting for {self.service_names['close']}")
232+
return None
219233
return client
220234

221235
##############################################################################
@@ -253,10 +267,12 @@ def spin(self):
253267
if self.parameters != old_parameters:
254268
if self.snapshot_stream is not None:
255269
self.snapshot_stream.reconfigure(self.parameters)
256-
old_parameters = copy.copy(self.parameters)
270+
old_parameters = copy.copy(self.parameters)
257271
if self.enqueued_connection_request_namespace is not None:
258272
self.connect(self.enqueued_connection_request_namespace)
259-
self.enqueued_connection_request_namespace = None
273+
# If connection failed, keep retrying with the latest enqueued namespace.
274+
if self.snapshot_stream.connected:
275+
self.enqueued_connection_request_namespace = None
260276
rclpy.spin_once(self.node, timeout_sec=0.1)
261277
if self.snapshot_stream is not None:
262278
self.snapshot_stream.shutdown()

py_trees_ros_viewer/main_window.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,10 @@ def on_discovered_namespaces_changed(self, discovered_namespaces):
6060
console.logdebug("discovered namespaces changed callback {}[window]".format(discovered_namespaces))
6161
if (discovered_namespaces):
6262
self.ui.send_button.setEnabled(False)
63+
self.ui.reload_button.setEnabled(True)
6364
else:
6465
self.ui.send_button.setEnabled(True)
66+
self.ui.reload_button.setEnabled(False)
6567

6668
discovered_namespaces.sort()
6769

@@ -96,6 +98,7 @@ def onLoadFinished(self):
9698
console.logdebug("web page loaded [window]")
9799
self.web_app_loaded = True
98100
self.ui.send_button.setEnabled((self.ui.topic_combo_box.currentIndex() == -1))
101+
self.ui.reload_button.setEnabled(False)
99102
self.ui.screenshot_button.setEnabled(True)
100103
self.ui.blackboard_activity_checkbox.setEnabled(True)
101104
self.ui.blackboard_data_checkbox.setEnabled(True)

py_trees_ros_viewer/main_window.ui

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,16 @@
6161
</property>
6262
</widget>
6363
</item>
64+
<item>
65+
<widget class="QPushButton" name="reload_button">
66+
<property name="enabled">
67+
<bool>false</bool>
68+
</property>
69+
<property name="text">
70+
<string>Reload Tree</string>
71+
</property>
72+
</widget>
73+
</item>
6474
<item>
6575
<spacer name="horizontalSpacer">
6676
<property name="orientation">

py_trees_ros_viewer/main_window_ui.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ def setupUi(self, MainWindow):
4242
self.send_button.setEnabled(False)
4343
self.send_button.setObjectName("send_button")
4444
self.horizontalLayout.addWidget(self.send_button)
45+
self.reload_button = QtWidgets.QPushButton(self.tools_frame)
46+
self.reload_button.setEnabled(False)
47+
self.reload_button.setObjectName("reload_button")
48+
self.horizontalLayout.addWidget(self.reload_button)
4549
spacerItem = QtWidgets.QSpacerItem(186, 20, QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Minimum)
4650
self.horizontalLayout.addItem(spacerItem)
4751
self.blackboard_data_checkbox = QtWidgets.QCheckBox(self.tools_frame)
@@ -91,6 +95,7 @@ def retranslateUi(self, MainWindow):
9195
MainWindow.setWindowTitle(_translate("MainWindow", "PyTrees Viewer"))
9296
self.label.setText(_translate("MainWindow", "Namespace"))
9397
self.send_button.setText(_translate("MainWindow", "Send Demo Tree"))
98+
self.reload_button.setText(_translate("MainWindow", "Reload Tree"))
9499
self.blackboard_data_checkbox.setText(_translate("MainWindow", "Blackboard Data"))
95100
self.blackboard_activity_checkbox.setText(_translate("MainWindow", "Blackboard Activity"))
96101
self.periodic_checkbox.setText(_translate("MainWindow", "Periodic"))

py_trees_ros_viewer/viewer.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,15 @@ def on_connection_request(backend, namespace: str):
139139
with backend.lock:
140140
backend.enqueued_connection_request_namespace = namespace
141141

142+
def on_connection_reload_request(backend, window):
143+
"""
144+
Enqueue a connection request.
145+
146+
Cannot directly make the connection here since this is invariably the qt thread.
147+
"""
148+
namespace = window.ui.topic_combo_box.currentText()
149+
on_connection_request(backend, namespace)
150+
142151
##############################################################################
143152
# Main
144153
##############################################################################
@@ -184,6 +193,13 @@ def on_shutdown(unused_signal, unused_frame):
184193
demo_trees
185194
)
186195
)
196+
window.ui.reload_button.clicked.connect(
197+
functools.partial(
198+
on_connection_reload_request,
199+
backend,
200+
window,
201+
)
202+
)
187203
window.ui.screenshot_button.clicked.connect(
188204
functools.partial(
189205
capture_screenshot,

0 commit comments

Comments
 (0)