コード例 #1
0
ファイル: joints.py プロジェクト: robofit/arcor2
    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
コード例 #2
0
ファイル: relative_pose.py プロジェクト: robofit/arcor2
    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)
コード例 #3
0
    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
コード例 #4
0
ファイル: project.py プロジェクト: Croolman/arcor2
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)}")
コード例 #5
0
    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
コード例 #6
0
ファイル: integer_enum.py プロジェクト: Croolman/arcor2
    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."
            )
コード例 #7
0
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.PROJECT_PARAMETER:

            pparam = project.parameter(param.str_from_value())

            param_meta = object_action.parameter(param.name)
            if param_meta.type != pparam.type:
                raise Arcor2Exception(
                    "Action parameter type does not match project parameter 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.")

            parent_action = project.action(parsed_link.action_id)
            source_action_pt = parent_action.parse_type()

            parent_action_meta = glob.OBJECT_TYPES[scene.object(
                source_action_pt.obj_id).type].actions[
                    source_action_pt.action_type]

            if len(parent_action.flow(parsed_link.flow_name).outputs) != len(
                    parent_action_meta.returns):
                raise Arcor2Exception(
                    "Source action does not have outputs specified.")

            param_meta = object_action.parameter(param.name)

            try:
                if param_meta.type != parent_action_meta.returns[
                        parsed_link.output_index]:
                    raise Arcor2Exception(
                        "Param type does not match action output type.")
            except IndexError:
                raise Arcor2Exception(
                    f"Index {parsed_link.output_index} is invalid for action {object_action.name},"
                    f" which returns {len(object_action.returns)} values.")

        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)}"
                )
コード例 #8
0
ファイル: logic.py プロジェクト: NelaMm/arcor2
def add_logic_to_loop(type_defs: TypesDict, tree: Module, scene: CScene,
                      project: CProject) -> None:

    added_actions: Set[str] = set()

    def _blocks_to_start(action: Action, depth: int = 0) -> int:

        inputs, outputs = project.action_io(action.id)

        for inp in inputs:
            if inp.start == inp.START:
                continue
            parsed_input = inp.parse_start()

            prev_action = project.action(parsed_input.start_action_id)
            _, prev_action_outputs = project.action_io(prev_action.id)

            if len(prev_action_outputs) > 1:
                depth += 1
            _blocks_to_start(prev_action, depth)

        return depth

    def _add_logic(container: Container,
                   current_action: Action,
                   super_container: Optional[Container] = None) -> None:

        # more paths could lead  to the same action, so it might be already added
        # ...this is easier than searching the tree
        if current_action.id in added_actions:
            logger.debug(
                f"Action {current_action.name} already added, skipping.")
            return

        inputs, outputs = project.action_io(current_action.id)
        logger.debug(
            f"Adding action {current_action.name}, with {len(inputs)} input(s) and {len(outputs)} output(s)."
        )

        act = current_action.parse_type()
        ac_obj = scene.object(act.obj_id).name

        args: List[AST] = []

        # TODO make sure that the order of parameters is correct / re-order
        for param in current_action.parameters:

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

                parsed_link = param.parse_link()
                parent_action = project.action(parsed_link.action_id)

                # TODO add support for tuples
                assert len(parent_action.flow(FlowTypes.DEFAULT).outputs
                           ) == 1, "Only one result is supported atm."
                assert parsed_link.output_index == 0

                res_name = parent_action.flow(FlowTypes.DEFAULT).outputs[0]

                # make sure that the result already exists
                if parent_action.id not in added_actions:
                    raise SourceException(
                        f"Action {current_action.name} attempts to use result {res_name} "
                        f"of subsequent action {parent_action.name}.")

                args.append(Name(id=res_name, ctx=Load()))

            elif param.type == ActionParameter.TypeEnum.PROJECT_PARAMETER:
                args.append(
                    Name(id=project.parameter(param.str_from_value()).name,
                         ctx=Load()))
            else:

                plugin = plugin_from_type_name(param.type)

                args.append(
                    plugin.parameter_ast(type_defs, scene, project,
                                         current_action.id, param.name))

                list_of_imp_tup = plugin.need_to_be_imported(
                    type_defs, scene, project, current_action.id, param.name)

                if list_of_imp_tup:
                    # TODO what if there are two same names?
                    for imp_tup in list_of_imp_tup:
                        add_import(tree,
                                   imp_tup.module_name,
                                   imp_tup.class_name,
                                   try_to_import=False)

        add_method_call(
            container.body,
            ac_obj,
            act.action_type,
            args,
            [keyword(arg="an", value=Str(s=current_action.name, kind=""))],
            current_action.flow(FlowTypes.DEFAULT).outputs,
        )

        added_actions.add(current_action.id)

        if not outputs:
            raise SourceException(
                f"Action {current_action.name} has no outputs.")
        elif len(outputs) == 1:
            output = outputs[0]

            if output.end == output.END:
                # TODO this is just temporary (while there is while loop), should be rather Return()
                container.body.append(Continue())
                return

            seq_act = project.action(output.end)
            seq_act_inputs, _ = project.action_io(seq_act.id)
            if len(seq_act_inputs
                   ) > 1:  # the action belongs to a different block

                if seq_act.id in added_actions:
                    return

                logger.debug(
                    f"Action {seq_act.name} going to be added to super_container."
                )

                # test if this is the correct super_container -> count distance (number of blocks) to the START
                blocks_to_start: Dict[str, int] = {}

                for inp in seq_act_inputs:
                    parsed_start = inp.parse_start()
                    pact = project.action(parsed_start.start_action_id)
                    blocks_to_start[pact.id] = _blocks_to_start(pact)
                winner = min(blocks_to_start, key=blocks_to_start.get
                             )  # type: ignore  # TODO what is wrong with it?

                # TODO if blocks_to_start is cached somewhere, the second part of the condition is useless
                # it might happen that there are two different ways with the same distance
                if winner == current_action.id or all(
                        value == list(blocks_to_start.values())[0]
                        for value in blocks_to_start.values()):
                    assert super_container is not None
                    _add_logic(super_container, seq_act)
                return

            logger.debug(f"Sequential action: {seq_act.name}")
            _add_logic(container, seq_act, super_container)

        else:

            root_if: Optional[If] = None

            # action has more outputs - each output should have condition
            for idx, output in enumerate(outputs):
                if not output.condition:
                    raise SourceException("Missing condition.")

                # TODO use parameter plugin (action metadata will be needed - to get the return types)
                # TODO support for other countable types
                # ...this will only work for booleans
                from arcor2 import json

                condition_value = json.loads(output.condition.value)
                comp = NameConstant(value=condition_value, kind=None)
                what = output.condition.parse_what()
                output_name = project.action(what.action_id).flow(
                    what.flow_name).outputs[what.output_index]

                cond = If(
                    test=Compare(left=Name(id=output_name, ctx=Load()),
                                 ops=[Eq()],
                                 comparators=[comp]),
                    body=[],
                    orelse=[],
                )

                if idx == 0:
                    root_if = cond
                    container.body.append(root_if)
                    logger.debug(f"Adding branch for: {condition_value}")
                else:
                    assert isinstance(root_if, If)
                    root_if.orelse.append(cond)

                if output.end == output.END:
                    cond.body.append(
                        Continue())  # TODO should be rather return
                    continue

                _add_logic(cond, project.action(output.end), container)

    current_action = project.action(project.first_action_id())
    # having 'while True' default loop is temporary solution until there will be support for functions/loops
    loop = main_loop(tree)
    _add_logic(loop, current_action)

    logger.debug(
        f"Unused actions: {[project.action(act_id).name for act_id in project.action_ids() - added_actions]}"
    )

    if loop and isinstance(loop.body[0], Pass):
        # pass is not necessary now
        del loop.body[0]

    if loop and isinstance(loop.body[-1], Continue):
        # delete unnecessary continue
        del loop.body[-1]
コード例 #9
0
 def orientation_id(cls, project: CProject, action_id: str,
                    parameter_id: str) -> str:
     return cls._id_from_value(
         project.action(action_id).parameter(parameter_id).value)