예제 #1
0
    def test_offline_goal(self):

        method_prefix = self.__message_prefix + "TestOfflineGoal"
        planner_prefix = method_prefix + "/Manager"
        m = Manager(activationThreshold=7, prefix=planner_prefix)

        topic_name = method_prefix + '/Topic'

        sensor = SimpleTopicSensor(topic=topic_name,
                                   message_type=Bool,
                                   initial_value=False)
        condition = Condition(sensor, BooleanActivator())

        pddl_function_name = condition.getFunctionNames()[0]
        SetTrueBehavior(effect_name=pddl_function_name,
                        topic_name=topic_name,
                        name=method_prefix + "SetTrue",
                        plannerPrefix=planner_prefix)
        goal = OfflineGoal('CentralGoal', planner_prefix=planner_prefix)
        goal.add_condition(condition)
        m.add_goal(goal)
        for x in range(0, 3, 1):
            m.step()
            rospy.sleep(0.1)

        goal.fetchStatus(3)

        self.assertTrue(goal.satisfied, 'Goal is not satisfied')

        goal.unregister()
예제 #2
0
    def test_activator(self):
        method_prefix = self.__message_prefix + "TestOfflineGoal"
        planner_prefix = method_prefix + "Manager"
        m = Manager(activationThreshold=7, prefix=planner_prefix)

        topic_name = 'IncreaseTopicTest/Topic'

        sensor = TopicSensor(topic=topic_name, name='IncreaseTopicTestSensor', message_type=Int32,
                             initial_value=0)
        activator = GreedyActivator()
        condition = Condition(sensor=sensor, activator=activator)

        IncreaserBehavior(topic_name=topic_name, effect_name=sensor.name,
                          createLogFiles=True, planner_prefix=planner_prefix)
        goal = OfflineGoal(name=self.__message_prefix + 'CentralGoal', planner_prefix=planner_prefix)
        goal.add_condition(condition)
        m.add_goal(goal)

        number_of_steps = 15
        for x in range(0, number_of_steps + 1 , 1):
            m.step()
            rospy.sleep(0.1)

        # it takes 2 steps until the activation has increased
        expected_behaviour_steps = number_of_steps - 2
        self.assertEquals(expected_behaviour_steps, sensor.latestValue)
예제 #3
0
    def test_conditions_in_multiple_levels(self):
        """
        Testing conditions that are used as well on the highest manager hierarchy level as well as in a sub manager of
        a NetworkBehaviour. In particular one conditions is used as precondition, the other one as goal condition.
        """

        method_prefix = self.__message_prefix + "/test_conditions_in_multiple_levels"

        pre_con_sensor = Sensor(name="Precon_sensor", initial_value=False)
        pre_con = Condition(pre_con_sensor, BooleanActivator(desiredValue=True))

        topic_name = method_prefix + '/Topic'
        sensor = TopicSensor(topic=topic_name, message_type=Int32, initial_value=0)
        condition = Condition(sensor, ThresholdActivator(thresholdValue=3))

        planner_prefix = method_prefix + "/Manager"
        m = Manager(activationThreshold=7, prefix=planner_prefix)
        goal = OfflineGoal('CentralGoal', planner_prefix=planner_prefix)
        goal.add_condition(condition)
        m.add_goal(goal)

        effect = Effect(sensor_name=sensor.name, indicator=1, sensor_type=int, activator_name=condition.activator.name)

        first_level_network = NetworkBehaviour(name=method_prefix + '/FirstLevel', planner_prefix=planner_prefix,
                                               createLogFiles=True)
        first_level_network.add_effects([effect])
        first_level_network.add_precondition(pre_con)

        goal_with_same_cond = OfflineGoal('CentralGoal2', planner_prefix=planner_prefix)
        goal_with_same_cond.add_condition(condition)
        first_level_network.add_goal(goal_with_same_cond)

        increaser_behavior = IncreaserBehavior(effect_name=sensor.name, topic_name=topic_name,
                                               name=method_prefix + "TopicIncreaser",
                                               planner_prefix=first_level_network.get_manager_prefix())

        increaser_behavior.add_precondition(pre_con)

        # activate the first_level_network increaser_Behavior
        for x in range(0, 3, 1):
            self.assertFalse(first_level_network._isExecuting)
            m.step()
            pre_con_sensor.update(True)
            rospy.sleep(0.1)

        self.assertTrue(first_level_network._isExecuting)

        for x in range(0, 4, 1):
            m.step()
            rospy.sleep(0.1)

        self.assertTrue(increaser_behavior._isExecuting)
예제 #4
0
    def test_multiple_embedded_network_behaviors(self):
        """
        Tests the case, that one network behavior is embedded into another network behavior.
        The goal requires to receive an int (3) in a topic.
        """

        method_prefix = self.__message_prefix + "/test_multiple_embedded_network_behaviors"

        topic_name = method_prefix + '/Topic'
        sensor = SimpleTopicSensor(topic=topic_name,
                                   message_type=Int32,
                                   initial_value=0)
        condition = Condition(sensor, ThresholdActivator(thresholdValue=3))

        planner_prefix = method_prefix + "/Manager"
        m = Manager(activationThreshold=7, prefix=planner_prefix)
        goal = OfflineGoal('CentralGoal', planner_prefix=planner_prefix)
        goal.add_condition(condition)
        m.add_goal(goal)

        effect = Effect(sensor_name=sensor.name,
                        indicator=1,
                        sensor_type=int,
                        activator_name=condition.activator.name)

        first_level_network = NetworkBehavior(name=method_prefix +
                                              '/FirstLevel',
                                              plannerPrefix=planner_prefix,
                                              createLogFiles=True)
        first_level_network.add_effects_and_goals([(sensor, effect)])

        second_level_network = NetworkBehavior(
            name=method_prefix + '/SecondLevel',
            plannerPrefix=first_level_network.get_manager_prefix(),
            createLogFiles=True)
        # Doesnt matter, whether the effects are added via the constructor or the add method.
        # Both methods are used here, to demonstrate both ways.
        second_level_network.add_effects_and_goals([(sensor, effect)])

        pddl_function_name = condition.getFunctionNames()[0]
        increaser_behavior = IncreaserBehavior(
            effect_name=pddl_function_name,
            topic_name=topic_name,
            name=method_prefix + "TopicIncreaser",
            plannerPrefix=second_level_network.get_manager_prefix())

        # activate the first_level_network, second_level_network and increaser_Behavior
        for x in range(0, 3, 1):
            self.assertFalse(first_level_network._isExecuting)
            m.step()
            rospy.sleep(0.1)
        self.assertTrue(first_level_network._isExecuting)

        for x in range(0, 3, 1):
            self.assertFalse(second_level_network._isExecuting)
            first_level_network.do_step()
            rospy.sleep(0.1)
        self.assertTrue(second_level_network._isExecuting)

        for x in range(0, 3, 1):
            self.assertFalse(increaser_behavior._isExecuting)
            second_level_network.do_step()
            rospy.sleep(0.1)
        self.assertTrue(increaser_behavior._isExecuting)

        # Satisfy goal
        for step in range(0, 3, 1):
            sensor.sync()
            self.assertEqual(step, sensor.value)
            second_level_network.do_step()
            rospy.sleep(0.1)

        goal.fetchStatus(3)
        self.assertTrue(goal.satisfied, 'Goal is not satisfied')
예제 #5
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()
예제 #6
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()