Package rocon_gateway :: Module flipped_interface
[frames] | no frames]

Source Code for Module rocon_gateway.flipped_interface

  1  #!/usr/bin/env python 
  2  # 
  3  # License: BSD 
  4  #   https://raw.github.com/robotics-in-concert/rocon_multimaster/master/rocon_gateway/LICENSE 
  5  # 
  6   
  7  ############################################################################## 
  8  # Imports 
  9  ############################################################################## 
 10   
 11  import copy 
 12  import re 
 13  import rocon_utilities 
 14   
 15  # Local imports 
 16  import utils 
 17  import interactive_interface 
 18   
 19  ############################################################################## 
 20  # Flipped Interface 
 21  ############################################################################## 
 22   
 23   
24 -class FlippedInterface(interactive_interface.InteractiveInterface):
25 ''' 26 The flipped interface is the set of rules 27 (pubs/subs/services/actions) and rules controlling flips 28 to other gateways. 29 '''
30 - def __init__(self, firewall, default_rule_blacklist, default_rules, all_targets):
31 ''' 32 Initialises the flipped interface. 33 34 @param firewall : flag to prevent this gateway from accepting flips 35 @type Bool 36 @param default_rule_blacklist : used when in flip all mode 37 @type dictionary of gateway 38 @param default_rules : static rules to flip on startup 39 @type gateway_msgs.msg.RemoteRule[] 40 @param all_targets : static flip all targets to flip to on startup 41 @type string[] 42 43 ''' 44 interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets) 45 46 self.firewall = firewall 47 48 # Function aliases 49 self.flipped = self.active 50 self.flip_all = self.add_all 51 self.unflip_all = self.remove_all
52 53 ########################################################################## 54 # Monitoring 55 ########################################################################## 56
57 - def update(self, connections, remote_gateway_hub_index, unique_name):
58 ''' 59 Computes a new flipped interface and returns two dictionaries - 60 removed and newly added flips so the watcher thread can take 61 appropriate action (inform the remote gateways). 62 63 This is run in the watcher thread (warning: take care - other 64 additions come from ros service calls in different threads!) 65 66 @param connections : list of all the system state connections from the local master 67 @type connection type keyed dictionary of utils.Connection lists. 68 69 @param remote_gateway_hub_index : full gateway-hub database index to parse 70 @type gateway hash names keyed into a dic with a list of their hubs 71 72 @param unique_name : this gateway's unique hash name 73 @type string 74 75 @return new_flips, removed_flips (i.e. those that are no longer on the local master) 76 @rtype pair of connection type keyed dictionary of gateway_msgs.msg.Rule lists. 77 ''' 78 # SLOW, EASY METHOD 79 80 flipped = utils.create_empty_connection_type_dictionary() 81 new_flips = utils.create_empty_connection_type_dictionary() 82 removed_flips = utils.create_empty_connection_type_dictionary() 83 remote_gateways = remote_gateway_hub_index.keys() 84 diff = lambda l1, l2: [x for x in l1 if x not in l2] # diff of lists 85 self._lock.acquire() 86 # Prune locally cached flip list for flips that have lost their remotes, keep the rules though 87 for connection_type in utils.connection_types: 88 # flip.gateway is a hash name, so is the remote_gateways list 89 self.flipped[connection_type] = [flip for flip in self.flipped[connection_type] if flip.gateway in remote_gateways] 90 # Totally regenerate a new flipped interface, compare with old 91 for connection_type in connections: 92 for connection in connections[connection_type]: 93 flipped[connection_type].extend(self._generate_flips(connection.rule.type, connection.rule.name, connection.rule.node, remote_gateways, unique_name)) 94 new_flips[connection_type] = diff(flipped[connection_type], self.flipped[connection_type]) 95 removed_flips[connection_type] = diff(self.flipped[connection_type], flipped[connection_type]) 96 self.flipped = copy.deepcopy(flipped) 97 self._lock.release() 98 return new_flips, removed_flips
99 100 # OPTIMISED METHOD 101 # Keep old rule state and old flip rules/patterns around 102 # 103 # 1 - If flip rules/patterns disappeared [diff(old_rules,new_rules)] 104 # Check if the current flips are still valid 105 # If not all are, remove and unflip them 106 # 107 # 2 - If rules disappeared [diff(old_conns,new_conns)] 108 # If matching any in flipped, remove and unflip 109 # 110 # 3 - If flip rules/patterns appeared [diff(new_rules,old_rules)] 111 # parse all conns, if match found, flip 112 # 113 # 4 - If rules appeared [diff(new_conns,old_conns)] 114 # check for matches, if found, flou 115 # 116 # diff = lambda l1,l2: [x for x in l1 if x not in l2] # diff of lists 117 118 ########################################################################## 119 # Utility Methods 120 ########################################################################## 121
122 - def _generate_flips(self, connection_type, name, node, remote_gateways, unique_name):
123 ''' 124 Checks if a local rule (obtained from master.get_system_state) 125 is a suitable association with any of the rules or patterns. This can 126 return multiple matches, since the same local rule 127 properties can be multiply flipped to different remote gateways. 128 129 Used in the update() call above that is run in the watcher thread. 130 Note, don't need to lock here as the update() function takes care of it. 131 132 @param connection_type : rule type 133 @type str : string constant from gateway_msgs.msg.Rule 134 135 @param name : fully qualified topic, service or action name 136 @type str 137 138 @param node : ros node name (coming from master.get_system_state) 139 @type str 140 141 @param gateways : gateways that are available (registered on the hub) 142 @type string 143 144 @return all the flip rules that match this local rule 145 @return list of RemoteRule objects updated with node names from self.watchlist 146 ''' 147 matched_flip_rules = [] 148 for flip_rule in self.watchlist[connection_type]: 149 # Check if the flip rule corresponds to an existing gateway 150 matched_gateways = [] 151 for gateway in remote_gateways: 152 # check for regular expression or perfect match 153 gateway_match_result = re.match(flip_rule.gateway, gateway) 154 if gateway_match_result and gateway_match_result.group() == gateway: 155 matched_gateways.append(gateway) 156 elif flip_rule.gateway == rocon_utilities.gateway_basename(gateway): 157 matched_gateways.append(gateway) 158 if not matched_gateways: 159 continue 160 161 # Check names 162 rule_name = flip_rule.rule.name 163 matched = self.is_matched(flip_rule, rule_name, name, node) 164 165 if not utils.is_all_pattern(flip_rule.rule.name): 166 if not matched: 167 rule_name = '/' + unique_name + '/' + flip_rule.rule.name 168 matched = self.is_matched(flip_rule, rule_name, name, node) 169 170 if not matched: 171 rule_name = '/' + flip_rule.rule.name 172 matched = self.is_matched(flip_rule, rule_name, name, node) 173 174 if matched: 175 for gateway in matched_gateways: 176 matched_flip = copy.deepcopy(flip_rule) 177 matched_flip.gateway = gateway # just in case we used a regex or matched basename 178 matched_flip.rule.name = name # just in case we used a regex 179 matched_flip.rule.node = node # just in case we used a regex 180 matched_flip_rules.append(matched_flip) 181 182 return matched_flip_rules
183 184 ########################################################################## 185 # Accessors for Gateway Info 186 ########################################################################## 187
188 - def get_flipped_connections(self):
189 ''' 190 Gets the flipped connections list for GatewayInfo consumption. 191 192 @return the list of flip rules that are activated and have been flipped. 193 @rtype RemoteRule[] 194 ''' 195 flipped_connections = [] 196 for connection_type in utils.connection_types: 197 flipped_connections.extend(copy.deepcopy(self.flipped[connection_type])) 198 return flipped_connections
199 200 201 if __name__ == "__main__": 202 203 gateways = ['dude', 'dudette'] 204 dudes = ['fred', 'dude'] 205 dudes[:] = [x for x in dudes if x in gateways] 206 print dudes 207