def getDefaultTopicName(self, thread_port_name, input=False, output=False):
        if not input and not output:
            return False, "No direction specified"

        thread_name = tfs.getName(self.thread)

        # Ottengo tutte le connesioni di un processo che mappano la porta specificata in process_port_name
        # del thread associato a questo processo con una porta qualunque del thread.
        connections = tfs.getAllConnectionsPerPort(self.process, thread_name, thread_port_name,
                                                   input=input,
                                                   output=output)

        names = []

        # Per ognuna delle connesioni trovate sopra bisogna cercare la porta verso cui (o da cui) è presente
        # la connessione e poi cercare la proprietà del topic name su di essa
        for c in connections:

            process_port_name = None
            # Ottengo il nome della porta
            if input:
                port_info = tfs.getPortInfoByDestPortInfo(c, thread_name, thread_port_name)
                (process_name, process_port_name) = tfs.getSourceFromPortInfo(port_info)
            elif output:
                port_info = tfs.getPortInfoBySourcePortInfo(c, thread_name, thread_port_name)
                (process_name, process_port_name) = tfs.getDestFromPortInfo(port_info)

            # La porta è una feature, quindi si usa getFeatureByName
            process_port = tfs.getFeatureByName(self.process, process_port_name)

            (topic_namespace, topic_name) = tfs.getDefaultTopicName(process_port)

            if topic_namespace is None or topic_name is None:
                return False, "Unable to get topic name"

            names.append(topic_name)

        # Rimuovo i duplicati
        names = list(set(names))

        if len(names) < 1:
            return False, "No topic name defined"

        if len(names) > 1:
            return False, "Multiple topic names defined"

        self.topic = names[0]

        return True, ""
Example #2
0
    def addPortForTopicFromPortName(self, port_name, connection):
        try:
            port = self.process.find("./" + XMLTags.tags['TAG_FEATURES'] +
                                     "/" + XMLTags.tags['TAG_FEATURE'] + "/" +
                                     "[" + XMLTags.tags['TAG_NAME'] + "='" +
                                     port_name + "']")
        except Exception:
            return False

        (topic_properties_namespace,
         default_topic_name) = tfs.getDefaultTopicName(port)
        (topic_properties_namespace,
         new_topic_name) = tfs.getTopicName(connection)

        if default_topic_name is None or new_topic_name is None:
            log.warning("No topic remap for port {} of process {}".format(
                port_name, self.name))
            return True

        # Se ho già controllato quella porta vado oltre
        if self.hasPortForTopic(port_name):
            if self.topic_ports[port_name] == new_topic_name:
                return True
            else:
                log.error(
                    "Multiple topics defined for port {} of process {}".format(
                        port_name, self.name))
                return False

        r = Remap(default_topic_name, new_topic_name)

        self.topic_ports[port_name] = new_topic_name

        self.addRemap(r)

        return True
Example #3
0
    def populateData(self):
        main_thread = self.associated_class.getMainThread()

        if main_thread == None:
            return False, "Unable to get the Main Thread"

        #########################
        # TRANSFORMATION FRAME #
        ########################

        # Controllo l'uso del Transformation Frame
        self.thread_uses_tf = self.setUsesTransformationFrame()

        ###############
        # Output Port #
        ###############

        # Essendo birezeizonale posso trovare la connessione sia come source che come dest
        conn_by_source = True
        process_input_port = tfs.getConnectionPortInfoBySource(
            self.process, self.type, self.input_port_name)

        if process_input_port is None:
            conn_by_source = False
            process_output_port = tfs.getConnectionPortInfoByDest(
                self.process, self.type, self.input_port_name)

        if process_input_port is None:
            return (
                False,
                "Unable to find the right binding between process requires subprogram access port and "
                "thread input port")

        if conn_by_source:
            (source_parent_name,
             source_name) = tfs.getDestFromPortInfo(process_input_port)
        else:
            (source_parent_name,
             source_name) = tfs.getSourceFromPortInfo(process_output_port)

        if source_parent_name is None or source_name is None:
            return False, "Unable to find the process provides subprogram access port name"

        self.process_port = tfs.getFeatureByName(self.process,
                                                 name=source_name)

        if self.process_port is None:
            return False, "Unable to find the process provides subprogram access port feature"

        # Dopo aver trovato la porta del process, controllo il nome di default del
        # services associato
        (topic_namespace, self.default_service_name) = tfs.getDefaultTopicName(
            self.process_port)

        if self.default_service_name == None:
            self.default_service_name = "service_name_default"
            log.warning(
                "Default Service Name not found, set as {} as default.".format(
                    self.default_service_name))

        ##################################
        ### ASN.1 Request and Response ###
        ##################################

        (aadl_namespace,
         aadl_type) = tfs.getPortDatatypeByPort(self.process_port)
        if aadl_namespace == None or aadl_type == None:
            return (False, "Unable to identify process port type")

        # Controllo se c'è un file ASN.1 associato alla porta. Se c'è allora il tipo di servizio
        # è custom e lo dovrò generare, mentre se non c'è allora è un servizio standard ROS
        port_data_info = tfs.getPortDataInfo(self.process_port)
        if port_data_info == None:
            return (False, "Unable to get the port data info for process port")

        self.asn_description = tfs.getSourceText(port_data_info)

        if self.asn_description == None:
            # @TODO: Standard Service
            log.warning("STANDARD SERVICE")
            # return (False, "Unable to find property Source_Text for the services caller with ASN.1 description")
        else:
            # Creo il servizio custom e lo associo al nodo che lo ha generato
            self.service = sfs.getServiceFromJSON(aadl_namespace, aadl_type,
                                                  self.asn_description,
                                                  self.associated_class)
            if self.service == None:
                return (False, "Error in ASN.1 parsing")

        # Genero ed aggiungo la libreria del services al nodo
        service_library = Library(self.associated_class)
        service_library.setPath("{}/{}.h".format(self.service.namespace,
                                                 self.service.name))
        self.associated_class.addLibrary(service_library)

        ##########################
        ### SERVICE SERVER VAR ###
        ##########################

        var_service_server = Variable(self.associated_class)
        var_service_server.setName("service_server_{}".format(self.name))
        var_service_server.setType(ROS_ServiceServer(self.associated_class))
        self.associated_class.addInternalVariable(var_service_server)

        ###############################
        ### SERVICE SERVER CALLBACK ###
        ###############################

        self.server_callback = Method(self.associated_class)
        self.server_callback.method_name = "{}_service_callback".format(
            self.name)
        self.server_callback.return_type = Bool(self.associated_class)
        self.server_callback.namespace = self.associated_class.class_name

        # REQUEST Parameter
        input_param_req = Variable(self.associated_class)
        input_param_req.setName("&req")
        input_param_req.setType(
            ROS_ServiceServer_Request(
                self.associated_class, "{}::{}".format(self.service.namespace,
                                                       self.service.name)))
        input_param_req.setIsParameter()

        # RESPONSE Parameter
        input_param_res = Variable(self.associated_class)
        input_param_res.setName("&res")
        input_param_res.setType(
            ROS_ServiceServer_Response(
                self.associated_class, "{}::{}".format(self.service.namespace,
                                                       self.service.name)))
        input_param_res.setIsParameter()

        self.server_callback.addInputParameter(input_param_req)
        self.server_callback.addInputParameter(input_param_res)

        ###############
        # SOURCE TEXT #
        ###############
        function = tfs.getSubcomponentByInfo(self.thread,
                                             name=self.function_name,
                                             namespace="ros",
                                             category="subprogram")
        if function is None:
            return False, "Unable to find the function subprogram"

        self.source_text_function = self.createSourceTextFileFromSourceText(
            tfs.getSourceText(function), tfs.getSourceName(function))

        if self.source_text_function is None:
            return False, "Unable to find property Source_Text or Source_Name"

        self.source_text_function.setTF(self.thread_uses_tf)

        # Aggiungo la chiamata alla funzione custom
        if self.source_text_function != None:
            self.source_text_function.addServiceReqAndRes(
                input_param_req, input_param_res)
            self.source_text_function.addLibrary(service_library)

            self.source_text_function.setFunctionType(
                Bool(self.associated_class))
            code = "return {};".format(
                self.source_text_function.generateInlineCode())
            self.server_callback.addMiddleCode(code)

        self.associated_class.addPrivateMethod(self.server_callback)

        main_thread.prepare.addMiddleCode(
            "{} = handle.advertiseService(\"{}\", {}, this);".format(
                var_service_server.name, self.default_service_name,
                self.server_callback.getThreadPointer()))

        return (True, "")
Example #4
0
    def populateData(self):
        main_thread = self.associated_class.getMainThread()

        if main_thread == None:
            return (False, "Unable to get the Main Thread")

        ###################
        ### Output Port ###
        ###################

        # Essendo bidirezionale posso trovare la connessione sia come source che come dest
        conn_by_source = True
        process_output_port = tfs.getConnectionPortInfoBySource(
            self.process, self.type, self.output_port_name)
        if process_output_port == None:
            conn_by_source = False
            process_output_port = tfs.getConnectionPortInfoByDest(
                self.process, self.type, self.output_port_name)

        if process_output_port == None:
            return (
                False,
                "Unable to find the right binding between process requires subprogram access port and "
                "thread input port")

        if conn_by_source:
            (dest_parent_name,
             dest_name) = tfs.getDestFromPortInfo(process_output_port)
        else:
            (dest_parent_name,
             dest_name) = tfs.getSourceFromPortInfo(process_output_port)

        if dest_parent_name == None or dest_name == None:
            return (
                False,
                "Unable to find the process requires subprogram access port name"
            )

        self.process_port = tfs.getFeatureByName(self.process, name=dest_name)

        if self.process_port == None:
            return (
                False,
                "Unable to find the process requires subprogram access port feature"
            )

        # Dopo aver trovato la porta del process, controllo il nome di default del
        # services associato
        (topic_namespace, self.default_service_name) = tfs.getDefaultTopicName(
            self.process_port)

        if self.default_service_name == None:
            self.default_service_name = "service_name_default"
            log.warning(
                "Default Service Name not found, set as {} as default.".format(
                    self.default_service_name))

        ##################################
        ### ASN.1 Request and Response ###
        ##################################

        (aadl_namespace,
         aadl_type) = tfs.getPortDatatypeByPort(self.process_port)
        if aadl_namespace is None or aadl_type is None:
            return False, "Unable to identify process port type"

        # Controllo se c'è un file ASN.1 associato alla porta. Se c'è allora il tipo di servizio
        # è custom e lo dovrò generare, mentre se non c'è allora è un servizio standard ROS
        port_data_info = tfs.getPortDataInfo(self.process_port)
        if port_data_info is None:
            return False, "Unable to get the port data info for process port"

        self.asn_description = tfs.getSourceText(port_data_info)

        if self.asn_description is None:
            self.service = Service(aadl_namespace, aadl_type)
        else:
            # Creo il servizio custom e lo associo al nodo che lo ha generato
            self.service = sfs.getServiceFromJSON(self.asn_description,
                                                  self.associated_class)
        # if self.service == None:
        #     return (False, "Error in ASN.1 parsing")

        # self.associated_class.addService( self.service )

        # Genero ed aggiungo la libreria del services al nodo
        service_library = Library(self.service.namespace)
        service_library.setPath("{}/{}.h".format(self.service.namespace,
                                                 self.service.name))
        self.associated_class.addLibrary(service_library)

        ##########################
        ### SERVICE CLIENT VAR ###
        ##########################

        var_serviceclient = Variable(self.associated_class)
        var_serviceclient.setName("service_client_{}".format(self.name))
        var_serviceclient.setType(ROS_ServiceClient(self.associated_class))
        self.associated_class.addInternalVariable(var_serviceclient)

        main_thread.prepare.addMiddleCode(
            "{} = handle.serviceClient<{}::{}>(\"{}\");".format(
                var_serviceclient.name, self.service.namespace,
                self.service.name, self.default_service_name))

        return True, ""