Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rclpy wait for service #127

Closed
wants to merge 49 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
372c1a9
Dirty: First proof of concept for wait_for_service implementation
sloretz Oct 10, 2017
817990a
Moved wait set code to its own class for code reuse
sloretz Oct 13, 2017
9b91a62
Added timeout_sec_to_nsec()
sloretz Oct 13, 2017
371c917
wait_for_service() implemented with timers
sloretz Oct 13, 2017
b17f497
Added unit tests for timeout_sec_to_nsec()
sloretz Oct 13, 2017
35898a6
Added test for WaitSet class
sloretz Oct 13, 2017
5b1ca62
Use negative timeouts to mean block forever
sloretz Oct 13, 2017
489bc0e
Double quotes to single quotes
sloretz Oct 13, 2017
f854466
Added wait_for_service() tests and fixed bugs it caught
sloretz Oct 13, 2017
9255e1f
Eliminate blind exception warning
sloretz Oct 13, 2017
f89a222
Reduce flakiness of test by increasing time to 0.1s
sloretz Oct 13, 2017
39ac231
Comment says negative timeouts block forever
sloretz Oct 17, 2017
3237ed8
Use :returns:
sloretz Oct 17, 2017
7acb2a6
Move add_subscriptions()
sloretz Oct 17, 2017
4720d3f
arugments -> arguments
sloretz Oct 17, 2017
395934a
Daemon as keyword arg
sloretz Oct 17, 2017
1c9a098
Remove unnecessary namespace argument
sloretz Oct 17, 2017
655425f
Use S_TO_NS in test
sloretz Oct 17, 2017
ccd93d8
More tests using S_TO_NS
sloretz Oct 17, 2017
441bbb5
Use monotonic clock for testing timer time
sloretz Oct 17, 2017
8733c14
Increased test timeout by 30 seconds
sloretz Oct 17, 2017
3f26246
CheckExact -> IsValid
sloretz Oct 17, 2017
0a79f28
Fixed wait_set not clearing ready_pointers
sloretz Oct 17, 2017
65c545f
Remove unnecessary namespace keyword arg
sloretz Oct 18, 2017
d81684c
Non-blocking wait
sloretz Oct 18, 2017
4bbc323
remove expression that always evaluates to True
sloretz Oct 18, 2017
99280ae
Raise ValueError on invalid capsule
sloretz Oct 19, 2017
1d2beeb
Simplified timeout_sec_to_nsec
sloretz Oct 19, 2017
6980711
Added 'WaitSet.destroy()' and made executor use it
sloretz Oct 24, 2017
c69858f
GraphListener periodically checks if rclpy is shutdown
sloretz Oct 24, 2017
4cd2fb1
Misc fixes after pycapsule names
sloretz Oct 25, 2017
0cf2aeb
Wait set class always clears entities before waiting
sloretz Oct 31, 2017
7843c5c
Remove underscore on import
sloretz Oct 31, 2017
ded618f
Reformat timeout line
sloretz Oct 31, 2017
e8f7fd6
Use () when raising exceptions
sloretz Oct 31, 2017
149ad43
Removed _ on imports
sloretz Oct 31, 2017
dd86a13
Executor optimizations
sloretz Nov 1, 2017
6352e86
Fixed executor yielding entities to wrong node
sloretz Nov 1, 2017
0dbf8c7
Use list() only where necessary
sloretz Nov 1, 2017
1a2ce96
Docstring in imperitive mood
sloretz Nov 1, 2017
7ee5ead
Executors reuse iterator
sloretz Nov 1, 2017
3628db4
moved some wait_set code into C
sloretz Nov 2, 2017
b71d1c5
Avoid another list comprehension
sloretz Nov 2, 2017
9d9113d
Replaced WaitSet with C code in executor
sloretz Nov 3, 2017
adfddf6
Remove test code
sloretz Nov 3, 2017
315db4e
Use lists instead of set
sloretz Nov 8, 2017
e078c47
Use locally defined function instead of member function
sloretz Nov 8, 2017
5c92085
Shorten code using macro
sloretz Nov 8, 2017
70b8652
Move everything to new wait_set code
sloretz Nov 9, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 27 additions & 1 deletion rclpy/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,24 @@ function(configure_python_c_extension_library _library_name)
)
endfunction()


# Sigint handling stuff
add_library(
rclpy_sigint
SHARED src/rclpy/sigint_gc.c
)
target_include_directories(rclpy_sigint PUBLIC ${CMAKE_SOURCE_DIR})
configure_python_c_extension_library(rclpy_sigint)
ament_target_dependencies(rclpy_sigint
"rcl"
)

# Main library
add_library(
rclpy
SHARED src/rclpy/_rclpy.c
)
target_link_libraries(rclpy rclpy_sigint)
configure_python_c_extension_library(rclpy)
ament_target_dependencies(rclpy
"rcl"
Expand All @@ -93,6 +107,18 @@ ament_target_dependencies(rclpy_logging
"rcutils"
)

# WaitSet wrapper library
add_library(
rclpy_wait_set
SHARED src/rclpy/_rclpy_wait_set.c
)
target_link_libraries(rclpy_wait_set rclpy_sigint)
configure_python_c_extension_library(rclpy_wait_set)
ament_target_dependencies(rclpy_wait_set
"rcl"
"rcutils"
)

if(BUILD_TESTING)
find_package(ament_lint_auto REQUIRED)
ament_lint_auto_find_test_dependencies()
Expand All @@ -110,7 +136,7 @@ if(BUILD_TESTING)
WORKING_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}"
PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE}"
APPEND_ENV AMENT_PREFIX_PATH=${ament_index_build_path}
TIMEOUT 90
TIMEOUT 120
)
endif()
endif()
Expand Down
54 changes: 43 additions & 11 deletions rclpy/rclpy/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@

import threading

from rclpy.graph_listener import GraphEventSubscription
from rclpy.impl.implementation_singleton import rclpy_implementation as _rclpy
from rclpy.impl.implementation_singleton import rclpy_wait_set_implementation as _rclpy_wait_set
import rclpy.utilities


Expand All @@ -23,24 +25,18 @@ class ResponseThread(threading.Thread):
def __init__(self, client):
threading.Thread.__init__(self)
self.client = client
self.wait_set = _rclpy.rclpy_get_zero_initialized_wait_set()
_rclpy.rclpy_wait_set_init(self.wait_set, 0, 1, 0, 1, 0)
_rclpy.rclpy_wait_set_clear_entities('client', self.wait_set)
_rclpy.rclpy_wait_set_add_entity(
'client', self.wait_set, self.client.client_handle)
self._wait_set = _rclpy_wait_set.WaitSet()

def run(self):
[sigint_gc, sigint_gc_handle] = _rclpy.rclpy_get_sigint_guard_condition()
_rclpy.rclpy_wait_set_add_entity('guard_condition', self.wait_set, sigint_gc)
self._wait_set.add_guard_conditions([sigint_gc])
self._wait_set.add_clients([self.client.client_handle])

_rclpy.rclpy_wait(self.wait_set, -1)

guard_condition_ready_list = \
_rclpy.rclpy_get_ready_entities('guard_condition', self.wait_set)
self._wait_set.wait(-1)

# destroying here to make sure we dont call shutdown before cleaning up
_rclpy.rclpy_destroy_entity(sigint_gc)
if sigint_gc_handle in guard_condition_ready_list:
if self._wait_set.is_ready(sigint_gc):
rclpy.utilities.shutdown()
return
response = _rclpy.rclpy_take_response(
Expand Down Expand Up @@ -77,3 +73,39 @@ def wait_for_future(self):
thread1 = ResponseThread(self)
thread1.start()
thread1.join()

def service_is_ready(self):
return _rclpy.rclpy_service_server_is_available(self.node_handle, self.client_handle)

def wait_for_service(self, timeout_sec=None):
"""
Block until the service is available.

:param timeout_sec: Seconds to wait. Block forever if None or negative. Don't wait if 0
:type timeout_sec: float or None
:rtype: bool
:returns: true if the service is available
"""
timeout_nsec = rclpy.utilities.timeout_sec_to_nsec(timeout_sec)
result = self.service_is_ready()
if result or timeout_sec == 0:
return result

event = threading.Event()

def on_graph_event():
nonlocal self
nonlocal event
nonlocal result
result = self.service_is_ready()
if result:
event.set()

def on_timeout():
nonlocal event
event.set()

with GraphEventSubscription(self.node_handle, on_graph_event, timeout_nsec, on_timeout):
event.wait()

return result
Loading