Package dynamic_reconfigure :: Module server

Source Code for Module dynamic_reconfigure.server

  1  # Software License Agreement (BSD License) 
  2  # 
  3  # Copyright (c) 2009, Willow Garage, Inc. 
  4  # All rights reserved. 
  5  # 
  6  # Redistribution and use in source and binary forms, with or without 
  7  # modification, are permitted provided that the following conditions 
  8  # are met: 
  9  # 
 10  #  * Redistributions of source code must retain the above copyright 
 11  #    notice, this list of conditions and the following disclaimer. 
 12  #  * Redistributions in binary form must reproduce the above 
 13  #    copyright notice, this list of conditions and the following 
 14  #    disclaimer in the documentation and/or other materials provided 
 15  #    with the distribution. 
 16  #  * Neither the name of Willow Garage, Inc. nor the names of its 
 17  #    contributors may be used to endorse or promote products derived 
 18  #    from this software without specific prior written permission. 
 19  # 
 20  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
 21  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
 22  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 
 23  # FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 
 24  # COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 
 25  # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 
 26  # BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
 27  # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 
 28  # CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 29  # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 
 30  # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
 31  # POSSIBILITY OF SUCH DAMAGE. 
 32   
 33  """ 
 34  Python client API for dynamic_reconfigure (L{DynamicReconfigureClient}) as well as  
 35  example server implementation (L{DynamicReconfigureServer}). 
 36  """ 
 37   
 38  from __future__ import with_statement 
 39   
 40  import roslib; roslib.load_manifest('dynamic_reconfigure') 
 41  import rospy 
 42  import rosservice                   
 43  import threading 
 44  import time 
 45  import copy 
 46  from dynamic_reconfigure import DynamicReconfigureCallbackException 
 47  from dynamic_reconfigure.srv import Reconfigure as ReconfigureSrv 
 48  from dynamic_reconfigure.msg import Config as ConfigMsg 
 49  from dynamic_reconfigure.msg import ConfigDescription as ConfigDescrMsg 
 50  from dynamic_reconfigure.msg import IntParameter, BoolParameter, StrParameter, DoubleParameter, ParamDescription 
 51  from dynamic_reconfigure.encoding import * 
 52   
53 -class Server(object):
54 - def __init__(self, type, callback):
55 self.mutex = threading.Lock() 56 self.type = type 57 self.config = type.defaults.copy() 58 59 self.description = encode_description(type) 60 self._copy_from_parameter_server() 61 self.callback = callback 62 self._clamp(self.config) 63 64 # setup group defaults 65 self.config['groups'] = get_tree(self.description) 66 self.config = initial_config(encode_config(self.config), type.config_description) 67 68 self.descr_topic = rospy.Publisher('~parameter_descriptions', ConfigDescrMsg, latch=True) 69 self.descr_topic.publish(self.description); 70 71 self.update_topic = rospy.Publisher('~parameter_updates', ConfigMsg, latch=True) 72 self._change_config(self.config, type.all_level) 73 74 self.set_service = rospy.Service('~set_parameters', ReconfigureSrv, self._set_callback)
75
76 - def update_configuration(self, changes):
77 with self.mutex: 78 new_config = copy.deepcopy(self.config) 79 new_config.update(changes) 80 self._clamp(new_config) 81 return self._change_config(new_config, self._calc_level(new_config, self.config))
82
84 for param in extract_params(self.type.config_description): 85 try: 86 self.config[param['name']] = rospy.get_param("~" + param['name']) 87 except KeyError: 88 pass
89
91 for param in extract_params(self.type.config_description): 92 rospy.set_param('~' + param['name'], self.config[param['name']])
93
94 - def _change_config(self, config, level):
95 self.config = self.callback(config, level) 96 if self.config is None: 97 msg = 'Reconfigure callback should return a possibly updated configuration.' 98 rospy.logerr(msg) 99 raise DynamicReconfigureCallbackException(msg) 100 101 self._copy_to_parameter_server() 102 103 self.update_topic.publish(encode_config(self.config)) 104 105 return self.config
106
107 - def _calc_level(self, config1, config2):
108 level = 0 109 for param in extract_params(self.type.config_description): 110 if config1[param['name']] != config2[param['name']]: 111 level |= param['level'] 112 113 return level
114
115 - def _clamp(self, config):
116 for param in extract_params(self.type.config_description): 117 maxval = self.type.max[param['name']] 118 minval = self.type.min[param['name']] 119 val = config[param['name']] 120 if val > maxval and maxval != "": 121 config[param['name']] = maxval 122 elif val < minval and minval != "": 123 config[param['name']] = minval
124
125 - def _set_callback(self, req):
126 return encode_config(self.update_configuration(decode_config(req.config, self.type.config_description)))
127