00001
00002
00003
00004 import roslib; roslib.load_manifest('frame_registrar')
00005 import rospy
00006 import sys
00007 import os
00008 import yaml
00009 import traceback
00010 from roboframenet_msgs.msg import *
00011 from roboframenet_msgs.srv import *
00012
00013
00014
00015
00016
00017
00018 semantic_frames = {}
00019
00020
00021
00022
00023
00024
00025
00026 class _SemanticFrame(object):
00027 def __init__(self, name):
00028 self.name = name
00029 self.description = ""
00030 self.frame_elements = []
00031 self.children = []
00032
00033 self.callbacks = []
00034
00035
00036 @staticmethod
00037 def import_yaml(yaml):
00038 try:
00039 sf = _SemanticFrame(yaml['name'])
00040 sf.description = yaml['description']
00041 if 'frame_elements' in yaml:
00042 for fe in yaml['frame_elements']:
00043 f = _FrameElement(fe['name'], fe['is_core'])
00044 if not f.is_core and 'default' in fe:
00045 f.default = str(fe['default'])
00046 sf.frame_elements.append(f)
00047 if 'children' in yaml:
00048 for child in yaml['children']:
00049 sf.children.append(map(lambda subchild:
00050 _RelatedFrame.import_yaml(subchild),
00051 listify(child)))
00052 if 'parents' in yaml:
00053 for parent in yaml['parents']:
00054 parent_relframe = _RelatedFrame.import_yaml(parent)
00055 parent_semframe = get_semantic_frame(parent_relframe.name)
00056
00057
00058
00059 parent_relframe.name = sf.name
00060 parent_semframe.children.append(parent_relframe)
00061
00062
00063 except:
00064 rospy.logerr("Error converting yaml '" +
00065 (yaml['name'] if 'name' in yaml else "???") +
00066 "' to _SemanticFrame: " + str((sys.exc_info())))
00067 traceback.print_tb(sys.exc_info()[2])
00068 else:
00069 return sf
00070
00071 def get_frame_element(self, name):
00072 for fe in self.frame_elements:
00073 if fe.name == name:
00074 return fe
00075 rospy.logerr("Frame " + str(self) + " does not have frame element '" +
00076 name + "'! Returning False.")
00077 return False
00078
00079 def describe_frame(self):
00080 return self.description
00081
00082 def has_callbacks(self):
00083 return self.callbacks
00084
00085
00086
00087 def to_ros_EmptySemanticFrame(self):
00088 esf = EmptySemanticFrame()
00089 esf.name = self.name
00090 for fe in self.frame_elements:
00091
00092
00093 efe = EmptyFrameElement()
00094 efe.name = fe.name
00095 efe.default = fe.default
00096 efe.is_core = fe.is_core
00097 esf.frame_elements.append(efe)
00098 return esf
00099
00100 def __str__(self):
00101 return self.to_str(self.name)
00102
00103 @staticmethod
00104 def to_str(name):
00105 return "<_SemanticFrame '" + name + "'>"
00106
00107
00108
00109 class _FilledSemanticFrame(_SemanticFrame):
00110 def __init__(self, semframe):
00111 self.name = semframe.name
00112 self.description = semframe.description
00113 self.frame_elements = map(lambda fe: _FilledFrameElement(fe.name, fe.is_core),
00114 semframe.frame_elements)
00115 self.children = semframe.children
00116
00117 self.callbacks = semframe.callbacks
00118
00119 def fill_frame_element(self, name, arg):
00120 fe = self.get_frame_element(name)
00121 if fe:
00122 fe.argument = arg
00123 return True
00124 else:
00125 return False
00126
00127 def describe_frame():
00128 return(self.description + '\n' +
00129 '\n'.join([(element.name + " == " + element.argument)
00130 for element in frame_elements]) +
00131 '\n')
00132
00133
00134
00135 def to_ros_FilledSemanticFrame(self):
00136 fsf = FilledSemanticFrame()
00137 fsf.name = self.name
00138 fsf.action_server_topics = self.callbacks
00139 for fe in self.frame_elements:
00140
00141
00142 ffe = FilledFrameElement()
00143 ffe.name = fe.name
00144 ffe.argument = fe.argument
00145 fsf.frame_elements.append(ffe)
00146 return fsf
00147
00148
00149 class _FrameElement:
00150 def __init__(self, name, is_core):
00151 self.name = name
00152 self.is_core = is_core
00153 self.default = ""
00154
00155
00156 class _FilledFrameElement:
00157 def __init__(self, name, is_core):
00158 self.name = name
00159 self.is_core = is_core
00160 self.argument = ""
00161
00162
00163 class _RelatedFrame(object):
00164 def __init__(self, name):
00165 self.name = name
00166 self.frame_element_relations = []
00167
00168 @staticmethod
00169 def import_yaml(yaml):
00170 rf = _RelatedFrame(yaml['name'])
00171 if 'frame_element_relations' in yaml:
00172 for relation in yaml['frame_element_relations']:
00173
00174 if 'parent_name' in relation:
00175 parent = relation['parent_name']
00176 parent_is_value = False
00177 elif 'parent_value' in relation:
00178 parent = relation['parent_value']
00179 parent_is_value = True
00180 else:
00181 rospy.logerr("_RelatedFrame.import_yaml: No parent name or value!")
00182
00183 if 'child_name' in relation:
00184 child = relation['child_name']
00185 child_is_value = False
00186 elif 'child_value' in relation:
00187 child = relation['child_value']
00188 child_is_value = True
00189 else:
00190 rospy.logerr("_RelatedFrame.import_yaml: No child name or value!")
00191 rf.frame_element_relations.append(_FrameElementRelation(parent,
00192 parent_is_value,
00193 child,
00194 child_is_value))
00195 return rf
00196
00197
00198
00199 class _FrameElementRelation:
00200
00201 def __init__(self, parent, parent_is_value, child, child_is_value):
00202 self.parent = parent
00203 self.parent_is_value = parent_is_value
00204 if child_is_value:
00205 self.child = map(lambda c: c, listify(child))
00206 else:
00207 self.child = child
00208 self.child_is_value = child_is_value
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 def listify(x):
00219 return x if isinstance(x, list) else [x]
00220
00221
00222
00223 def get_semantic_frame(frame_name):
00224 global semantic_frames
00225 if frame_name in semantic_frames:
00226 return semantic_frames[frame_name]
00227 else:
00228 rospy.logwarn("get_semantic_frame: " +
00229 _SemanticFrame.to_str(frame_name) +
00230 " not found. (This may be normal. Or not.)")
00231 return False
00232
00233
00234
00235
00236 def store_semantic_frame(frame):
00237 global semantic_frames
00238 if not isinstance(frame, _SemanticFrame):
00239 rospy.logerr("store_semantic_frame: Given object (" + str(frame) +
00240 ") is not a _SemanticFrame object! Ignoring request.")
00241 return False
00242 else:
00243 if frame.name in semantic_frames:
00244 rospy.logwarn("store_semantic_frame: Frame with name '" +
00245 str(frame.name) + "' previously stored in" +
00246 " semantic_frames. Overwriting!")
00247 semantic_frames[frame.name] = frame
00248 rospy.loginfo("Added new semantic frame " + str(frame) + ".")
00249 return True
00250
00251
00252
00253
00254 def load_semantic_frame_yaml(filename):
00255 try:
00256 frame_yaml = yaml.load(open(filename, 'r'))
00257 except:
00258 rospy.logerr("Error loading file '%s': %s" % (str(filename), str(sys.exc_info())))
00259 return False
00260 else:
00261 return store_semantic_frame(_SemanticFrame.import_yaml(frame_yaml))
00262
00263
00264
00265
00266
00267 def fill_semantic_frame_sequences_from_filled_lexical_unit(filled_lexical_unit):
00268 FilledSemanticFrame_sequences = []
00269 filled_sem_frame = fill_semantic_frame_from_filled_lexical_unit(filled_lexical_unit)
00270 if filled_sem_frame:
00271 fsf_sequences = fill_semantic_frame_descendants(filled_sem_frame)
00272 FilledSemanticFrame_sequences.extend(fsf_sequences)
00273 else:
00274 rospy.logwarn("cb_GetFrames: No filled_sem_frame for filled_lexical_unit:\n" + str(filled_lexical_unit))
00275 return FilledSemanticFrame_sequences
00276
00277
00278
00279 def fill_semantic_frame_from_filled_lexical_unit(filled_lexical_unit):
00280 semantic_frame = get_semantic_frame(filled_lexical_unit.frame_name)
00281 if semantic_frame:
00282 filled_semantic_frame = _FilledSemanticFrame(semantic_frame)
00283
00284 for frame_element in filled_lexical_unit.frame_elements:
00285
00286
00287 if not filled_semantic_frame.fill_frame_element(frame_element.name,
00288 frame_element.argument):
00289 rospy.logwarn("fill_semantic_frame_from_filled_lexical_unit:" +
00290 " Frame element parameter '" + frame_element.name +
00291 "' could not be filled (argument '" +
00292 frame_element.argument + "') in frame " +
00293 str(filled_semantic_frame) + ".")
00294
00295 for fe in filled_semantic_frame.frame_elements:
00296 if fe.is_core and not fe.argument:
00297 rospy.logwarn("fill_semantic_frame_from_filled_lexical_unit:" +
00298 " Core element '" + fe.name + "' has no" +
00299 " argument! Offending filled lexical unit:\n" +
00300 str(filled_lexical_unit))
00301 return False
00302
00303 return filled_semantic_frame
00304 else:
00305 rospy.logwarn("fill_semantic_frame_from_filled_lexical_unit: Requested frame " +
00306 _SemanticFrame.to_str(filled_lexical_unit.frame_name) +
00307 " does not exist!")
00308 return False
00309
00310
00311
00312
00313 def fill_semantic_frame_descendants(filled_sem_frame):
00314 filled = [[filled_sem_frame]]
00315 for rf_child_list in filled_sem_frame.children:
00316 filled_child_frames = []
00317 for rf_child in rf_child_list:
00318 filled_child_frame = fill_semantic_frame_from_parent(filled_sem_frame, rf_child)
00319 if filled_child_frame:
00320 filled_child_frames.append(filled_child_frame)
00321
00322 all_filled = (len(filled_child_frames) == len(rf_child_list))
00323
00324
00325 if all_filled:
00326 child_combinations = []
00327 for filled_child_frame in filled_child_frames:
00328 child_combinations.append(fill_semantic_frame_descendants(filled_child_frame))
00329 all_combinations = map(lambda combo: reduce(lambda a,b: list_join(a,b), combo),
00330 all_combinations_of_lists(child_combinations))
00331 filled.extend(all_combinations)
00332 return filled
00333
00334
00335 def list_join(a,b):
00336 c = []
00337 c.extend(a)
00338 c.extend(b)
00339 return c
00340
00341
00342 def all_combinations_of_lists(lists):
00343 def all_combinations_of_lists_recursion(lists, index):
00344 if len(lists) == index: return [[]]
00345 combinations = []
00346 recursed_combinations = all_combinations_of_lists_recursion(lists, index+1)
00347 for item in lists[index]:
00348 for recursed_combination in recursed_combinations:
00349 r = [item]
00350 r.extend(recursed_combination)
00351 combinations.append(r)
00352 return combinations
00353 return all_combinations_of_lists_recursion(lists,0)
00354
00355
00356
00357
00358
00359
00360
00361
00362 def fill_semantic_frame_from_parent(filled_parent, rf_child):
00363
00364 child = get_semantic_frame(rf_child.name)
00365 if not child: return False
00366 filled_child = _FilledSemanticFrame(child)
00367
00368 for reln in rf_child.frame_element_relations:
00369
00370 parent_value = (reln.parent
00371 if reln.parent_is_value
00372 else filled_parent.get_frame_element(reln.parent).argument)
00373
00374 if reln.child_is_value:
00375 if not (parent_value in reln.child):
00376 rospy.loginfo("Could not fill frame " + str(child) +
00377 " from frame " + str(filled_parent) +
00378 ": Parent " + ("" if reln.parent_is_value else reln.parent + " with ") +
00379 "value " + parent_value +
00380 " is not in list of required values " + str(reln.child) +
00381 ". (This is normal.)")
00382 return False
00383
00384 else:
00385
00386 fe = filled_child.get_frame_element(reln.child)
00387 if (not parent_value) and fe and fe.is_core:
00388 rospy.loginfo("Could not fill frame " + str(child) +
00389 " from frame " + str(filled_parent) +
00390 ": Cannot fill core element '" + reln.child +
00391 "'. (This is normal.)")
00392 return False
00393
00394 success = filled_child.fill_frame_element(reln.child, parent_value)
00395 if not success:
00396 print reln.child
00397 rospy.logwarn("Aborting filling frame " + str(child) +
00398 " from frame " + str(filled_parent) +
00399 ": Cannot fill element '" + reln.child +
00400 "' from element '" + reln.parent +
00401 "'. (This should not happen.)")
00402 return False
00403 rospy.loginfo("Filled frame " + str(child) +
00404 " from frame " + str(filled_parent) + ".")
00405 return filled_child
00406
00407
00408
00409
00410
00411
00412
00413 def cb_AddFrame(req):
00414 response = AddFrameResponse()
00415 response.success = load_semantic_frame_yaml(req.absolute_file_path)
00416 return response
00417
00418
00419 def cb_FilledLexicalUnits(pub, msg):
00420 def frame_list_has_callbacks(frame_list):
00421 if len(frame_list) == 0: return True
00422 return (len(frame_list[0].action_server_topics) > 0 and
00423 frame_list_has_callbacks(frame_list[1:]))
00424 def frame_sequences_str(frame_sequences):
00425 return '\n'.join(map(lambda sequence:
00426 ('[' +
00427 ', '.join(map(lambda frame: frame.name,
00428 sequence.frames)) +
00429 ']'),
00430 frame_sequences))
00431 filled_lexical_units = msg.lexical_units
00432 rospy.loginfo("frame_registrar: Received " +
00433 str(len(filled_lexical_units)) +
00434 " filled lexical units:\n" +
00435 '\n'.join(map(lambda flu:
00436 flu.verb + "\t->\t" + flu.frame_name,
00437 filled_lexical_units)) +
00438 '\n')
00439 frame_sequences = FilledSemanticFrameListList()
00440 frame_sequences.frame_lists = []
00441 for flu in filled_lexical_units:
00442 flu_frame_sequences = \
00443 fill_semantic_frame_sequences_from_filled_lexical_unit(flu)
00444
00445 for flu_frame_sequence in flu_frame_sequences:
00446 frame_sequence = FilledSemanticFrameList()
00447 frame_sequence.frames = map(lambda frame:
00448 frame.to_ros_FilledSemanticFrame(),
00449 flu_frame_sequence)
00450 frame_sequences.frame_lists.append(frame_sequence)
00451
00452
00453 rospy.loginfo("frame_registrar: Converted filled lexical units to " +
00454 str(len(frame_sequences.frame_lists)) +
00455 " sequence(s) of semantic frames:\n" +
00456 frame_sequences_str(frame_sequences.frame_lists) + '\n')
00457 frame_sequences.frame_lists = \
00458 filter(lambda sequence: frame_list_has_callbacks(sequence.frames),
00459 frame_sequences.frame_lists)
00460 rospy.loginfo("frame_registrar: There are " +
00461 str(len(frame_sequences.frame_lists)) +
00462 " sequence(s) which have callbacks:\n" +
00463 frame_sequences_str(frame_sequences.frame_lists) + '\n')
00464
00465 if frame_sequences.frame_lists:
00466 pub.publish(frame_sequences)
00467 else:
00468 rospy.logwarn("frame_registrar: No publishable frame sequences! " +
00469 "(Aborting publishing.)")
00470
00471
00472 def cb_GetEmptyFrame(req):
00473 resp = GetEmptyFrameResponse()
00474 frame = req.frame_name
00475 resp.frame = get_semantic_frame(req.frame_name).to_ros_EmptySemanticFrame()
00476 return resp
00477
00478
00479 def cb_RegisterWithFrame(req):
00480 response = RegisterWithFrameResponse()
00481 frame = get_semantic_frame(req.frame_name)
00482 if frame:
00483 frame.callbacks.append(req.callback_topic)
00484 rospy.loginfo("cb_RegisterWithFrame: Registered callback with topic '" +
00485 req.callback_topic + "' to frame " +
00486 _SemanticFrame.to_str(req.frame_name))
00487 response.success = True
00488 else:
00489 rospy.logwarn("cb_RegisterWithFrame: Frame " + _SemanticFrame.to_str(req.frame_name) +
00490 " is not yet available. (Callback has topic '" + req.callback_topic +
00491 "'.) Ignoring request.")
00492 response.success = False
00493 return response
00494
00495
00496
00497
00498
00499
00500
00501 def main():
00502 rospy.init_node('frame_registrar')
00503
00504
00505
00506 frame_relpath = '../frames'
00507 frame_filenames = filter(lambda fn: fn[-5:] == '.yaml', os.listdir(frame_relpath))
00508 rospy.loginfo("frame_registrar: Loading semantic frames...")
00509 for frame_filename in frame_filenames:
00510 load_semantic_frame_yaml(os.path.join(frame_relpath, frame_filename))
00511 rospy.loginfo("frame_registrar: Done loading semantic frames.")
00512
00513 pub = rospy.Publisher('filled_semantic_frames', FilledSemanticFrameListList)
00514 rospy.Subscriber('filled_lexical_units', FilledLexicalUnitList, lambda msg: cb_FilledLexicalUnits(pub, msg))
00515 rospy.Service('add_frame', AddFrame, cb_AddFrame)
00516 rospy.Service('get_empty_frame', GetEmptyFrame, cb_GetEmptyFrame)
00517 rospy.Service('register_with_frame', RegisterWithFrame, cb_RegisterWithFrame)
00518 rospy.loginfo("frame_registrar: Services up.")
00519 rospy.spin()
00520
00521 if __name__ == '__main__':
00522 main()
00523
00524
00525