示例#1
0
    def direct_reply(self, result, reply_delay=None, marker=None):
        """
        Reply to the current goal with the given result, after `reply_delay` amount of seconds.

        :param result: a ...Result of the type associated with the type of this server
        :param reply_delay: how long to 'reply_delay/calculate' on this goal before sending the reply
        :param marker: A str that is printed in the output for easy reference between different replies
        """
        assert self._waiting_for == 'direct_reply', "reply cannot follow an 'await_goal', use reply_directly"

        if reply_delay is None:
            reply_delay = self.default_reply_delay

        self._next_reply = result

        # The second {} will be filled by countdown_sleep
        countdown_sleep(reply_delay, text="{}.direct_reply{}: Think for {}s. "
                        .format(self._name, '({})'.format(marker) if marker else '', reply_delay) + "Remaining {}s...")

        self._reply.set()
        self._sent.wait()
        self._sent.clear()

        self._waiting_for = None

        print("{}.direct_reply{}: Finished replying".format(self._name, '({})'.format(marker) if marker else ''))
示例#2
0
    def reply_conditionally(self, condition, true_result, false_result, timeout=None, reply_delay=None, marker=None):
        """
        Reply one of two possibilities, based on a condition. This is a callable that, given a Goal, returns a bool
        If True, then reply with the true_reply and vice versa.
        An AssertionError is raised when a goal is not received within the given timeout.

        :param condition: callable(...Goal) -> bool
        :param true_result: a ...Result
        :param false_result: a ...Result
        :param timeout: seconds to wait for the goal. Defaults to None to wait indefinitely
        :param reply_delay: Delay the reply by this amount of seconds
        :param marker: A str that is printed in the output for easy reference between different replies
        :return: bool
        """
        if reply_delay is None:
            reply_delay = self.default_reply_delay

        print('\n########  {}.reply_conditionally{}  ###########'
            .format(self._name, '({})'.format(marker) if marker else ''))

        assert self._waiting_for is None, "reply_conditionally{} cannot follow an 'await_goal', use reply_directly".format('({})'.format(marker) if marker else '')
        self.default_reply = None

        print("{}.reply_conditionally{}: Waiting {}for goal..."
            .format(self._name, '({})'.format(marker) if marker else '',
                    str(timeout)+'s ' if timeout is not None else ''))
        assert self._request.wait(timeout), "{}.reply_conditionally{} did not get a goal in time"\
            .format(self._name, '({})'.format(marker) if marker else '')

        self._request.clear()
        print("{}.reply_conditionally{}: Got goal: {}"
            .format(self._name, '({})'.format(marker) if marker else '', self.goal_formatter(self._current_goal)))

        print("{}: Think for {}s...".format(self._name, reply_delay))
        match = condition(self._current_goal)
        if match:
            self._next_reply = true_result
        else:
            self._next_reply = false_result
        countdown_sleep(reply_delay, text="{}.reply_conditionally{}: Think for {}s. "
                        .format(self._name, '({})'.format(marker) if marker else '', reply_delay) + "Remaining {}s...")
        # raw_input("Press the any-key to continue: ")

        self._reply.set()
        self._sent.wait()
        self._sent.clear()

        print("{}.reply_conditionally{}: Finished replying"
            .format(self._name, '({})'.format(marker) if marker else ''))

        return match
    def _execute_cb(self):
        """
        Called when the underlying action server receives a goal.
        If the default_result is None, it will wait for a custom result to be set via reply* otherwise
        return the default_result after the given default_result_delay

        In the reply-case,it then notifies self.reply* (which should be called by a test script outside this class),
        after which self.reply* determines the result to the goal.
        Then it notifies _execute_cb that the result has been determined so that _execute_cb can send it
        """
        print('\n########  {}.execute  ###########'.format(self._name))

        self._current_goal = self._as.accept_new_goal()
        self._received_goals.append(self._current_goal)

        try:
            goal_str = self.goal_formatter(self._current_goal)
        except Exception as e:
            rospy.logerr("goal_formatter of {} raised an exception: {}".format(
                self._name, e))
            goal_str = self._current_goal
        print('{}.execute: From {} to Goal: {}'.format(self._name,
                                                       self.pose_bl, goal_str))

        if self.default_reply is not None:
            countdown_sleep(self._default_reply_delay,
                            text="{}.execute: Wait for {}s. ".format(
                                self._name, self._default_reply_delay) +
                            "Remaining {}s...")
            self._call_pre_reply_callbacks(self._current_goal,
                                           self.default_reply)
            self._send_result(self.default_reply)
        else:
            self._request.set()
            # Now, wait for  to be called, which sets the _reply event AND the _next_reply
            self._reply.wait()
            self._reply.clear()

            self._call_pre_reply_callbacks(self._current_goal,
                                           self._next_reply)
            self._send_result(self._next_reply)

            self._next_reply = None
            self._current_goal = None
            self._sent.set()
    def _execute_cb(self, request):
        """
        Called when the underlying service receives a goal.
        If the default_result is None, it will wait for a custom result to be set via reply* otherwise
        return the default_result after the given default_result_delay

        In the reply-case,it then notifies self.reply* (which should be called by a test script outside this class),
        after which self.reply* determines the result to the goal.
        Then it notifies _execute_cb that the result has been determined so that _execute_cb can send it
        """

        self._current_goal = request
        try:
            request_str = self.goal_formatter(self._current_goal)
        except Exception as e:
            rospy.logerr(
                "request_formatter of {} raised an exception: {}".format(
                    self._name, e))
            request_str = self._current_goal
        print('{}.execute: Request: {}'.format(self._name, request_str))

        if self.default_reply is not None:
            result = self.default_reply
            countdown_sleep(self._default_reply_delay,
                            text="{}.execute: Wait for {}s. ".format(
                                self._name, self._default_reply_delay) +
                            "Remaining {}s...")
        else:
            self._request.set()
            # Now, wait for  to be called, which sets the _reply event AND the _next_reply
            self._reply.wait()
            self._reply.clear()

            result = self._next_reply

            self._next_reply = None
            self._current_goal = None
            self._sent.set()

        self._call_pre_reply_callbacks(request, result)
        return result
示例#5
0
    def reply(self, result, timeout=None, reply_delay=None, marker=None):
        """
        Reply to the next goal with the given result, after `reply_delay` amount of seconds.
        An AssertionError is raised when a goal is not received within the given timeout.

        :param result: an ...ActionResult of the type associated with the Action-type of this server
        :param timeout: how long to wait for the goal? Defaults to None to wait indefinitely
        :param reply_delay: how to to reply_delay/calculate on this goal before sending the reply
        :param marker: A str that is printed in the output for easy reference between different replies
        :return: None
        """
        if reply_delay is None:
            reply_delay = self.default_reply_delay

        print('\n########  {}.reply{}  ###########'.format(self._name, '({})'.format(marker) if marker else ''))

        assert self._waiting_for is None, "reply{} cannot follow an 'await_goal', use reply_directly".format('({})'.format(marker) if marker else '')
        self.default_reply = None

        print("{}.reply{}: Waiting {}for goal...".format(self._name, '({})'.format(marker) if marker else '',
                                                         str(timeout)+'s ' if timeout is not None else ''))

        assert self._request.wait(timeout), \
            "{}.reply{} did not get a goal in time".format(self._name, '({})'.format(marker) if marker else '')

        self._request.clear()
        print("{}.reply{}: Got goal: {}"
            .format(self._name, '({})'.format(marker) if marker else '', self.goal_formatter(self._current_goal)))

        self._next_reply = result

        # The second {} will be filled by countdown_sleep
        countdown_sleep(reply_delay, text="{}.reply{}: Think for {}s. ".format(self._name, '({})'.format(marker) if marker else '', reply_delay) + "Remaining {}s...")

        self._reply.set()
        self._sent.wait()
        self._sent.clear()

        print("{}.reply{}: Finished replying"
            .format(self._name, '({})'.format(marker) if marker else ''))