示例#1
0
class NetworkBehaviour(BehaviourBase):
    """
    Behavior, which encapsulates an additional manager and behaviors.
    This allows to build hierarchies of hybrid behaviour planners.
    """

    MANAGER_POSTFIX = "Manager"
    TYPE_STRING = "Network"

    def __init__(self,
                 name,
                 requires_execution_steps=True,
                 only_running_for_deciding_interruptible=Manager.
                 USE_ONLY_RUNNING_BEHAVIOURS_FOR_INTERRUPTIBLE_DEFAULT_VALUE,
                 correlations=None,
                 always_update_activation=False,
                 guarantee_decision=False,
                 **kwargs):
        """
        :param correlations: tuple <Effect>
        :param name: name of the behaviour that is also used to create the sub manager name together with the NetworkBehaviour.MANAGER_POSTFIX
        :param requires_execution_steps: whether the execution steps should be caused from the parent manager or not.
                If not, the step method must be called manually
        :param always_update_activation: if set to True the entire activation calculation of the sub manager is updated on each behaviour computation update
        :param guarantee_decision: if there are executable behaviours in the local network, adjust the thresholds until
               at least one behaviour is selected
        :param kwargs: args for the manager, except the prefix arg
        """
        super(NetworkBehaviour,
              self).__init__(name=name,
                             requires_execution_steps=requires_execution_steps,
                             **kwargs)
        if "interruptable" in kwargs:
            rhbplog.logwarn(
                "Interruptable parameter will be ignored in a NetworkBehaviour. Interruptable attribute is "
                "evaluated based on the running or registered parameters, "
                "see 'only_running_for_deciding_interruptible'")
        self.requires_execution_steps = requires_execution_steps
        self.always_update_activation = always_update_activation
        self.guarantee_decision = guarantee_decision
        manager_args = {}
        manager_args.update(kwargs)
        manager_args['prefix'] = self.get_manager_prefix()
        self.__manager = Manager(enabled=False,
                                 use_only_running_behaviors_for_interRuptible=
                                 only_running_for_deciding_interruptible,
                                 **manager_args)

        self.__goal_name_prefix = name + "/Goals/"
        self.__goal_counter = 0

        if correlations is not None:
            self.add_effects(correlations)

    def get_manager_prefix(self):
        """
        Return the manager prefix generated by the behaviour name and the MANAGER_POSTFIX
        :return: the manager prefix str
        """
        return self._name + '/' + NetworkBehaviour.MANAGER_POSTFIX

    def __generate_goal_name(self, effect):
        """
        :param effect: instance of type  Effect
        :return: unique name for goal
        """
        # x as separator between counter an sensor names, to prevent conflict, caused by unusual names
        name = self.__goal_name_prefix + str(
            self.__goal_counter) + 'X' + effect.sensor_name
        self.__goal_counter += 1
        return name

    def _create_goal(self, sensor, effect, goal_name):
        """
        Generate goals, which made the manager trying to work infinitely on the given effect,
         until the network is stopped. Therefore the goal shouldn't reachable (except the goal for boolean effects)
        :param sensor: instance of type Sensor
        :param effect: instance of type  Effect
        :param goal_name: unique name for the goal
        :return: a goal, which causes the manager to work on the effect during the whole time
        :raises RuntimeError: if the creation of a goal for an effect of this
                type is not possible
        """

        try:
            condition = create_condition_from_effect(effect=effect,
                                                     sensor=sensor)
            return OfflineGoal(name=goal_name,
                               planner_prefix=self.get_manager_prefix(),
                               permanent=True,
                               conditions={condition})
        except RuntimeError:
            raise RuntimeError(
                msg="Can't create goal for effect type '" +
                effect.sensor_type +
                "'.Overwrite the method _create_goal to handle the type")

    @deprecated
    def add_correlations(self, correlations):
        """
        Adds the given effects to the correlations of this Behavior. 
        DEPRECATED: Use *add_effects* instead
        :param correlations: list of Effects
        """
        self.add_effects(correlations)

    @deprecated
    def add_correlations_and_goals(self, sensor_correlations):
        """
        Adds the given effects to the correlations of this Behavior. 
        Furthermore creates a goal for each Effect and registers it at the nested Manager
        DEPRECATED: Use *add_effects_and_goals* instead
        :param sensor_correlations: list of tuples of (Sensor, Effect)
        """
        self.add_effects_and_goals(sensor_correlations)

    def add_effects(self, effects):
        """
        Adds the given effects to this Behavior. 
        :param effects: list of Effects
        """
        self._correlations.extend(effects)

    def add_effects_and_goals(self, sensor_effect):
        """
        Adds the given effects to the correlations of this Behavior. 
        Furthermore creates a goal for each Effect and registers it at the nested Manager
        :param sensor_effect: list of tuples of (Sensor, Effect)
        """
        for sensor, effect in sensor_effect:
            goal_name = self.__generate_goal_name(effect)
            goal = self._create_goal(sensor=sensor,
                                     effect=effect,
                                     goal_name=goal_name)
            self.__manager.add_goal(goal)
            self._correlations.append(effect)

    def add_goal(self, goal):
        """
        Adds the given goal to nested manager
        :param goal: AbstractGoalRepresentation
        """
        self.__manager.add_goal(goal)

    def updateComputation(self, manager_step):
        super(NetworkBehaviour, self).updateComputation(manager_step)

        # only trigger the update if not already activated because then it would be executed anyhow
        if self.always_update_activation and not self.__manager.enabled:
            self.__manager.update_activation(plan_if_necessary=False)

        if not self._isExecuting:
            self.__manager.send_discovery()

    def do_step(self):
        self.__manager.step(guarantee_decision=self.guarantee_decision)

    def start(self):
        self.__manager.enable()

    def stop(self):
        self.__manager.disable()

    def _is_interruptible(self):
        return self.__manager.is_interruptible()
示例#2
0
class NetworkBehavior(BehaviourBase):
    """
    Behavior, which encapsulates an additional manager and behaviors.
    This allows to build hierarchies of hybrid behaviour planners.
    """

    MANAGER_POSTFIX = "Manager"

    def __init__(self,
                 name,
                 requires_execution_steps=True,
                 only_running_for_deciding_interruptible=Manager.
                 USE_ONLY_RUNNING_BEHAVIOURS_FOR_INTERRUPTIBLE_DEFAULT_VALUE,
                 correlations=None,
                 always_update_activation=False,
                 **kwargs):
        """
        :param correlations: tuple <Effect>
        :param name: name of the behaviour that is also used to create the sub manager name together with the NetworkBehavior.MANAGER_POSTFIX
        :param requires_execution_steps: whether the execution steps should be caused from the parent manager or not.
                If not, the step method must be called manually
        :param always_update_activation: if set to True the entire activation calculation of the sub manager is updated on each behaviour computation update
        :param kwargs: args for the manager, except the prefix arg
        """
        super(NetworkBehavior,
              self).__init__(name=name,
                             requires_execution_steps=requires_execution_steps,
                             **kwargs)
        self.requires_execution_steps = requires_execution_steps
        self.always_update_activation = always_update_activation
        manager_args = {}
        manager_args.update(kwargs)
        manager_args['prefix'] = self.get_manager_prefix()
        self.__manager = Manager(activated=False,
                                 use_only_running_behaviors_for_interRuptible=
                                 only_running_for_deciding_interruptible,
                                 **manager_args)

        self.__goal_name_prefix = name + "/Goals/"
        self.__goal_counter = 0

        if correlations is not None:
            self.add_effects(correlations)

    def updateComputation(self, manager_step):
        super(NetworkBehavior, self).updateComputation(manager_step)
        if not self._isExecuting:
            self.__manager.send_discovery()

    def _restore_condition_name_from_pddl_function_name(
            self, pddl_function_name, sensor_name):
        return Activator.restore_condition_name_from_pddl_function_name(
            pddl_function_name=pddl_function_name, sensor_name=sensor_name)

    def get_manager_prefix(self):
        """
        Return the manager prefix generated by the behaviour name and the MANAGER_POSTFIX
        :return: the manager prefix str
        """
        return self._name + '/' + NetworkBehavior.MANAGER_POSTFIX

    def __generate_goal_name(self, effect):
        """
        :param effect: instance of type  Effect
        :return: unique name for goal
        """
        # x as separator between counter an sensor names, to prevent conflict, caused by unusual names
        name = self.__goal_name_prefix + str(
            self.__goal_counter) + 'X' + effect.sensor_name
        self.__goal_counter += 1
        return name

    def _create_goal(self, sensor, effect, goal_name, activator_name):
        """
        Generate goals, which made the manager trying to work infinitely on the given effect,
         until the network is stopped. Therefore the goal shouldn't reachable (except the goal for boolean effects)
        :param sensor: instance of type Sensor
        :param effect: instance of type  Effect
        :param goal_name: unique name for the goal
        :return: a goal, which causes the manager to work on the effect during the whole time
        """
        if effect.sensor_type == str(bool):
            desired_value = True if effect.indicator > 0 else False
            activator = BooleanActivator(name=activator_name,
                                         desiredValue=desired_value)
            condition = Condition(activator=activator, sensor=sensor)
            return OfflineGoal(name=goal_name,
                               planner_prefix=self.get_manager_prefix(),
                               permanent=True,
                               conditions={condition})
        if effect.sensor_type == str(int) or effect.sensor_type == str(float):
            activator = GreedyActivator(maximize=effect.indicator > 0,
                                        step_size=abs(effect.indicator),
                                        name=activator_name)
            condition = Condition(activator=activator, sensor=sensor)
            return OfflineGoal(goal_name,
                               planner_prefix=self.get_manager_prefix(),
                               permanent=True,
                               conditions={condition})
        raise RuntimeError(
            msg='Cant create goal for effect type \'' + effect.sensor_type +
            '\'. Overwrite the method _create_goal to handle the type')

    @deprecated
    def add_correlations(self, correlations):
        """
        Adds the given effects to the correlations of this Behavior. 
        DEPRECATED: Use *add_effects* instead
        :param correlations: list of Effects
        """
        self.add_effects(correlations)

    @deprecated
    def add_correlations_and_goals(self, sensor_correlations):
        """
        Adds the given effects to the correlations of this Behavior. 
        Furthermore creates a goal for each Effect and registers it at the nested Manager
        DEPRECATED: Use *add_effects_and_goals* instead
        :param sensor_correlations: list of tuples of (Sensor, Effect)
        """
        self.add_effects_and_goals(sensor_correlations)

    def add_effects(self, effects):
        """
        Adds the given effects to this Behavior. 
        :param effects: list of Effects
        """
        self._correlations.extend(effects)

    def add_effects_and_goals(self, sensor_effect):
        """
        Adds the given effects to the correlations of this Behavior. 
        Furthermore creates a goal for each Effect and registers it at the nested Manager
        :param sensor_effect: list of tuples of (Sensor, Effect)
        """
        #TODO this might has to be revised
        for sensor, effect in sensor_effect:
            goal_name = self.__generate_goal_name(effect)
            if not effect.activator_name:
                activator_name = self._restore_condition_name_from_pddl_function_name(
                    effect.sensor_name, sensor.name)
            else:
                activator_name = effect.activator_name
            goal = self._create_goal(sensor=sensor,
                                     effect=effect,
                                     goal_name=goal_name,
                                     activator_name=activator_name)
            self.__manager.add_goal(goal)
            self._correlations.append(effect)

    def add_goal(self, goal):
        """
        Adds the given goal to nested manager
        :param goal: AbstractGoalRepresentation
        """
        self.__manager.add_goal(goal)

    def updateComputation(self, manager_step):
        super(NetworkBehavior, self).updateComputation(manager_step)

        # only trigger the update if not already activated because then it would be executed anyhow
        if self.always_update_activation and not self.__manager.activated:
            self.__manager.update_activation(plan_if_necessary=False)

    def do_step(self):
        self.__manager.step()

    def start(self):
        self.__manager.activate()

    def stop(self):
        self.__manager.deactivate()

    def _is_interruptible(self):
        return self.__manager.is_interruptible()
示例#3
0
class ManagerNode(object):
    """
    ROS node wrapper for the rhbp manager/planner
    """

    def __init__(self):
        rospy.init_node('behaviourPlannerManager', log_level=rospy.WARN)
        prefix = rospy.get_param("~prefix", "")
        self._manager = Manager(prefix=prefix)
        self.rate = rospy.Rate(rospy.get_param("~frequency", 1))

        self.automatic_stepping = rospy.get_param("~automatic_stepping", True)

        if not self.automatic_stepping:
            rospy.logwarn("Started in manual stepping mode")

        self._init_services(prefix)

    def _init_services(self, prefix):
        """
        init all services handlers
        :param prefix: manager prefix
        """
        self._set_automatic_stepping_service = rospy.Service(prefix + '/' + 'set_automatic_stepping', SetStepping,
                                                             self._set_stepping_callback)
        self._get_automatic_stepping_service = rospy.Service(prefix + '/' + 'get_automatic_stepping', GetStepping,
                                                             self._get_stepping_callback)
        self._stepping_service = rospy.Service(prefix + '/' + 'step', Empty, self._step_callback)

    def _set_stepping_callback(self, request):
        """
        Callback service for enabling or disabling automatic stepping in the given frequency
        :param request:
        """
        self.automatic_stepping = request.automatic_stepping

        rospy.loginfo("Automatic Stepping changed to " + str(self.automatic_stepping))

        return SetSteppingResponse()

    def _get_stepping_callback(self, request):
        """
        Callback service for getting the current automatic stepping setting
        :param request:
        """
        response = GetSteppingResponse(self.automatic_stepping)

        return response

    def _step_callback(self, request):
        """
        Service callback for manual planning/manager steps
        :param request:
        """
        if not self.automatic_stepping:
            self._manager.step()
        else:
            rospy.logwarn("No manual stepping if automatic stepping is enabled")
        return EmptyResponse()

    def run(self):
        """
        Executing the node after initialization
        """
        while (not rospy.is_shutdown()):
            if self.automatic_stepping:
                self._manager.step()
            else:
                self._manager.send_discovery()
            self.rate.sleep()