Beispiel #1
0
    def _check_haros_name_is_complete(self, haros_name, context=''):
        """
        Check if the HAROS name does not hint at an incomplete model (does not
        contain `?` as the last token if it contains `/` or is not `?`)

        :param haros_name: the HAROS string name to check
        :type haros_name: str
        :param context: optional context string for logging, defaults to ''
        :type context: str, optional
        :return: boolean to indicate if most likely complete model (`True`)
            or not (`False`)
        :rtype: boolean
        """
        # VALIDATION AND ERROR HANDLING: Handle HAROS Issue where Models may be Incomplete and thus,
        # Have Incomplete Names and Even Types.
        if '/' in haros_name:
            complete = (haros_name.strip().split('/')[-1] != '?')
        else:
            complete = (haros_name.strip() != '?')
        if not complete:
            if context:
                context = '. [In {}]'.format(context)
            Logger.get_logger().log(LoggerLevel.ERROR, '[{}] INCOMPLETE HAROS Model Information Encountered for "{}"{}.'.format(
                                    self.__class__.TYPE, haros_name, context))
        return complete
    def _haros_model_instances(self):
        """
        Returns the appropriate HAROS Model Instances

        :return: A set of HAROS Service Specifications
        :rtype: set(ServicePrimitive)
        """
        encountered_haros_service_spec_ids = set()
        haros_service_specs = set()
        for haros_service_instance in self._haros_configuration.services:
            haros_service_spec = haros_service_instance.server
            # Handle Error Case Where Service Spec was a `NoneType` - from Acceptance Testing
            # with `chris_rrbot_modeling` demo.
            if haros_service_spec:
                haros_service_spec_id = haros_service_spec.type
                if (haros_service_spec_id not in encountered_haros_service_spec_ids):
                    # Add Required Fields to Allow HAROS Primitive to be Used in Remodeler Structure.
                    haros_service_spec.id = haros_service_spec_id
                    haros_service_spec.name = haros_service_spec_id
                    haros_service_specs.add(haros_service_spec)
                    encountered_haros_service_spec_ids.add(haros_service_spec_id)
            else:
                Logger.get_logger().log(LoggerLevel.ERROR, '[{}] Cannot Locate Service Spec for Service "{}".'.format(
                                        self.__class__.TYPE, haros_service_instance.id))
        return haros_service_specs
    def _merge_haros_parameter_links_with_chris_parameter_nodes(self, haros_parameter_model, chris_parameter_model):
        """
        Helper merging method to merge the HAROS Parameter Node Links with the
        CHRIS Parameter Nodes

        :param haros_parameter_model: the HAROS Parameter model
        :type haros_parameter_model: Parameter
        :param chris_parameter_model: the CHRIS Parameter model
        :type chris_parameter_model: Parameter
        :return: boolean indicating if the model was updated (`True`) or not (`False`)
        :rtype: boolean
        """
        model_updated = False
        for link in haros_parameter_model.writes:
            haros_node_instance_name = link.node.id
            if self._check_haros_name_is_complete(haros_node_instance_name, 'Check for Parameter Nodes'):
                if haros_node_instance_name not in chris_parameter_model.setting_node_names:
                    Logger.get_logger().log(LoggerLevel.INFO, '[{}] Adding HAROS Param\'s Setting Node "{}" to CHRIS Param Instance.'.format(
                        self.__class__.TYPE, haros_node_instance_name))
                    chris_parameter_model.setting_node_names.add(
                        haros_node_instance_name)
                    model_updated = True
        for link in haros_parameter_model.reads:
            haros_node_instance_name = link.node.id
            if self._check_haros_name_is_complete(haros_node_instance_name, 'Check for Parameter Nodes'):
                if haros_node_instance_name not in chris_parameter_model.reading_node_names:
                    Logger.get_logger().log(LoggerLevel.INFO, '[{}] Adding HAROS Param\'s Reading Node "{}" to CHRIS Param Instance.'.format(
                        self.__class__.TYPE, haros_node_instance_name))
                    chris_parameter_model.reading_node_names.add(
                        haros_node_instance_name)
                    model_updated = True
        return model_updated
    def read_model_from_pickle(directory_path,
                               base_file_name,
                               spec_only=False):
        """
        Read model banks from directory containing YAML files
        :param directory_path: file path to YAML files
        :param base_file_name: base file name used in YAML files
        :return : instance of ROSModel
        """
        bank_dict = {}
        Logger.get_logger().log(LoggerLevel.INFO,
                                'Reading ROS model from pickle files ...')
        #  ROSModel.get_yaml_processor()
        for bank_type, bank_output_name in ROSModel.BANK_TYPES_TO_OUTPUT_NAMES.items(
        ):
            if spec_only and bank_type not in ROSModel.SPECIFICATION_TYPES:
                print "Specifications only - skipping ", bank_output_name
                continue

            file_name = '{}/{}_{}.pkl'.format(directory_path, base_file_name,
                                              bank_output_name)
            try:
                with open(file_name, 'rb') as fin:
                    bank_data = pickle.load(fin)
                    bank_dict[bank_type] = bank_data
            except IOError:
                Logger.get_logger().log(
                    LoggerLevel.ERROR,
                    'Failed to read Pickle data for {} : {}'.format(
                        bank_output_name, file_name))
                bank_dict[bank_type] = ROSModel.BANK_TYPES_TO_BANK_CLASS[
                    bank_type]()

        # Create instance of the model class
        return ROSModel(bank_dict)
    def load_model(input_directory, spec_only=False):
        """
        Load  model from folder
        :param input_directory: the input directory pointing to either yaml or pickle files (e.g. output/yaml)
        :return: ROSModel instance with models stored in dictionary by type
        """
        try:
            input_type, input_base_file_name = get_input_file_type(
                input_directory)
        except IOError as e:
            Logger.get_logger().log(
                LoggerLevel.ERROR,
                'Failed to deduce type from ' + input_directory + ' ...')
            print "                                     Did you specify input folder with yaml or pickle files?"
            print "                                     " + e
            return None

        if input_type == 'yaml':
            return ROSModel.read_model_from_yaml(input_directory,
                                                 input_base_file_name,
                                                 spec_only)
        elif input_type == 'pkl':
            return ROSModel.read_model_from_pickle(input_directory,
                                                   input_base_file_name,
                                                   spec_only)
        else:
            Logger.get_logger().log(
                LoggerLevel.ERROR, 'Unknown ROS model input type from ' +
                input_directory + ' ...')
            return None
 def save_model_yaml_files(self, directory_path, base_file_name):
     """
     Save the ROS bank metamodel instances to yaml files
     :param directory_path : directory to store files
     :param base_file_name:
     :return: None
     """
     try:
         Logger.get_logger().log(
             LoggerLevel.INFO,
             'Saving YAML files for ROS Computation Graph.')
         #  ROSModel.get_yaml_processor()
         create_directory_path(directory_path)
         for bank_type, bank in self._bank_dictionary.items():
             bank_output_name = ROSModel.BANK_TYPES_TO_OUTPUT_NAMES[
                 bank_type]
             file_name = '{}/{}_{}.yaml'.format(directory_path,
                                                base_file_name,
                                                bank_output_name)
             yaml_file = open(file_name, 'w')
             yaml.dump(bank, yaml_file, sort_keys=True)
             yaml_file.close()
     except IOError as ex:
         Logger.get_logger().log(
             LoggerLevel.ERROR,
             'Failed to save YAML files for ROS Computation Graph.')
         print "     ", ex
Beispiel #7
0
    def _helper_merge_haros_model_with_chris_model(self, bank_type,
                                                   haros_model, chris_model):
        """
        Main merging helper method that handles specific details regarding the
        merging of a specific Service HAROS model with a specific Service
        CHRIS model

        :param bank_type: the corresponding CHRIS Model Bank Type
        :type bank_type: BankType
        :param haros_model: the specific HAROS model to obtain data from
        :type haros_model: Service
        :param chris_model: the specific CHRIS Model to merge data into
        :type chris_model: Service
        """
        model_updated = False
        # VALIDATE Service Types to Alert the User of INCONSISTENT / INACCURATE DATA.
        haros_service_type = haros_model.type
        chris_service_type = chris_model.construct_type
        if (haros_service_type != chris_service_type):
            Logger.get_logger().log(
                LoggerLevel.ERROR,
                '[{}] HAROS Service\'s Type "{}" does NOT Match CHRIS Service\'s Type "{}".'
                .format(self.__class__.TYPE, haros_service_type,
                        chris_service_type))
        model_updated |= self._helper_merge_haros_services_with_chris_model(
            [haros_model.server], chris_model.service_provider_node_names,
            'Provided')
        chris_model_service_clients = set()
        if self._helper_merge_haros_services_with_chris_model(
                haros_model.clients, chris_model_service_clients, 'Client'):
            chris_model.service_client_node_names = chris_model_service_clients
            model_updated = True
        return model_updated
    def update_bank(self, bank_type, bank_dictionary):
        """
        Add a new bank data to ROS model
        :param bank_type: a BankType
        :param bank_dictionary: dictionary of name to entity instances
        """

        if bank_type not in BankType:
            raise ValueError("Invalid bank type " + str(bank_type))

        if bank_type not in self._bank_dictionary:
            self._bank_dictionary[bank_type] = {}

        # Validate the inputs
        for key, value in bank_dictionary.items():
            if not isinstance(key, str):
                raise KeyError(
                    "ROSModel.update_bank: All keys must be strings - not " +
                    str(type(key)))
            if not isinstance(value,
                              self._bank_dictionary[bank_type].entity_class):
                raise ValueError(
                    "ROSModel.update_bank: All values must be {} - not {}".
                    format(
                        self._bank_dictionary[bank_type].entity_class.__name__,
                        value.__class__.__name__))

        # Merge dictionarys
        Logger.get_logger().log(
            LoggerLevel.INFO,
            "Update {}".format(self.BANK_TYPES_TO_OUTPUT_NAMES[bank_type]))
        self._bank_dictionary[bank_type].update(bank_dictionary)
    def save_model_info_files(self, directory_path, base_file_name):
        """
        Save the ROS model to human-readable files
        :param directory_path : directory to store files
        :param base_file_name: file name string
        :return:
        """
        try:
            Logger.get_logger().log(
                LoggerLevel.INFO,
                'Saving human-readable files for ROS Computation Graph.')
            create_directory_path(directory_path)
            for bank_type, bank in self._bank_dictionary.items():
                rows = []
                rows.append(str(bank))
                bank_output_name = ROSModel.BANK_TYPES_TO_OUTPUT_NAMES[
                    bank_type]
                file_name = '{}/{}_{}.txt'.format(directory_path,
                                                  base_file_name,
                                                  bank_output_name)
                with open(file_name, 'w') as fout:
                    fout.write('\n'.join(rows))

        except IOError as ex:
            Logger.get_logger().log(
                LoggerLevel.ERROR,
                'Failed to save human-readable files for ROS Computation Graph.'
            )
            print "     ", ex
Beispiel #10
0
    def machine(self):
        """
        Extracts the machine ID from the uri information
        :return: machine ID as string
        """
        if self._machine is None:
            self._machine = "UNKNOWN MACHINE"  # initialize

            if "UNKNOWN" in self._uri:
                # Abandon if uri is unknown
                return self._machine

            tokens = self.uri.split("/")
            if len(tokens) < 2:
                # expect at least one / in uri
                Logger.get_logger().log(
                    LoggerLevel.ERROR,
                    '{}: {}.'.format("UNKNOWN MACHINE", tokens))
            else:
                if tokens[-1] == "":
                    # Assumes last token is empty after trailing /
                    address = tokens[-2]
                else:
                    address = tokens[-1]

                # Assumes machine : pid  format of uri
                self._machine = address.split(":")[0]

        return self._machine
Beispiel #11
0
    def _helper_merge_haros_model_with_chris_model(self, bank_type,
                                                   haros_model, chris_model):
        """
        Main merging helper method that handles specific details regarding the
        merging of a specific Topic HAROS model with a specific Topic
        CHRIS model

        :param bank_type: the corresponding CHRIS Model Bank Type
        :type bank_type: BankType
        :param haros_model: the specific HAROS model to obtain data from
        :type haros_model: Topic
        :param chris_model: the specific CHRIS Model to merge data into
        :type chris_model: Topic
        """
        model_updated = False
        haros_topic_type = haros_model.type
        chris_topic_type = chris_model.construct_type
        # VALIDATE Topic Types to Alert the User of INCONSISTENT / INACCURATE DATA.
        if haros_topic_type != chris_topic_type:
            Logger.get_logger().log(
                LoggerLevel.ERROR,
                '[{}] HAROS Topic\'s Type "{}" does NOT Match CHRIS Topic\'s Type "{}".'
                .format(self.__class__.TYPE, haros_topic_type,
                        chris_topic_type))
        model_updated |= self._merge_haros_topic_links_with_chris_topic_nodes(
            haros_model, chris_model)
        return model_updated
    def _collect_parameters_info(self):
        """
        Helper method to create ParameterBuilders within the
        ROSModelBuilder's ParameterBankBuilder and to map parameters to
        associated NodeBuilders (obtained from the ROS Master API)
        """
        for parameter_name in self._master.getParamNames():
            # Initialize parameter bank for each parameter name
            self.parameter_bank[parameter_name]  # pylint: disable=W0104

        try:
            for parameter_name, node_names in self._master.getParamsToSettingCallers().items():
                for node_name in node_names:
                    if (node_name == '/roslaunch') or (not filters.NodeFilter.get_filter().should_filter_out(node_name)):
                        self.parameter_bank[parameter_name].add_setting_node_name(node_name)
                    if not filters.NodeFilter.get_filter().should_filter_out(node_name):
                        self.node_bank[node_name].add_parameter_name(parameter_name, 'set', None)
            for parameter_name, node_names in self._master.getParamsToReadingCallers().items():
                for node_name in node_names:
                    if (node_name == '/roslaunch') or not filters.NodeFilter.get_filter().should_filter_out(node_name):
                        self.parameter_bank[parameter_name].add_reading_node_name(node_name)
                    if not filters.NodeFilter.get_filter().should_filter_out(node_name):
                        self.node_bank[node_name].add_parameter_name(parameter_name, 'read', None)

        except AttributeError:
            msg = '\n  Standard roscore does NOT provide parameter setting/reading information!\n' + \
                    '     Use custom roscore if desired.\n' + \
                    '     See chris_ros_snapshot README for more info!'

            Logger.get_logger().log(LoggerLevel.WARNING, msg)
    def _create_new_chris_model(self, instance_name, haros_instance):
        """
        Creates a new Node CHRIS model with the instance name and based on the
        corresponding HAROS instance

        :param instance_name: the HAROS instance name
        :type instance_name: str
        :param haros_instance: the corresponding HAROS model
        :type haros_instance: NodeInstance
        :return: a tuple containing the Bank Type and new CHRIS model
        :rtype: Tuple(BankType, Node)
        """
        # DECISION: If HAROS cannot provide the ability to distinguish between a Nodelet and a Nodelet Manager, we will
        # just attempt to populate the newly created model into a Nodelet Bank (if we can tell if the HAROS
        # model represents a Nodelet) or just the Node Bank otherwise (which will catch Nodelet Managers
        # since there is no easy way to tell if it is a Manager). Besides, we should be able to gather all
        # Nodes using our CHRIS ROS Snapshot tool.
        if haros_instance.node.nodelet_class:
            Logger.get_logger().log(
                LoggerLevel.ERROR,
                '[{}] Create new chris nodelet model"{}".'.format(
                    self.__class__.TYPE, instance_name))

            return (BankType.NODELET,
                    self._chris_model_banks[BankType.NODELET][instance_name])

        Logger.get_logger().log(
            LoggerLevel.ERROR, '[{}] Create new chris node model"{}".'.format(
                self.__class__.TYPE, instance_name))
        return (BankType.NODE,
                self._chris_model_banks[BankType.NODE][instance_name])
Beispiel #14
0
    def _update_chris_model_version(cls, chris_model, model_updated):
        """
        Increments the version and updates the source list for the CHRIS model,
        if it has been updated

        :param chris_model: the CHRIS model to update version and source for
        :type chris_model: _EntityMetamodel
        :param model_updated: `True` if model has been updated; `False` if not
        :type model_updated: boolean
        """
        if model_updated:
            chris_model.version = chris_model.version + 1
            new_sources = set()
            if isinstance(chris_model.source, list):
                for source in chris_model.source:
                    new_sources.add(source)
                new_sources.add(cls.REMODELER_SOURCE_NAME)
                chris_model.source = sorted(new_sources)
            elif isinstance(chris_model.source, str):
                for source in chris_model.source.split(','):
                    new_sources.add(source.strip())
                new_sources.add(cls.REMODELER_SOURCE_NAME)
                chris_model.source = ', '.join(sorted(new_sources))
            else:
                Logger.get_logger().log(LoggerLevel.ERROR,
                                        '[{}] Error Setting Source(s) for CHRIS Model "{}".'.format(cls.TYPE, chris_model.name))
    def __init__(self):
        """
        Instantiates an instance of the PackageModeler
        """
        self._package_bank = PackageSpecificationBank()
        self._node_bank = NodeSpecificationBank()
        self._action_bank = TypeSpecificationBank()
        self._message_bank = TypeSpecificationBank()
        self._service_bank = TypeSpecificationBank()
        self._ros_model = None
        self._rospack = rospkg.RosPack()
        self._packages = None
        self._package_paths = None
        self._message_paths = None
        self._service_paths = None
        self._action_paths = None

        self._installed_deb_cache = None

        try:
            cache = apt.Cache()
            self._installed_deb_cache = {
                pkg.name: pkg
                for pkg in cache if pkg.is_installed
            }
        except:
            Logger.get_logger().log(
                LoggerLevel.ERROR,
                'Cannot get installed package version (is this Ubuntu?) ...')
    def _match_token_types(node_name, io_names, io_builders, spec_types):
        """
        Look for matched tokens and/or data types between node and spec
        :param node_name:
        :param io_names: relevant names to process (dict)
        :param io_builders: builder for relevant type
        :param spec_types: corresponding data in specification
        :return: True if all valid, False otherwise
        """
        try:
            if spec_types is None:
                if len(io_names) > 0:
                    # Nothing defined for spec
                    return False
            else:
                # We have action clients to match up in the spec
                available_tokens = set(spec_types)
                io_is_valid = True
                for io_name in sorted(io_names):
                    builder = io_builders[io_name]
                    io_type = builder.construct_type
                    token = io_name.split("/")[-1]

                    if token not in available_tokens or io_type != spec_types[token]:
                        # look from matching item remaining tokens

                        # prefer substring match
                        potential = set([ss for ss in available_tokens if token in ss])
                        remaining = available_tokens - potential
                        for test in sorted(potential):
                            if spec_types[test] == io_type:
                                # found match
                                io_names[io_name] = test
                                available_tokens.remove(test)
                                break
                        if io_names[io_name] is None:
                            for test in sorted(remaining):
                                if spec_types[test] == io_type:
                                    # found match
                                    io_names[io_name] = test
                                    available_tokens.remove(test)
                                    break
                        if io_names[io_name] is None:
                            # If still None, then no match found
                            Logger.get_logger().log(LoggerLevel.WARNING, '      Node {} unmatched data {} !'.format(node_name, io_name))
                            io_is_valid = False
                    else:
                        # Found valid match
                        io_names[io_name] = token
                        available_tokens.remove(token)

                return io_is_valid

        except Exception as ex:
            print type(ex)
            print ex
            track = traceback.format_exc()
            print track
            sys.exit(-1)
def create_directory_path(directory_path):
    """
    Create directory path if required
    :param directory_path:
    :return: None
    """
    if not os.path.exists(directory_path):
        Logger.get_logger().log(
            LoggerLevel.DEBUG,
            'Creating directory path {}.'.format(directory_path))
        os.makedirs(directory_path)
    def _collect_packages(self):
        """
        Dictionary of packages to location
        """

        # Retrieve the package information
        self._packages = self._rospack.list()

        self._package_paths = {
            package: self._rospack.get_path(package)
            for package in self._packages
        }

        self._message_paths = {
            package: [os.path.join(self._rospack.get_path(package), 'msg')]
            for package in self._packages
        }
        self._service_paths = {
            package: [os.path.join(self._rospack.get_path(package), 'srv')]
            for package in self._packages
        }
        self._action_paths = {
            package: [os.path.join(self._rospack.get_path(package), 'action')]
            for package in self._packages
        }

        for package_name in self._packages:
            try:

                try:
                    path = self._package_paths[package_name]
                except ValueError:
                    path = "UNKNOWN PATH"

                try:
                    package_dependencies = self._rospack.get_depends(
                        package_name)
                except rospkg.common.ResourceNotFound:
                    #pylint: disable=redefined-variable-type
                    package_dependencies = "NO DEPENDENCIES DEFINED"

                installed_version = self._get_installed_version(package_name)

                package = self._package_bank[package_name]
                package.update_attributes(directory_path=path,
                                          dependencies=package_dependencies,
                                          source=PackageModeler.source_name,
                                          installed_version=installed_version)

            except Exception as ex:
                Logger.get_logger().log(
                    LoggerLevel.ERROR,
                    "Processing {} {} : {}".format(package_name, type(ex), ex))
                raise ex  # kill for now to debug
Beispiel #19
0
    def _extract_action_names_and_remove_corresponding_topics(
            self, topic_bank_builder, action_bank_builder):
        """
        Associates the ROS Node with Action Server / Client related
        Action names from the ActionBankBuilder and removes the
        Action-related Topics from the ROS Node's Topic store

        :param topic_bank_builder: the TopicBankBuilder to use for
            Action-related Topic name removal
        :type topic_bank_builder: TopicBankBuilder
        :param action_bank_builder: the ActionBankBuilder to use for
            Action-related Topic name removal and Action Server / Client
            reference
        :type action_bank_builder: ActionBankBuilder
        :return: the mapping of Action Server / Client roles ('server'
            or 'client') to extracted Action names
        :rtype: dict{str: dict{str:str}}
        """
        extracted_action_names = {'server': dict(), 'client': dict()}
        valid_topic_names = [
            topic_name for topic_name in
            topic_bank_builder.names_to_entity_builders.keys()
        ]
        for status, topic_name_dict in {
                'published': self.published_topic_names,
                'subscribed': self.subscribed_topic_names
        }.items():
            #Logger.get_logger().log(LoggerLevel.INFO,
            #                        'Searching for {} action topics for node {}.'.format(status, self.name))
            for topic_name in set(topic_name_dict.keys()):
                if topic_name not in valid_topic_names:
                    topic_builder = TopicBuilder(topic_name)
                    name_base, name_suffix = topic_builder.name_base, topic_builder.name_suffix
                    if (name_base in action_bank_builder.names_to_entity_builders) and \
                        (name_suffix in ActionBuilder.TOPIC_SUFFIXES):
                        action_builder = action_bank_builder[name_base]
                        log_message = 'Found action {}. Removing topic {} from node {}.'.format(
                            name_base, topic_name, self.name)
                        if self.name in action_builder.client_node_names:
                            extracted_action_names['client'][name_base] = None
                            self.remove_topic_name(topic_name, status)
                        elif self.name in action_builder.server_node_names:
                            extracted_action_names['server'][name_base] = None
                            self.remove_topic_name(topic_name, status)
                        else:
                            log_message = 'Failed to find action {}. Will NOT remove topic {} from node {}.'.format(
                                name_base, topic_name, self.name)
                        Logger.get_logger().log(LoggerLevel.INFO, log_message)
        return extracted_action_names
Beispiel #20
0
    def _helper_populate_new_chris_model(self, bank_type, instance_name, haros_model, new_chris_model_instance):
        """
        Helper method to help populate the new CHRIS model based on the corresponding HAROS model

        :param bank_type: the Bank Type used to create the new CHRIS model
        :type bank_type: BankType
        :param instance_name: the HAROS instance name
        :type instance_name: str
        :param haros_model: the corresponding HAROS model
        :type haros_model: MetamodelObject
        :param new_chris_model_instance: the new CHRIS model to update/populate
        :type new_chris_model_instance: _EntityMetamodel
        """
        Logger.get_logger().log(LoggerLevel.INFO, '[{}] Not Populating New Model "{}".'.format(
            self.__class__.TYPE, instance_name))
def check_for_version_request(options):
    """
    Checks the command line options for a version request; if present and true,
    shows the version and exits; else, does nothing

    :param options: argparse command line options with `version` boolean present
    :type options: argparse.Namespace
    """
    if options.version:
        file_name = os.path.join(os.path.dirname(
            __file__), '..', '..', 'VERSION')
        with open(file_name) as input_file:
            version = input_file.read().strip()
            Logger.get_logger().log(LoggerLevel.INFO,
                                    'chris_haros_model_merger version: {}.'.format(version))
        sys.exit(0)
Beispiel #22
0
    def _gather_uri(self):
        """
        Helper method to gather the ROS Node URI from the ROS Master

        :return: the gathered ROS Node URI from the ROS Master
        :rtype: str
        """
        try:
            return ROSUtilities.get_ros_utilities().master.lookupNode(
                self.name)
        except rosgraph.masterapi.MasterError as ex:
            error_message = 'URI for node {} cannot be retrieved from ROS Master'.format(
                self.name)
            Logger.get_logger().log(LoggerLevel.ERROR,
                                    '{}: {}.'.format(error_message, ex))
            return "UNKNOWN URI FOR {}".format(self.name)
    def _helper_populate_new_chris_model(self, bank_type, instance_name, haros_model, new_chris_model_instance):
        """
        Helper method to help populate the new Service Specification CHRIS model
        based on the corresponding HAROS model

        :param bank_type: the Bank Type used to create the new CHRIS model
        :type bank_type: BankType
        :param instance_name: the HAROS instance name
        :type instance_name: str
        :param haros_model: the corresponding HAROS model
        :type haros_model: ServicePrimitive
        :param new_chris_model_instance: the new CHRIS model to update/populate
        :type new_chris_model_instance: ServiceSpecification
        """
        Logger.get_logger().log(LoggerLevel.INFO, '[{}] No Additional Population is Possible for Service Spec "{}".'.format(
            self.__class__.TYPE, instance_name))
Beispiel #24
0
    def _create_new_chris_model(self, instance_name, haros_instance):
        """
        Creates a new CHRIS model with the instance name and based on the
        corresponding HAROS instance

        :param instance_name: the HAROS instance name
        :type instance_name: str
        :param haros_instance: the corresponding HAROS model
        :type haros_instance: MetamodelObject
        :return: a tuple containing the Bank Type and new CHRIS model
        :rtype: Tuple(BankType, _EntityMetamodel)
        """
        chosen_chris_model_bank_type = self._chris_model_banks.keys()[0]
        Logger.get_logger().log(LoggerLevel.INFO, '[{}] Create new chris model from base_remodeler type={} "{}"...'.format(
            self.__class__.TYPE, chosen_chris_model_bank_type, instance_name))
        return (chosen_chris_model_bank_type, self._chris_model_banks[chosen_chris_model_bank_type][instance_name])
    def get_yaml_processor():
        """
        Return YAML handler
        """
        Logger.get_logger().log(LoggerLevel.INFO,
                                " Set up YAML processing for meta models ...")
        for sub_class in _BankMetamodel.__subclasses__():
            #  print "adding representor and constructor for ", sub_class.yaml_tag
            yaml.add_representer(sub_class.yaml_tag, sub_class.__repr__)
            partial_func = partial(ROSModel.yaml_constructor, sub_class)
            yaml.add_constructor(sub_class.yaml_tag, partial_func)

        for sub_class in _EntityMetamodel.__subclasses__():
            #  print "adding representor and constructor for ", sub_class.yaml_tag
            yaml.add_representer(sub_class.yaml_tag, sub_class.__repr__)
            partial_func = partial(ROSModel.yaml_constructor, sub_class)
            yaml.add_constructor(sub_class.yaml_tag, partial_func)
    def _merge_haros_node_links_with_chris_node_parameters(
            self, haros_node_model_links, chris_node_model_parameters,
            link_type):
        """
        Helper merging method to merge the HAROS Node Parameters Links with the
        CHRIS Node Parameters

        :param haros_node_model_links: HAROS Read or Written Parameter Links
        :type haros_node_model_links: list[ParameterPrimitive]
        :param chris_node_model_parameters: CHRIS Written or Read Parameter Names to Types
        :type chris_node_model_parameters: dict{str: str}
        :param link_type: Read or Written Link Types (`Read` or `Set`) for logging
        :type link_type: str
        :return: boolean indicating if the model was updated (`True`) or not (`False`)
        :rtype: boolean
        """
        model_updated = False
        for haros_link in haros_node_model_links:
            haros_parameter_instance_name = haros_link.param_name
            if self._check_haros_name_is_complete(
                    haros_parameter_instance_name,
                    'Check for Node Parameters'):
                # VALIDATE Parameter Parent Types to Alert the User of INCONSISTENT / INACCURATE DATA.
                if haros_parameter_instance_name in chris_node_model_parameters:
                    haros_parameter_parent_type = haros_link.parameter.name
                    chris_parameter_parent_type = chris_node_model_parameters[
                        haros_parameter_instance_name]
                    if haros_parameter_parent_type != chris_parameter_parent_type:
                        Logger.get_logger().log(
                            LoggerLevel.ERROR,
                            '[{}] HAROS "{}" Parameter Parent\'s Type "{}" for Parameter "{}" does NOT Match CHRIS Parameter Parent\'s Type "{}".'
                            .format(self.__class__.TYPE, link_type,
                                    haros_parameter_parent_type,
                                    haros_parameter_instance_name,
                                    chris_parameter_parent_type))
                # elif haros_parameter_instance_name not in chris_node_model_parameters:
                else:
                    Logger.get_logger().log(
                        LoggerLevel.INFO,
                        '[{}] Adding HAROS Node\'s {} Parameter "{}" to CHRIS Node Instance.'
                        .format(self.__class__.TYPE, link_type,
                                haros_parameter_instance_name))
                    chris_node_model_parameters[
                        haros_parameter_instance_name] = haros_link.parameter.name
                    model_updated = True
        return model_updated
    def _merge_haros_node_links_with_chris_node_services(
            self, haros_node_model_links, chris_node_model_services,
            link_type):
        """
        Helper merging method to merge the HAROS Node Service Links with the
        CHRIS Node Services

        :param haros_node_model_links: HAROS Service Server or Client Links
        :type haros_node_model_links: list[ServicePrimitive]
        :param chris_node_model_services: CHRIS Provided or Client Service Names to Types
        :type chris_node_model_services: dict{str: str}
        :param link_type: Server or Client Link Types (`Provided` or `Client`) for logging
        :type link_type: str
        :return: boolean indicating if the model was updated (`True`) or not (`False`)
        :rtype: boolean
        """
        model_updated = False
        for haros_link in haros_node_model_links:
            haros_service_instance_name = haros_link.service.id
            if self._check_haros_name_is_complete(haros_service_instance_name,
                                                  'Check for Node Services'):
                # VALIDATE Service Parent Types to Alert the User of INCONSISTENT / INACCURATE DATA.
                if haros_service_instance_name in chris_node_model_services:
                    haros_service_parent_type = haros_link.service.name
                    chris_service_parent_type = chris_node_model_services[
                        haros_service_instance_name]
                    if haros_service_parent_type != chris_service_parent_type:
                        Logger.get_logger().log(
                            LoggerLevel.ERROR,
                            '[{}] HAROS "{}" Service Parent\'s Type "{}" for Service "{}" does NOT Match CHRIS Service Parent\'s Type "{}".'
                            .format(self.__class__.TYPE, link_type,
                                    haros_service_parent_type,
                                    haros_service_instance_name,
                                    chris_service_parent_type))
                # elif haros_service_instance_name not in chris_node_model_services:
                else:
                    Logger.get_logger().log(
                        LoggerLevel.INFO,
                        '[{}] Adding HAROS Node\'s {} Service "{}" to CHRIS Node Instance.'
                        .format(self.__class__.TYPE, link_type,
                                haros_service_instance_name))
                    chris_node_model_services[
                        haros_service_instance_name] = haros_link.service.name
                    model_updated = True
        return model_updated
Beispiel #28
0
    def _merge_haros_model_with_chris_model(self, bank_type, haros_instance_name, haros_model, chris_model):
        """
        Method that handles merging of a specific HAROS model with a specific
        CHRIS model

        :param bank_type: the corresponding CHRIS Model Bank Type
        :type bank_type: BankType
        :param haros_instance_name: the string HAROS model instance name
        :type haros_instance_name: str
        :param haros_model: the specific HAROS model to obtain data from
        :type haros_model: MetamodelObject
        :param chris_model: the specific CHRIS Model to merge data into
        :type chris_model: _EntityMetamodel
        """
        Logger.get_logger().log(LoggerLevel.INFO, '[{}] Merging HAROS Instance with CHRIS Instance "{}".'.format(
            self.__class__.TYPE, haros_instance_name))
        model_updated = self._helper_merge_haros_model_with_chris_model(
            bank_type, haros_model, chris_model)
        self.__class__._update_chris_model_version(chris_model, model_updated)
Beispiel #29
0
    def _helper_merge_haros_model_with_chris_model(self, bank_type, haros_model, chris_model):
        """
        Main merging helper method that handles specific details regarding the
        merging of a specific Package Specification HAROS model with a specific
        Package Specification CHRIS model

        :param bank_type: the corresponding CHRIS Model Bank Type
        :type bank_type: BankType
        :param haros_model: the specific HAROS model to obtain data from
        :type haros_model: Package
        :param chris_model: the specific CHRIS Model to merge data into
        :type chris_model: PackageSpecification
        """
        model_updated = False
        haros_package_name = haros_model.name
        # VALIDATE Package Directory Path to Alert the User of INCONSISTENT / INACCURATE DATA.
        haros_directory_path = haros_model.path
        chris_directory_path = chris_model.directory_path
        if (haros_directory_path and (haros_directory_path != chris_directory_path)):
            Logger.get_logger().log(LoggerLevel.ERROR, '[{}] HAROS Package Directory Path "{}" for Package "{}" does NOT Match CHRIS Package Directory Path "{}".'.format(
                self.__class__.TYPE, haros_directory_path, haros_package_name, chris_directory_path))
         # VALIDATE Package Version to Alert the User of INCONSISTENT / INACCURATE DATA.
        haros_version = haros_model.version
        chris_installed_version = chris_model.installed_version
        if (haros_version and (haros_version != chris_installed_version)):
            Logger.get_logger().log(LoggerLevel.ERROR, '[{}] HAROS Package Version "{}" for Package "{}" does NOT Match CHRIS Package Installed Version "{}".'.format(
                self.__class__.TYPE, haros_version, haros_package_name, chris_installed_version))
        # VALIDATE Package Metapackage Status to Alert the User of INCONSISTENT / INACCURATE DATA.
        haros_is_metapackage = haros_model.is_metapackage
        chris_is_metapackage = chris_model.is_metapackage
        if (haros_is_metapackage != chris_is_metapackage):
            Logger.get_logger().log(LoggerLevel.ERROR, '[{}] HAROS Package Metapackage Status "{}" for Package "{}" does NOT Match CHRIS Package Metapackage Status "{}".'.format(
                self.__class__.TYPE, haros_is_metapackage, haros_package_name, chris_is_metapackage))
        # VALIDATE Package URL to Alert the User of INCONSISTENT / INACCURATE DATA.
        haros_vcs_url = haros_model.vcs_url
        chris_url = chris_model.url
        if haros_vcs_url:
            if (chris_url and (haros_vcs_url != chris_url)):
                Logger.get_logger().log(LoggerLevel.ERROR, '[{}] HAROS Package URL "{}" for Package "{}" does NOT Match CHRIS Package URL "{}".'.format(
                    self.__class__.TYPE, haros_vcs_url, haros_package_name, chris_url))
            else:
                chris_model.url = haros_vcs_url
                model_updated = True
        model_updated |= self._helper_merge_haros_dependencies_with_chris_model(
            haros_model, chris_model)
        model_updated |= self._helper_merge_haros_nodes_with_chris_model(
            haros_model, chris_model)
        haros_description = haros_model.description
        if (haros_description):
            chris_model.description = haros_description.strip()
            model_updated = True
        return model_updated
Beispiel #30
0
    def _helper_merge_haros_dependencies_with_chris_model(self, haros_model, chris_model):
        """
        Helper merging method to merge the HAROS Package Specification Dependencies
        with the CHRIS Package Specification Dependencies

        :param haros_node_model: the HAROS Package Specification model
        :type haros_node_model: Package
        :param chris_node_model: the CHRIS Package Specification model
        :type chris_node_model: PackageSpecification
        :return: boolean indicating if the model was updated (`True`) or not (`False`)
        :rtype: boolean
        """
        model_updated = False
        for haros_dependency_name in haros_model.dependencies.packages:
            if self._check_haros_name_is_complete(haros_dependency_name, 'Check for Node Spec Dependency'):
                if haros_dependency_name not in chris_model.dependencies:
                    Logger.get_logger().log(LoggerLevel.INFO, '[{}] Adding HAROS Package Spec\'s Dependency "{}" to CHRIS Package Spec.'.format(
                        self.__class__.TYPE, haros_dependency_name))
                    chris_model.dependencies.append(haros_dependency_name)
                    model_updated = True
        return model_updated