Esempio n. 1
0
async def rename_object_cb(req: srpc.s.RenameObject.Request,
                           ui: WsClient) -> None:

    scene = glob.LOCK.scene_or_exception(ensure_project_closed=True)
    target_obj = scene.object(req.args.id)

    if target_obj.name == req.args.new_name:
        raise Arcor2Exception("Name unchanged")

    for obj_name in scene.object_names():
        if obj_name == req.args.new_name:
            raise Arcor2Exception("Object name already exists.")

    hlp.is_valid_identifier(req.args.new_name)

    user_name = glob.USERS.user_name(ui)
    await ensure_locked(req.args.id, ui)

    if req.dry_run:
        return None

    target_obj.name = req.args.new_name

    scene.update_modified()

    evt = sevts.s.SceneObjectChanged(target_obj)
    evt.change_type = Event.Type.UPDATE
    asyncio.ensure_future(notif.broadcast_event(evt))

    asyncio.create_task(glob.LOCK.write_unlock(req.args.id, user_name, True))
    return None
Esempio n. 2
0
async def add_action_point_orientation_cb(
        req: srpc.p.AddActionPointOrientation.Request, ui: WsClient) -> None:
    """Adds orientation and joints to the action point.

    :param req:
    :return:
    """

    assert glob.SCENE
    assert glob.PROJECT

    ap = glob.PROJECT.bare_action_point(req.args.action_point_id)
    hlp.is_valid_identifier(req.args.name)
    unique_name(req.args.name, glob.PROJECT.ap_orientation_names(ap.id))

    if req.dry_run:
        return None

    orientation = common.NamedOrientation(req.args.name, req.args.orientation)
    glob.PROJECT.upsert_orientation(ap.id, orientation)

    evt = sevts.p.OrientationChanged(orientation)
    evt.change_type = Event.Type.ADD
    evt.parent_id = ap.id
    asyncio.ensure_future(notif.broadcast_event(evt))
    return None
Esempio n. 3
0
def check_flows(parent: Union[CachedProject, common.ProjectFunction],
                action: common.Action, action_meta: ObjectAction) -> None:
    """Raises exception if there is something wrong with flow(s).

    :param parent:
    :param action:
    :param action_meta:
    :return:
    """

    flow = action.flow(
    )  # searches default flow (just this flow is supported so far)

    # it is ok to not specify any output (if the values are not going to be used anywhere)
    # return value(s) won't be stored in variable(s)
    if not flow.outputs:
        return

    # otherwise, all return values have to be stored in variables
    if len(flow.outputs) != len(action_meta.returns):
        raise Arcor2Exception(
            "Number of the flow outputs does not match the number of action outputs."
        )

    for output in flow.outputs:
        hlp.is_valid_identifier(output)

    outputs: Set[str] = set()

    for act in parent.actions:
        for fl in act.flows:
            for output in fl.outputs:
                if output in outputs:
                    raise Arcor2Exception(f"Output '{output}' is not unique.")
Esempio n. 4
0
async def rename_object_cb(req: srpc.s.RenameObject.Request,
                           ui: WsClient) -> None:

    assert glob.SCENE

    target_obj = glob.SCENE.object(req.args.id)

    if target_obj.name == req.args.new_name:
        return

    for obj_name in glob.SCENE.object_names():
        if obj_name == req.args.new_name:
            raise Arcor2Exception("Object name already exists.")

    hlp.is_valid_identifier(req.args.new_name)

    if req.dry_run:
        return None

    target_obj.name = req.args.new_name

    glob.SCENE.update_modified()

    evt = sevts.s.SceneObjectChanged(target_obj)
    evt.change_type = Event.Type.UPDATE
    asyncio.ensure_future(notif.broadcast_event(evt))
    return None
Esempio n. 5
0
async def add_action_point_joints_using_robot_cb(
        req: srpc.p.AddActionPointJointsUsingRobot.Request,
        ui: WsClient) -> None:

    ensure_scene_started()

    assert glob.SCENE
    assert glob.PROJECT

    ap = glob.PROJECT.bare_action_point(req.args.action_point_id)

    hlp.is_valid_identifier(req.args.name)
    unique_name(req.args.name, glob.PROJECT.ap_joint_names(ap.id))

    new_joints = await get_robot_joints(req.args.robot_id)

    if req.dry_run:
        return None

    prj = common.ProjectRobotJoints(req.args.name, req.args.robot_id,
                                    new_joints, True)
    glob.PROJECT.upsert_joints(ap.id, prj)

    evt = sevts.p.JointsChanged(prj)
    evt.change_type = Event.Type.ADD
    evt.parent_id = ap.id
    asyncio.ensure_future(notif.broadcast_event(evt))
    return None
Esempio n. 6
0
async def rename_action_point_cb(req: srpc.p.RenameActionPoint.Request,
                                 ui: WsClient) -> None:

    assert glob.SCENE
    assert glob.PROJECT

    ap = glob.PROJECT.bare_action_point(req.args.action_point_id)

    if req.args.new_name == ap.name:
        return None

    hlp.is_valid_identifier(req.args.new_name)
    unique_name(req.args.new_name, glob.PROJECT.action_points_names)

    if req.dry_run:
        return None

    ap.name = req.args.new_name

    glob.PROJECT.update_modified()

    evt = sevts.p.ActionPointChanged(ap)
    evt.change_type = Event.Type.UPDATE_BASE
    asyncio.ensure_future(notif.broadcast_event(evt))
    return None
Esempio n. 7
0
def check_project_parameter(proj: CachedProject, parameter: ProjectParameter) -> None:

    hlp.is_valid_identifier(parameter.name)

    for pparam in proj.parameters:

        if parameter.id == pparam.id:
            continue

        if parameter.name == pparam.name:
            raise Arcor2Exception(f"Project parameter name {parameter.name} is duplicate.")

    check_parameter(parameter)
Esempio n. 8
0
async def add_action_cb(req: rpc.project.AddActionRequest,
                        ui: WsClient) -> None:

    assert glob.PROJECT
    assert glob.SCENE

    ap = glob.PROJECT.action_point(req.args.action_point_id)

    unique_name(req.args.name, glob.PROJECT.action_user_names())

    if not hlp.is_valid_identifier(req.args.name):
        raise Arcor2Exception("Action name has to be valid Python identifier.")

    new_action = common.Action(common.uid(), req.args.name, req.args.type,
                               req.args.parameters)

    updated_project = copy.deepcopy(glob.PROJECT)
    updated_ap = updated_project.action_point(req.args.action_point_id)
    updated_ap.actions.append(new_action)

    check_action_params(updated_project, new_action,
                        find_object_action(new_action))

    if req.dry_run:
        return None

    ap.actions.append(new_action)

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.ActionChanged(events.EventType.ADD, ap.id,
                                 data=new_action)))
    return None
Esempio n. 9
0
async def rename_object_cb(req: rpc.scene.RenameObjectRequest,
                           ui: WsClient) -> None:

    assert glob.SCENE

    target_obj = glob.SCENE.object(req.args.id)

    for obj_name in glob.SCENE.object_names():
        if obj_name == req.args.new_name:
            raise Arcor2Exception("Object name already exists.")

    if not hlp.is_valid_identifier(req.args.new_name):
        raise Arcor2Exception("Object name invalid (should be snake_case).")

    if req.dry_run:
        return None

    target_obj.name = req.args.new_name

    glob.SCENE.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.SceneObjectChanged(events.EventType.UPDATE,
                                      data=target_obj)))
    return None
Esempio n. 10
0
async def rename_action_point_cb(req: rpc.project.RenameActionPointRequest,
                                 ui: WsClient) -> None:

    assert glob.SCENE and glob.PROJECT

    ap = glob.PROJECT.action_point(req.args.action_point_id)

    if req.args.new_name == ap.name:
        return None

    if not hlp.is_valid_identifier(req.args.new_name):
        raise Arcor2Exception("Name has to be valid Python identifier.")

    unique_name(req.args.new_name, glob.PROJECT.action_points_names)

    if req.dry_run:
        return None

    ap.name = req.args.new_name

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.ActionPointChanged(events.EventType.UPDATE_BASE,
                                      data=ap.bare())))
    return None
Esempio n. 11
0
async def rename_action_point_joints_cb(
        req: srpc.p.RenameActionPointJoints.Request, ui: WsClient) -> None:

    assert glob.PROJECT

    ap, joints = glob.PROJECT.ap_and_joints(req.args.joints_id)
    hlp.is_valid_identifier(req.args.new_name)
    unique_name(req.args.new_name, glob.PROJECT.ap_joint_names(ap.id))

    if req.dry_run:
        return None

    joints.name = req.args.new_name
    glob.PROJECT.update_modified()

    evt = sevts.p.JointsChanged(joints)
    evt.change_type = Event.Type.UPDATE_BASE
    asyncio.ensure_future(notif.broadcast_event(evt))

    return None
Esempio n. 12
0
async def add_action_point_cb(req: srpc.p.AddActionPoint.Request,
                              ui: WsClient) -> None:

    assert glob.SCENE
    assert glob.PROJECT

    hlp.is_valid_identifier(req.args.name)
    unique_name(req.args.name, glob.PROJECT.action_points_names)
    check_ap_parent(req.args.parent)

    if req.dry_run:
        return None

    ap = glob.PROJECT.upsert_action_point(common.ActionPoint.uid(),
                                          req.args.name, req.args.position,
                                          req.args.parent)

    evt = sevts.p.ActionPointChanged(ap)
    evt.change_type = Event.Type.ADD
    asyncio.ensure_future(notif.broadcast_event(evt))
    return None
Esempio n. 13
0
async def rename_action_point_orientation_cb(
        req: srpc.p.RenameActionPointOrientation.Request,
        ui: WsClient) -> None:

    assert glob.PROJECT

    ap, ori = glob.PROJECT.bare_ap_and_orientation(req.args.orientation_id)
    hlp.is_valid_identifier(req.args.new_name)
    unique_name(req.args.new_name, glob.PROJECT.ap_orientation_names(ap.id))

    if req.dry_run:
        return None

    ori.name = req.args.new_name
    glob.PROJECT.update_modified()

    evt = sevts.p.OrientationChanged(ori)
    evt.change_type = Event.Type.UPDATE_BASE
    asyncio.ensure_future(notif.broadcast_event(evt))

    return None
Esempio n. 14
0
def check_constant(constant: common.ProjectConstant) -> None:

    assert glob.PROJECT

    hlp.is_valid_identifier(constant.name)

    for const in glob.PROJECT.constants:

        if constant.id == const.id:
            continue

        if constant.name == const.name:
            raise Arcor2Exception("Name has to be unique.")

    # TODO check using (constant?) plugin
    import json

    val = json.loads(constant.value)

    if not isinstance(val, (int, float, str, bool)):
        raise Arcor2Exception("Only basic types are supported so far.")
Esempio n. 15
0
def object_instance_from_res(object_name: str, object_id: str,
                             cls_name: str) -> AnnAssign:

    try:
        is_valid_identifier(object_name)
    except Arcor2Exception as e:
        raise Arcor2Exception(f"Object name {object_name} invalid. {str(e)}")

    try:
        is_valid_type(cls_name)
    except Arcor2Exception as e:
        raise Arcor2Exception(f"Class name {cls_name} invalid. {str(e)}")

    return AnnAssign(
        target=Name(id=object_name, ctx=Store()),
        annotation=Name(id=cls_name, ctx=Load()),
        value=Subscript(value=get_name_attr("res", "objects"),
                        slice=Index(value=Str(s=object_id, kind="")),
                        ctx=Load()),
        simple=1,
    )
Esempio n. 16
0
def check_object(scene: CachedScene,
                 obj: SceneObject,
                 new_one: bool = False) -> None:
    """Checks if object can be added into the scene."""

    assert not obj.children

    if obj.type not in glob.OBJECT_TYPES:
        raise Arcor2Exception("Unknown object type.")

    obj_type = glob.OBJECT_TYPES[obj.type]

    if obj_type.meta.disabled:
        raise Arcor2Exception("Object type disabled.")

    check_object_parameters(obj_type, obj.parameters)

    # TODO check whether object needs parent and if so, if the parent is in scene and parent_id is set
    if obj_type.meta.needs_parent_type:
        pass

    if obj_type.meta.has_pose and obj.pose is None:
        raise Arcor2Exception("Object requires pose.")

    if not obj_type.meta.has_pose and obj.pose is not None:
        raise Arcor2Exception("Object do not have pose.")

    if obj_type.meta.abstract:
        raise Arcor2Exception("Cannot instantiate abstract type.")

    if new_one:

        if obj.id in scene.object_ids:
            raise Arcor2Exception(
                "Object/service with that id already exists.")

        if obj.name in scene.object_names():
            raise Arcor2Exception("Name is already used.")

    hlp.is_valid_identifier(obj.name)
Esempio n. 17
0
def check_object(obj_types: ObjectTypeDict, scene: CachedScene, obj: SceneObject, new_one: bool = False) -> None:
    """Checks if object can be added into the scene."""

    assert not obj.children

    if obj.type not in obj_types:
        raise Arcor2Exception(f"Unknown ObjectType {obj.type}.")

    obj_type = obj_types[obj.type]

    if obj_type.meta.disabled:
        raise Arcor2Exception(f"ObjectType {obj.type} is disabled. {obj_type.meta.problem}")

    check_object_parameters(obj_type, obj.parameters)

    # TODO check whether object needs parent and if so, if the parent is in scene and parent_id is set
    if obj_type.meta.needs_parent_type:
        pass

    if obj_type.meta.has_pose and obj.pose is None:
        raise Arcor2Exception(f"Object {obj.name} requires pose.")

    if not obj_type.meta.has_pose and obj.pose is not None:
        raise Arcor2Exception(f"Object {obj.name} should not have pose.")

    if obj_type.meta.abstract:
        raise Arcor2Exception(f"ObjectType {obj.type} is abstract.")

    if new_one:

        if obj.id in scene.object_ids:
            raise Arcor2Exception(f"Object {obj.name} has duplicate id.")

        if obj.name in scene.object_names():
            raise Arcor2Exception(f"Object name {obj.name} is duplicate.")

    hlp.is_valid_identifier(obj.name)
Esempio n. 18
0
async def add_action_point_orientation_using_robot_cb(
        req: srpc.p.AddActionPointOrientationUsingRobot.Request,
        ui: WsClient) -> None:
    """Adds orientation and joints to the action point.

    :param req:
    :return:
    """

    ensure_scene_started()

    assert glob.SCENE
    assert glob.PROJECT

    ap = glob.PROJECT.bare_action_point(req.args.action_point_id)
    hlp.is_valid_identifier(req.args.name)
    unique_name(req.args.name, glob.PROJECT.ap_orientation_names(ap.id))

    if req.dry_run:
        return None

    new_pose = await get_end_effector_pose(req.args.robot.robot_id,
                                           req.args.robot.end_effector)

    if ap.parent:
        new_pose = tr.make_pose_rel_to_parent(glob.SCENE, glob.PROJECT,
                                              new_pose, ap.parent)

    orientation = common.NamedOrientation(req.args.name, new_pose.orientation)
    glob.PROJECT.upsert_orientation(ap.id, orientation)

    evt = sevts.p.OrientationChanged(orientation)
    evt.change_type = Event.Type.ADD
    evt.parent_id = ap.id
    asyncio.ensure_future(notif.broadcast_event(evt))
    return None
Esempio n. 19
0
async def add_action_point_cb(req: rpc.project.AddActionPointRequest,
                              ui: WsClient) -> None:

    assert glob.SCENE
    assert glob.PROJECT

    unique_name(req.args.name, glob.PROJECT.action_points_names)
    check_ap_parent(req.args.parent)

    if not hlp.is_valid_identifier(req.args.name):
        raise Arcor2Exception("Name has to be valid Python identifier.")

    if req.dry_run:
        return None

    ap = common.ProjectActionPoint(common.uid(), req.args.name,
                                   req.args.position, req.args.parent)
    glob.PROJECT.action_points.append(ap)

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.ActionPointChanged(events.EventType.ADD, data=ap)))
    return None
Esempio n. 20
0
async def add_object_to_scene(obj: SceneObject,
                              add_to_scene=True,
                              srv_obj_ok=False,
                              dry_run: bool = False):
    """

    :param obj:
    :param add_to_scene: Set to false to only create object instance and add its collision model (if any).
    :return:
    """

    assert glob.SCENE

    if obj.type not in glob.OBJECT_TYPES:
        raise Arcor2Exception("Unknown object type.")

    obj_meta = glob.OBJECT_TYPES[obj.type]

    if obj_meta.disabled:
        raise Arcor2Exception("Object type disabled.")

    if srv_obj_ok:  # just for internal usage

        if not obj_meta.needs_services <= osa.valid_service_types().keys():
            raise Arcor2Exception(
                "Some of required services is not available.")

        if not obj_meta.needs_services <= glob.SERVICES_INSTANCES.keys():
            raise Arcor2Exception(
                "Some of required services is not in the scene.")

    elif obj_meta.needs_services:
        raise Arcor2Exception("Service(s)-based object.")

    if obj_meta.abstract:
        raise Arcor2Exception("Cannot instantiate abstract type.")

    if obj.id in glob.SCENE_OBJECT_INSTANCES or obj.id in glob.SERVICES_INSTANCES:
        raise Arcor2Exception("Object/service with that id already exists.")

    if obj.name in instances_names():
        raise Arcor2Exception("Name is already used.")

    if not hlp.is_valid_identifier(obj.name):
        raise Arcor2Exception("Object name invalid (should be snake_case).")

    if dry_run:
        return None

    await glob.logger.debug(f"Creating instance {obj.id} ({obj.type}).")

    if obj.type in otu.built_in_types_names():
        cls = otu.get_built_in_type(obj.type)
    else:
        obj_type = await storage.get_object_type(obj.type)
        cls = hlp.type_def_from_source(obj_type.source, obj_type.id, Generic)

    coll_model: Optional[Models] = None
    if obj_meta.object_model:
        coll_model = obj_meta.object_model.model()

    if not obj_meta.needs_services:
        obj_inst = cls(obj.id, obj.name, obj.pose, coll_model)
    else:

        srv_args: List[Service] = []

        for name, ttype in get_type_hints(cls.__init__).items():

            # service arguments should be listed first
            if not issubclass(ttype, Service):
                break

            try:
                srv_args.append(glob.SERVICES_INSTANCES[ttype.__name__])
            except KeyError:
                return False, f"Object type {obj.type} has invalid typ annotation in the constructor, " \
                              f"service {ttype.__name__} not available."

        try:
            obj_inst = cls(*srv_args, obj.id, obj.name, obj.pose,
                           coll_model)  # type: ignore
        except TypeError as e:
            raise Arcor2Exception("System error.") from e

    glob.SCENE_OBJECT_INSTANCES[obj.id] = obj_inst

    if add_to_scene:
        glob.SCENE.objects.append(obj)

    await collision(obj_inst, add=True)

    return None
Esempio n. 21
0
async def auto_add_object_to_scene(obj_type_name: str,
                                   dry_run: bool = False) -> None:

    assert glob.SCENE

    if obj_type_name not in glob.OBJECT_TYPES:
        raise Arcor2Exception("Unknown object type.")

    if obj_type_name in otu.built_in_types_names():
        raise Arcor2Exception("Does not work for built in types.")

    obj_meta = glob.OBJECT_TYPES[obj_type_name]

    if not obj_meta.needs_services:
        raise Arcor2Exception("Ordinary object.")

    if obj_meta.abstract:
        raise Arcor2Exception("Cannot instantiate abstract type.")

    if not obj_meta.needs_services <= osa.valid_service_types().keys():
        raise Arcor2Exception("Some of required services is not available.")

    if not obj_meta.needs_services <= glob.SERVICES_INSTANCES.keys():
        raise Arcor2Exception("Some of required services is not in the scene.")

    if dry_run:
        return None

    obj_type = await storage.get_object_type(obj_type_name)
    cls = hlp.type_def_from_source(obj_type.source, obj_type.id, Generic)

    args: List[Service] = [
        glob.SERVICES_INSTANCES[srv_name]
        for srv_name in obj_meta.needs_services
    ]

    assert hasattr(cls, otu.SERVICES_METHOD_NAME)
    for obj_inst in cls.from_services(*args):  # type: ignore

        assert isinstance(obj_inst, Generic)

        if not hlp.is_valid_identifier(obj_inst.name):
            # TODO add message to response
            await glob.logger.warning(f"Object id {obj_inst.id} invalid.")
            continue

        if obj_inst.id in glob.SCENE_OBJECT_INSTANCES:
            await glob.logger.warning(
                f"Object id {obj_inst.id} already in scene.")
            continue

        if obj_inst.name in instances_names():
            await glob.logger.warning(f"Duplicate object name {obj_inst.name}."
                                      )
            continue

        glob.SCENE_OBJECT_INSTANCES[obj_inst.id] = obj_inst

        obj = obj_inst.scene_object()
        glob.SCENE.objects.append(obj)

        asyncio.ensure_future(
            notif.broadcast_event(
                events.SceneObjectChanged(events.EventType.ADD, data=obj)))

        if obj_meta.object_model:
            obj_inst.collision_model = obj_meta.object_model.model()
            await collision(obj_inst, add=True)

    return None
Esempio n. 22
0
def test_is_valid_identifier(val, expectation) -> None:
    with expectation:
        hlp.is_valid_identifier(val)
Esempio n. 23
0
def test_is_valid_identifier(val):
    assert hlp.is_valid_identifier(val)