flipped_interface.py
Go to the documentation of this file.
00001 #!/usr/bin/env python
00002 #
00003 # License: BSD
00004 #   https://raw.github.com/robotics-in-concert/rocon_multimaster/master/rocon_gateway/LICENSE
00005 #
00006 
00007 ##############################################################################
00008 # Imports
00009 ##############################################################################
00010 
00011 import roslib
00012 roslib.load_manifest('rocon_gateway')
00013 from gateway_msgs.msg import Rule, RemoteRule, ConnectionType
00014 import copy
00015 import re
00016 
00017 # Local imports
00018 import utils
00019 import interactive_interface
00020 
00021 ##############################################################################
00022 # Flipped Interface
00023 ##############################################################################
00024 
00025 
00026 class FlippedInterface(interactive_interface.InteractiveInterface):
00027     '''
00028       The flipped interface is the set of rules
00029       (pubs/subs/services/actions) and rules controlling flips
00030       to other gateways.
00031     '''
00032     def __init__(self, firewall, default_rule_blacklist, default_rules, all_targets):
00033         '''
00034           Initialises the flipped interface.
00035 
00036           @param firewall : flag to prevent this gateway from accepting flips
00037           @type Bool
00038           @param default_rule_blacklist : used when in flip all mode
00039           @type dictionary of gateway
00040           @param default_rules : static rules to flip on startup
00041           @type gateway_msgs.msg.RemoteRule[]
00042           @param all_targets : static flip all targets to flip to on startup
00043           @type string[]
00044 
00045         '''
00046         interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets)
00047 
00048         self.firewall = firewall
00049 
00050         # Function aliases
00051         self.flipped = self.active
00052         self.flip_all = self.add_all
00053         self.unflip_all = self.remove_all
00054 
00055     ##########################################################################
00056     # Monitoring
00057     ##########################################################################
00058 
00059     def update(self, connections, gateways,unique_name):
00060         '''
00061           Computes a new flipped interface and returns two dictionaries -
00062           removed and newly added flips so the watcher thread can take
00063           appropriate action (inform the remote gateways).
00064 
00065           This is run in the watcher thread (warning: take care - other
00066           additions come from ros service calls in different threads!)
00067 
00068           @param connections : list of all the system state connections from the local master
00069           @type connection type keyed dictionary of utils.Connection lists.
00070 
00071           @param gateways : gateways that are available (registered on the hub)
00072           @type string
00073 
00074           @return new_flips, old_flips
00075           @rtype pair of connection type keyed dictionary of gateway_msgs.msg.Rule lists.
00076         '''
00077         # SLOW, EASY METHOD
00078 
00079         flipped = utils.createEmptyConnectionTypeDictionary()
00080         new_flips = utils.createEmptyConnectionTypeDictionary()
00081         removed_flips = utils.createEmptyConnectionTypeDictionary()
00082         diff = lambda l1,l2: [x for x in l1 if x not in l2]  # diff of lists
00083         self._lock.acquire()
00084         # Prune flips that are not in the gateway list anymore, keep the rules though
00085         for connection_type in utils.connection_types:
00086             self.flipped[connection_type] = [flip for flip in self.flipped[connection_type] if flip.gateway in gateways]
00087         # Totally regenerate a new flipped interface, compare with old
00088         for connection_type in connections:
00089             for connection in connections[connection_type]:
00090                 flipped[connection_type].extend(self._generate_flips(connection.rule.type, connection.rule.name, connection.rule.node, gateways,unique_name))
00091             new_flips[connection_type] = diff(flipped[connection_type],self.flipped[connection_type])
00092             removed_flips[connection_type] = diff(self.flipped[connection_type],flipped[connection_type])
00093         self.flipped = copy.deepcopy(flipped)
00094         self._lock.release()
00095         return new_flips, removed_flips
00096         
00097         # OPTIMISED METHOD
00098         #   Keep old rule state and old flip rules/patterns around
00099         #
00100         #   1 - If flip rules/patterns disappeared [diff(old_rules,new_rules)]
00101         #         Check if the current flips are still valid
00102         #         If not all are, remove and unflip them
00103         #
00104         #   2 - If rules disappeared [diff(old_conns,new_conns)]
00105         #         If matching any in flipped, remove and unflip
00106         #
00107         #   3 - If flip rules/patterns appeared [diff(new_rules,old_rules)]
00108         #         parse all conns, if match found, flip
00109         #
00110         #   4 - If rules appeared [diff(new_conns,old_conns)]
00111         #         check for matches, if found, flou
00112         #
00113         # diff = lambda l1,l2: [x for x in l1 if x not in l2] # diff of lists
00114 
00115     ##########################################################################
00116     # Utility Methods
00117     ##########################################################################
00118 
00119         
00120     def _generate_flips(self, type, name, node, gateways,unique_name):
00121         '''
00122           Checks if a local rule (obtained from master.getSystemState) 
00123           is a suitable association with any of the rules or patterns. This can
00124           return multiple matches, since the same local rule 
00125           properties can be multiply flipped to different remote gateways.
00126             
00127           Used in the update() call above that is run in the watcher thread.
00128           Note, don't need to lock here as the update() function takes care of it.
00129           
00130           @param type : rule type
00131           @type str : string constant from gateway_msgs.msg.Rule
00132           
00133           @param name : fully qualified topic, service or action name
00134           @type str
00135           
00136           @param node : ros node name (coming from master.getSystemState)
00137           @type str
00138 
00139           @param gateways : gateways that are available (registered on the hub)
00140           @type string
00141           
00142           @return all the flip rules that match this local rule
00143           @return list of RemoteRule objects updated with node names from self.watchlist
00144         '''
00145         matched_flip_rules = []
00146         for flip_rule in self.watchlist[type]:
00147             # Check if the flip rule corresponds to an existing gateway
00148             matched_gateways = []
00149             for gateway in gateways:
00150                 if re.match(flip_rule.gateway, gateway):
00151                     matched_gateways.append(gateway)
00152             if not matched_gateways:
00153                 continue
00154 
00155             # Check names
00156             rule_name = flip_rule.rule.name
00157             matched = self.is_matched(flip_rule,rule_name,name,node)
00158 
00159             if not matched:
00160                 rule_name = '/' + unique_name + '/' + flip_rule.rule.name
00161                 matched = self.is_matched(flip_rule,rule_name,name,node)
00162 
00163             if not matched: 
00164                 rule_name = '/' + flip_rule.rule.name
00165                 matched = self.is_matched(flip_rule,rule_name,name,node)
00166 
00167             if matched:
00168                 for gateway in matched_gateways:
00169                     matched_flip = copy.deepcopy(flip_rule)
00170                     matched_flip.gateway = gateway # just in case we used a regex
00171                     matched_flip.rule.name = name  # just in case we used a regex
00172                     matched_flip.rule.node = node  # just in case we used a regex
00173                     matched_flip_rules.append(matched_flip)
00174         return matched_flip_rules
00175     
00176     ##########################################################################
00177     # Accessors for Gateway Info
00178     ##########################################################################
00179 
00180     def get_flipped_connections(self):
00181         '''
00182           Gets the flipped connections list for GatewayInfo consumption.
00183           
00184           @return the list of flip rules that are activated and have been flipped.
00185           @rtype RemoteRule[]
00186         '''
00187         flipped_connections = []
00188         for connection_type in utils.connection_types:
00189             flipped_connections.extend(copy.deepcopy(self.flipped[connection_type]))
00190         return flipped_connections
00191     
00192     
00193 if __name__ == "__main__":
00194     
00195     gateways = ['dude','dudette']
00196     dudes = ['fred', 'dude']
00197     dudes[:] = [x for x in dudes if x in gateways]
00198     print dudes
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Properties Friends


rocon_gateway
Author(s): Daniel Stonier, Jihoon Lee,
autogenerated on Tue Jan 15 2013 17:43:24