3 from flexbe_core.core import PreemptableState, OperatableStateMachine, LockableStateMachine
8 This is the superclass for all implemented behaviors. 13 Please call this superclass constructor first when overriding it with your behavior. 16 self.
name =
"unnamed behavior" 31 Should create the state machine for this behavior and return it. 32 It is called immediately before executing the behavior, 33 so used parameters will have their final value when called. 35 @return The complete state machine for this behavior. 43 Adds a parameter to this behavior. 44 The parameter should be declared in the behavior manifest. 47 @param name: The name of the parameter. 50 @param default: The default value of this parameter. Be sure to set it to the right type. 52 setattr(self, name, default)
56 Adds another behavior as part of this behavior. 57 This other behavior should be declared as contained in the behavior manifest. 59 @type behavior_class: class 60 @param behavior_class: The class implementing the other behavior. 62 @type behavior_id: string 63 @param behavior_id: Unique identifier for this behavior instance. 65 if not hasattr(self,
'contains'):
66 Logger.logerr(
'Behavior was not initialized! Please call superclass constructor.')
67 instance = behavior_class()
68 self.
contains[behavior_id] = instance
70 def use_behavior(self, behavior_class, behavior_id, default_keys=None, parameters=None):
72 Creates a state machine implementing the given behavior to use it in the behavior state machine. 73 Behavior has to be added first. 75 @type behavior_class: class 76 @param behavior_class: The class implementing the other behavior. 78 @type behavior_id: string 79 @param behavior_id: Same identifier as used for adding. 81 @type default_keys: list 82 @param default_keys: List of input keys of the behavior which should be ignored 83 and instead use the default values as given by the behavior. 85 @type parameters: dict 86 @param parameters: Optional assignment of values to behavior parameters. 87 Any assigned parameter will be ignored for runtime customization, 88 i.e., cannot be overwritten by a user who runs the behavior. 91 Logger.logerr(
'Tried to use a behavior without adding it!')
94 if parameters
is not None:
95 for parameter, value
in parameters.items():
96 setattr(self.
contains[behavior_id], parameter, value)
100 if default_keys
is not None:
101 state_machine._input_keys = list(set(state_machine._input_keys) - set(default_keys))
102 for key
in state_machine._input_keys:
103 state_machine._own_userdata(remove_key=key)
111 Prepares this behavior for execution by building its state machine. 117 if input_data
is None:
119 for k, v
in input_data.items():
120 if k
in self._state_machine._own_userdata:
121 self._state_machine._own_userdata[k] = v
125 Set the given parameter of this behavior or any sub-behavior. 126 Use a path specification to refer to the corresponding sub-behavior. 127 The parameter value is propagated to all sub-behaviors according to the propagation rules. 128 Also, the value is casted to the type of the parameter if required. 131 @param name: Name of the parameter, possibly including the path to a sub-behavior. 134 @param value: New value of the parameter of same type as before (or can be casted to that type). 136 @return: Whether the parameter existed and could be set. 138 name_split = name.rsplit(
'/', 1)
139 behavior = name_split[0]
if len(name_split) == 2
else '' 145 if b.startswith(behavior)
and hasattr(behaviors[b], key):
152 Confirms that this behavior is ready for execution. 156 self._state_machine.confirm(self.
name, self.
id)
160 Called when the behavior is executed. 161 Need to call self.execute_behavior when ready to start the state machine and return its result. 163 @return: A string containing the execution result such as finished or failed. 165 result = self._state_machine.spin()
166 self._state_machine.destroy()
171 Prepares the behavior for being executed after a behavior switch. 174 @param name: The name of this behavior. 179 raise RuntimeError(
"Did not find locked state in new behavior!")
180 state_container = state._parent
181 state_container.remove_state(state)
182 for sm
in states[1:]:
184 sm.replace_userdata(state_container.userdata)
185 state_container = state_container._parent
186 states[1].replace_state(state)
190 return self._state_machine.get_deep_state()
193 state = self._state_machine.get_deep_state()
194 while state
is not None:
195 if state.is_locked():
198 state = state._parent
202 PreemptableState.preempt =
True 212 contain_list = {path+
"/"+key: value
for (key, value)
in getattr(obj,
'contains', {}).items()}
214 for b_id, b_inst
in contain_list.items():
216 contain_list.update(add_to_list)
223 attr = getattr(self, name)
225 if not isinstance(value, type(attr)):
226 if type(attr)
is int:
228 elif type(attr)
is float:
230 elif type(attr)
is bool:
231 value = (value !=
"0")
232 elif type(attr)
is dict:
234 value = getattr(yaml,
'full_load', yaml.load)(value)
235 setattr(self, name, value)
237 def set_up(self, id, autonomy_level, debug):
243 path_elements = path.split(
'/')
244 if len(path_elements) < 2:
246 state_label = path_elements[1]
247 new_path =
"/".join(path_elements[1:])
249 if state_label
in container:
251 if childlist
is None:
253 childlist.append(container)
def get_locked_state(self)
def use_behavior(self, behavior_class, behavior_id, default_keys=None, parameters=None)
def set_up(self, id, autonomy_level, debug)
def get_contained_behaviors(self)
def add_behavior(self, behavior_class, behavior_id)
def set_parameter(self, name, value)
def _set_typed_attribute(self, name, value)
def get_current_state(self)
def prepare_for_execution(self, input_data=None)
def _get_state_machine(self)
def _get_states_of_path(self, path, container)
def add_parameter(self, name, default)
def _collect_contained(self, obj, path)
def prepare_for_switch(self, state)