Beispiel #1
0
    def call_async(self, request: SrvTypeRequest) -> Future:
        """
        Make a service request and asyncronously get the result.

        :param request: The service request.
        :return: A future that completes when the request does.
        :raises: TypeError if the type of the passed request isn't an instance
          of the Request type of the provided service when the client was
          constructed.
        """
        if not isinstance(request, self.srv_type.Request):
            raise TypeError()

        with self._lock:
            with self.handle:
                sequence_number = self.__client.send_request(request)
            if sequence_number in self._pending_requests:
                raise RuntimeError(
                    f'Sequence ({sequence_number}) conflicts with pending request'
                )

            future = Future()
            self._pending_requests[sequence_number] = future

            future.add_done_callback(self.remove_pending_request)

        return future
Beispiel #2
0
    def _get_result_async(self, goal_handle):
        """
        Request the result for an active goal asynchronously.

        :param goal_handle: Handle to the goal to cancel.
        :type goal_handle: :class:`ClientGoalHandle`
        :return: a Future instance that completes when the get result request has been processed.
        :rtype: :class:`rclpy.task.Future` instance
        """
        if not isinstance(goal_handle, ClientGoalHandle):
            raise TypeError(
                'Expected type ClientGoalHandle but received {}'.format(type(goal_handle)))

        result_request = self._action_type.Impl.GetResultService.Request()
        result_request.goal_id = goal_handle.goal_id
        sequence_number = _rclpy_action.rclpy_action_send_result_request(
            self._client_handle,
            result_request)
        if sequence_number in self._pending_result_requests:
            raise RuntimeError(
                'Sequence ({}) conflicts with pending result request'.format(sequence_number))

        future = Future()
        self._pending_result_requests[sequence_number] = future
        future.add_done_callback(self._remove_pending_result_request)
        # Add future so executor is aware
        self.add_future(future)

        return future
Beispiel #3
0
    def spin_until_future_complete(self,
                                   future: Future,
                                   timeout_sec: float = None) -> None:
        """Execute callbacks until a given future is done or a timeout occurs."""
        # Make sure the future wakes this executor when it is done
        future.add_done_callback(lambda x: self.wake())

        if timeout_sec is None or timeout_sec < 0:
            while self._context.ok(
            ) and not future.done() and not self._is_shutdown:
                self.spin_once_until_future_complete(future, timeout_sec)
        else:
            start = time.monotonic()
            end = start + timeout_sec
            timeout_left = timeout_sec

            while self._context.ok(
            ) and not future.done() and not self._is_shutdown:
                self.spin_once_until_future_complete(future, timeout_left)
                now = time.monotonic()

                if now >= end:
                    return

                timeout_left = end - now
Beispiel #4
0
    def _cancel_goal_async(self, goal_handle):
        """
        Send a cancel request for an active goal and asynchronously get the result.

        :param goal_handle: Handle to the goal to cancel.
        :type goal_handle: :class:`ClientGoalHandle`
        :return: a Future instance that completes when the cancel request has been processed.
        :rtype: :class:`rclpy.task.Future` instance
        """
        if not isinstance(goal_handle, ClientGoalHandle):
            raise TypeError(
                'Expected type ClientGoalHandle but received {}'.format(
                    type(goal_handle)))

        cancel_request = CancelGoal.Request()
        cancel_request.goal_info.goal_id = goal_handle.goal_id
        sequence_number = self._client_handle.send_cancel_request(
            cancel_request)
        if sequence_number in self._pending_cancel_requests:
            raise RuntimeError(
                'Sequence ({}) conflicts with pending cancel request'.format(
                    sequence_number))

        future = Future()
        self._pending_cancel_requests[sequence_number] = future
        future.add_done_callback(self._remove_pending_cancel_request)
        # Add future so executor is aware
        self.add_future(future)

        return future
Beispiel #5
0
    def test_add_done_callback_invokes_callback(self):
        called = False

        def cb(fut):
            nonlocal called
            called = True

        f = Future()
        f.set_result('Anything')
        f.add_done_callback(cb)
        assert called
Beispiel #6
0
    def test_set_exception_invokes_callbacks(self):
        called = False

        def cb(fut):
            nonlocal called
            called = True

        f = Future()
        f.add_done_callback(cb)
        f.set_exception('Anything')
        assert called
Beispiel #7
0
    def test_cancel_invokes_callbacks(self):
        called = False

        def cb(fut):
            nonlocal called
            called = True

        f = Future()
        f.add_done_callback(cb)
        f.cancel()
        assert called
def main(args=None):
    rclpy.init(args=args)
    node = SkibotNode()
    executor = MultiThreadedExecutor(num_threads=4)
    executor.add_node(node)
    future = Future()
    future.add_done_callback(lambda fut: print("Future is done"))

    executor.spin_until_future_complete(future)

    node.destroy_node()
    rclpy.shutdown()
Beispiel #9
0
    def send_goal_async(self, goal, feedback_callback=None, goal_uuid=None):
        """
        Send a goal and asynchronously get the result.

        The result of the returned Future is set to a ClientGoalHandle when receipt of the goal
        is acknowledged by an action server.

        :param goal: The goal request.
        :type goal: action_type.Goal
        :param feedback_callback: Callback function for feedback associated with the goal.
        :type feedback_callback: function
        :param goal_uuid: Universally unique identifier for the goal.
            If None, then a random UUID is generated.
        :type: unique_identifier_msgs.UUID
        :return: a Future instance to a goal handle that completes when the goal request
            has been accepted or rejected.
        :rtype: :class:`rclpy.task.Future` instance
        :raises: TypeError if the type of the passed goal isn't an instance of
          the Goal type of the provided action when the service was
          constructed.
        """
        if not isinstance(goal, self._action_type.Goal):
            raise TypeError()

        request = self._action_type.Impl.SendGoalService.Request()
        request.goal_id = self._generate_random_uuid(
        ) if goal_uuid is None else goal_uuid
        request.goal = goal
        sequence_number = _rclpy_action.rclpy_action_send_goal_request(
            self._client_handle, request)
        if sequence_number in self._pending_goal_requests:
            raise RuntimeError(
                'Sequence ({}) conflicts with pending goal request'.format(
                    sequence_number))

        if feedback_callback is not None:
            # TODO(jacobperron): Move conversion function to a general-use package
            goal_uuid = bytes(request.goal_id.uuid)
            self._feedback_callbacks[goal_uuid] = feedback_callback

        future = Future()
        self._pending_goal_requests[sequence_number] = future
        self._sequence_number_to_goal_id[sequence_number] = request.goal_id
        future.add_done_callback(self._remove_pending_goal_request)
        # Add future so executor is aware
        self.add_future(future)

        return future
Beispiel #10
0
    def call_async(self, req):
        """
        Make a service request and asyncronously get the result.

        :return: a Future instance that completes when the request does
        :rtype: :class:`rclpy.task.Future` instance
        """
        sequence_number = _rclpy.rclpy_send_request(self.client_handle, req)
        if sequence_number in self._pending_requests:
            raise RuntimeError('Sequence (%r) conflicts with pending request' %
                               sequence_number)

        future = Future()
        self._pending_requests[sequence_number] = future

        future.add_done_callback(self.remove_pending_request)

        return future
Beispiel #11
0
    def call_async(self, request: SrvTypeRequest) -> Future:
        """
        Make a service request and asyncronously get the result.

        :param request: The service request.
        :return: A future that completes when the request does.
        """
        sequence_number = _rclpy.rclpy_send_request(self.client_handle,
                                                    request)
        if sequence_number in self._pending_requests:
            raise RuntimeError('Sequence (%r) conflicts with pending request' %
                               sequence_number)

        future = Future()
        self._pending_requests[sequence_number] = future

        future.add_done_callback(self.remove_pending_request)

        return future
Beispiel #12
0
 def spin_once_until_future_complete(self,
                                     future: Future,
                                     timeout_sec: float = None) -> None:
     future.add_done_callback(lambda x: self.wake())
     self._spin_once_impl(timeout_sec, future.done)
Beispiel #13
0
 def test_set_exception_schedules_callbacks(self):
     executor = DummyExecutor()
     f = Future(executor=executor)
     f.add_done_callback(lambda f: None)
     f.set_exception('Anything')
     self.assertTrue(executor.done_callbacks)
Beispiel #14
0
 def test_cancel_schedules_callbacks(self):
     executor = DummyExecutor()
     f = Future(executor=executor)
     f.add_done_callback(lambda f: None)
     f.cancel()
     self.assertTrue(executor.done_callbacks)