operatable_state.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 import rospy
00003 
00004 from flexbe_core.core.preemptable_state import PreemptableState
00005 from flexbe_core.core.operatable_state_machine import OperatableStateMachine
00006 
00007 from flexbe_core.proxy import ProxyPublisher, ProxySubscriberCached
00008 from flexbe_msgs.msg import Container, OutcomeRequest
00009 from std_msgs.msg import UInt8, String
00010 
00011 from flexbe_core.state_logger import StateLogger
00012 
00013 
00014 class OperatableState(PreemptableState):
00015     """
00016     A state that supports autonomy levels and silent mode.
00017     Also, it allows being tracked by a GUI or anything else
00018     as it reports each transition and its initial structure.
00019     An additional method is provided to report custom status messages to the widget.
00020     """
00021     
00022     def __init__(self, *args, **kwargs):
00023         super(OperatableState, self).__init__(*args, **kwargs)
00024         self.transitions = None
00025         self.autonomy = None
00026         
00027         self._mute = False  # is set to true when used in silent state machine (don't report transitions)
00028         self._sent_outcome_requests = []  # contains those outcomes that already requested a transition
00029         
00030         self._outcome_topic = 'flexbe/mirror/outcome'
00031         self._request_topic = 'flexbe/outcome_request'
00032         self._debug_topic = 'flexbe/debug/current_state'
00033         self._pub = ProxyPublisher()
00034         
00035         self.__execute = self.execute
00036         self.execute = self._operatable_execute
00037         
00038         
00039     def _build_msg(self, prefix, msg):
00040         """
00041         Adds this state to the initial structure message.
00042         
00043         @type prefix: string
00044         @param prefix: A path consisting of the container hierarchy containing this state.
00045         
00046         @type msg: ContainerStructure
00047         @param msg: The message that will finally contain the structure message.
00048         """
00049         
00050         # set path
00051         name = prefix + self.name
00052         
00053         # no children
00054         children = None
00055         
00056         # set outcomes
00057         outcomes = self._outcome_list
00058         
00059         # set transitions and autonomy levels
00060         transitions = []
00061         autonomy = []
00062         for i in range(len(outcomes)):
00063             outcome = outcomes[i]
00064             if outcome == 'preempted':          # set preempt transition
00065                 transitions.append('preempted')
00066                 autonomy.append(-1)
00067             else:
00068                 transitions.append(str(self.transitions[outcome]))
00069                 autonomy.append(self.autonomy[outcome])
00070         
00071         # add to message
00072         msg.containers.append(Container(name, children, outcomes, transitions, autonomy))
00073         
00074 
00075     def _operatable_execute(self, *args, **kwargs):
00076         outcome = self.__execute(*args, **kwargs)
00077         
00078         if self._is_controlled:
00079             log_requested_outcome = outcome
00080 
00081             # request outcome because autonomy level is too low
00082             if not self._force_transition and (self.autonomy.has_key(outcome) and self.autonomy[outcome] >= OperatableStateMachine.autonomy_level):
00083                 if self._sent_outcome_requests.count(outcome) == 0:
00084                     self._pub.publish(self._request_topic, OutcomeRequest(outcome=self._outcome_list.index(outcome), target=self._parent._get_path() + "/" + self.name))
00085                     rospy.loginfo("<-- Want result: %s > %s", self.name, outcome)
00086                     StateLogger.log_state_execution(self._get_path(), self.__class__.__name__, outcome, not self._force_transition, False)
00087                     self._sent_outcome_requests.append(outcome)
00088                 outcome = OperatableState._loopback_name
00089             
00090             # autonomy level is high enough, report the executed transition
00091             elif outcome != OperatableState._loopback_name:
00092                 self._sent_outcome_requests = []
00093                 rospy.loginfo("State result: %s > %s", self.name, outcome)
00094                 self._pub.publish(self._outcome_topic, UInt8(self._outcome_list.index(outcome)))
00095                 self._pub.publish(self._debug_topic, String("%s > %s" % (self._get_path(), outcome)))
00096                 StateLogger.log_state_execution(self._get_path(), self.__class__.__name__, outcome, not self._force_transition, True)
00097 
00098         self._force_transition = False
00099         
00100         return outcome
00101 
00102     def _notify_skipped(self):
00103         super(OperatableState, self)._notify_skipped()
00104 
00105 
00106     def _enable_ros_control(self):
00107         super(OperatableState, self)._enable_ros_control()
00108         self._pub.createPublisher(self._outcome_topic, UInt8)
00109         self._pub.createPublisher(self._debug_topic, String)
00110         self._pub.createPublisher(self._request_topic, OutcomeRequest)
00111     
00112     
00113     
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 


flexbe_core
Author(s): Philipp Schillinger
autogenerated on Thu Jun 6 2019 19:32:27