예제 #1
0
class Example(object):
    def __init__(self):
        # Create a D(ynamic)DynamicReconfigure
        self.ddr = DDynamicReconfigure("class_example")

        # Add variables (name, description, default value, min, max, edit_method)
        self.ddr.add_variable("decimal", "float/double variable", 0.0, -1.0, 1.0)
        self.ddr.add_variable("integer", "integer variable", 0, -1, 1)
        self.ddr.add_variable("bool", "bool variable", True)
        self.ddr.add_variable("string", "string variable", "string dynamic variable")
        enum_method = self.ddr.enum([ self.ddr.const("Small",      "int", 0, "A small constant"),
                           self.ddr.const("Medium",     "int", 1, "A medium constant"),
                           self.ddr.const("Large",      "int", 2, "A large constant"),
                           self.ddr.const("ExtraLarge", "int", 3, "An extra large constant")],
                         "An enum example")
        self.ddr.add_variable("enumerate", "enumerate variable", 1, 0, 3, edit_method=enum_method)

        self.add_variables_to_self()

        self.ddr.start(self.dyn_rec_callback)

    def add_variables_to_self(self):
        var_names = self.ddr.get_variable_names()
        for var_name in var_names:
            self.__setattr__(var_name, None)

    def dyn_rec_callback(self, config, level):
        rospy.loginfo("Received reconf call: " + str(config))
        # Update all variables
        var_names = self.ddr.get_variable_names()
        for var_name in var_names:
            self.__dict__[var_name] = config[var_name]
        return config
예제 #2
0
import rospy
from ddynamic_reconfigure_python.ddynamic_reconfigure import DDynamicReconfigure

def dyn_rec_callback(config, level):
    rospy.loginfo("Received reconf call: " + str(config))
    return config

if __name__ == '__main__':
    rospy.init_node('test_ddynrec')

    # Create a D(ynamic)DynamicReconfigure
    ddynrec = DDynamicReconfigure("example_dyn_rec")

    # Add variables (name, description, default value, min, max, edit_method)
    ddynrec.add_variable("decimal", "float/double variable", 0.0, -1.0, 1.0)
    ddynrec.add_variable("integer", "integer variable", 0, -1, 1)
    ddynrec.add_variable("bool", "bool variable", True)
    ddynrec.add_variable("string", "string variable", "string dynamic variable")
    enum_method = ddynrec.enum([ ddynrec.const("Small",      "int", 0, "A small constant"),
                       ddynrec.const("Medium",     "int", 1, "A medium constant"),
                       ddynrec.const("Large",      "int", 2, "A large constant"),
                       ddynrec.const("ExtraLarge", "int", 3, "An extra large constant")],
                     "An enum example")
    ddynrec.add_variable("enumerate", "enumerate variable", 1, 0, 3, edit_method=enum_method)

    # Start the server
    ddynrec.start(dyn_rec_callback)

    rospy.spin()
class RestClient(object):
    def __init__(self, rest_name, ignored_parameters=[]):
        self.rest_name = rest_name
        self.ignored_parameters = ignored_parameters
        self.rest_services = []
        self.ddr = None

        rospy.init_node(rest_name + '_client', log_level=rospy.INFO)

        self.host = rospy.get_param('~host', '')
        if not self.host:
            rospy.logerr('host is not set')
            sys.exit(1)

        self._setup_ddr()

    def _get_rest_parameters(self):
        try:
            url = 'http://{}/api/v1/nodes/{}/parameters'.format(
                self.host, self.rest_name)
            res = requests_retry_session().get(url)
            if res.status_code != 200:
                rospy.logerr("Getting parameters failed with status code: %d",
                             res.status_code)
                return []
            return res.json()
        except Exception as e:
            rospy.logerr(str(e))
            return []

    def _set_rest_parameters(self, parameters):
        try:
            url = 'http://{}/api/v1/nodes/{}/parameters'.format(
                self.host, self.rest_name)
            res = requests_retry_session().put(url, json=parameters)
            j = res.json()
            rospy.logdebug("set parameters response: %s",
                           json.dumps(j, indent=2))
            if 'return_code' in j and j['return_code']['value'] != 0:
                rospy.logwarn("Setting parameter failed: %s",
                              j['return_code']['message'])
                return []
            if res.status_code != 200:
                rospy.logerr("Setting parameters failed with status code: %d",
                             res.status_code)
                return []
            return j
        except Exception as e:
            rospy.logerr(str(e))
            return []

    def _setup_ddr(self):
        self.ddr = DDynamicReconfigure(rospy.get_name())
        rest_params = [
            p for p in self._get_rest_parameters()
            if p['name'] not in self.ignored_parameters
        ]

        def enum_method_from_param(p):
            if p['type'] != 'string':
                return ""
            enum_matches = re.findall(r'.*\[(?P<enum>.+)\].*',
                                      p['description'])
            if not enum_matches:
                return ""
            enum_names = [str(e.strip()) for e in enum_matches[0].split(',')]
            enum_list = [self.ddr.const(n, 'str', n, n) for n in enum_names]
            return self.ddr.enum(enum_list, p['name'] + '_enum')

        for p in rest_params:
            level = 0
            edit_method = enum_method_from_param(p)
            if p['type'] == 'int32':
                self.ddr.add(p['name'], 'int', level, p['description'],
                             p['default'], p['min'], p['max'])
            elif p['type'] == 'float64':
                self.ddr.add(p['name'], 'double', level, p['description'],
                             p['default'], p['min'], p['max'])
            elif p['type'] == 'string':
                self.ddr.add(p['name'],
                             'str',
                             level,
                             p['description'],
                             str(p['default']),
                             edit_method=edit_method)
            elif p['type'] == 'bool':
                self.ddr.add(p['name'], 'bool', level, p['description'],
                             p['default'])
            else:
                rospy.logwarn("Unsupported parameter type: %s", p['type'])

        self.ddr.start(self._dyn_rec_callback)

    def _dyn_rec_callback(self, config, level):
        rospy.logdebug("Received reconf call: " + str(config))
        new_rest_params = [{
            'name': n,
            'value': config[n]
        } for n in self.ddr.get_variable_names() if n in config]
        if new_rest_params:
            returned_params = self._set_rest_parameters(new_rest_params)
            for p in returned_params:
                if p['name'] not in config:
                    rospy.logerr("param %s not in config", p['name'])
                    continue
                config[p['name']] = p['value']
        return config

    def call_rest_service(self, name, srv_type=None, request=None):
        try:
            args = {}
            if request is not None:
                # convert ROS request to JSON (with custom API mappings)
                args = convert_ros_message_to_dictionary(request)
                rospy.logdebug('calling {} with args: {}'.format(name, args))

            url = 'http://{}/api/v1/nodes/{}/services/{}'.format(
                self.host, self.rest_name, name)
            res = requests_retry_session().put(url, json={'args': args})

            j = res.json()
            rospy.logdebug("{} rest response: {}".format(
                name, json.dumps(j, indent=2)))
            rc = j['response'].get('return_code')
            if rc is not None and rc['value'] < 0:
                rospy.logwarn("service {} returned an error: [{}] {}".format(
                    name, rc['value'], rc['message']))

            # convert to ROS response
            if srv_type is not None:
                response = convert_dictionary_to_ros_message(
                    srv_type._response_class(),
                    j['response'],
                    strict_mode=False)
            else:
                response = j['response']
        except Exception as e:
            rospy.logerr(str(e))
            if srv_type is not None:
                response = srv_type._response_class()
                if hasattr(response, 'return_code'):
                    response.return_code.value = -1000
                    response.return_code.message = str(e)
        return response

    def add_rest_service(self, srv_type, srv_name, callback):
        """create a service and inject the REST-API service name"""
        srv = rospy.Service(rospy.get_name() + "/" + srv_name, srv_type,
                            partial(callback, srv_name, srv_type))
        self.rest_services.append(srv)