async def create_object_instance(obj: SceneObject, overrides: Optional[List[Parameter]] = None ) -> None: obj_type = glob.OBJECT_TYPES[obj.type] # settings -> dataclass assert obj_type.type_def glob.logger.debug( f"Creating instance of {obj_type.type_def.__name__} with name {obj.name}. " f"Parameters: {obj.parameters}, overrides: {overrides}.") settings = settings_from_params(obj_type.type_def, obj.parameters, overrides) assert obj_type.type_def is not None try: try: if issubclass(obj_type.type_def, Robot): assert obj.pose is not None glob.SCENE_OBJECT_INSTANCES[ obj.id] = await hlp.run_in_executor( obj_type.type_def, obj.id, obj.name, obj.pose, settings) elif issubclass(obj_type.type_def, GenericWithPose): assert obj.pose is not None coll_model: Optional[Models] = None if obj_type.meta.object_model: coll_model = obj_type.meta.object_model.model() glob.SCENE_OBJECT_INSTANCES[ obj.id] = await hlp.run_in_executor( obj_type.type_def, obj.id, obj.name, obj.pose, coll_model, settings) elif issubclass(obj_type.type_def, Generic): assert obj.pose is None glob.SCENE_OBJECT_INSTANCES[ obj.id] = await hlp.run_in_executor( obj_type.type_def, obj.id, obj.name, settings) else: raise Arcor2Exception("Object type with unknown base.") except (TypeError, ValueError) as e: # catch some most often exceptions raise Arcor2Exception("Unhandled error.") from e except Arcor2Exception as e: # make the exception a bit more user-friendly by including the object's name raise Arcor2Exception( f"Failed to initialize {obj.name}. {str(e)}") from e return None
def test_settings_from_params() -> None: settings = settings_from_params( TestObjectWithSettings, [ Parameter("string", "string", json.dumps("value")), Parameter("integer", "integer", json.dumps(1)), Parameter("boolean", "boolean", json.dumps(False)), Parameter("double", "double", json.dumps(1.0)), Parameter("enum", "enum", json.dumps(MyEnum.OPT1)), Parameter("nested_settings", "dataclass", NestedSettings(True).to_json()), ], [Parameter("integer", "integer", json.dumps(2)), Parameter("double", "double", json.dumps(2.0))], ) assert isinstance(settings, TestObjectSettings)
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 __init__(self, scene: Scene, project: Project, models: Dict[str, Optional[Models]]) -> None: self.project = CachedProject(project) self.scene = CachedScene(scene) if self.project.scene_id != self.scene.id: raise ResourcesException("Project/scene not consistent!") self.objects: Dict[str, Generic] = {} self.type_defs: TypesDict = {} built_in = built_in_types_names() if scene_service.started(): scene_service.stop() scene_service.delete_all_collisions() 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 scene_obj_type in self.scene.object_types: # get all type-defs assert scene_obj_type not in self.type_defs if scene_obj_type in built_in: module = importlib.import_module( arcor2.object_types.__name__ + "." + humps.depascalize(scene_obj_type)) else: module = importlib.import_module( Resources.CUSTOM_OBJECT_TYPES_MODULE + "." + humps.depascalize(scene_obj_type)) cls = getattr(module, scene_obj_type) patch_object_actions( cls, get_action_name_to_id(self.scene, self.project, cls.__name__)) self.type_defs[cls.__name__] = cls scene_objects = list(self.scene.objects) # sort according to OT initialization priority (highest is initialized first) scene_objects.sort(key=lambda x: self.type_defs[x.type].INIT_PRIORITY, reverse=True) for scene_obj in scene_objects: cls = self.type_defs[scene_obj.type] assert scene_obj.id not in self.objects, "Duplicate object id {}!".format( scene_obj.id) settings = settings_from_params( cls, scene_obj.parameters, self.project.overrides.get(scene_obj.id, None)) if issubclass(cls, Robot): self.objects[scene_obj.id] = cls(scene_obj.id, scene_obj.name, scene_obj.pose, settings) elif issubclass(cls, GenericWithPose): self.objects[scene_obj.id] = cls(scene_obj.id, scene_obj.name, scene_obj.pose, models[scene_obj.type], settings) elif issubclass(cls, Generic): self.objects[scene_obj.id] = cls(scene_obj.id, scene_obj.name, settings) else: raise Arcor2Exception("Unknown base class.") 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) scene_service.start() print_event(package_info_event) # 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)