pulled_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/license/LICENSE
00005 #
00006 
00007 ##############################################################################
00008 # Imports
00009 ##############################################################################
00010 
00011 import copy
00012 import re
00013 import rocon_gateway_utils
00014 
00015 from . import utils
00016 from . import interactive_interface
00017 
00018 ##############################################################################
00019 # Pulled Interface
00020 ##############################################################################
00021 
00022 
00023 class PulledInterface(interactive_interface.InteractiveInterface):
00024 
00025     '''
00026       The pulled interface is the set of rules
00027       (pubs/subs/services/actions) and rules controlling pulls from
00028       other gateways.
00029     '''
00030 
00031     def __init__(self, default_rule_blacklist, default_rules, all_targets):
00032         '''
00033           Initialises the pulled interface.
00034 
00035           @param default_rule_blacklist : used when in flip all mode
00036           @type dictionary of gateway
00037           @param default_rules : static rules to pull on startup
00038           @type gateway_msgs.msg.RemoteRule[]
00039           @param all_targets : static pull all targets to pull to on startup
00040           @type string[]
00041         '''
00042         interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets)
00043 
00044         # Function aliases
00045         self.pulled = self.active
00046         self.pull_all = self.add_all
00047         self.unpull_all = self.remove_all
00048 
00049     def update(self, remote_connections, unique_name):
00050         '''
00051           Computes a new pulled interface from the incoming connections list
00052            and returns two dictionaries -
00053           removed and newly added pulls so the watcher thread can take
00054           appropriate action ((un)registrations).
00055 
00056           This is run in the watcher thread (warning: take care - other
00057           additions come from ros service calls in different threads!)
00058 
00059           @param remote_gateway_hub_index : full gateway-hub database index to parse
00060           @type gateway hash names keyed into a dic with a list of their hubs
00061         '''
00062         # SLOW, EASY METHOD
00063         #   Totally regenerate a new pulled interface, compare with old
00064         pulled = utils.create_empty_connection_type_dictionary()
00065         new_pulls = utils.create_empty_connection_type_dictionary()
00066         removed_pulls = utils.create_empty_connection_type_dictionary()
00067 
00068         self._lock.acquire()
00069         # Totally regenerate a new pulled interface, compare with old
00070         for remote_gateway in remote_connections.keys():
00071             connections = remote_connections[remote_gateway]
00072             for connection_type in connections:
00073                 for connection in connections[connection_type]:
00074                     pulled[connection_type].extend(
00075                         self._generate_pulls(
00076                             connection.rule.type,
00077                             connection.rule.name,
00078                             connection.rule.node,
00079                             remote_gateway,
00080                             unique_name))
00081         for connection_type in utils.connection_types:
00082             new_pulls[connection_type] = utils.difflist(pulled[connection_type], self.pulled[connection_type])
00083             removed_pulls[connection_type] = utils.difflist(self.pulled[connection_type], pulled[connection_type])
00084         self.pulled = copy.deepcopy(pulled)
00085         self._lock.release()
00086         return new_pulls, removed_pulls
00087 
00088         # OPTIMISED METHOD
00089         #   Keep old rule state and old flip rules/patterns around
00090         #
00091         #   1 - If flip rules/patterns disappeared [diff(old_rules,new_rules)]
00092         #         Check if the current flips are still valid
00093         #         If not all are, remove and unflip them
00094         #
00095         #   2 - If rules disappeared [diff(old_conns,new_conns)]
00096         #         If matching any in pulled, remove and unflip
00097         #
00098         #   3 - If flip rules/patterns appeared [diff(new_rules,old_rules)]
00099         #         parse all conns, if match found, flip
00100         #
00101         #   4 - If rules appeared [diff(new_conns,old_conns)]
00102         #         check for matches, if found, flou
00103         #
00104         # difflist = lambda l1,l2: [x for x in l1 if x not in l2] # diff of lists
00105 
00106     ##########################################################################
00107     # Utility Methods
00108     ##########################################################################
00109 
00110     def _generate_pulls(self, connection_type, name, node, gateway, unique_name):
00111         '''
00112           Checks if a local rule (obtained from master.get_system_state)
00113           is a suitable association with any of the rules or patterns. This can
00114           return multiple matches, since the same local rule
00115           properties can be multiply pulled to different remote gateways.
00116 
00117           Used in the update() call above that is run in the watcher thread.
00118 
00119           Note, don't need to lock here as the update() function takes care of it.
00120 
00121           @param connection_type : rule type
00122           @type str : string constant from gateway_msgs.Rule
00123 
00124           @param name : fully qualified topic, service or action name
00125           @type str
00126 
00127           @param node : ros node name (coming from master.get_system_state)
00128           @type str
00129 
00130           @param gateway : remote gateway hash name.
00131           @type str
00132 
00133           @return all the pull rules that match this local rule
00134           @return list of RemoteRule objects updated with node names from self.watchlist
00135         '''
00136         matched_pull_rules = []
00137         for rule in self.watchlist[connection_type]:
00138             # check for regular expression or perfect match
00139             gateway_match_result = re.match(rule.gateway, gateway)
00140             matched = False
00141             if gateway_match_result and gateway_match_result.group() == gateway:
00142                 matched = True
00143             elif rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
00144                 matched = True
00145             if not matched:
00146                 continue
00147 
00148             # Check names
00149             rule_name = rule.rule.name
00150             matched = self.is_matched(rule, rule_name, name, node)
00151             if not matched:
00152                 rule_name = '/' + unique_name + '/' + rule.rule.name
00153                 matched = self.is_matched(rule, rule_name, name, node)
00154 
00155             if not matched:
00156                 rule_name = '/' + rule.rule.name
00157                 matched = self.is_matched(rule, rule_name, name, node)
00158 
00159             if matched:
00160                 matched_pull = copy.deepcopy(rule)
00161                 matched_pull.gateway = gateway  # just in case we used a regex or matched basename
00162                 matched_pull.rule.name = name   # just in case we used a regex
00163                 matched_pull.rule.node = node   # just in case we used a regex
00164                 matched_pull_rules.append(matched_pull)
00165         return matched_pull_rules
00166 
00167     ##########################################################################
00168     # Pulled Interface Specific Methods
00169     ##########################################################################
00170 
00171     def list_remote_gateway_names(self):
00172         '''
00173           Collects all gateways that it should watch for (i.e. those
00174           currently handled by existing registrations).
00175 
00176           @return set of gateway string ids
00177           @rtype set of string
00178         '''
00179         gateways = []
00180         for connection_type in utils.connection_types:
00181             for registration in self.registrations[connection_type]:
00182                 if registration.remote_gateway not in gateways:
00183                     gateways.append(registration.remote_gateway)
00184         return gateways


rocon_gateway
Author(s): Daniel Stonier , Jihoon Lee , Piyush Khandelwal
autogenerated on Sat Jun 8 2019 18:48:44