Beispiel #1
0
def upload_def(type_def: Type[Generic], model: Optional[Models] = None, urdf: Optional[Urdf] = None) -> None:

    if not issubclass(type_def, GenericWithPose) and model:
        raise UploadException("Object without pose can't have collision model.")

    try:
        check_object_type(type_def)
    except Arcor2Exception as e:
        print(e)
        raise UploadException(f"There is something wrong with source code of '{type_def.__name__}'.")

    obj_type = ObjectType(
        id=type_def.__name__, source=get_containing_module_sources(type_def), description=type_def.description()
    )

    if model:
        obj_type.model = model.metamodel()
        ps.put_model(model)

    print(f"Storing '{obj_type.id}'...")
    ps.update_object_type(obj_type)

    if urdf:

        if not os.path.isdir(urdf.path_to_directory):
            print(f"{urdf.path_to_directory} is not a directory.")
            return

        print(f"Storing URDF package for '{obj_type.id}'.")

        paths: List[str] = []

        # full path is in form src/python/arcor2_fit_demo/data/dobot-m1/dobot_m1_description/meshes
        # so we need to remove the prefix (e.g. src/python/arcor2_fit_demo/data/dobot-m1)
        # let's find the prefix...
        for root, _, files in os.walk(urdf.path_to_directory):
            for filename in files:
                paths.append(os.path.join(root, filename))

        prefix = os.path.commonpath(paths)

        mem_zip = BytesIO()
        with zipfile.ZipFile(mem_zip, mode="w", compression=zipfile.ZIP_DEFLATED) as zf:
            for root, _, files in os.walk(urdf.path_to_directory):
                for filename in files:
                    path = os.path.join(root, filename)
                    # in the archive, the path will be without the prefix
                    zf.write(path, os.path.relpath(path, prefix))

        mem_zip.seek(0)
        ps.upload_mesh_file(urdf.archive_name, mem_zip.getvalue())
Beispiel #2
0
async def get_object_data(object_types: ObjectTypeDict, obj_id: str) -> None:

    glob.logger.debug(f"Processing {obj_id}.")

    if obj_id in object_types:
        glob.logger.debug(f"{obj_id} already processed, skipping...")
        return

    obj = await storage.get_object_type(obj_id)

    if obj_id in glob.OBJECT_TYPES and glob.OBJECT_TYPES[obj_id].type_def is not None:

        stored_type_def = glob.OBJECT_TYPES[obj_id].type_def
        assert stored_type_def

        # TODO do not compare sources but 'modified`
        # the code we get from type_def has Unix line endings, while the code from Project service might have Windows...
        obj.source = convert_line_endings_to_unix(obj.source)

        if get_containing_module_sources(stored_type_def) == obj.source:
            glob.logger.debug(f"No need to update {obj_id}.")
            return

    try:
        bases = otu.base_from_source(obj.source, obj_id)
        if bases and bases[0] not in object_types.keys() | built_in_types_names():
            glob.logger.debug(f"Getting base class {bases[0]} for {obj_id}.")
            await get_object_data(object_types, bases[0])

        for mixin in bases[1:]:
            mixin_obj = await storage.get_object_type(mixin)

            await hlp.run_in_executor(
                hlp.save_and_import_type_def,
                mixin_obj.source,
                mixin_obj.id,
                object,
                settings.OBJECT_TYPE_PATH,
                settings.OBJECT_TYPE_MODULE,
            )

    except Arcor2Exception as e:
        glob.logger.warn(f"Disabling object type {obj.id}: can't get a base. {str(e)}")
        object_types[obj_id] = ObjectTypeData(
            ObjectTypeMeta(obj_id, "Object type disabled.", disabled=True, problem="Can't get base.")
        )
        return

    glob.logger.debug(f"Updating {obj_id}.")

    try:
        type_def = await hlp.run_in_executor(
            hlp.save_and_import_type_def,
            obj.source,
            obj.id,
            Generic,
            settings.OBJECT_TYPE_PATH,
            settings.OBJECT_TYPE_MODULE,
        )
    except Arcor2Exception as e:
        glob.logger.debug(f"{obj.id} is probably not an object type. {str(e)}")
        return

    assert issubclass(type_def, Generic)

    try:
        meta = meta_from_def(type_def)
        otu.get_settings_def(type_def)  # just to check if settings are ok
    except Arcor2Exception as e:
        glob.logger.warning(f"Disabling object type {obj.id}.")
        glob.logger.debug(e, exc_info=True)
        object_types[obj_id] = ObjectTypeData(
            ObjectTypeMeta(obj_id, "Object type disabled.", disabled=True, problem=str(e))
        )
        return

    if obj.model:
        try:
            model = await storage.get_model(obj.model.id, obj.model.type)
        except Arcor2Exception:
            glob.logger.error(f"{obj.model.id}: failed to get collision model of type {obj.model.type}.")
            meta.disabled = True
            meta.problem = "Can't get collision model."
            object_types[obj_id] = ObjectTypeData(meta)
            return

        kwargs = {model.type().value.lower(): model}
        meta.object_model = ObjectModel(model.type(), **kwargs)  # type: ignore

    ast = parse(obj.source)
    otd = ObjectTypeData(meta, type_def, object_actions(type_def, ast), ast)

    object_types[obj_id] = otd
Beispiel #3
0
async def get_object_data(object_types: ObjectTypeDict, obj_id: str) -> None:

    glob.logger.debug(f"Processing {obj_id}.")

    if obj_id in object_types:
        glob.logger.debug(f"{obj_id} already processed, skipping...")
        return

    obj = await storage.get_object_type(obj_id)

    if obj_id in glob.OBJECT_TYPES and glob.OBJECT_TYPES[
            obj_id].type_def is not None:

        stored_type_def = glob.OBJECT_TYPES[obj_id].type_def
        assert stored_type_def
        if hash(get_containing_module_sources(stored_type_def)) == hash(
                obj.source):
            glob.logger.debug(f"No need to update {obj_id}.")
            return

    try:
        base = otu.base_from_source(obj.source, obj_id)
        if base and base not in object_types.keys() | built_in_types_names():
            glob.logger.debug(f"Getting base class {base} for {obj_id}.")
            await get_object_data(object_types, base)
    except Arcor2Exception:
        object_types[obj_id] = ObjectTypeData(
            ObjectTypeMeta(obj_id,
                           "Object type disabled.",
                           disabled=True,
                           problem="Can't get base."))
        return

    glob.logger.debug(f"Updating {obj_id}.")

    try:
        type_def = await hlp.run_in_executor(
            hlp.save_and_import_type_def,
            obj.source,
            obj.id,
            Generic,
            settings.OBJECT_TYPE_PATH,
            settings.OBJECT_TYPE_MODULE,
        )
        assert issubclass(type_def, Generic)
        meta = meta_from_def(type_def)
        otu.get_settings_def(type_def)  # just to check if settings are ok
    except Arcor2Exception as e:
        glob.logger.warning(f"Disabling object type {obj.id}.")
        glob.logger.debug(e, exc_info=True)
        object_types[obj_id] = ObjectTypeData(
            ObjectTypeMeta(obj_id,
                           "Object type disabled.",
                           disabled=True,
                           problem=str(e)))
        return

    if obj.model:
        try:
            model = await storage.get_model(obj.model.id, obj.model.type)
        except Arcor2Exception:
            glob.logger.error(
                f"{obj.model.id}: failed to get collision model of type {obj.model.type}."
            )
            meta.disabled = True
            meta.problem = "Can't get collision model."
            object_types[obj_id] = ObjectTypeData(meta)
            return

        kwargs = {model.type().value.lower(): model}
        meta.object_model = ObjectModel(model.type(), **kwargs)  # type: ignore

    ast = parse(obj.source)
    otd = ObjectTypeData(meta, type_def, object_actions(type_def, ast), ast)

    object_types[obj_id] = otd
Beispiel #4
0
def upload_whatever(type_def: Type[object]) -> None:

    obj_type = ObjectType(id=type_def.__name__, source=get_containing_module_sources(type_def))
    print(f"Storing '{obj_type.id}'...")
    ps.update_object_type(obj_type)
Beispiel #5
0
def upload_def(
    type_def: type[Generic],
    model: Optional[Models] = None,
    urdf: Optional[Urdf] = None,
    file_to_upload: Optional[str] = None,
) -> None:
    """Uploads ObjectType definition to the Project service.

    :param type_def: Class definition.
    :param model: Collision model.
    :param urdf: If the type is robot, path to its URDF can be given here.
    :param file_to_upload: Path to a file. Used e.g. to upload a mesh together with the ObjectType.
    :return:
    """

    if not issubclass(type_def, Robot) and urdf:
        raise UploadException("Parameter 'urdf' set for non-Robot.")

    try:
        check_object_type(type_def)
    except Arcor2Exception as e:
        raise UploadException(
            f"{type_def.__name__} is not a valid ObjectType. {str(e)}")

    obj_type = ObjectType(id=type_def.__name__,
                          source=get_containing_module_sources(type_def),
                          description=type_def.description())

    if issubclass(type_def, CollisionObject):
        if not model:
            raise UploadException(
                "Parameter 'model' must be set for CollisionObject.")

        if model.id != obj_type.id:
            raise UploadException(
                "Model id have to be the same as ObjectType id.")

        obj_type.model = model.metamodel()

        if isinstance(model, Mesh):

            if not type_def.mesh_filename:
                raise UploadException("Mesh filename not set.")

            if not file_to_upload:
                raise UploadException(
                    "For mesh collision model, file_to_upload parameter have to be set."
                )

            try:
                with open(file_to_upload, "rb") as f:
                    ps.upload_file(type_def.mesh_filename, f.read())
            except OSError as e:
                raise UploadException(f"Failed to read mesh file. {str(e)}")

        ps.put_model(model)

    else:
        if model:
            raise UploadException(
                "Parameter 'model' set for non-CollisionObject.")

    print(f"Storing '{obj_type.id}'...")
    ps.update_object_type(obj_type)

    if urdf:

        if not os.path.isdir(urdf.path_to_directory):
            print(f"{urdf.path_to_directory} is not a directory.")
            return

        print(f"Storing URDF package for '{obj_type.id}'.")

        paths: list[str] = []

        # full path is in form src/python/arcor2_fit_demo/data/dobot-m1/dobot_m1_description/meshes
        # so we need to remove the prefix (e.g. src/python/arcor2_fit_demo/data/dobot-m1)
        # let's find the prefix...
        for root, _, files in os.walk(urdf.path_to_directory):
            for filename in files:
                paths.append(os.path.join(root, filename))

        prefix = os.path.commonpath(paths)

        mem_zip = BytesIO()
        with zipfile.ZipFile(mem_zip,
                             mode="w",
                             compression=zipfile.ZIP_DEFLATED) as zf:
            for root, _, files in os.walk(urdf.path_to_directory):
                for filename in files:
                    path = os.path.join(root, filename)
                    # in the archive, the path will be without the prefix
                    zf.write(path, os.path.relpath(path, prefix))

        mem_zip.seek(0)
        ps.upload_file(urdf.archive_name, mem_zip.getvalue())