예제 #1
0
    def _compute_direction(self, classpath):
        klass = get_class(classpath)

        from morse.core.actuator import Actuator
        from morse.core.sensor import Sensor

        if klass:
            if issubclass(klass, Actuator):
                return "IN"
            elif issubclass(klass, Sensor):
                return "OUT"
            else:
                logger.error("%s: no direction is precised nor can be " "computed automatically." % classpath)
                return None
예제 #2
0
    def _compute_direction(self, classpath):
        klass = get_class(classpath)

        from morse.core.actuator import Actuator
        from morse.core.sensor import Sensor

        if klass:
            if issubclass(klass, Actuator):
                return 'IN'
            elif issubclass(klass, Sensor):
                return 'OUT'
            else:
                logger.error("%s: no direction is precised nor can be "
                             "computed automatically." % classpath)
                return None
예제 #3
0
    def add_stream(self,
                   datastream,
                   method=None,
                   path=None,
                   classpath=None,
                   direction=None,
                   **kwargs):
        """ Add a data stream interface to the component

        Do the binding between a component and the method to export/import its
        data. This must be used in general by sensors and actuators. A single
        component can make several calls to this function to add bindings with
        more than one middleware.

        :param datastream: enum in ['ros', 'socket', 'yarp', 'text', 'pocolibs', 'moos']
        :param classpath: if set, force to use the configuration of the given
                          component, instead of our own (default=None).

        You can pass other argument to this method, they will be added as a map
        to the configuration.

        .. code-block:: python

            component.add_stream('ros', topic='/myrobots/data')
            component.add_stream('moos', moos_host='127.0.0.1', moos_port=9000,
                                    moos_name='iMorse')

        """
        self._err_if_not_exportable()

        if not classpath:
            classpath = self.property_value("classpath")

        if not classpath:
            logger.error("%s: no classpath defined for this "
                         "component! Check component definition " % self.name)
            return

        level = self.property_value("abstraction_level") or "default"

        if not direction:
            direction = self._compute_direction(classpath)
            if not direction:
                return

        config = []
        # Configure the datastream for this component
        if not method:
            if not classpath in MORSE_DATASTREAM_DICT:
                klass = get_class(classpath)

                from morse.core.actuator import Actuator
                from morse.core.sensor import Sensor
                # Check if we can use default interface...
                if klass and \
                   issubclass(klass, Actuator) and \
                   datastream in INTERFACE_DEFAULT_IN:

                    logger.warning("%s: no interfaces available for this "
                                   "component! Trying to use default one "
                                   "for %s." % (classpath, datastream))
                    config = [INTERFACE_DEFAULT_IN[datastream]]

                elif klass and \
                     issubclass(klass, Sensor) and \
                     datastream in INTERFACE_DEFAULT_OUT:

                    logger.warning("%s: no interfaces available for this "
                                   "component! Trying to use default one "
                                   "for %s." % (classpath, datastream))
                    config = [INTERFACE_DEFAULT_OUT[datastream]]

                else:
                    logger.error(
                        "%s: no interfaces available for this component!"
                        " Check builder/data.py." % classpath)
                    return

            else:
                interfaces = MORSE_DATASTREAM_DICT[classpath]

                if not level in interfaces:

                    if level == "default":  # we need to look for the default level
                        module_name, class_name = classpath.rsplit('.', 1)
                        klass = load_module_attribute(module_name, class_name)

                        if not hasattr(klass, "_levels"):
                            logger.error(
                                "Component <%s> does not declare any "
                                "default interface. You must call "
                                "`add_stream` with an explicit method "
                                "and Python module." % str(classpath))
                            return

                        # iterate over levels to find the one with the default flag
                        for key, value in klass._levels.items():
                            if value[2]:
                                level = key
                                # set the right default level
                                self.properties(abstraction_level=level)
                                logger.info("Using default level <%s> for "
                                            "component <%s>" %
                                            (level, classpath))
                                break

                        if level == "default":
                            logger.error(
                                "Component <%s> does not declare any"
                                "default interface, and none of its "
                                "abstraction levels is marked as the "
                                "default one. You must call `add_stream`"
                                " with an explicit method and Python "
                                "module." % str(classpath))
                            return

                        if not level in interfaces:
                            logger.error(
                                "%s: no interfaces defined for this "
                                "component for abstraction level <%s>!"
                                "Check builder/data.py." % (classpath, level))
                            return

                    else:
                        logger.error(
                            "%s: no interfaces defined for this component"
                            "for abstraction level <%s>! Check "
                            "builder/data.py." % (classpath, level))

                interfaces = interfaces[level]
                if not datastream in interfaces:
                    logger.error(
                        "%s: no %s interface defined for this component "
                        "for abstraction level <%s>! "
                        "Check builder/data.py." %
                        (classpath, datastream, level))
                    return

                config = interfaces[datastream]
                if isinstance(config, list):
                    config = config[0]

                if config == INTERFACE_DEFAULT_OUT:
                    config = INTERFACE_DEFAULT_OUT[datastream]
                if config == INTERFACE_DEFAULT_IN:
                    config = INTERFACE_DEFAULT_IN[datastream]
                if isinstance(config, str):
                    config = [config]

        elif not path:
            config = [method]
        else:
            config = [method, path]

        if datastream in MORSE_DATASTREAM_MODULE:
            datastream_classpath = MORSE_DATASTREAM_MODULE[datastream]
        else:
            datastream_classpath = datastream

        config.insert(0, datastream_classpath)
        config.append(direction)
        config.append(
            kwargs)  # append additional configuration (eg. topic name)
        Configuration.link_datastream(self, config)
예제 #4
0
    def add_stream(self, datastream, method=None, path=None, classpath=None, direction=None, **kwargs):
        """ Add a data stream interface to the component

        Do the binding between a component and the method to export/import its
        data. This must be used in general by sensors and actuators. A single
        component can make several calls to this function to add bindings with
        more than one middleware.

        :param datastream: enum in ['ros', 'socket', 'yarp', 'text', 'pocolibs']
        :param classpath: if set, force to use the configuration of the given
                          component, instead of our own (default=None).

        You can pass other argument to this method, they will be added as a map
        to the configuration.

        .. code-block:: python

            component.add_stream('ros', topic='/myrobots/data')

        """
        if not classpath:
            classpath = self.property_value("classpath")

        if not classpath:
            logger.error("%s: no classpath defined for this " "component! Check component definition " % self.name)
            return

        level = self.property_value("abstraction_level") or "default"

        config = []
        # Configure the datastream for this component
        if not method:
            if not classpath in MORSE_DATASTREAM_DICT:

                # Check if we can use default interface...
                from morse.core.actuator import Actuator
                from morse.core.sensor import Sensor

                klass = get_class(classpath)
                if klass and issubclass(klass, Actuator) and datastream in INTERFACE_DEFAULT_IN:

                    logger.warning(
                        "%s: no interfaces available for this "
                        "component! Trying to use default one "
                        "for %s." % (classpath, datastream)
                    )
                    config = [INTERFACE_DEFAULT_IN[datastream]]

                elif klass and issubclass(klass, Sensor) and datastream in INTERFACE_DEFAULT_OUT:

                    logger.warning(
                        "%s: no interfaces available for this "
                        "component! Trying to use default one "
                        "for %s." % (classpath, datastream)
                    )
                    config = [INTERFACE_DEFAULT_OUT[datastream]]

                else:
                    logger.error(
                        "%s: no interfaces available for this component!" " Check builder/data.py." % classpath
                    )
                    return

            else:
                interfaces = MORSE_DATASTREAM_DICT[classpath]

                if not level in interfaces:

                    if level == "default":  # we need to look for the default level
                        module_name, class_name = classpath.rsplit(".", 1)
                        klass = load_module_attribute(module_name, class_name)

                        if not hasattr(klass, "_levels"):
                            logger.error(
                                "Component <%s> does not declare any "
                                "default interface. You must call "
                                "`add_stream` with an explicit method "
                                "and Python module." % str(classpath)
                            )
                            return

                        # iterate over levels to find the one with the default flag
                        for key, value in klass._levels.items():
                            if value[2] == True:
                                level = key
                                # set the right default level
                                self.properties(abstraction_level=level)
                                logger.info("Using default level <%s> for " "component <%s>" % (level, classpath))
                                break

                        if level == "default":
                            logger.error(
                                "Component <%s> does not declare any"
                                "default interface, and none of its "
                                "abstraction levels is marked as the "
                                "default one. You must call `add_stream`"
                                " with an explicit method and Python "
                                "module." % str(classpath)
                            )
                            return

                        if not level in interfaces:
                            logger.error(
                                "%s: no interfaces defined for this "
                                "component for abstraction level <%s>!"
                                "Check builder/data.py." % (classpath, level)
                            )
                            return

                    else:
                        logger.error(
                            "%s: no interfaces defined for this component"
                            "for abstraction level <%s>! Check "
                            "builder/data.py." % (classpath, level)
                        )

                interfaces = interfaces[level]
                if not datastream in interfaces:
                    logger.error(
                        "%s: no %s interface defined for this component "
                        "for abstraction level <%s>! "
                        "Check builder/data.py." % (classpath, datastream, level)
                    )
                    return

                config = interfaces[datastream]
                if isinstance(config, list):
                    config = config[0]

                if config == INTERFACE_DEFAULT_OUT:
                    config = INTERFACE_DEFAULT_OUT[datastream]
                if config == INTERFACE_DEFAULT_IN:
                    config = INTERFACE_DEFAULT_IN[datastream]
                if isinstance(config, str):
                    config = [config]

        elif not path:
            config = [method]
        else:
            config = [method, path]

        if datastream in MORSE_DATASTREAM_MODULE:
            datastream_classpath = MORSE_DATASTREAM_MODULE[datastream]
        else:
            datastream_classpath = datastream

        config.insert(0, datastream_classpath)
        config.append(kwargs)  # append additional configuration (eg. topic name)
        Configuration.link_datastream(self, config)