def METHOD_NAME(objects_to_be_replaced: List[MeshObject], objects_to_replace_with: List[MeshObject],
                    ignore_collision_with: Optional[List[MeshObject]] = None, replace_ratio: float = 1,
                    copy_properties: bool = True, max_tries: int = 100,
                    relative_pose_sampler: Callable[[MeshObject], None] = None):
    """
    Replaces mesh objects with another mesh objects and scales them accordingly, the replaced objects and the
    objects to replace with in following steps:
    1. Randomly select a subset of objects_to_be_replaced.
    2. For each of these objects, sample other objects from objects_to_replace_with and try to replace them.
    3. In each try, the poses of the objects are aligned and a check for collisions with other objects is done.
    4. An object is skipped if max_tries is reached.
    :param objects_to_be_replaced: Objects, which should be removed from the scene.
    :param objects_to_replace_with: Objects, which will be tried to be added to the scene.
    :param ignore_collision_with: Objects, which are not checked for collisions with.
    :param replace_ratio: Ratio of objects in the original scene, which will be replaced.
    :param copy_properties: Copies the custom properties of the objects_to_be_replaced to the objects_to_replace_with.
    :param max_tries: Maximum number of tries to replace one object.
    :param relative_pose_sampler: A function that randomly perturbs the pose of the object to replace with
                                  (after it has been aligned to the object to replace).
    """
    if ignore_collision_with is None:
        ignore_collision_with = []
    # Hide new objects from renderers until they are added
    for obj in objects_to_replace_with:
        obj.hide()
    check_collision_with = []
    for obj in get_all_mesh_objects():
        if obj not in ignore_collision_with:
            check_collision_with.append(obj)
    # amount of replacements depends on the amount of objects and the replace ratio
    objects_to_be_replaced = random.sample(objects_to_be_replaced, k=int(len(objects_to_be_replaced) * replace_ratio))
    if len(objects_to_be_replaced) == 0:
        print("Warning: The amount of objects, which should be replace is zero!")
    # Go over all objects we should replace
    for current_object_to_be_replaced in objects_to_be_replaced:
        print(current_object_to_be_replaced.get_name())
        # Do at most max_tries to replace the object with a random object from  objects_to_replace_with
        tries = 0
        while tries < max_tries:
            current_object_to_replace_with = np.random.choice(objects_to_replace_with)
            if _ObjectReplacer.replace(current_object_to_be_replaced, current_object_to_replace_with,
                                       check_collision_with, relative_pose_sampler=relative_pose_sampler):
                # Duplicate the added object to be able to add it again
                duplicate_new_object = current_object_to_replace_with.duplicate()
                # Copy properties to the newly duplicated object
                if copy_properties:
                    for key, value in current_object_to_be_replaced.get_all_cps().items():
                        duplicate_new_object.set_cp(key, value)
                duplicate_new_object.hide(False)
                print('Replaced ', current_object_to_be_replaced.get_name(), ' by ', duplicate_new_object.get_name())
                # Delete the original object and remove it from the list
                check_collision_with.remove(current_object_to_be_replaced)
                current_object_to_be_replaced.delete()
                break
            tries += 1
        if tries == max_tries:
            print("Could not replace " + current_object_to_be_replaced.get_name())