Example #1
0
async def calibrate_robot_cb(req: srpc.r.CalibrateRobot.Request, ui: WsClient) -> None:

    glob.LOCK.scene_or_exception()
    user_name = glob.USERS.user_name(ui)

    ensure_scene_started()

    if not req.args.camera_id:
        for obj in glob.SCENE_OBJECT_INSTANCES.values():
            if isinstance(obj, Camera):
                req.args.camera_id = obj.id
                break
        else:
            raise Arcor2Exception("No camera found.")

    async with ctx_write_lock(req.args.camera_id, user_name, auto_unlock=False):

        robot_inst = get_robot_instance(req.args.robot_id)

        if not robot_inst.urdf_package_name:
            raise Arcor2Exception("Robot with model required!")

        camera_inst = get_instance(req.args.camera_id, Camera)

        if camera_inst.color_camera_params is None:
            raise Arcor2Exception("Calibrated camera required!")

        await ensure_write_locked(req.args.robot_id, user_name)

        asyncio.ensure_future(calibrate_robot(robot_inst, camera_inst, req.args.move_to_calibration_pose, user_name))

        return None
Example #2
0
async def object_aiming_done_cb(req: srpc.o.ObjectAimingDone.Request,
                                ui: WsClient) -> None:
    """Calls scene service to get a new pose for the object.

    In case of success, robot and object are kept locked, unlocking is responsibility of ui.
    On failure, UI may do another attempt or call ObjectAimingCancel.

    :param req:
    :param ui:
    :return:
    """

    scene = glob.LOCK.scene_or_exception()
    fo, user_name = await object_aiming_check(ui)

    obj_type = glob.OBJECT_TYPES[scene.object(fo.obj_id).type].meta
    assert obj_type.object_model
    assert obj_type.object_model.mesh

    focus_points = obj_type.object_model.mesh.focus_points

    assert focus_points

    if len(fo.poses) < len(focus_points):
        raise Arcor2Exception(
            f"Only {len(fo.poses)} points were done out of {len(focus_points)}."
        )

    obj = scene.object(fo.obj_id)
    assert obj.pose

    obj_inst = get_instance(fo.obj_id, CollisionObject)

    if req.dry_run:
        return

    fp: list[Position] = []
    rp: list[Position] = []

    for idx, pose in fo.poses.items():

        fp.append(focus_points[idx].position)
        rp.append(pose.position)

    mfa = MeshFocusAction(fp, rp)

    logger.debug(f"Attempt to aim object {obj_inst.name}, data: {mfa}")

    try:
        new_pose = await scene_srv.focus(mfa)  # TODO how long does it take?
    except scene_srv.SceneServiceException as e:
        logger.error(f"Aiming failed with: {e}, mfa: {mfa}.")
        raise Arcor2Exception(f"Aiming failed. {str(e)}") from e

    logger.info(f"Done aiming for {obj_inst.name}.")

    _objects_being_aimed.pop(user_name, None)
    asyncio.create_task(
        update_scene_object_pose(scene, obj, new_pose, obj_inst))
    return None
Example #3
0
def get_camera_instance(obj_id: str) -> Camera:

    obj = get_instance(obj_id)

    if not isinstance(obj, Camera):
        raise Arcor2Exception("Not a camera.")

    return obj
Example #4
0
async def cancel_action_cb(req: srpc.p.CancelAction.Request,
                           ui: WsClient) -> None:

    assert glob.SCENE
    assert glob.PROJECT

    if not glob.RUNNING_ACTION:
        raise Arcor2Exception("No action is running.")

    action = glob.PROJECT.action(glob.RUNNING_ACTION)
    obj_id, action_name = action.parse_type()
    obj = get_instance(obj_id)

    if not find_object_action(glob.SCENE, action).meta.cancellable:
        raise Arcor2Exception("Action is not cancellable.")

    try:
        action_method = getattr(obj, action_name)
        cancel_method = getattr(obj,
                                obj.CANCEL_MAPPING[action_method.__name__])
    except AttributeError as e:
        raise Arcor2Exception("Internal error.") from e

    cancel_params: Dict[str, Any] = {}

    # TODO fix or remove this?
    """
    cancel_sig = inspect.signature(cancel_method)

    assert glob.RUNNING_ACTION_PARAMS is not None

    for param_name in cancel_sig.parameters.keys():
        try:
            cancel_params[param_name] = glob.RUNNING_ACTION_PARAMS[param_name]
        except KeyError as e:
            raise Arcor2Exception("Cancel method parameters should be subset of action parameters.") from e
    """

    await hlp.run_in_executor(cancel_method, *cancel_params.values())

    asyncio.ensure_future(notif.broadcast_event(sevts.a.ActionCancelled()))
    glob.RUNNING_ACTION = None
    glob.RUNNING_ACTION_PARAMS = None
Example #5
0
async def action_param_values_cb(
        req: srpc.o.ActionParamValues.Request,
        ui: WsClient) -> srpc.o.ActionParamValues.Response:

    glob.LOCK.scene_or_exception()

    async with ctx_read_lock(req.args.id, glob.USERS.user_name(ui)):
        ensure_scene_started()

        inst = get_instance(req.args.id)

        parent_params = {}

        for pp in req.args.parent_params:
            parent_params[pp.id] = pp.value

        try:
            method_name, required_parent_params = inst.DYNAMIC_PARAMS[
                req.args.param_id]
        except KeyError:
            raise Arcor2Exception(
                "Unknown parameter or values not constrained.")

        if parent_params.keys() != required_parent_params:
            raise Arcor2Exception("Not all required parent params were given.")

        # TODO validate method parameters vs parent_params (check types)?

        resp = srpc.o.ActionParamValues.Response()

        try:
            method = getattr(inst, method_name)
        except AttributeError:
            glob.logger.error(
                f"Unable to get values for parameter {req.args.param_id}, "
                f"object/service {inst.id} has no method named {method_name}.")
            raise Arcor2Exception("System error.")

        # TODO update hlp.run_in_executor to support kwargs
        resp.data = await asyncio.get_event_loop().run_in_executor(
            None, functools.partial(method, **parent_params))
        return resp
Example #6
0
async def execute_action_cb(req: srpc.p.ExecuteAction.Request,
                            ui: WsClient) -> None:

    assert glob.SCENE
    assert glob.PROJECT

    ensure_scene_started()

    if glob.RUNNING_ACTION:
        raise Arcor2Exception(
            f"Action {glob.RUNNING_ACTION} is being executed. "
            f"Only one action can be executed at a time.")

    action = glob.PROJECT.action(req.args.action_id)

    obj_id, action_name = action.parse_type()

    params: List[Any] = []

    for param in action.parameters:

        if param.type == common.ActionParameter.TypeEnum.LINK:

            parsed_link = param.parse_link()
            try:
                results = project.PREV_RESULTS[parsed_link.action_id]
            except KeyError:
                prev_action = glob.PROJECT.action(parsed_link.action_id)
                raise Arcor2Exception(
                    f"Action '{prev_action.name}' has to be executed first.")

            # an action result could be a tuple or a single value
            if isinstance(results, tuple):
                params.append(results[parsed_link.output_index])
            else:
                assert parsed_link.output_index == 0
                params.append(results)

        elif param.type == common.ActionParameter.TypeEnum.CONSTANT:
            const = glob.PROJECT.constant(param.str_from_value())
            # TODO use plugin to get the value
            import json

            params.append(json.loads(const.value))
        else:

            try:
                params.append(
                    plugin_from_type_name(
                        param.type).parameter_execution_value(
                            get_types_dict(), glob.SCENE, glob.PROJECT,
                            action.id, param.name))
            except ParameterPluginException as e:
                glob.logger.error(e)
                raise Arcor2Exception(
                    f"Failed to get value for parameter {param.name}.")

    obj = get_instance(obj_id)

    if isinstance(obj, Robot):
        if obj.move_in_progress:
            raise Arcor2Exception(
                "Can't execute actions while the robot moves.")

    if not hasattr(obj, action_name):
        raise Arcor2Exception(
            "Internal error: object does not have the requested method.")

    if req.dry_run:
        return

    glob.RUNNING_ACTION = action.id
    glob.RUNNING_ACTION_PARAMS = params

    glob.logger.debug(
        f"Running action {action.name} ({type(obj)}/{action_name}), params: {params}."
    )

    # schedule execution and return success
    asyncio.ensure_future(
        project.execute_action(getattr(obj, action_name), params))
    return None