def get_os_path_to_library(self, library_path, library_name, allow_user_interaction=True):
        """Find library_os_path of library

        This function retrieves the file system library_os_path of a library specified by a library_path and a 
        library_name. In case the library does not exist any more at its original location, the user has to specify 
        an alternative location.

        :param str library_path: The library_path of the library, that must be relative and within a library_root_path 
                             given in the config.yaml by LIBRARY_PATHS
        :param str library_name: The name of the library
        :param bool allow_user_interaction: Whether the user may be asked to specify library location
        :return: library_os_path within filesystem, library_path, library_name
        :rtype: str, str, str
        :raises rafcon.core.custom_exceptions.LibraryNotFoundException: if the cannot be found
        """
        original_path_and_name = os.path.join(library_path, library_name)
        library_path_root = library_path.split(os.sep)[0]

        if library_path.split(os.sep) and \
                (library_path.startswith(os.sep) or library_path.endswith(os.sep) or os.sep + os.sep in library_path):
            raise LibraryNotFoundException("A library_path is not considered to start or end with {2} or to have two "
                                           "path separators {2}{2} in a row like '{0}' with library name {1}"
                                           "".format(library_path, library_name, os.sep))

        if not self._library_root_paths:
            raise LibraryNotFoundException("There are no libraries registered")

        # skip already skipped states
        if original_path_and_name in self._skipped_states or library_path_root in self._skipped_library_roots:
            # if an already skipped state shall be loaded again, directly raise the exception to jump over this state
            raise LibraryNotFoundException("Library '{0}' not found in subfolder {1}".format(library_name,
                                                                                             library_path))

        # replace already replaced states
        if original_path_and_name in self._replaced_libraries:
            new_library_os_path = self._replaced_libraries[original_path_and_name][0]
            new_library_path = self._replaced_libraries[original_path_and_name][1]

            # only show debug message if a state is automatically replaced by the appropriate library state
            # chosen by the user before
            if not self._replaced_libraries[original_path_and_name][2]:
                logger.debug("The library with library_path \"{0}\" and name \"{1}\" "
                             "is automatically replaced by the library "
                             "with file system library_os_path \"{2}\" and library_path \"{3}\""
                             "".format(library_path, library_name, new_library_os_path, new_library_path))
            return new_library_os_path, new_library_path, library_name

        # a boolean to indicate if a state was regularly found or by the help of the user
        regularly_found = True

        library_os_path = self._get_library_os_path_from_library_dict_tree(library_path, library_name)
        while library_os_path is None:  # until the library is found or the user aborts

            regularly_found = False
            new_library_os_path = None
            if allow_user_interaction:
                notice = "Cannot find library '{0}' in library_path '{1}' in any of the library root paths. " \
                         "Please check your library root paths configuration in config.yaml " \
                         "LIBRARY_PATHS and environment variable RAFCON_LIBRARY_PATH. " \
                         "If your library_path is correct and the library was moved, please " \
                         "select the new root/library_os_path folder of the library which should be situated within a "\
                         "loaded library_root_path. If not, please abort.".format(library_name, library_path)
                interface.show_notice_func(notice)
                new_library_os_path = interface.open_folder_func("Select root folder for library name '{0}'"
                                                                 "".format(original_path_and_name))
            if new_library_os_path is None:
                # User clicked cancel => cancel library search
                # If the library root path is existent (e.g. "generic") and only the specific library state is not (
                # e.g. "generic/wait", then the state is added to the skipped states.
                # If the library root path is not existing, we ignore the whole library, preventing the user from
                # endless dialogs for each missing library state.
                if library_path_root not in self.libraries:
                    self._skipped_library_roots.append(library_path_root)
                else:
                    self._skipped_states.append(original_path_and_name)
                raise LibraryNotFoundException("Library '{0}' not found in sub-folder {1}".format(library_name,
                                                                                                  library_path))

            if not os.path.exists(new_library_os_path):
                logger.error('Specified library_os_path does not exist')
                continue

            # check if valid library_path and library_name can be created
            library_path, library_name = self.get_library_path_and_name_for_os_path(new_library_os_path)
            if library_path is None:
                logger.error("Specified library_os_path not within loaded library_root_path list or your config.yaml "
                             "file LIBRARY_PATHS or in the list of paths in environment variable RAFCON_LIBRARY_PATH")
                continue  # Allow the user to change the directory

            # verification if library is also in library tree
            library_os_path = self._get_library_os_path_from_library_dict_tree(library_path, library_name)
            if library_os_path is not None:
                assert library_os_path == new_library_os_path

        # save the replacement in order that for a future occurrence the correct library_os_path can be used,
        # without asking the user for the correct library_os_path
        self._replaced_libraries[original_path_and_name] = (library_os_path, library_path, regularly_found)
        return library_os_path, library_path, library_name
Find library_os_path of library

        This function retrieves the file system library_os_path of a library specified by a library_path and a 
        library_name. In case the library does not exist any more at its original location, the user has to specify 
        an alternative location.

        :param str library_path: The library_path of the library, that must be relative and within a library_root_path 
                             given in the config.yaml by LIBRARY_PATHS
        :param str library_name: The name of the library
        :param bool allow_user_interaction: Whether the user may be asked to specify library location
        :return: library_os_path within filesystem, library_path, library_name
        :rtype: str, str, str
        :raises rafcon.core.custom_exceptions.LibraryNotFoundException: if the cannot be found