Swarm-SLAM  1.0.0
C-SLAM Framework
neighbors_manager.py
Go to the documentation of this file.
1 from cslam.neighbor_monitor import NeighborMonitor
2 from cslam_common_interfaces.msg import RobotIdsAndOrigin
3 from std_msgs.msg import String
4 
5 import rclpy
6 
7 
9  """Manage neighbors to keep track of which other robots are in communication range
10  """
11  def __init__(self, node, params):
12  self.nodenode = node
13  self.paramsparams = params
14  self.robot_idrobot_id = self.paramsparams['robot_id']
15  self.max_nb_robotsmax_nb_robots = self.paramsparams['max_nb_robots']
16  self.neighbors_monitorsneighbors_monitors = {}
17  for rid in range(self.max_nb_robotsmax_nb_robots):
18  if rid != self.robot_idrobot_id:
19  self.neighbors_monitorsneighbors_monitors[rid] = NeighborMonitor(
20  self.nodenode, rid, self.
21  params['neighbor_management.enable_neighbor_monitoring'],
22  self.paramsparams['neighbor_management.init_delay_sec'],
23  self.paramsparams['neighbor_management.max_heartbeat_delay_sec'])
24 
25  self.subscribersubscriber = self.nodenode.create_subscription(
26  String, 'cslam/get_current_neighbors',
27  self.get_current_neighbors_callbackget_current_neighbors_callback, 100)
28  self.neighbors_publisherneighbors_publisher = self.nodenode.create_publisher(
29  RobotIdsAndOrigin, 'cslam/current_neighbors', 100)
30 
32  """Check which neighbors are in range
33 
34  """
35  is_robot_in_range = {}
36  robots_in_range_list = []
37  for i in range(self.max_nb_robotsmax_nb_robots):
38  if i == self.robot_idrobot_id:
39  is_robot_in_range[i] = True
40  robots_in_range_list.append(i)
41  elif self.neighbors_monitorsneighbors_monitors[i].is_alive():
42  is_robot_in_range[i] = True
43  robots_in_range_list.append(i)
44  else:
45  is_robot_in_range[i] = False
46  return is_robot_in_range, robots_in_range_list
47 
49  """This method check if the local robot (that runs this node), is the
50  default broker based on its current neighbors.
51 
52  Returns:
53  bool: is the local robot the default broker
54  among the robots in range
55  """
56  is_broker = True
57  for i in range(self.max_nb_robotsmax_nb_robots):
58  if i != self.robot_idrobot_id and self.neighbors_monitorsneighbors_monitors[i].is_alive():
59  # Note: This is an arbitrary condition that selects the
60  # lowest ID alive as broker. Could be change to any other cond.
61  # (e.g., selecting the robot with the most computing power)
62  if self.robot_idrobot_id > i:
63  is_broker = False
64  return is_broker
65 
66  def select_from_which_kf_to_send(self, latest_local_id):
67  """This function finds the range of descriptors to send
68  so that we do not loose info
69  """
70 
71  from_kf_id = latest_local_id
72  for i in range(self.max_nb_robotsmax_nb_robots):
73  if i != self.robot_idrobot_id:
74  if self.neighbors_monitorsneighbors_monitors[i].is_alive():
75  from_kf_id = min(
76  self.neighbors_monitorsneighbors_monitors[i].last_keyframe_sent,
77  from_kf_id)
78 
79  for i in range(self.max_nb_robotsmax_nb_robots):
80  if i != self.robot_idrobot_id:
81  if self.neighbors_monitorsneighbors_monitors[i].is_alive():
82  self.neighbors_monitorsneighbors_monitors[
83  i].last_keyframe_sent = latest_local_id
84 
85  return from_kf_id + 1
86 
87  def select_from_which_match_to_send(self, latest_local_match_idx):
88  """This function finds the range of matches to send
89  so that we do not loose info
90  """
91 
92  from_match_id = latest_local_match_idx
93  for i in range(self.max_nb_robotsmax_nb_robots):
94  if i != self.robot_idrobot_id:
95  if self.neighbors_monitorsneighbors_monitors[i].is_alive():
96  from_match_id = min(
97  self.neighbors_monitorsneighbors_monitors[i].last_match_sent,
98  from_match_id)
99 
100  for i in range(self.max_nb_robotsmax_nb_robots):
101  if i != self.robot_idrobot_id:
102  if self.neighbors_monitorsneighbors_monitors[i].is_alive():
103  self.neighbors_monitorsneighbors_monitors[
104  i].last_match_sent = latest_local_match_idx
105 
106  return from_match_id + 1
107 
108  def useless_descriptors(self, last_kf_id):
109  """Determines which descriptors are not useless and can be deleted
110 
111  Args:
112  last_kf_id (int): last keyframe id in the list of descriptors
113  Returns:
114  int: the id of the first descriptor that is not useless
115  """
116  from_kf_id = last_kf_id
117  for i in range(self.max_nb_robotsmax_nb_robots):
118  if i != self.robot_idrobot_id:
119  from_kf_id = min(self.neighbors_monitorsneighbors_monitors[i].last_keyframe_sent,
120  from_kf_id)
121  return from_kf_id
122 
123  def useless_matches(self, last_match_id):
124  """Determines which matches are not useless and can be deleted
125 
126  Args:
127  last_match_id (int): last match id in the list of matches
128  Returns:
129  int: the id of the first match that is not useless
130  """
131  from_match_id = last_match_id
132  for i in range(self.max_nb_robotsmax_nb_robots):
133  if i != self.robot_idrobot_id:
134  from_match_id = min(self.neighbors_monitorsneighbors_monitors[i].last_match_sent,
135  from_match_id)
136  return from_match_id
137 
138  def update_received_kf_id(self, other_robot_id, kf_id):
139  """Keep monitors up to date with received keyframes
140 
141  Args:
142  other_robot_id (int): other robot id
143  kf_id (int): keyframe id
144  """
145  self.neighbors_monitorsneighbors_monitors[other_robot_id].last_keyframe_received = kf_id
146 
147  def get_unknown_range(self, descriptors):
148  """_summary_
149 
150  Args:
151  descriptors (list): list of descriptors with ids info
152 
153  Returns:
154  range: indexes in list to process
155  """
156  other_robot_id = descriptors[0].robot_id
157  kf_ids = [d.keyframe_id for d in descriptors]
158  last_id = max(kf_ids)
159 
160  list_index_range = [
161  i for i in range(len(descriptors)) if descriptors[i].keyframe_id >
162  self.neighbors_monitorsneighbors_monitors[other_robot_id].last_keyframe_received
163  ]
164 
165  self.update_received_kf_idupdate_received_kf_id(
166  other_robot_id,
167  max(self.neighbors_monitorsneighbors_monitors[other_robot_id].last_keyframe_received,
168  last_id))
169  return list_index_range
170 
172  """Publish the current neighbors in range
173 
174  Args:
175  msg (String): Empty
176  """
177  is_robot_in_range, robots_in_range_list = self.check_neighbors_in_rangecheck_neighbors_in_range(
178  )
179  robots_in_range_list.remove(self.robot_idrobot_id)
180  msg = RobotIdsAndOrigin()
181  msg.robots.ids = robots_in_range_list
182  for i in robots_in_range_list:
183  msg.origins.ids.append(self.neighbors_monitorsneighbors_monitors[i].origin_robot_id)
184 
185  self.neighbors_publisherneighbors_publisher.publish(msg)
def select_from_which_kf_to_send(self, latest_local_id)
def update_received_kf_id(self, other_robot_id, kf_id)
def select_from_which_match_to_send(self, latest_local_match_idx)