Пример #1
0
    def set_contained_state(label,
                            state,
                            loop_outcomes=[],
                            break_outcomes=[],
                            final_outcome_map={}):
        """Set the contained state
        
        @type label: string
        @param label: The label of the state being added.
        
        @type state: L{smach.State}
        @param state: An instance of a class implementing the L{smach.State} interface.

        @param loop_outcomes: List of contained state outcomes that should cause
        the iterator to continue. If this is empty, all outcomes that are not
        in the break_outcomes list will cause the iterator to continue to
        iterate. NOTE: loop_outcomes will be overriden by break_outcomes if both
        parameters are used.

        @param break_outcomes: List of contained state outcomes that should
        cause the iterator to break. When the contained state emits an outcome
        in this list, the container will terminate and return either that
        outcome or the outcome it is mapped to in final_outcome_map. NOTE:
        loop_outcomes will be overriden by break_outcomes if both
        parameters are used.

        @param final_outcome_map: A map from contained state outcomes to container
        outcomes. On termination of the iterator (either from finishing or from
        a break) this map will be used to translate contained state outcomes to
        container outcomes.
        Unspecified contained state outcomes will fall through as
        container outcomes.
        """
        # Get currently opened container
        self = Iterator._currently_opened_container()

        self._state_label = label
        self._state = state

        # Get potential state outcomes
        state_outcomes = state.get_registered_outcomes()

        # Check for loop and break outcomes
        if loop_outcomes and break_outcomes:
            smach.logwarn(
                'Both loop_outcomes and break_outcomes were specified when constructing SMACH iterator container.'
            )

        if break_outcomes:
            self._break_outcomes = break_outcomes
            for outcome in state_outcomes:
                if outcome not in break_outcomes:
                    self._loop_outcomes.append(outcome)
        else:
            self._loop_outcomes = loop_outcomes
            for outcome in state_outcomes:
                if outcome not in loop_outcomes:
                    self._break_outcomes.append(outcome)

        self._final_outcome_map = final_outcome_map
Пример #2
0
    def set_contained_state(
            label,
            state,
            loop_outcomes = [],
            break_outcomes = [],
            final_outcome_map = {}):
        """Set the contained state
        
        @type label: string
        @param label: The label of the state being added.
        
        @type state: L{smach.State}
        @param state: An instance of a class implementing the L{smach.State} interface.

        @param loop_outcomes: List of contained state outcomes that should cause
        the iterator to continue. If this is empty, all outcomes that are not
        in the break_outcomes list will cause the iterator to continue to
        iterate. NOTE: loop_outcomes will be overriden by break_outcomes if both
        parameters are used.

        @param break_outcomes: List of contained state outcomes that should
        cause the iterator to break. When the contained state emits an outcome
        in this list, the container will terminate and return either that
        outcome or the outcome it is mapped to in final_outcome_map. NOTE:
        loop_outcomes will be overriden by break_outcomes if both
        parameters are used.

        @param final_outcome_map: A map from contained state outcomes to container
        outcomes. On termination of the iterator (either from finishing or from
        a break) this map will be used to translate contained state outcomes to
        container outcomes.
        Unspecified contained state outcomes will fall through as
        container outcomes.
        """
        # Get currently opened container
        self = Iterator._currently_opened_container()

        self._state_label = label
        self._state = state

        # Get potential state outcomes
        state_outcomes = state.get_registered_outcomes()

        # Check for loop and break outcomes
        if loop_outcomes and break_outcomes:
            smach.logwarn('Both loop_outcomes and break_outcomes were specified when constructing SMACH iterator container.')

        if break_outcomes:
            self._break_outcomes = break_outcomes
            for outcome in state_outcomes:
                if outcome not in break_outcomes:
                    self._loop_outcomes.append(outcome)
        else:
            self._loop_outcomes = loop_outcomes
            for outcome in state_outcomes:
                if outcome not in loop_outcomes:
                    self._break_outcomes.append(outcome)

        self._final_outcome_map = final_outcome_map
Пример #3
0
 def _copy_output_keys(self, ud, parent_ud):
     if parent_ud is not None:
         output_keys = self.get_registered_output_keys()
         for ok in output_keys:
             try:
                 parent_ud[ok] = ud[ok]
             except KeyError:
                 smach.logwarn("Attempting to copy output key '%s', but this key does not exist.")
Пример #4
0
 def _copy_input_keys(self, parent_ud, ud):
     if parent_ud is not None:
         input_keys = self.get_registered_input_keys()
         for ik in input_keys:
             try:
                 ud[ik] = parent_ud[ik]
             except KeyError:
                 smach.logwarn("Attempting to copy input key '%s', but this key does not exist.")
Пример #5
0
 def _copy_output_keys(self, ud, parent_ud):
     if parent_ud is not None:
         output_keys = self.get_registered_output_keys()
         for ok in output_keys:
             try:
                 parent_ud[ok] = ud[ok]
             except KeyError:
                 smach.logwarn(
                     "Attempting to copy output key '%s', but this key does not exist."
                 )
Пример #6
0
 def _copy_input_keys(self, parent_ud, ud):
     if parent_ud is not None:
         input_keys = self.get_registered_input_keys()
         for ik in input_keys:
             try:
                 ud[ik] = parent_ud[ik]
             except KeyError:
                 smach.logwarn(
                     "Attempting to copy input key '%s', but this key does not exist."
                 )
Пример #7
0
    def set_initial_state(self, initial_states, userdata=smach.UserData()):
        smach.logdebug("Setting initial state to "+str(initial_states))

        if len(initial_states) > 1:
            smach.logwarn("Attempting to set initial state to include more than one state, but the StateMachine container can only have one initial state.")

        # Set the initial state label
        if len(initial_states) > 0:
            self._initial_state_label = initial_states[0]
        # Set local userdata
        self.userdata.update(userdata)
Пример #8
0
    def set_initial_state(self, initial_states, userdata):
        # Check initial state
        if len(initial_states) > 1:
            smach.logwarn("Attempting to set initial state to include more than one state, but Iterator container can only have one initial state." % (self._state_label))

        if len(initial_states) > 0:
            if initial_states[0] != self._state_label:
                smach.logwarn("Attempting to set state '%s' as initial state in Iterator container. The only available state is '%s'." % (initial_states[0], self._state_label))
                raise KeyError()

        # Set local userdata
        self.userdata.update(userdata)
Пример #9
0
    def set_initial_state(self, initial_states, userdata):
        # Check initial state
        if len(initial_states) > 1:
            smach.logwarn(
                "Attempting to set initial state to include more than one state, but Iterator container can only have one initial state."
                % (self._state_label))

        if len(initial_states) > 0:
            if initial_states[0] != self._state_label:
                smach.logwarn(
                    "Attempting to set state '%s' as initial state in Iterator container. The only available state is '%s'."
                    % (initial_states[0], self._state_label))
                raise KeyError()

        # Set local userdata
        self.userdata.update(userdata)
Пример #10
0
    def execute(self, parent_ud = smach.UserData()):
        """Overloaded execute method.
        This starts all the threads.
        """
        # Reset child outcomes
        self._child_outcomes = {}

        # Copy input keys
        self._copy_input_keys(parent_ud, self.userdata)

        # Spew some info
        smach.loginfo("Concurrence starting with userdata: \n\t%s" %
                (str(self.userdata.keys())))

        # Call start callbacks
        self.call_start_cbs()

        # Create all the threads
        for (label, state) in self._states.iteritems():
            # Initialize child outcomes
            self._child_outcomes[label] = None
            self._threads[label] = threading.Thread(
                    name='concurrent_split:'+label,
                    target=self._state_runner,
                    args=(label,))

        # Launch threads
        for thread in self._threads.values():
            thread.start()
        
        # Wait for done notification
        self._done_cond.acquire()
        self._done_cond.wait()
        self._done_cond.release()

        # Preempt any running states
        smach.logdebug("SMACH Concurrence preempting running states.")
        for label in self._states:
            if self._child_outcomes[label] == None:
                self._states[label].request_preempt()

        # Wait for all states to terminate
        while not smach.is_shutdown():
            if all([o is not None for o in self._child_outcomes.values()]):
                break
            self._done_cond.acquire()
            self._done_cond.wait()
            self._done_cond.release()

        # Check for user code exception
        if self._user_code_exception:
            self._user_code_exception = False
            raise smach.InvalidStateError("A concurrent state raised an exception during execution.")

        # Check for preempt
        if self.preempt_requested():
            # initialized serviced flag
            children_preempts_serviced = True

            # Service this preempt if 
            for (label,state) in self._states.iteritems():
                if state.preempt_requested():
                    # Reset the flag
                    children_preempts_serviced = False
                    # Complain
                    smach.logwarn("State '%s' in concurrence did not service preempt." % label) 
                    # Recall the preempt if it hasn't been serviced
                    state.recall_preempt()
            if children_preempts_serviced:
                smach.loginfo("Concurrence serviced preempt.")
                self.service_preempt()

        # Spew some debyg info
        smach.loginfo("Concurrent Outcomes: "+str(self._child_outcomes))

        # Initialize the outcome
        outcome = self._default_outcome

        # Determine the outcome from the outcome map
        smach.logdebug("SMACH Concurrence determining contained state outcomes.")
        for (container_outcome, outcomes) in self._outcome_map.iteritems():
            if all([self._child_outcomes[label] == outcomes[label] for label in outcomes.keys()]):
                smach.logdebug("Terminating concurrent split with mapped outcome.")
                outcome = container_outcome

        # Check outcome callback
        if self._outcome_cb:
            try:
                cb_outcome = self._outcome_cb(copy.copy(self._child_outcomes))
                if cb_outcome:
                    if cb_outcome == str(cb_outcome):
                        outcome = cb_outcome
                    else:
                        smach.logerr("Outcome callback returned a non-string '%s', using default outcome '%s'" % (str(cb_outcome), self._default_outcome))
                else:
                    smach.logwarn("Outcome callback returned None, using outcome '%s'" % outcome)
            except:
                raise smach.InvalidUserCodeError(("Could not execute outcome callback '%s': " % self._outcome_cb)+traceback.format_exc())

        # Cleanup
        self._threads = {}
        self._child_outcomes = {}

        # Call termination callbacks
        self.call_termination_cbs(self._states.keys(), outcome)

        # Copy output keys
        self._copy_output_keys(self.userdata, parent_ud)

        return outcome