예제 #1
0
async def update_action_point_using_robot_cb(
        req: rpc.project.UpdateActionPointUsingRobotRequest,
        ui: WsClient) -> None:

    assert glob.SCENE and glob.PROJECT

    ap = glob.PROJECT.action_point(req.args.action_point_id)
    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)

    ap.invalidate_joints()
    for joints in ap.robot_joints:
        asyncio.ensure_future(
            notif.broadcast_event(
                events.JointsChanged(events.EventType.UPDATE,
                                     ap.id,
                                     data=joints)))

    ap.position = new_pose.position

    glob.PROJECT.update_modified()

    asyncio.ensure_future(
        notif.broadcast_event(
            events.ActionPointChanged(events.EventType.UPDATE_BASE,
                                      data=ap.bare())))
    return None
예제 #2
0
async def remove_from_scene_cb(req: rpc.scene.RemoveFromSceneRequest,
                               ui: WsClient) -> None:

    assert glob.SCENE

    if not req.args.force and {
            proj.name
            async for proj in projects_using_object(glob.SCENE.id, req.args.id)
    }:
        raise Arcor2Exception(
            "Can't remove object/service that is used in project(s).")

    if req.dry_run:
        return None

    if req.args.id in glob.SCENE_OBJECT_INSTANCES:

        obj = glob.SCENE.object(req.args.id)
        glob.SCENE.objects = [
            obj for obj in glob.SCENE.objects if obj.id != req.args.id
        ]
        obj_inst = glob.SCENE_OBJECT_INSTANCES[req.args.id]
        await collision(obj_inst, remove=True)
        del glob.SCENE_OBJECT_INSTANCES[req.args.id]
        if req.args.id in OBJECTS_WITH_UPDATED_POSE:
            OBJECTS_WITH_UPDATED_POSE.remove(req.args.id)
        asyncio.ensure_future(
            notif.broadcast_event(
                events.SceneObjectChanged(events.EventType.REMOVE, data=obj)))

    elif req.args.id in glob.SERVICES_INSTANCES:

        # first check if some object is not using it
        for obj in glob.SCENE.objects:
            if req.args.id in glob.OBJECT_TYPES[obj.type].needs_services:
                raise Arcor2Exception(
                    f"Object {obj.id} ({obj.type}) "
                    f"relies on the service to be removed: {req.args.id}.")

        srv = glob.SCENE.service(req.args.id)
        glob.SCENE.services = [
            srv for srv in glob.SCENE.services if srv.type != req.args.id
        ]
        del glob.SERVICES_INSTANCES[req.args.id]
        asyncio.ensure_future(
            notif.broadcast_event(
                events.SceneServiceChanged(events.EventType.REMOVE, data=srv)))

    else:
        raise Arcor2Exception("Unknown id.")

    glob.SCENE.update_modified()
    asyncio.ensure_future(remove_object_references_from_projects(req.args.id))
    return None
예제 #3
0
async def remove_action_point_joints_cb(
        req: rpc.project.RemoveActionPointJointsRequest, ui: WsClient) -> None:
    """
    Removes joints from action point.
    :param req:
    :return:
    """

    assert glob.SCENE and glob.PROJECT

    ap, joints = glob.PROJECT.ap_and_joints(req.args.joints_id)

    for act in glob.PROJECT.actions():
        for param in act.parameters:
            if PARAM_PLUGINS[param.type].uses_robot_joints(
                    glob.PROJECT, act.id, param.id, req.args.joints_id):
                raise Arcor2Exception(
                    f"Joints used in action {act.name} (parameter {param.id})."
                )

    joints_to_be_removed = ap.joints(req.args.joints_id)
    ap.robot_joints = [
        joints for joints in ap.robot_joints if joints.id != req.args.joints_id
    ]

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.JointsChanged(events.EventType.REMOVE,
                                 data=joints_to_be_removed)))
    return None
예제 #4
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
예제 #5
0
async def update_service_configuration_cb(
        req: rpc.scene.UpdateServiceConfigurationRequest,
        ui: WsClient) -> None:

    assert glob.SCENE

    srv = glob.SCENE.service(req.args.type)

    # first check if some object is not using it
    for obj in glob.SCENE.objects:
        if req.args.type in glob.OBJECT_TYPES[obj.type].needs_services:
            raise Arcor2Exception(
                f"Object {obj.name} ({obj.type}) relies "
                f"on the service to be removed: {req.args.type}.")

    if req.dry_run:
        return None

    # TODO destroy current instance
    glob.SERVICES_INSTANCES[req.args.type] = await hlp.run_in_executor(
        glob.TYPE_DEF_DICT[req.args.type], req.args.new_configuration)
    srv.configuration_id = req.args.new_configuration

    glob.SCENE.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.SceneServiceChanged(events.EventType.UPDATE, data=srv)))

    return None
예제 #6
0
async def new_scene_cb(req: rpc.scene.NewSceneRequest, ui: WsClient) -> None:
    """
    Creates and opens a new scene on the server. Fails if any scene is open or if scene id/name already exists.
    :param req:
    :return:
    """

    if glob.PACKAGE_STATE.state in (common.PackageStateEnum.PAUSED,
                                    common.PackageStateEnum.RUNNING):
        raise Arcor2Exception("Can't create scene while package runs.")

    assert glob.SCENE is None

    for scene_id in (await storage.get_scenes()).items:
        if req.args.name == scene_id.name:
            raise Arcor2Exception("Name already used.")

    if req.dry_run:
        return None

    glob.SCENE = common.Scene(common.uid(), req.args.name, desc=req.args.desc)
    asyncio.ensure_future(
        notif.broadcast_event(
            events.OpenScene(data=events.OpenSceneData(glob.SCENE))))
    return None
예제 #7
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
예제 #8
0
async def update_action_cb(req: rpc.project.UpdateActionRequest,
                           ui: WsClient) -> None:

    assert glob.PROJECT
    assert glob.SCENE

    updated_project = copy.deepcopy(glob.PROJECT)

    updated_action = updated_project.action(req.args.action_id)
    updated_action.parameters = req.args.parameters

    check_action_params(updated_project, updated_action,
                        find_object_action(updated_action))

    if req.dry_run:
        return None

    orig_action = glob.PROJECT.action(req.args.action_id)
    orig_action.parameters = updated_action.parameters

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.ActionChanged(events.EventType.UPDATE,
                                 data=updated_action)))
    return None
예제 #9
0
async def remove_action_point_orientation_cb(req: rpc.project.RemoveActionPointOrientationRequest, ui: WsClient) -> \
        None:
    """
    Removes orientation.
    :param req:
    :return:
    """

    assert glob.SCENE and glob.PROJECT

    ap, orientation = glob.PROJECT.ap_and_orientation(req.args.action_point_id)

    for act in glob.PROJECT.actions():
        for param in act.parameters:
            if PARAM_PLUGINS[param.type].uses_orientation(
                    glob.PROJECT, act.id, param.id, req.args.orientation_id):
                raise Arcor2Exception(
                    f"Orientation used in action {act.name} (parameter {param.id})."
                )

    if req.dry_run:
        return None

    ap.orientations = [
        ori for ori in ap.orientations if ori.id != req.args.orientation_id
    ]

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.OrientationChanged(events.EventType.REMOVE,
                                      data=orientation)))
    return None
예제 #10
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
예제 #11
0
async def update_action_point_orientation_using_robot_cb(
        req: rpc.project.UpdateActionPointOrientationUsingRobotRequest,
        ui: WsClient) -> None:
    """
    Updates orientation and joint of the action point.
    :param req:
    :return:
    """

    assert glob.SCENE and glob.PROJECT

    ap = glob.PROJECT.action_point(req.args.action_point_id)
    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)

    ori = glob.PROJECT.orientation(req.args.orientation_id)
    ori.orientation = new_pose.orientation

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.OrientationChanged(events.EventType.UPDATE, data=ori)))
    return None
예제 #12
0
async def add_action_point_orientation_using_robot_cb(
        req: rpc.project.AddActionPointOrientationUsingRobotRequest,
        ui: WsClient) -> None:
    """
    Adds orientation and joints to the action point.
    :param req:
    :return:
    """

    assert glob.SCENE and glob.PROJECT

    ap = glob.PROJECT.action_point(req.args.action_point_id)
    unique_name(req.args.name, ap.orientation_names())

    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(common.uid(), req.args.name,
                                          new_pose.orientation)
    ap.orientations.append(orientation)

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.OrientationChanged(events.EventType.ADD,
                                      ap.id,
                                      data=orientation)))
    return None
예제 #13
0
async def add_action_point_orientation_cb(
        req: rpc.project.AddActionPointOrientationRequest,
        ui: WsClient) -> None:
    """
    Adds orientation and joints to the action point.
    :param req:
    :return:
    """

    assert glob.SCENE and glob.PROJECT

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

    unique_name(req.args.name, ap.orientation_names())

    if req.dry_run:
        return None

    orientation = common.NamedOrientation(common.uid(), req.args.name,
                                          req.args.orientation)
    ap.orientations.append(orientation)

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.OrientationChanged(events.EventType.ADD,
                                      ap.id,
                                      data=orientation)))
    return None
예제 #14
0
async def update_action_logic_cb(req: rpc.project.UpdateActionLogicRequest,
                                 ui: WsClient) -> None:

    assert glob.PROJECT
    assert glob.SCENE

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

    allowed_values = glob.PROJECT.action_ids() | common.ActionIOEnum.set() | {
        ""
    }

    for inp in req.args.inputs:
        if inp.default not in allowed_values:
            raise Arcor2Exception("Unknown input value.")

    for out in req.args.outputs:
        if out.default not in allowed_values:
            raise Arcor2Exception("Unknown output value.")

    action.inputs = req.args.inputs
    action.outputs = req.args.outputs

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.ActionChanged(events.EventType.UPDATE, data=action)))
    return None
예제 #15
0
async def focus_object_done_cb(req: rpc.objects.FocusObjectDoneRequest,
                               ui: WsClient) -> None:

    obj_id = req.args.id

    if obj_id not in FOCUS_OBJECT:
        raise Arcor2Exception(
            "focusObjectStart/focusObject has to be called first.")

    obj_type = glob.OBJECT_TYPES[osa.get_obj_type_name(obj_id)]

    assert obj_type.object_model and obj_type.object_model.mesh

    focus_points = obj_type.object_model.mesh.focus_points

    assert focus_points

    if len(FOCUS_OBJECT[obj_id]) < len(focus_points):
        raise Arcor2Exception("Not all points were done.")

    robot_id, end_effector = FOCUS_OBJECT_ROBOT[obj_id].as_tuple()
    robot_inst = await osa.get_robot_instance(robot_id)
    assert hasattr(robot_inst, "focus")  # mypy does not deal with hasattr

    assert glob.SCENE

    obj = glob.SCENE.object(obj_id)

    fp: List[Position] = []
    rp: List[Position] = []

    for idx, pose in FOCUS_OBJECT[obj_id].items():

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

    mfa = MeshFocusAction(fp, rp)

    await glob.logger.debug(
        f'Attempt to focus for object {obj_id}, data: {mfa}')

    try:
        obj.pose = await hlp.run_in_executor(robot_inst.focus,
                                             mfa)  # type: ignore
    except Arcor2Exception as e:
        await glob.logger.error(f"Focus failed with: {e}, mfa: {mfa}.")
        raise Arcor2Exception("Focusing failed.") from e

    await glob.logger.info(f"Done focusing for {obj_id}.")

    clean_up_after_focus(obj_id)

    asyncio.ensure_future(
        notif.broadcast_event(
            events.SceneObjectChanged(events.EventType.UPDATE, data=obj)))
    asyncio.ensure_future(scene_object_pose_updated(glob.SCENE.id, obj.id))
    return None
예제 #16
0
async def save_project_cb(req: rpc.project.SaveProjectRequest,
                          ui: WsClient) -> None:

    assert glob.SCENE and glob.PROJECT
    await storage.update_project(glob.PROJECT)
    glob.PROJECT.modified = (await
                             storage.get_project(glob.PROJECT.id)).modified
    asyncio.ensure_future(notif.broadcast_event(events.ProjectSaved()))
    return None
예제 #17
0
async def delete_project_cb(req: rpc.project.DeleteProjectRequest,
                            ui: WsClient) -> None:

    project = await storage.get_project(req.args.id)
    await storage.delete_project(req.args.id)
    asyncio.ensure_future(
        notif.broadcast_event(
            events.ProjectChanged(events.EventType.REMOVE,
                                  data=project.bare())))
    return None
예제 #18
0
async def save_scene_cb(req: rpc.scene.SaveSceneRequest, ui: WsClient) -> None:

    assert glob.SCENE
    await storage.update_scene(glob.SCENE)
    glob.SCENE.modified = (await storage.get_scene(glob.SCENE.id)).modified
    asyncio.ensure_future(notif.broadcast_event(events.SceneSaved()))
    for obj_id in OBJECTS_WITH_UPDATED_POSE:
        asyncio.ensure_future(scene_object_pose_updated(glob.SCENE.id, obj_id))
    OBJECTS_WITH_UPDATED_POSE.clear()
    return None
예제 #19
0
async def copy_scene_cb(req: rpc.scene.CopySceneRequest, ui: WsClient) -> None:

    # TODO check if target_name is unique
    async with managed_scene(req.args.source_id, make_copy=True) as scene:
        scene.name = req.args.target_name
        asyncio.ensure_future(
            notif.broadcast_event(
                events.SceneChanged(events.EventType.UPDATE_BASE,
                                    data=scene.bare())))

    return None
예제 #20
0
async def update_scene_description_cb(
        req: rpc.scene.UpdateSceneDescriptionRequest, ui: WsClient) -> None:

    async with managed_scene(req.args.scene_id) as scene:
        scene.desc = req.args.new_description
        scene.update_modified()
        asyncio.ensure_future(
            notif.broadcast_event(
                events.SceneChanged(events.EventType.UPDATE_BASE,
                                    data=scene.bare())))
    return None
예제 #21
0
async def open_scene_cb(req: rpc.scene.OpenSceneRequest, ui: WsClient) -> None:

    if glob.PACKAGE_STATE.state in (common.PackageStateEnum.PAUSED,
                                    common.PackageStateEnum.RUNNING):
        raise Arcor2Exception("Can't open scene while package runs.")

    await open_scene(req.args.id)
    assert glob.SCENE
    asyncio.ensure_future(
        notif.broadcast_event(
            events.OpenScene(data=events.OpenSceneData(glob.SCENE))))
    return None
예제 #22
0
async def update_project_description_cb(
        req: rpc.project.UpdateProjectDescriptionRequest,
        ui: WsClient) -> None:

    async with managed_project(req.args.project_id) as project:

        project.desc = req.args.new_description
        project.update_modified()

        asyncio.ensure_future(
            notif.broadcast_event(
                events.ProjectChanged(events.EventType.UPDATE_BASE,
                                      data=project.bare())))
    return None
예제 #23
0
async def update_action_point_position_cb(
        req: rpc.project.UpdateActionPointPositionRequest,
        ui: WsClient) -> None:

    assert glob.SCENE and glob.PROJECT

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

    ap.position = req.args.new_position
    ap.invalidate_joints()
    for joints in ap.robot_joints:
        asyncio.ensure_future(
            notif.broadcast_event(
                events.JointsChanged(events.EventType.UPDATE,
                                     ap.id,
                                     data=joints)))

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.ActionPointChanged(events.EventType.UPDATE_BASE,
                                      data=ap.bare())))
    return None
예제 #24
0
async def new_object_type_cb(req: rpc.objects.NewObjectTypeRequest,
                             ui: WsClient) -> None:

    meta = req.args

    if meta.type in glob.OBJECT_TYPES:
        raise Arcor2Exception("Object type already exists.")

    if meta.base not in glob.OBJECT_TYPES:
        raise Arcor2Exception(
            f"Unknown base object type '{meta.base}', "
            f"known types are: {', '.join(glob.OBJECT_TYPES.keys())}.")

    if not hlp.is_valid_type(meta.type):
        raise Arcor2Exception("Object type invalid (should be CamelCase).")

    if req.dry_run:
        return None

    obj = meta.to_object_type()
    obj.source = new_object_type_source(glob.OBJECT_TYPES[meta.base], meta)

    if meta.object_model and meta.object_model.type != Model3dType.MESH:
        assert meta.type == meta.object_model.model().id
        await storage.put_model(meta.object_model.model())

    # TODO check whether mesh id exists - if so, then use existing mesh, if not, upload a new one
    if meta.object_model and meta.object_model.type == Model3dType.MESH:
        # ...get whole mesh (focus_points) based on mesh id
        assert meta.object_model.mesh
        try:
            meta.object_model.mesh = await storage.get_mesh(
                meta.object_model.mesh.id)
        except storage.PersistentStorageException as e:
            await glob.logger.error(e)
            raise Arcor2Exception(
                f"Mesh ID {meta.object_model.mesh.id} does not exist.")

    await storage.update_object_type(obj)

    glob.OBJECT_TYPES[meta.type] = meta
    glob.ACTIONS[meta.type] = otu.object_actions(
        TYPE_TO_PLUGIN, hlp.type_def_from_source(obj.source, obj.id, Generic),
        obj.source)
    otu.add_ancestor_actions(meta.type, glob.ACTIONS, glob.OBJECT_TYPES)

    asyncio.ensure_future(
        notif.broadcast_event(
            events.ChangedObjectTypesEvent(events.EventType.ADD, data=[meta])))
    return None
예제 #25
0
async def rename_scene_cb(req: rpc.scene.RenameSceneRequest,
                          ui: WsClient) -> None:

    unique_name(req.args.new_name, (await scene_names()))

    if req.dry_run:
        return None

    async with managed_scene(req.args.id) as scene:
        scene.name = req.args.new_name
        asyncio.ensure_future(
            notif.broadcast_event(
                events.SceneChanged(events.EventType.UPDATE_BASE,
                                    data=scene.bare())))
    return None
예제 #26
0
async def update_project_has_logic_cb(
        req: rpc.project.UpdateProjectHasLogicRequest, ui: WsClient) -> None:

    async with managed_project(req.args.project_id) as project:

        if project.has_logic and not req.args.new_has_logic:

            for act in project.actions():
                act.inputs.clear()
                act.outputs.clear()

                if glob.PROJECT and glob.PROJECT.id == req.args.project_id:
                    asyncio.ensure_future(
                        notif.broadcast_event(
                            events.ActionChanged(events.EventType.UPDATE,
                                                 data=act)))

        project.has_logic = req.args.new_has_logic
        project.update_modified()
        asyncio.ensure_future(
            notif.broadcast_event(
                events.ProjectChanged(events.EventType.UPDATE_BASE,
                                      data=project.bare())))
    return None
예제 #27
0
async def update_action_point_joints_cb(
        req: rpc.project.UpdateActionPointJointsRequest, ui: WsClient) -> None:

    assert glob.SCENE and glob.PROJECT

    robot_joints = glob.PROJECT.joints(req.args.joints_id)
    new_joints = await get_robot_joints(req.args.robot_id)
    robot_joints.joints = new_joints
    robot_joints.robot_id = req.args.robot_id
    robot_joints.is_valid = True

    glob.PROJECT.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.JointsChanged(events.EventType.UPDATE, data=robot_joints)))
    return None
예제 #28
0
async def copy_project_cb(req: rpc.project.CopyProjectRequest,
                          ui: WsClient) -> None:

    unique_name(req.args.target_name, (await project_names()))

    if req.dry_run:
        return None

    async with managed_project(req.args.source_id, make_copy=True) as project:

        project.name = req.args.target_name
        asyncio.ensure_future(
            notif.broadcast_event(
                events.ProjectChanged(events.EventType.UPDATE_BASE,
                                      data=project.bare())))

    return None
예제 #29
0
async def add_service_to_scene_cb(req: rpc.scene.AddServiceToSceneRequest,
                                  ui: WsClient) -> None:

    assert glob.SCENE

    srv = req.args
    await add_service_to_scene(srv, req.dry_run)

    if req.dry_run:
        return None

    glob.SCENE.services.append(srv)
    glob.SCENE.update_modified()
    asyncio.ensure_future(
        notif.broadcast_event(
            events.SceneServiceChanged(events.EventType.ADD, data=srv)))
    return None
예제 #30
0
async def cancel_action_cb(req: rpc.project.CancelActionRequest,
                           ui: WsClient) -> None:

    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)

    for act in glob.ACTIONS[obj.__class__.__name__]:
        if act.name != action_name:
            continue

        if not act.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] = {}

    cancel_sig = inspect.signature(cancel_method)

    assert glob.RUNNING_ACTION_PARAMS is not None

    for param_name, param in cancel_sig.parameters.items():
        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(events.ActionCancelledEvent()))
    glob.RUNNING_ACTION = None
    glob.RUNNING_ACTION_PARAMS = None