pulled_interface.py
Go to the documentation of this file.
1 #!/usr/bin/env python
2 #
3 # License: BSD
4 # https://raw.github.com/robotics-in-concert/rocon_multimaster/license/LICENSE
5 #
6 
7 ##############################################################################
8 # Imports
9 ##############################################################################
10 
11 import copy
12 import re
13 import rocon_gateway_utils
14 
15 from . import utils
16 from . import interactive_interface
17 
18 ##############################################################################
19 # Pulled Interface
20 ##############################################################################
21 
22 
24 
25  '''
26  The pulled interface is the set of rules
27  (pubs/subs/services/actions) and rules controlling pulls from
28  other gateways.
29  '''
30 
31  def __init__(self, default_rule_blacklist, default_rules, all_targets):
32  '''
33  Initialises the pulled interface.
34 
35  @param default_rule_blacklist : used when in flip all mode
36  @type dictionary of gateway
37  @param default_rules : static rules to pull on startup
38  @type gateway_msgs.msg.RemoteRule[]
39  @param all_targets : static pull all targets to pull to on startup
40  @type string[]
41  '''
42  interactive_interface.InteractiveInterface.__init__(self, default_rule_blacklist, default_rules, all_targets)
43 
44  # Function aliases
45  self.pulled = self.active
46  self.pull_all = self.add_all
47  self.unpull_all = self.remove_all
48 
49  def update(self, remote_connections, unique_name):
50  '''
51  Computes a new pulled interface from the incoming connections list
52  and returns two dictionaries -
53  removed and newly added pulls so the watcher thread can take
54  appropriate action ((un)registrations).
55 
56  This is run in the watcher thread (warning: take care - other
57  additions come from ros service calls in different threads!)
58 
59  @param remote_gateway_hub_index : full gateway-hub database index to parse
60  @type gateway hash names keyed into a dic with a list of their hubs
61  '''
62  # SLOW, EASY METHOD
63  # Totally regenerate a new pulled interface, compare with old
64  pulled = utils.create_empty_connection_type_dictionary()
65  new_pulls = utils.create_empty_connection_type_dictionary()
66  removed_pulls = utils.create_empty_connection_type_dictionary()
67 
68  self._lock.acquire()
69  # Totally regenerate a new pulled interface, compare with old
70  for remote_gateway in remote_connections.keys():
71  connections = remote_connections[remote_gateway]
72  for connection_type in connections:
73  for connection in connections[connection_type]:
74  pulled[connection_type].extend(
75  self._generate_pulls(
76  connection.rule.type,
77  connection.rule.name,
78  connection.rule.node,
79  remote_gateway,
80  unique_name))
81  for connection_type in utils.connection_types:
82  new_pulls[connection_type] = utils.difflist(pulled[connection_type], self.pulled[connection_type])
83  removed_pulls[connection_type] = utils.difflist(self.pulled[connection_type], pulled[connection_type])
84  self.pulled = copy.deepcopy(pulled)
85  self._lock.release()
86  return new_pulls, removed_pulls
87 
88  # OPTIMISED METHOD
89  # Keep old rule state and old flip rules/patterns around
90  #
91  # 1 - If flip rules/patterns disappeared [diff(old_rules,new_rules)]
92  # Check if the current flips are still valid
93  # If not all are, remove and unflip them
94  #
95  # 2 - If rules disappeared [diff(old_conns,new_conns)]
96  # If matching any in pulled, remove and unflip
97  #
98  # 3 - If flip rules/patterns appeared [diff(new_rules,old_rules)]
99  # parse all conns, if match found, flip
100  #
101  # 4 - If rules appeared [diff(new_conns,old_conns)]
102  # check for matches, if found, flou
103  #
104  # difflist = lambda l1,l2: [x for x in l1 if x not in l2] # diff of lists
105 
106  ##########################################################################
107  # Utility Methods
108  ##########################################################################
109 
110  def _generate_pulls(self, connection_type, name, node, gateway, unique_name):
111  '''
112  Checks if a local rule (obtained from master.get_system_state)
113  is a suitable association with any of the rules or patterns. This can
114  return multiple matches, since the same local rule
115  properties can be multiply pulled to different remote gateways.
116 
117  Used in the update() call above that is run in the watcher thread.
118 
119  Note, don't need to lock here as the update() function takes care of it.
120 
121  @param connection_type : rule type
122  @type str : string constant from gateway_msgs.Rule
123 
124  @param name : fully qualified topic, service or action name
125  @type str
126 
127  @param node : ros node name (coming from master.get_system_state)
128  @type str
129 
130  @param gateway : remote gateway hash name.
131  @type str
132 
133  @return all the pull rules that match this local rule
134  @return list of RemoteRule objects updated with node names from self.watchlist
135  '''
136  matched_pull_rules = []
137  for rule in self.watchlist[connection_type]:
138  # check for regular expression or perfect match
139  gateway_match_result = re.match(rule.gateway, gateway)
140  matched = False
141  if gateway_match_result and gateway_match_result.group() == gateway:
142  matched = True
143  elif rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
144  matched = True
145  if not matched:
146  continue
147 
148  # Check names
149  rule_name = rule.rule.name
150  matched = self.is_matched(rule, rule_name, name, node)
151  if not matched:
152  rule_name = '/' + unique_name + '/' + rule.rule.name
153  matched = self.is_matched(rule, rule_name, name, node)
154 
155  if not matched:
156  rule_name = '/' + rule.rule.name
157  matched = self.is_matched(rule, rule_name, name, node)
158 
159  if matched:
160  matched_pull = copy.deepcopy(rule)
161  matched_pull.gateway = gateway # just in case we used a regex or matched basename
162  matched_pull.rule.name = name # just in case we used a regex
163  matched_pull.rule.node = node # just in case we used a regex
164  matched_pull_rules.append(matched_pull)
165  return matched_pull_rules
166 
167  ##########################################################################
168  # Pulled Interface Specific Methods
169  ##########################################################################
170 
172  '''
173  Collects all gateways that it should watch for (i.e. those
174  currently handled by existing registrations).
175 
176  @return set of gateway string ids
177  @rtype set of string
178  '''
179  gateways = []
180  for connection_type in utils.connection_types:
181  for registration in self.registrations[connection_type]:
182  if registration.remote_gateway not in gateways:
183  gateways.append(registration.remote_gateway)
184  return gateways
def is_matched(self, rule, rule_name, name, node)
Accessors for Gateway Info.
def list_remote_gateway_names(self)
Pulled Interface Specific Methods.
def __init__(self, default_rule_blacklist, default_rules, all_targets)
def update(self, remote_connections, unique_name)
def _generate_pulls(self, connection_type, name, node, gateway, unique_name)
Utility Methods.


rocon_gateway
Author(s): Daniel Stonier , Jihoon Lee , Piyush Khandelwal
autogenerated on Mon Jun 10 2019 14:40:10