def parameter_value( cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str ) -> List[Pose]: ret: List[Pose] = [] ap, action = project.action_point_and_action(action_id) parameter = action.parameter(parameter_id) for orientation_id in cls._param_value_list(parameter): ret.append(Pose(ap.position, project.orientation(orientation_id).orientation)) return ret
def check_action_params( scene: CachedScene, project: CachedProject, action: common.Action, object_action: ObjectAction ) -> None: _, action_type = action.parse_type() assert action_type == object_action.name if len(object_action.parameters) != len(action.parameters): raise Arcor2Exception("Unexpected number of parameters.") for req_param in object_action.parameters: param = action.parameter(req_param.name) if param.type == common.ActionParameter.TypeEnum.CONSTANT: const = project.constant(param.str_from_value()) param_meta = object_action.parameter(param.name) if param_meta.type != const.type: raise Arcor2Exception("Param type does not match constant type.") elif param.type == common.ActionParameter.TypeEnum.LINK: parsed_link = param.parse_link() if parsed_link.action_id == action.id: raise Arcor2Exception("Can't use own result as a parameter.") outputs = project.action(parsed_link.action_id).flow(parsed_link.flow_name).outputs assert len(outputs) == len(object_action.returns) param_meta = object_action.parameter(param.name) if param_meta.type != object_action.returns[parsed_link.output_index]: raise Arcor2Exception("Param type does not match action output type.") else: if param.type not in known_parameter_types(): raise Arcor2Exception(f"Parameter {param.name} of action {action.name} has unknown type: {param.type}.") try: plugin_from_type_name(param.type).parameter_value( get_types_dict(), scene, project, action.id, param.name ) except ParameterPluginException as e: raise Arcor2Exception(f"Parameter {param.name} of action {action.name} has invalid value. {str(e)}")
def test_blind_branch() -> None: scene = Scene("s1") obj = SceneObject("test_name", Test.__name__) scene.objects.append(obj) project = Project("p1", "s1") ap1 = ActionPoint("ap1", Position()) project.action_points.append(ap1) ac1 = Action("ac1", f"{obj.id}/test", flows=[Flow(outputs=["bool_res"])]) ap1.actions.append(ac1) ac2 = Action("ac2", f"{obj.id}/test", flows=[Flow()]) ap1.actions.append(ac2) ac3 = Action("ac3", f"{obj.id}/test", flows=[Flow()]) ap1.actions.append(ac3) ac4 = Action("ac4", f"{obj.id}/test", flows=[Flow()]) ap1.actions.append(ac4) project.logic.append(LogicItem(LogicItem.START, ac1.id)) project.logic.append(LogicItem(ac1.id, ac2.id, ProjectLogicIf(f"{ac1.id}/default/0", json.dumps(True)))) project.logic.append(LogicItem(ac1.id, ac3.id, ProjectLogicIf(f"{ac1.id}/default/0", json.dumps(False)))) project.logic.append(LogicItem(ac2.id, ac4.id)) project.logic.append(LogicItem(ac4.id, LogicItem.END)) with pytest.raises(SourceException, match=f"Action {ac3.name} has no outputs."): program_src({Test.__name__: Test}, CachedProject(project), CachedScene(scene))
def uses_robot_joints(cls, project: CProject, action_id: str, parameter_id: str, robot_joints_id: str) -> bool: value_id = cls._id_from_value( project.action(action_id).parameter(parameter_id).value) return value_id == robot_joints_id
def test_constant() -> None: scene = Scene("s1") obj = SceneObject("test_name", Test.__name__) scene.objects.append(obj) project = Project("p1", "s1") ap1 = ActionPoint("ap1", Position()) project.action_points.append(ap1) const_value = 1234 const = ProjectParameter("int_const", "integer", json.dumps(const_value)) project.parameters.append(const) ac1 = Action( "ac1", f"{obj.id}/test_par", flows=[Flow()], parameters=[ ActionParameter("param", ActionParameter.TypeEnum.CONSTANT, json.dumps(const.id)) ], ) ap1.actions.append(ac1) project.logic.append(LogicItem(LogicItem.START, ac1.id)) project.logic.append(LogicItem(ac1.id, LogicItem.END)) src = program_src({Test.__name__: Test}, CachedProject(project), CachedScene(scene)) assert f"{const.name} = {const_value}" in src assert f"test_name.{Test.test_par.__name__}({const.name}, an='ac1')" in src
def test_obj_relative_ap_global() -> None: scene = Scene("s1") # object rotated 90° clock-wise so1 = SceneObject( "so1", "WhatEver", Pose(Position(1, 0, 0), Orientation(0, 0, -0.707, 0.707))) scene.objects.append(so1) cached_scene = CachedScene(scene) project = Project("p1", scene.id) ap1 = ActionPoint("ap1", Position(1, 0, 0), parent=so1.id) project.action_points.append(ap1) ap2 = ActionPoint("ap2", Position(1, 0, 0), parent=ap1.id) no1 = NamedOrientation("o1", Orientation()) ap2.orientations.append(no1) project.action_points.append(ap2) cached_project = CachedProject(project) make_relative_ap_global(cached_scene, cached_project, ap2) check_ap(ap2) assert ap2.position == Position(1, -2, 0) assert so1.pose assert no1.orientation == so1.pose.orientation make_global_ap_relative(cached_scene, cached_project, ap2, ap1.id) assert ap2.position == Position(1, 0, 0) assert no1.orientation == Orientation() check_ap(ap2)
def test_global_aps_cls() -> None: proj = Project("test", "scene_id") pos = Position(1, 2, 3) ap1 = ActionPoint("ap1", pos) ap1_o1 = NamedOrientation("o1", Orientation(0.707, 0, 0, 0.707)) ap1.orientations.append(ap1_o1) ap1_j1 = ProjectRobotJoints("j1", "robot", [Joint("whatever", 1234)]) ap1.robot_joints.append(ap1_j1) proj.action_points.append(ap1) os.environ["ARCOR2_PROJECT_PATH"] = "/tmp" import arcor2.resources # noqa my_name = "my_module" my_spec = importlib.util.spec_from_loader(my_name, loader=None) my_module = importlib.util.module_from_spec(my_spec) cproj = CachedProject(proj) src = global_action_points_class(cproj) exec(src, my_module.__dict__) sys.modules["my_module"] = my_module aps = my_module.ActionPoints(SimResources(cproj)) # type: ignore assert aps.ap1.position == pos assert aps.ap1.position is not pos assert aps.ap1.poses.o1 == Pose(ap1.position, ap1_o1.orientation) assert aps.ap1.poses.o1.orientation is not ap1_o1.orientation assert aps.ap1.joints.j1 == ap1_j1 assert aps.ap1.joints.j1 is not ap1_j1
def parameter_value( cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str ) -> RelativePose: try: return RelativePose.from_json(project.action(action_id).parameter(parameter_id).value) except ValidationError as e: raise ParameterPluginException(e)
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
def test_prev_result() -> None: scene = Scene("s1") obj = SceneObject("test_name", Test.__name__) scene.objects.append(obj) project = Project("p1", "s1") ap1 = ActionPoint("ap1", Position()) project.action_points.append(ap1) ac1 = Action("ac1", f"{obj.id}/{Test.get_int.__name__}", flows=[Flow(outputs=["res"])]) ap1.actions.append(ac1) ac2 = Action( "ac2", f"{obj.id}/{Test.test_par.__name__}", flows=[Flow()], parameters=[ ActionParameter("param", ActionParameter.TypeEnum.LINK, json.dumps(f"{ac1.id}/default/0")) ], ) ap1.actions.append(ac2) project.logic.append(LogicItem(LogicItem.START, ac1.id)) project.logic.append(LogicItem(ac1.id, ac2.id)) project.logic.append(LogicItem(ac2.id, LogicItem.END)) src = program_src({Test.__name__: Test}, CachedProject(project), CachedScene(scene)) assert f"res = test_name.{Test.get_int.__name__}(an='{ac1.name}')" in src assert f"test_name.{Test.test_par.__name__}(res, an='{ac2.name}')" in src # test wrong order of logic project.logic.clear() project.logic.append(LogicItem(LogicItem.START, ac2.id)) project.logic.append(LogicItem(ac2.id, ac1.id)) project.logic.append(LogicItem(ac1.id, LogicItem.END)) with pytest.raises(SourceException): program_src({Test.__name__: Test}, CachedProject(project), CachedScene(scene))
def uses_orientation(cls, project: CProject, action_id: str, parameter_id: str, orientation_id: str) -> bool: action = project.action(action_id) param = action.parameter(parameter_id) for ori_id in cls._param_value_list(param): if ori_id == orientation_id: return True return False
async def update_project(project: CachedProject) -> datetime: assert project.id ret = await ps.update_project(project.project) project.modified = ret if not project.created: project.created = project.modified _projects_list.listing[project.id] = IdDesc(project.id, project.name, project.created, project.modified, project.description) _projects[project.id] = deepcopy(project) _projects[project.id].int_modified = None return ret
def parameter_value( cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str ) -> Pose: try: ap, ori = project.bare_ap_and_orientation(cls.orientation_id(project, action_id, parameter_id)) except Arcor2Exception as e: raise ParameterPluginException("Failed to get scene/project data.") from e return Pose(ap.position, ori.orientation)
def test_slots() -> None: """Tests whether classes from cached module uses __slots__.""" s = Scene("") p = Project("", s.id) assert not hasattr(CachedScene(s), "__dict__") assert not hasattr(CachedProject(p), "__dict__") assert not hasattr(UpdateableCachedScene(s), "__dict__") assert not hasattr(UpdateableCachedProject(p), "__dict__")
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
def test_get_value() -> None: p = Pose(Position(1, 2, 3), Orientation(1, 0, 0, 0)) scene = Scene("s1") obj = SceneObject("test_name", TestObject.__name__) scene.objects.append(obj) project = Project("p1", "s1") ap1 = ActionPoint("ap1", Position(1, 0, 0)) project.action_points.append(ap1) ap2 = ActionPoint("ap2", Position(), parent=ap1.id) project.action_points.append(ap2) ori1 = NamedOrientation("ori1", p.orientation) ap2.orientations.append(ori1) invalid_param_name = "invalid_param" ac1 = Action( "ac1", f"{obj.id}/{TestObject.action.__name__}", parameters=[ ActionParameter(param_name, PosePlugin.type_name(), json.dumps(ori1.id)), ActionParameter(invalid_param_name, PosePlugin.type_name(), json.dumps("non_sense")), ], ) ap1.actions.append(ac1) cscene = CachedScene(scene) cproject = CachedProject(project) with pytest.raises(Arcor2Exception): PosePlugin.parameter_value(type_defs, cscene, cproject, ac1.id, "non_sense") with pytest.raises(Arcor2Exception): PosePlugin.parameter_value(type_defs, cscene, cproject, "non_sense", param_name) with pytest.raises(ParameterPluginException): PosePlugin.parameter_value(type_defs, cscene, cproject, ac1.id, invalid_param_name) value = PosePlugin.parameter_value(type_defs, cscene, cproject, ac1.id, param_name) exe_value = PosePlugin.parameter_execution_value(type_defs, cscene, cproject, ac1.id, param_name) assert value == value assert value != exe_value
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
def parameter_value(cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str) -> ProjectRobotJoints: try: ap, action = project.action_point_and_action(action_id) param = action.parameter(parameter_id) joints_id = cls._id_from_value(param.value) robot_id, action_method_name = action.parse_type() joints = project.joints(joints_id) except Arcor2Exception as e: raise ParameterPluginException( "Failed to get necessary data from project.") from e if joints.robot_id != robot_id: raise ParameterPluginException("Joints are for different robot.") return joints
def parameter_ast(cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str) -> Attribute: ap, action = project.action_point_and_action(action_id) joints = project.joints( cls._id_from_value(action.parameter(parameter_id).value)) return Attribute( value=Attribute( value=Attribute( value=Name(id="aps", ctx=Load()), attr=ap.name, ctx=Load() # TODO this should not be hardcoded ), attr="joints", # TODO this should not be hardcoded ctx=Load(), ), attr=joints.name, ctx=Load(), )
async def get_project(project_id: str) -> CachedProject: async with _projects_list_lock: try: project = _projects[project_id] assert project.modified except KeyError: project = CachedProject(await ps.get_project(project_id)) _projects[project_id] = project else: await _update_list(ps.get_projects, _projects_list, _projects) if project_id not in _projects_list.listing: _projects.pop(project_id, None) raise Arcor2Exception("Project removed externally.") # project in cache is outdated if project.modified < _projects_list.listing[project_id].modified: project = CachedProject(await ps.get_project(project_id)) _projects[project_id] = project return project
def test_get_value() -> None: scene = Scene("s1", "s1") obj = SceneObject("test_name", TestObject.__name__) prj = ProjectRobotJoints("name", obj.id, [Joint("name", 0.333)]) scene.objects.append(obj) project = Project("p1", "s1") ap1 = ActionPoint("ap1", Position(1, 0, 0)) ap1.robot_joints.append(prj) project.action_points.append(ap1) invalid_param_name = "invalid_param" act = Action( "ac1", f"{obj.id}/{TestObject.action.__name__}", parameters=[ ActionParameter(param_name, JointsPlugin.type_name(), json.dumps(prj.id)), ActionParameter(invalid_param_name, JointsPlugin.type_name(), json.dumps("non_sense")), ], ) ap1.actions.append(act) cscene = CachedScene(scene) cproject = CachedProject(project) with pytest.raises(Arcor2Exception): JointsPlugin.parameter_value(type_defs, cscene, cproject, act.id, "non_sense") with pytest.raises(Arcor2Exception): JointsPlugin.parameter_value(type_defs, cscene, cproject, "non_sense", param_name) with pytest.raises(ParameterPluginException): JointsPlugin.parameter_value(type_defs, cscene, cproject, act.id, invalid_param_name) value = JointsPlugin.parameter_value(type_defs, cscene, cproject, act.id, param_name) exe_value = JointsPlugin.parameter_execution_value(type_defs, cscene, cproject, act.id, param_name) assert value == value assert value == exe_value
def test_get_value() -> None: img = Image.new("RGB", (320, 240)) scene = Scene("s1", "s1") obj = SceneObject("test_name", TestObject.__name__) scene.objects.append(obj) project = Project("p1", "s1") ap1 = ActionPoint("ap1", Position(1, 0, 0)) project.action_points.append(ap1) invalid_param_name = "invalid_param" ac1 = Action( "ac1", f"{obj.id}/{TestObject.action.__name__}", parameters=[ ActionParameter(param_name, ImagePlugin.type_name(), ImagePlugin.value_to_json(img)), ActionParameter(invalid_param_name, ImagePlugin.type_name(), json.dumps("non_sense")), ], ) ap1.actions.append(ac1) cscene = CachedScene(scene) cproject = CachedProject(project) with pytest.raises(Arcor2Exception): ImagePlugin.parameter_value(type_defs, cscene, cproject, ac1.id, "non_sense") with pytest.raises(Arcor2Exception): ImagePlugin.parameter_value(type_defs, cscene, cproject, "non_sense", param_name) with pytest.raises(ParameterPluginException): ImagePlugin.parameter_value(type_defs, cscene, cproject, ac1.id, invalid_param_name) value = ImagePlugin.parameter_value(type_defs, cscene, cproject, ac1.id, param_name) exe_value = ImagePlugin.parameter_execution_value(type_defs, cscene, cproject, ac1.id, param_name) assert value == value assert value == exe_value
def parameter_execution_value( cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str ) -> List[Pose]: ap, action = project.action_point_and_action(action_id) if not ap.parent: return copy.deepcopy(cls.parameter_value(type_defs, scene, project, action_id, parameter_id)) parameter = action.parameter(parameter_id) ret: List[Pose] = [] for orientation_id in cls._param_value_list(parameter): ret.append(copy.deepcopy(tr.abs_pose_from_ap_orientation(scene, project, orientation_id))) return ret
def test_get_value(self, val: str) -> None: scene = Scene("s1") obj = SceneObject("test_name", TestObject.__name__) scene.objects.append(obj) project = Project("p1", "s1") ap1 = ActionPoint("ap1", Position()) project.action_points.append(ap1) invalid_param_name = "invalid_param" ac1 = Action( "ac1", f"{obj.id}/{TestObject.action.__name__}", parameters=[ ActionParameter(param_name, StringPlugin.type_name(), StringPlugin.value_to_json(val)), ActionParameter(invalid_param_name, StringPlugin.type_name(), json.dumps(666)), ], ) ap1.actions.append(ac1) cscene = CachedScene(scene) cproject = CachedProject(project) with pytest.raises(Arcor2Exception): StringPlugin.parameter_value({}, cscene, cproject, ac1.id, "non_sense") with pytest.raises(Arcor2Exception): StringPlugin.parameter_value({}, cscene, cproject, "non_sense", param_name) with pytest.raises(ParameterPluginException): StringPlugin.parameter_value({}, cscene, cproject, ac1.id, invalid_param_name) value = StringPlugin.parameter_value({}, cscene, cproject, ac1.id, param_name) exe_value = StringPlugin.parameter_execution_value({}, cscene, cproject, ac1.id, param_name) assert value == val assert value == exe_value
def test_make_relative_ap_global_and_relative_again() -> None: scene = Scene("s1") so1 = SceneObject("so1", "WhatEver", Pose(Position(3, 0, 0), Orientation())) scene.objects.append(so1) cached_scene = CachedScene(scene) project = Project("p1", scene.id) ap1 = ActionPoint("ap1", Position(-1, 0, 0), parent=so1.id) project.action_points.append(ap1) ap2 = ActionPoint("ap2", Position(-1, 0, 0), parent=ap1.id) project.action_points.append(ap2) ap3 = ActionPoint( "ap3", Position(-1, 0, 0), parent=ap2.id, orientations=[NamedOrientation("bla", random_orientation())]) project.action_points.append(ap3) cached_project = CachedProject(project) assert ap3.parent ap3_parent = get_parent_pose(cached_scene, cached_project, ap3.parent) assert Pose(ap2.position, Orientation()) == ap3_parent.pose assert ap3_parent.parent_id == ap1.id make_relative_ap_global(cached_scene, cached_project, ap3) check_ap(ap3) assert ap3.parent is None assert ap3.position.x == 0.0 # type: ignore make_global_ap_relative(cached_scene, cached_project, ap3, ap2.id) check_ap(ap3) assert ap3.parent == ap2.id assert ap3.position.x == -1 ap3.parent = "something_unknown" with pytest.raises(Arcor2Exception): make_relative_ap_global(cached_scene, cached_project, ap3)
def parameter_ast( cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str ) -> Attribute: ori_ap, ori = project.bare_ap_and_orientation(cls.orientation_id(project, action_id, parameter_id)) return Attribute( value=Attribute( value=Attribute( value=Name(id="aps", ctx=Load()), attr=ori_ap.name, ctx=Load() # TODO this should not be hardcoded ), attr="poses", # TODO this should not be hardcoded ctx=Load(), ), attr=ori.name, ctx=Load(), )
def abs_pose_from_ap_orientation(scene: CScene, project: CProject, orientation_id: str) -> Pose: """Returns absolute Pose without modifying anything within the project. :param orientation_id: :return: """ ap, ori = project.bare_ap_and_orientation(orientation_id) pose = Pose(ap.position, ori.orientation) parent_id = ap.parent while parent_id: parent = get_parent_pose(scene, project, parent_id) pose = make_pose_abs(parent.pose, pose) parent_id = parent.parent_id return pose
def parameter_value( cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str ) -> Any: action = project.action(action_id) param_value = action.parameter(parameter_id).value try: val = cls._value_from_json(param_value) except ParameterPluginException as e: raise ParameterPluginException( f"Parameter {action.name}/{parameter_id} has invalid value: '{param_value}'." ) from e if not isinstance(val, cls.type()): raise ParameterPluginException(f"Parameter {action.name}/{parameter_id} has invalid type: '{type(val)}'.") return val
def get_parent_pose(scene: CScene, project: CProject, parent_id: str) -> Parent: """Returns pose of the parent and parent of the parent (if any). :param scene: :param project: :param parent_id: :return: """ if parent_id in scene.object_ids: parent_obj = scene.object(parent_id) if not parent_obj.pose: raise Arcor2Exception("Parent object does not have pose!") # TODO find parent object in the graph (SceneObject has "children" property) return Parent(parent_obj.pose, None) elif parent_id in project.action_points_ids: ap = project.bare_action_point(parent_id) return Parent(Pose(ap.position, Orientation()), ap.parent) else: raise Arcor2Exception(f"Unknown parent_id {parent_id}.")
def parameter_value(cls, type_defs: TypesDict, scene: CScene, project: CProject, action_id: str, parameter_id: str) -> Enum: action = project.action(action_id) param = action.parameter(parameter_id) obj_id, action_type = action.parse_type() obj_type_name = scene.object(obj_id).type try: obj_type = type_defs[obj_type_name] except KeyError: raise ParameterPluginException( f"Unknown object type {obj_type_name}.") try: method = getattr(obj_type, action_type) except AttributeError: raise ParameterPluginException( f"Object type {obj_type_name} does not have method {action_type}." ) try: ttype = get_type_hints(method)[param.name] except KeyError: raise ParameterPluginException( f"Method {obj_type}/{method.__name__} does not have parameter {param.name}." ) if not issubclass(ttype, cls.type()): raise ParameterPluginException( f"Type {ttype.__name__} is not subclass of {cls.type().__name__}." ) try: return ttype(json.loads(param.value)) except ValueError: raise ParameterPluginException( f"Parameter {parameter_id} of action {action.name} has invalid value." )