def _parse_property(self, text, topic_types, pns=""): ast = self.property_parser.parse(text) refs = {} events = (ast.scope.activator, ast.pattern.trigger, ast.pattern.behaviour, ast.scope.terminator) for event in events: if event is None or not event.is_publish: continue topic = RosName.resolve(event.topic, private_ns=pns) if topic not in topic_types: raise HplTypeError( "No type information for topic '{}'".format(topic)) rostype = topic_types[topic] if event.alias: assert event.alias not in refs, "duplicate event alias" assert rostype.is_message, "topic type is not a message" # update refs without worries about temporal order of events # prop.sanity_check() already checks that refs[event.alias] = rostype for event in events: if event is None or not event.is_publish: continue topic = RosName.resolve(event.topic, private_ns=pns) rostype = topic_types[topic] event.predicate.refine_types(rostype, **refs) return ast
def _parse_assumption(self, text, topic_types, pns=""): ast = self.assumption_parser.parse(text) # assumptions, like events, also have .topic and .predicate topic = RosName.resolve(ast.topic, private_ns=pns) if topic not in topic_types: raise HplTypeError( "No type information for topic '{}'".format(topic)) ast.predicate.refine_types(topic_types[topic]) return ast
def extract_node(self, name, node_name, pkg_name, ns, ws, rossystem): pkg = Package(pkg_name) rospack = rospkg.RosPack() pkg.path = rospack.get_path(pkg_name) roscomponent = None #HAROS NODE EXTRACTOR node = Node(node_name, pkg, rosname=RosName(node_name)) srcdir = pkg.path[len(ws):] srcdir = os.path.join(ws, srcdir.split(os.sep, 1)[0]) bindir = os.path.join(ws, "build") #HAROS CMAKE PARSER parser = RosCMakeParser(srcdir, bindir, pkgs=[pkg]) model_str = "" if os.path.isfile(os.path.join(pkg.path, "CMakeLists.txt")): parser.parse(os.path.join(pkg.path, "CMakeLists.txt")) for target in parser.executables.itervalues(): if target.output_name == node_name: for file_in in target.files: full_path = file_in relative_path = full_path.replace( pkg.path + "/", "").rpartition("/")[0] file_name = full_path.rsplit('/', 1)[-1] source_file = SourceFile(file_name, relative_path, pkg) node.source_files.append(source_file) if node.language == "cpp": parser = CppAstParser(workspace=ws) analysis = RoscppExtractor(pkg, ws) if node.language == "py": parser = PyAstParser(workspace=ws) analysis = RospyExtractor(pkg, ws) #node.source_tree = parser.global_scope for sf in node.source_files: try: if parser.parse(sf.path) is not None: # ROS MODEL EXTRACT PRIMITIVES if node.language == "py": node_name = node_name.replace(".py", "") rosmodel = ros_model(pkg.name, node_name, node_name) roscomponent = ros_component(name, ns) try: self.extract_primitives(node, parser, analysis, rosmodel, roscomponent, pkg_name, node_name, node_name) # SAVE ROS MODEL model_str = rosmodel.save_model( self.args.model_path) except: pass except: pass if rossystem is not None and roscomponent is not None: rossystem.add_component(roscomponent) if self.args.output: print model_str
def _get_node_topics(self, node, pns): # FIXME this should be in the metamodel or extraction code topic_types = {} # topic -> TypeToken for call in chain(node.advertise, node.subscribe): if call.name == "?" or call.type == "?": self.log.warning( "Skipping unresolved topic '%s' in node '%s'.", call.name, node.node_name) continue topic = RosName.resolve(call.name, private_ns=pns) try: topic_types[topic] = get_type(call.type) except KeyError as e: self.log.warning(str(e)) return topic_types
def launch(self): self.parse_arg() if self.args.node: #FIND WORKSPACE: #Fixme: the env variable ROS_PACKAGE_PATH is not the best way to extract the workspace path ros_pkg_path = os.environ.get("ROS_PACKAGE_PATH") ws = ros_pkg_path[:ros_pkg_path.find("/src:")] #FIND PACKAGE PATH pkg = Package(self.args.package_name) rospack = rospkg.RosPack() pkg.path = rospack.get_path(self.args.package_name) #BONSAI PARSER parser = CppAstParser(workspace=ws) parser.set_library_path("/usr/lib/llvm-3.8/lib") parser.set_standard_includes( "/usr/lib/llvm-3.8/lib/clang/3.8.0/include") db_dir = os.path.join(ws, "build") if os.path.isfile(os.path.join(db_dir, "compile_commands.json")): parser.set_database(db_dir) #HAROS NODE EXTRACTOR analysis = NodeExtractor(pkg, env=dict(os.environ), ws=ws, node_cache=False, parse_nodes=True) node = Node(self.args.name, pkg, rosname=RosName(self.args.name)) srcdir = pkg.path[len(ws):] srcdir = os.path.join(ws, srcdir.split(os.sep, 1)[0]) bindir = os.path.join(ws, "build") #HAROS CMAKE PARSER parser = RosCMakeParser(srcdir, bindir, pkgs=[pkg]) parser.parse(os.path.join(pkg.path, "CMakeLists.txt")) for target in parser.executables.itervalues(): if target.output_name == self.args.name: for file_in in target.files: full_path = file_in relative_path = full_path.replace( pkg.path + "/", "").rpartition("/")[0] file_name = full_path.rsplit('/', 1)[-1] source_file = SourceFile(file_name, relative_path, pkg) node.source_files.append(source_file) parser = CppAstParser(workspace=ws) node.source_tree = parser.global_scope model_str = "" for sf in node.source_files: if parser.parse(sf.path) is None: print "File not found" else: # ROS MODEL EXTRACT PRIMITIVES rosmodel = ros_model(self.args.package_name, self.args.name, self.args.name) self.extract_primitives(node, parser.global_scope, analysis, rosmodel) # SAVE ROS MODEL model_str = rosmodel.save_model() if self.args.output: print model_str else: text_file = open(self.args.name + ".ros", "w") text_file.write(model_str) text_file.close()