示例#1
0
def project_problems(scene: CachedScene, project: CachedProject) -> List[str]:

    scene_objects: Dict[str, str] = {obj.id: obj.type for obj in scene.objects}
    problems: List[str] = []

    unknown_types = {obj.type
                     for obj in scene.objects} - glob.OBJECT_TYPES.keys()

    if unknown_types:
        return [f"Scene invalid, contains unknown types: {unknown_types}."]

    possible_parents = scene.object_ids | project.action_points_ids

    for ap in project.action_points:

        # test if all objects exists in scene
        if ap.parent and ap.parent not in possible_parents:
            problems.append(
                f"Action point {ap.name} has non-existing parent: {ap.parent}."
            )
            continue

        for joints in project.ap_joints(ap.id):
            if joints.robot_id not in scene.object_ids:
                problems.append(
                    f"Action point {ap.name} has joints ({joints.name}) for an unknown robot: {joints.robot_id}."
                )

        for action in project.actions:

            # check if objects have used actions
            obj_id, action_type = action.parse_type()

            if obj_id not in scene_objects.keys():
                problems.append(
                    f"Object ID {obj_id} which action is used in {action.name} does not exist in scene."
                )
                continue

            try:
                os_type = scene_objects[obj_id]  # object type
            except KeyError:
                os_type = obj_id  # service

            if action_type not in glob.OBJECT_TYPES[os_type].actions:
                problems.append(
                    f"Object type {scene_objects[obj_id]} does not have action {action_type} used in {action.id}."
                )
                continue

            try:
                check_action_params(
                    scene, project, action,
                    glob.OBJECT_TYPES[os_type].actions[action_type])
            except Arcor2Exception as e:
                problems.append(str(e))

    return problems
示例#2
0
def project_problems(obj_types: ObjectTypeDict, scene: CachedScene, project: CachedProject) -> list[str]:

    if project.scene_id != scene.id:
        return ["Project/scene mismatch."]

    problems: list[str] = scene_problems(obj_types, scene)

    for proj_param in project.parameters:
        try:
            check_project_parameter(project, proj_param)
        except Arcor2Exception as e:
            problems.append(str(e))

    for ap in project.action_points:

        try:
            check_ap_parent(scene, project, ap.parent)
        except Arcor2Exception:
            problems.append(f"Action point {ap.name} has invalid parent: {ap.parent}.")

        for joints in project.ap_joints(ap.id):
            if joints.robot_id not in scene.object_ids:
                problems.append(
                    f"Action point {ap.name} has joints ({joints.name}) for an unknown robot: {joints.robot_id}."
                )

        for action in project.actions:

            # check if objects have used actions
            obj_id, action_type = action.parse_type()

            if obj_id not in scene.object_ids:
                problems.append(f"Object ID {obj_id} which action is used in {action.name} does not exist in scene.")
                continue

            scene_obj = scene.object(obj_id)
            if action_type not in obj_types[scene_obj.type].actions:
                problems.append(
                    f"ObjectType {scene_obj.type} does not have action {action_type} used in {action.name}."
                )
                continue

            action_meta = obj_types[scene_obj.type].actions[action_type]

            try:
                check_action_params(obj_types, scene, project, action, action_meta)
            except Arcor2Exception as e:
                problems.append(str(e))

            try:
                check_flows(project, action, action_meta)
            except Arcor2Exception as e:
                problems.append(str(e))

    return problems
示例#3
0
def project_problems(scene: CachedScene, project: CachedProject) -> List[str]:

    scene_objects: Dict[str, str] = {obj.id: obj.type for obj in scene.objects}

    action_ids: Set[str] = set()
    problems: List[str] = []

    unknown_types = {obj.type for obj in scene.objects} - glob.OBJECT_TYPES.keys()

    if unknown_types:
        return [f"Scene invalid, contains unknown types: {unknown_types}."]

    for ap in project.action_points:

        # test if all objects exists in scene
        if ap.parent and ap.parent not in scene_objects:
            problems.append(f"Action point '{ap.name}' has parent '{ap.parent}' that does not exist in the scene.")
            continue

        for joints in project.ap_joints(ap.id):
            if not joints.is_valid:
                problems.append(
                    f"Action point {ap.name} has invalid joints: {joints.name} " f"(robot {joints.robot_id})."
                )

        for action in project.actions:

            if action.id in action_ids:
                problems.append(f"Action {action.name} of the {ap.name} is not unique.")

            # check if objects have used actions
            obj_id, action_type = action.parse_type()

            if obj_id not in scene_objects.keys():
                problems.append(f"Object ID {obj_id} which action is used in {action.name} does not exist in scene.")
                continue

            try:
                os_type = scene_objects[obj_id]  # object type
            except KeyError:
                os_type = obj_id  # service

            if action_type not in glob.OBJECT_TYPES[os_type].actions:
                problems.append(
                    f"Object type {scene_objects[obj_id]} does not have action {action_type} " f"used in {action.id}."
                )
                continue

            try:
                check_action_params(scene, project, action, glob.OBJECT_TYPES[os_type].actions[action_type])
            except Arcor2Exception as e:
                problems.append(str(e))

    return problems
示例#4
0
文件: utils.py 项目: Croolman/arcor2
def global_action_points_class(project: CachedProject) -> str:
    tree = Module(body=[])

    tree.body.append(
        ImportFrom(
            module=arcor2.data.common.__name__,
            names=[
                alias(name=ActionPoint.__name__, asname=None),
                alias(name=Position.__name__, asname=None),
                alias(name=Pose.__name__, asname=None),
                alias(name=ProjectRobotJoints.__name__, asname=None),
            ],
            level=0,
        ))

    tree.body.append(
        ImportFrom(
            module=copy.__name__,
            names=[alias(name=copy.deepcopy.__name__, asname=None)],
            level=0,
        ))

    tree.body.append(
        ImportFrom(
            module=RES_MODULE,
            names=[alias(name=RES_CLS, asname=None)],
            level=0,
        ))

    aps_init_body: List[Union[Assign, Pass]] = []

    for ap in project.action_points:

        ap_cls_body: List[Assign] = [
            Assign(
                targets=[
                    Attribute(value=Name(id="self", ctx=Load()),
                              attr="_position",
                              ctx=Store())
                ],
                value=Attribute(
                    value=Call(
                        func=Attribute(
                            value=Attribute(value=Name(id="res", ctx=Load()),
                                            attr="project",
                                            ctx=Load()),
                            attr=CachedProject.bare_action_point.__name__,
                            ctx=Load(),
                        ),
                        args=[Str(s=ap.id, kind="")],
                        keywords=[],
                    ),
                    attr="position",
                    ctx=Load(),
                ),
                type_comment=None,
            )
        ]

        ap_type_name = humps.pascalize(ap.name)

        ap_joints_init_body: List[Assign] = []

        for joints in project.ap_joints(ap.id):
            ap_joints_init_body.append(
                Assign(
                    targets=[
                        Attribute(value=Name(id="self", ctx=Load()),
                                  attr=f"_{joints.name}",
                                  ctx=Store())
                    ],
                    value=Call(
                        func=Attribute(
                            value=Attribute(value=Name(id="res", ctx=Load()),
                                            attr="project",
                                            ctx=Load()),
                            attr="joints",
                            ctx=Load(),
                        ),
                        args=[Str(s=joints.id, kind="")],
                        keywords=[],
                    ),
                    type_comment=None,
                ))

        if ap_joints_init_body:

            ap_joints_cls_def = ClassDef(
                name=f"{ap_type_name}Joints",
                bases=[],
                keywords=[],
                body=[
                    FunctionDef(
                        name="__init__",
                        args=arguments(
                            args=[
                                arg(arg="self",
                                    annotation=None,
                                    type_comment=None),
                                arg(arg="res",
                                    annotation=Name(id=RES_CLS, ctx=Load()),
                                    type_comment=None),
                            ],
                            vararg=None,
                            kwonlyargs=[],
                            kw_defaults=[],
                            kwarg=None,
                            defaults=[],
                        ),
                        body=ap_joints_init_body,
                        decorator_list=[],
                        returns=None,
                        type_comment=None,
                    )
                ],
                decorator_list=[],
            )

            for joints in project.ap_joints(ap.id):
                ap_joints_cls_def.body.append(
                    FunctionDef(
                        name=joints.name,
                        args=arguments(
                            args=[
                                arg(arg="self",
                                    annotation=None,
                                    type_comment=None)
                            ],
                            vararg=None,
                            kwonlyargs=[],
                            kw_defaults=[],
                            kwarg=None,
                            defaults=[],
                        ),
                        body=[
                            Return(value=Call(
                                func=Name(id=copy.deepcopy.__name__,
                                          ctx=Load()),
                                args=[
                                    Attribute(value=Name(id="self",
                                                         ctx=Load()),
                                              attr=f"_{joints.name}",
                                              ctx=Load())
                                ],
                                keywords=[],
                            ))
                        ],
                        decorator_list=[Name(id="property", ctx=Load())],
                        returns=Name(id=ProjectRobotJoints.__name__,
                                     ctx=Load()),
                        type_comment=None,
                    ))

            tree.body.append(ap_joints_cls_def)

            ap_cls_body.append(
                Assign(
                    targets=[
                        Attribute(value=Name(id="self", ctx=Load()),
                                  attr="joints",
                                  ctx=Store())
                    ],
                    value=Call(
                        func=Name(id=f"{ap_type_name}Joints", ctx=Load()),
                        args=[Name(id="res", ctx=Load())],
                        keywords=[],
                    ),
                    type_comment=None,
                ))

        ap_orientations_init_body: List[Assign] = []

        for ori in project.ap_orientations(ap.id):
            ap_orientations_init_body.append(
                Assign(
                    targets=[
                        Attribute(value=Name(id="self", ctx=Load()),
                                  attr=f"_{ori.name}",
                                  ctx=Store())
                    ],
                    value=Call(
                        func=Attribute(
                            value=Attribute(value=Name(id="res", ctx=Load()),
                                            attr="project",
                                            ctx=Load()),
                            attr="pose",
                            ctx=Load(),
                        ),
                        args=[Str(s=ori.id, kind="")],
                        keywords=[],
                    ),
                    type_comment=None,
                ))

        if ap_orientations_init_body:

            ap_orientations_cls_def = ClassDef(
                name=f"{ap_type_name}Poses",
                bases=[],
                keywords=[],
                body=[
                    FunctionDef(
                        name="__init__",
                        args=arguments(
                            args=[
                                arg(arg="self",
                                    annotation=None,
                                    type_comment=None),
                                arg(arg="res",
                                    annotation=Name(id=RES_CLS, ctx=Load()),
                                    type_comment=None),
                            ],
                            vararg=None,
                            kwonlyargs=[],
                            kw_defaults=[],
                            kwarg=None,
                            defaults=[],
                        ),
                        body=ap_orientations_init_body,
                        decorator_list=[],
                        returns=None,
                        type_comment=None,
                    )
                ],
                decorator_list=[],
            )

            for ori in project.ap_orientations(ap.id):
                ap_orientations_cls_def.body.append(
                    FunctionDef(
                        name=ori.name,
                        args=arguments(
                            args=[
                                arg(arg="self",
                                    annotation=None,
                                    type_comment=None)
                            ],
                            vararg=None,
                            kwonlyargs=[],
                            kw_defaults=[],
                            kwarg=None,
                            defaults=[],
                        ),
                        body=[
                            Return(value=Call(
                                func=Name(id=copy.deepcopy.__name__,
                                          ctx=Load()),
                                args=[
                                    Attribute(value=Name(id="self",
                                                         ctx=Load()),
                                              attr=f"_{ori.name}",
                                              ctx=Load())
                                ],
                                keywords=[],
                            ))
                        ],
                        decorator_list=[Name(id="property", ctx=Load())],
                        returns=Name(id=Pose.__name__, ctx=Load()),
                        type_comment=None,
                    ))

            tree.body.append(ap_orientations_cls_def)

            ap_cls_body.append(
                Assign(
                    targets=[
                        Attribute(value=Name(id="self", ctx=Load()),
                                  attr="poses",
                                  ctx=Store())
                    ],
                    value=Call(
                        func=Name(id=f"{ap_type_name}Poses", ctx=Load()),
                        args=[Name(id="res", ctx=Load())],
                        keywords=[],
                    ),
                    type_comment=None,
                ))

        ap_cls_def = ClassDef(
            name=ap_type_name,
            bases=[],
            keywords=[],
            body=[
                FunctionDef(
                    name="__init__",
                    args=arguments(
                        args=[
                            arg(arg="self", annotation=None,
                                type_comment=None),
                            arg(arg="res",
                                annotation=Name(id=RES_CLS, ctx=Load()),
                                type_comment=None),
                        ],
                        vararg=None,
                        kwonlyargs=[],
                        kw_defaults=[],
                        kwarg=None,
                        defaults=[],
                    ),
                    body=ap_cls_body,
                    decorator_list=[],
                    returns=None,
                    type_comment=None,
                )
            ],
            decorator_list=[],
        )

        # add copy property for position
        ap_cls_def.body.append(
            FunctionDef(
                name="position",
                args=arguments(
                    args=[arg(arg="self", annotation=None, type_comment=None)],
                    vararg=None,
                    kwonlyargs=[],
                    kw_defaults=[],
                    kwarg=None,
                    defaults=[],
                ),
                body=[
                    Return(value=Call(
                        func=Name(id=copy.deepcopy.__name__, ctx=Load()),
                        args=[
                            Attribute(value=Name(id="self", ctx=Load()),
                                      attr="_position",
                                      ctx=Load())
                        ],
                        keywords=[],
                    ))
                ],
                decorator_list=[Name(id="property", ctx=Load())],
                returns=Name(id=Position.__name__, ctx=Load()),
                type_comment=None,
            ))

        tree.body.append(ap_cls_def)

        aps_init_body.append(
            Assign(
                targets=[
                    Attribute(value=Name(id="self", ctx=Load()),
                              attr=ap.name,
                              ctx=Store())
                ],
                value=Call(func=Name(id=ap_type_name, ctx=Load()),
                           args=[Name(id="res", ctx=Load())],
                           keywords=[]),
                type_comment=None,
            ))

    if not aps_init_body:  # there are no action points
        aps_init_body.append(Pass())

    aps_cls_def = ClassDef(
        name="ActionPoints",
        bases=[],
        keywords=[],
        body=[
            FunctionDef(
                name="__init__",
                args=arguments(
                    args=[
                        arg(arg="self", annotation=None, type_comment=None),
                        arg(arg="res",
                            annotation=Name(id=RES_CLS, ctx=Load()),
                            type_comment=None),
                    ],
                    vararg=None,
                    kwonlyargs=[],
                    kw_defaults=[],
                    kwarg=None,
                    defaults=[],
                ),
                body=aps_init_body,
                decorator_list=[],
                returns=None,
                type_comment=None,
            )
        ],
        decorator_list=[],
    )

    tree.body.append(aps_cls_def)
    return tree_to_str(tree)
示例#5
0
class Resources:

    __slots__ = ("project", "scene", "objects", "args", "executor",
                 "_stream_futures")

    def __init__(self, apply_action_mapping: bool = True) -> None:

        models: dict[str, Optional[Models]] = {}

        scene = self.read_project_data(Scene.__name__.lower(), Scene)
        project = self.read_project_data(Project.__name__.lower(), Project)

        self.scene = CachedScene(scene)
        self.project = CachedProject(project)

        if self.project.scene_id != self.scene.id:
            raise ResourcesException("Project/scene not consistent!")

        # make all poses absolute
        for aps in self.project.action_points_with_parent:
            # Action point pose is relative to its parent object/AP pose in scene but is absolute during runtime.
            tr.make_relative_ap_global(self.scene, self.project, aps)

        for obj_type in self.scene.object_types:

            try:
                models[obj_type] = self.read_project_data(
                    "models/" + humps.depascalize(obj_type),
                    ObjectModel).model()
            except IOError:
                models[obj_type] = None

        type_defs: TypesDict = {}

        for scene_obj_type in self.scene.object_types:  # get all type-defs

            assert scene_obj_type not in type_defs
            assert scene_obj_type not in built_in_types_names()

            module = importlib.import_module(CUSTOM_OBJECT_TYPES_MODULE + "." +
                                             humps.depascalize(scene_obj_type))

            cls = getattr(module, scene_obj_type)
            patch_object_actions(cls)
            type_defs[cls.__name__] = cls

            if apply_action_mapping:
                patch_with_action_mapping(cls, self.scene, self.project)

        action.start_paused, action.breakpoints = parse_args()

        if action.breakpoints:
            ap_ids = self.project.action_points_ids
            for bp in action.breakpoints:
                if bp not in ap_ids:
                    raise ResourcesException(f"Breakpoint ID unknown: {bp}.")

        # orientations / joints have to be monkey-patched with AP's ID in order to make breakpoints work in @action
        for ap in self.project.action_points:

            setattr(ap.position, AP_ID_ATTR, ap.id)

            for joints in self.project.ap_joints(ap.id):
                setattr(joints, AP_ID_ATTR, ap.id)

        package_id = os.path.basename(os.getcwd())
        package_meta = package.read_package_meta(package_id)
        package_info_event = PackageInfo(
            PackageInfo.Data(package_id, package_meta.name, scene, project))

        for model in models.values():

            if not model:
                continue

            if isinstance(model, Box):
                package_info_event.data.collision_models.boxes.append(model)
            elif isinstance(model, Sphere):
                package_info_event.data.collision_models.spheres.append(model)
            elif isinstance(model, Cylinder):
                package_info_event.data.collision_models.cylinders.append(
                    model)
            elif isinstance(model, Mesh):
                package_info_event.data.collision_models.meshes.append(model)

        # following steps might take some time, so let UIs know about the package as a first thing
        print_event(package_info_event)

        # in order to prepare a clean environment (clears all configurations and all collisions)
        scene_service.stop()

        self.executor = concurrent.futures.ThreadPoolExecutor()
        futures: list[concurrent.futures.Future] = []

        for scene_obj in self.scene.objects:

            cls = type_defs[scene_obj.type]
            settings = settings_from_params(
                cls, scene_obj.parameters,
                self.project.overrides.get(scene_obj.id, None))

            if issubclass(cls, Robot):
                futures.append(
                    self.executor.submit(cls, scene_obj.id, scene_obj.name,
                                         scene_obj.pose, settings))
            elif issubclass(cls, CollisionObject):
                futures.append(
                    self.executor.submit(cls, scene_obj.id, scene_obj.name,
                                         scene_obj.pose,
                                         models[scene_obj.type], settings))
            elif issubclass(cls, GenericWithPose):
                futures.append(
                    self.executor.submit(cls, scene_obj.id, scene_obj.name,
                                         scene_obj.pose, settings))
            elif issubclass(cls, Generic):
                futures.append(
                    self.executor.submit(cls, scene_obj.id, scene_obj.name,
                                         settings))
            else:
                raise Arcor2Exception(
                    f"{cls.__name__} has unknown base class.")

        exceptions: list[Arcor2Exception] = []

        self.objects: dict[str, Generic] = {}

        for f in concurrent.futures.as_completed(futures):
            try:
                inst = f.result(
                )  # if an object creation resulted in exception, it will be raised here
            except Arcor2Exception as e:
                print_exception(e)
                exceptions.append(e)
            else:
                self.objects[
                    inst.id] = inst  # successfully initialized objects

        if exceptions:  # if something failed, tear down those that succeeded and stop
            self.cleanup_all_objects()
            raise ResourcesException(" ".join([str(e) for e in exceptions]),
                                     exceptions)

        scene_service.start()

        self._stream_futures: list[concurrent.futures.Future] = []

    def read_project_data(self, file_name: str, cls: type[T]) -> T:
        try:

            with open(os.path.join("data", file_name + ".json")) as scene_file:
                return cls.from_dict(
                    humps.decamelize(json.loads_type(scene_file.read(), dict)))

        except JsonSchemaValidationError as e:
            raise ResourcesException(f"Invalid project/scene: {e}")

    def cleanup_all_objects(self) -> None:
        """Calls cleanup method of all objects in parallel.

        Errors are just logged.
        """

        futures: list[concurrent.futures.Future] = []
        with concurrent.futures.ThreadPoolExecutor() as executor:
            for obj in self.objects.values():
                futures.append(executor.submit(obj.cleanup))
            for future in concurrent.futures.as_completed(futures):
                try:
                    future.result()
                except Arcor2Exception as e:
                    print_exception(e)

    def __enter__(self: R) -> R:

        if _streaming_period > 0:  # TODO could be also controlled by script argument (RunPackage flag)
            for inst in self.objects.values():

                if not isinstance(inst, Robot):
                    continue

                self._stream_futures.append(
                    self.executor.submit(stream_pose, inst))
                self._stream_futures.append(
                    self.executor.submit(stream_joints, inst))

        return self

    def __exit__(
        self,
        ex_type: Optional[type[BaseException]],
        ex_value: Optional[BaseException],
        traceback: Optional[TracebackType],
    ) -> bool:

        _shutting_down.set()

        try:
            concurrent.futures.wait(self._stream_futures, 1.0)
        except concurrent.futures.TimeoutError:
            pass

        if isinstance(ex_value, Exception):
            # this intentionally ignores KeyboardInterrupt (derived from BaseException)
            print_exception(ex_value)

        scene_service.stop()
        self.cleanup_all_objects()

        return True