Example #1
0
    def string2Method(self, method_string, robots):
        """
        Return the HandlerMethodConfig according to the input string from configEditor
        This functions must be located in HandlerSubsystem in order to get access to handler_configs dictionary

        method_string: a string that stores the information of a method configObj
                       for example: a = "nao_maeby.NaoSensorHandler.seePerson(name='nao', test=[1,2,3])"
        robots: a list of robots in the current experiment config. we need this to find the robot type and avaliable handlers
                based on robot_name
        """

        if not self.handler_configs:
            logging.error("Cannot find handler_configs dictionary, please load all handlers first.")
            return None

        try:
            call_descriptors, _ = parseCallString(method_string, mode="single")
            if len(call_descriptors[0].name) != 3:
                raise SyntaxError("Name must be in form of '<robot_name>.<handler_name>.<method_name>'")
        except SyntaxError:
            logging.exception("Cannot parse setting {!r}".format(method_string))
            return None

        robot_name, handler_name, method_name = call_descriptors[0].name

        # find which handler does this method belongs to
        handler_config = None

        if robot_name == "share":
            # this is a dummy sensor/actuator
            for h in self.handler_configs["share"][ht.SensorHandler] + \
                     self.handler_configs["share"][ht.ActuatorHandler]:
                if h.name == handler_name:
                    handler_config = h
                    break
        else:
            # this is a robot sensor/actuator
            for robot_config in robots:
                if robot_config.name == robot_name:
                    handler_config = robot_config.getHandlerByName(handler_name)
                    break

        # we did not find the correct handler config
        if handler_config is None:
            logging.error("Cannot recognize handler {!r} of robot {!r}".format(handler_name, robot_name))
            logging.error("Please make sure it is correctly loaded")
            return None

        # try to find the method config
        try:
            method_config = deepcopy(handler_config.getMethodByName(method_name))
        except ValueError:
            return None

        # update parameters of this method
        method_config.updateParaFromDict(call_descriptors[0].args)

        return method_config
Example #2
0
    def createPropositionMappingExecutionFunctionFromString(self, func_string, mode):
        """ Given a string description of the function(s) that some
            proposition maps to, create the appropriate HandlerMethodConfigs
            and return the function that will evaluate their execute() methods. """

        # Call the parser with appropriate arguments
        call_descriptors, eval_function = parseCallString(func_string, mode,
                                                          self._makeHandlerMethodConfigAndGetExecutionFunction)
        # Return the resulting function to be evaluated
        return eval_function
Example #3
0
    def createPropositionMappingExecutionFunctionFromString(
            self, func_string, mode):
        """ Given a string description of the function(s) that some
            proposition maps to, create the appropriate HandlerMethodConfigs
            and return the function that will evaluate their execute() methods. """

        # Call the parser with appropriate arguments
        call_descriptors, eval_function = parseCallString(
            func_string, mode,
            self._makeHandlerMethodConfigAndGetExecutionFunction)
        # Return the resulting function to be evaluated
        return eval_function
Example #4
0
    def fromString(cls, para_string):
        """
        Create a MethodParameterConfig from a single line of a comment from a
        handler method.

        para_string: string specifying the properties of the parameter
        """

        # Regular expression to help us out
        # NOTE: The description does not permit parentheses
        argRE = re.compile(
            '^\s*(?P<argName>\w+)\s*\(\s*(?P<type>\w+)\s*\)\s*:\s*(?P<description>[^\(]+)\s*(?P<settings>\(.+\))?\s*$',
            re.IGNORECASE)

        # Try to match
        m = argRE.search(para_string)

        if m is None:
            raise ValueError("Not a properly-formatted parameter description.")

        new_obj = cls(name=m.group('argName'),
                      para_type=m.group('type'),
                      desc=m.group('description'))

        if m.group('settings') is not None:
            # To make valid Python syntax, we just need to prepend
            # a dummy function name before the settings string
            try:
                call_desc, _ = parseCallString("dummy_function" +
                                               m.group("settings"),
                                               mode="single")
            except SyntaxError as e:
                raise SyntaxError(
                    "Error while parsing settings for parameter {!r}: {}".
                    format(m.group('argName'), e))

            settings = call_desc[0].args

            # Set all of the settings
            for k, v in settings.iteritems():
                if k.lower() not in [
                        'default', 'min_val', 'max_val', 'options', 'min',
                        'max'
                ]:
                    raise SyntaxError(
                        "Unrecognized setting name {!r} for parameter {!r}".
                        format(k.lower(), m.group('argName')))

                setattr(new_obj, k.lower(), v)

        new_obj.resetValue()

        return new_obj
Example #5
0
    def fromString(cls, para_string):
        """
        Create a MethodParameterConfig from a single line of a comment from a
        handler method.

        para_string: string specifying the properties of the parameter
        """

        # Regular expression to help us out
        # NOTE: The description does not permit parentheses
        argRE = re.compile('^\s*(?P<argName>\w+)\s*\(\s*(?P<type>\w+)\s*\)\s*:\s*(?P<description>[^\(]+)\s*(?P<settings>\(.+\))?\s*$', re.IGNORECASE)

        # Try to match
        m = argRE.search(para_string)

        if m is None:
            raise ValueError("Not a properly-formatted parameter description.")

        new_obj = cls(name=m.group('argName'),
                      para_type=m.group('type'),
                      desc=m.group('description'))

        if m.group('settings') is not None:
            # To make valid Python syntax, we just need to prepend
            # a dummy function name before the settings string
            try:
                call_desc, _ = parseCallString("dummy_function"+m.group("settings"),
                                               mode="single")
            except SyntaxError as e:
                raise SyntaxError("Error while parsing settings for parameter {!r}: {}".format(m.group('argName'), e))

            settings = call_desc[0].args

            # Set all of the settings
            for k, v in settings.iteritems():
                if k.lower() not in ['default', 'min_val', 'max_val', 'options', 'min', 'max']:
                    raise SyntaxError("Unrecognized setting name {!r} for parameter {!r}".format(k.lower(), m.group('argName')))

                setattr(new_obj, k.lower(), v)

        new_obj.resetValue()

        return new_obj
Example #6
0
    def fromData(self, robot_data, hsub):
        """
        Given a dictionary of robot handler information, returns a robot object holding all the information
        The dictionary is in the format returned by the readFromFile function
        If the necessary handler of the robot is not specified or can't be loaded, return None
        """

        # update robot name and type
        try:
            self.name = robot_data['RobotName'][0]
        except (KeyError, IndexError):
            raise ht.LoadingError("Cannot find robot name")
            self._setLoadFailureFlag()

        try:
            self.r_type = robot_data['Type'][0]
        except (KeyError, IndexError):
            raise ht.LoadingError("Cannot find robot type")
            self._setLoadFailureFlag()

        # update robot calibration matrix
        if 'CalibrationMatrix' in robot_data:
            self.calibration_matrix = self._getCalibrationMatrixFromString(''.join(robot_data['CalibrationMatrix']))

        # load handler configs
        for key, val in robot_data.iteritems():
            # Ignore config sections that aren't for handlers
            if not key.endswith('Handler'):
                continue

            # Find the intended type of the handler
            try:
                handler_type = ht.getHandlerTypeClass(key)
            except KeyError:
                logging.warning('Cannot recognize handler type {!r} for robot {}({})'.format(key, self.name, self.r_type))
                self._setLoadFailureFlag()
                continue

            # Go through the handler listings for this type
            for handler_config_str in val:
                # Parse this line
                try:
                    call_descriptors, _ = parseCallString(handler_config_str, mode="single")
                except SyntaxError:
                    # This is an invalid handler config description
                    logging.exception('Cannot recognize handler config description: \n \t {!r} \n \
                                    for handler type {!r} of robot {}({})'.format(handler_config_str, key, self.name, self.r_type))
                    self._setLoadFailureFlag()
                    continue

                # Figure out how to interpret the different parts of the CallDescriptor name
                if len(call_descriptors[0].name) == 3:
                    robot_type, h_type, handler_name = call_descriptors[0].name
                    # 3-part name is only valid for shared handlers
                    if robot_type != 'share':
                        raise SyntaxError("Name must be in form of 'share.<handler_type>.<handler_name>' or '<robot_type>.<handler_name>'")
                elif len(call_descriptors[0].name) == 2:
                    robot_type, handler_name = call_descriptors[0].name
                    h_type = None
                else:
                    raise SyntaxError("Name must be in form of 'share.<handler_type>.<handler_name>' or '<robot_type>.<handler_name>'")

                # Check that this handler belongs to this robot (it's kind of redundant that the `robot_type` must be
                # specified if we're only going to let it be one value...)
                if (robot_type != 'share') and (robot_type.lower() != self.r_type.lower()):
                    # this is a handler for a wrong robot
                    logging.warning('The handler config description: \n \t {!r} \n \
                                    is for robot {}, but is located in data for robot {}({})' \
                                    .format(handler_config_str, robot_type, self.name, self.r_type))
                    self._setLoadFailureFlag()
                    continue

                # if the description also specifies the handler type in it
                # we need to make sure it matches with the handler type we get from section name
                if h_type is not None:
                    # get the handler type as class object
                    try:
                        handler_type_from_str = ht.getHandlerTypeClass(h_type)
                    except KeyError:
                        logging.warning('Cannot recognize handler type {!r} in config description: \n \t {!r} \n \
                                        for robot {}({})'.format(h_type, handler_config_str, self.name, self.r_type))
                        self._setLoadFailureFlag()
                        continue

                    if handler_type_from_str != handler_type:
                        # the handler type from the description does not match the one from section name
                        logging.warning('Misplaced handler description: \n \t {!r} \n \
                                        in handler type {!r} for robot {}({})' \
                                        .format(handler_config_str, handler_type, self.name, self.r_type))
                        # we still want to put this handler config into the right type
                        handler_type = handler_type_from_str

                if robot_type == 'share' and h_type is None:
                    # This is a shared handler but no handler type information is given
                    logging.warning('Handler type info missing for {!r} handler in config description: \n \t {!r} \n \
                                    for robot {}({})'.format(robot_type, handler_config_str, self.name, self.r_type))
                    self._setLoadFailureFlag()
                    continue

                # now let's get the handler config object based on the info we have got
                handler_config = hsub.getHandlerConfigDefault(robot_type, handler_type, handler_name)

                # make sure it successfully loaded
                if handler_config is None:
                    self._setLoadFailureFlag()
                    continue

                # load all parameter values and overwrite the ones in the __init__ method of default handler config object
                try:
                    init_method_config = handler_config.getMethodByName('__init__')
                except ValueError:
                    logging.warning('Cannot update default parameters of default handler config {!r}'.format(handler_config.name))
                else:
                    init_method_config.updateParaFromDict(call_descriptors[0].args)

                # if it is successfully fetched, we save it at the corresponding handler type of this robot
                if handler_type not in self.handlers:
                    # This type of handler has not been loaded yet
                    self.handlers[handler_type] = handler_config
                else:
                    # This type of handler has been loaded, for now, we will NOT overwrite it with new entry
                    # A warning will be shown
                    logging.warning('Multiple handler configs are detected for handler type {!r} of robot {}({}). \
                            Will only load the first one.'.format(key, self.name, self.r_type))
                    break
Example #7
0
    def string2Method(self, method_string, robots):
        """
        Return the HandlerMethodConfig according to the input string from configEditor
        This functions must be located in HandlerSubsystem in order to get access to handler_configs dictionary

        method_string: a string that stores the information of a method configObj
                       for example: a = "nao_maeby.NaoSensorHandler.seePerson(name='nao', test=[1,2,3])"
        robots: a list of robots in the current experiment config. we need this to find the robot type and avaliable handlers
                based on robot_name
        """

        if not self.handler_configs:
            logging.error(
                "Cannot find handler_configs dictionary, please load all handlers first."
            )
            return None

        try:
            call_descriptors, _ = parseCallString(method_string, mode="single")
            if len(call_descriptors[0].name) != 3:
                raise SyntaxError(
                    "Name must be in form of '<robot_name>.<handler_name>.<method_name>'"
                )
        except SyntaxError:
            logging.exception(
                "Cannot parse setting {!r}".format(method_string))
            return None

        robot_name, handler_name, method_name = call_descriptors[0].name

        # find which handler does this method belongs to
        handler_config = None

        if robot_name == "share":
            # this is a dummy sensor/actuator
            for h in self.handler_configs["share"][ht.SensorHandler] + \
                     self.handler_configs["share"][ht.ActuatorHandler]:
                if h.name == handler_name:
                    handler_config = h
                    break
        else:
            # this is a robot sensor/actuator
            for robot_config in robots:
                if robot_config.name == robot_name:
                    handler_config = robot_config.getHandlerByName(
                        handler_name)
                    break

        # we did not find the correct handler config
        if handler_config is None:
            logging.error("Cannot recognize handler {!r} of robot {!r}".format(
                handler_name, robot_name))
            logging.error("Please make sure it is correctly loaded")
            return None

        # try to find the method config
        try:
            method_config = deepcopy(
                handler_config.getMethodByName(method_name))
        except ValueError:
            return None

        # update parameters of this method
        method_config.updateParaFromDict(call_descriptors[0].args)

        return method_config