Swarm-SLAM  1.0.0
C-SLAM Framework
test_sparse_matching.py
Go to the documentation of this file.
1 import unittest
2 
3 from cslam.loop_closure_sparse_matching import LoopClosureSparseMatching
4 from cslam.nns_matching import NearestNeighborsMatching
5 import random
6 import numpy as np
7 from collections import namedtuple
8 
9 GlobalDescriptor = namedtuple('GlobalDescriptor',
10  ['keyframe_id', 'robot_id', 'descriptor'])
11 
12 def set_params():
13  params = {}
14  params['robot_id'] = 0
15  params['max_nb_robots'] = 2
16  params['frontend.sensor_type'] = 'stereo'
17  params['frontend.similarity_threshold'] = 0.0
18  params["frontend.enable_sparsification"] = True
19  params["evaluation.enable_sparsification_comparison"] = False
20  return params
21 
22 
23 class TestSparseMatching(unittest.TestCase):
24  """Unit tests for sparse matching
25  """
26 
28  """Add local keyframe
29  """
30  params = set_params()
31  lcsm = LoopClosureSparseMatching(params)
32  descriptor = np.random.rand(10)
33  descriptor = descriptor / np.linalg.norm(descriptor)
34  lcsm.add_local_global_descriptor(descriptor, 1)
35  for i in range(len(descriptor)):
36  self.assertAlmostEqual(descriptor[i], lcsm.local_nnsm.data[0, i])
37 
39  """Add other robot keyframe
40  """
41  params = set_params()
42  lcsm = LoopClosureSparseMatching(params)
43  descriptor = np.random.rand(10)
44  descriptor = descriptor / np.linalg.norm(descriptor)
45  msg = GlobalDescriptor(0, 1, descriptor.tolist())
46  lcsm.add_other_robot_global_descriptor(msg)
47  for i in range(len(descriptor)):
48  self.assertAlmostEqual(descriptor[i],
49  lcsm.other_robots_nnsm[1].data[0, i])
50 
51  def test_similarity(self):
52  """Test that cosine similarity matching gives the same ordering as euclidean distance
53  """
54  nb_descriptors_in_db = 100
56  for i in range(nb_descriptors_in_db):
57  descriptor = np.random.rand(100)
58  descriptor = descriptor / np.linalg.norm(descriptor) # normalize
59  nnsm.add_item(descriptor, i)
60 
61  nb_descriptors_to_test = 100
62  k = 100
63  for i in range(nb_descriptors_to_test):
64  query = np.random.rand(100)
65  query = query / np.linalg.norm(query)
66  ds = np.linalg.norm(query[np.newaxis, :] - nnsm.data[:nnsm.n], axis=1)
67  ns_dist = np.argsort(ds)[:k]
68  ns_sim, sims = nnsm.search(query, k)
69  # Check if sorted by similarity
70  self.assertTrue(np.all(sims[:-1] >= sims[1:]))
71  # Check if same order as distance
72  for j in range(k):
73  id_d = ns_dist[j]
74  id_s = ns_sim[j]
75  if (id_d != id_s):
76  # If the distance or similarity are the same than the order does not matter.
77  if (abs(sims[id_d] - sims[id_s]) < 1e-6) or (abs(ds[id_d] - ds[id_s]) < 1e-6):
78  continue
79  self.assertEqual(ns_dist[j], ns_sim[j])
80  ns_sim_best, sim_best = nnsm.search_best(query)
81  self.assertEqual(ns_dist[0], ns_sim_best)
82 
83  def test_matches(self):
84  """Matches between descriptors
85  """
86  params = set_params()
87  lcsm = LoopClosureSparseMatching(params)
88 
89  descriptor0 = np.random.rand(10)
90  descriptor0 = descriptor0 / np.linalg.norm(descriptor0)
91  lcsm.add_local_global_descriptor(descriptor0, 2)
92 
93  descriptor1 = 1 - descriptor0
94  descriptor1 = descriptor1 / np.linalg.norm(descriptor1)
95  msg = GlobalDescriptor(3, 1, descriptor1.tolist())
96  lcsm.add_other_robot_global_descriptor(msg)
97 
98  descriptor2 = descriptor0
99  descriptor2[0] = 0.0
100  descriptor2[1] = 0.0
101  descriptor2 = descriptor2 / np.linalg.norm(descriptor2)
102  msg2 = GlobalDescriptor(4, 1, descriptor2.tolist())
103  lcsm.add_other_robot_global_descriptor(msg2)
104 
105  id = lcsm.candidate_selector.candidate_edges[(0, 2, 1, 4)].robot1_id
106  best_match_descriptor = lcsm.other_robots_nnsm[id].data[0]
107  for i in range(len(descriptor1)):
108  self.assertAlmostEqual(descriptor1[i], best_match_descriptor[i])
109 
111  """Select candidates
112  """
113  params = set_params()
114  params['max_nb_robots'] = 3
115  lcsm = LoopClosureSparseMatching(params)
116 
117  nb_local_kfs = 100
118  for i in range(nb_local_kfs):
119  descriptor = np.random.rand(10)
120  descriptor = descriptor / np.linalg.norm(descriptor)
121  lcsm.add_local_global_descriptor(descriptor, i)
122  nb_other_kfs = 100
123  for i in range(nb_other_kfs):
124  descriptor = np.random.rand(10)
125  descriptor = descriptor / np.linalg.norm(descriptor)
126  msg = GlobalDescriptor(i, 1, descriptor.tolist())
127  lcsm.add_other_robot_global_descriptor(msg)
128  for i in range(nb_other_kfs):
129  descriptor = np.random.rand(10)
130  descriptor = descriptor / np.linalg.norm(descriptor)
131  msg = GlobalDescriptor(i, 2, descriptor.tolist())
132  lcsm.add_other_robot_global_descriptor(msg)
133 
134  nb_candidates = 20
135  is_robot_considered = {}
136  for i in range(params['max_nb_robots']):
137  is_robot_considered[i] = True
138  selection = lcsm.select_candidates(nb_candidates, is_robot_considered)
139  self.assertEqual(len(selection), nb_candidates)
140 
142  """Select candidates
143  No robot 1 in range
144  """
145  params = set_params()
146  params['max_nb_robots'] = 4
147  lcsm = LoopClosureSparseMatching(params)
148 
149  nb_local_kfs = 100
150  for i in range(nb_local_kfs):
151  descriptor = np.random.rand(10)
152  descriptor = descriptor / np.linalg.norm(descriptor)
153  lcsm.add_local_global_descriptor(descriptor, i)
154  nb_other_kfs = 100
155  for i in range(nb_other_kfs):
156  descriptor = np.random.rand(10)
157  descriptor = descriptor / np.linalg.norm(descriptor)
158  msg = GlobalDescriptor(i, 2, descriptor.tolist())
159  lcsm.add_other_robot_global_descriptor(msg)
160  for i in range(nb_other_kfs):
161  descriptor = np.random.rand(10)
162  descriptor = descriptor / np.linalg.norm(descriptor)
163  msg = GlobalDescriptor(i, 3, descriptor.tolist())
164  lcsm.add_other_robot_global_descriptor(msg)
165 
166  nb_candidates = 20
167 
168  is_robot_considered = {}
169  for i in range(params['max_nb_robots']):
170  is_robot_considered[i] = True
171  selection = lcsm.select_candidates(nb_candidates, is_robot_considered)
172  self.assertEqual(len(selection), nb_candidates)
173 
175  """Select candidates
176  No robot 0 in range
177  """
178  params = set_params()
179  params['max_nb_robots'] = 4
180  params['robot_id'] = 1
181  lcsm = LoopClosureSparseMatching(params)
182 
183  nb_local_kfs = 100
184  for i in range(nb_local_kfs):
185  descriptor = np.random.rand(10)
186  descriptor = descriptor / np.linalg.norm(descriptor)
187  lcsm.add_local_global_descriptor(descriptor, i)
188  nb_other_kfs = 100
189  for i in range(nb_other_kfs):
190  descriptor = np.random.rand(10)
191  descriptor = descriptor / np.linalg.norm(descriptor)
192  msg = GlobalDescriptor(i, 2, descriptor.tolist())
193  lcsm.add_other_robot_global_descriptor(msg)
194  for i in range(nb_other_kfs):
195  descriptor = np.random.rand(10)
196  descriptor = descriptor / np.linalg.norm(descriptor)
197  msg = GlobalDescriptor(i, 3, descriptor.tolist())
198  lcsm.add_other_robot_global_descriptor(msg)
199 
200  nb_candidates = 20
201 
202  is_robot_considered = {}
203  for i in range(params['max_nb_robots']):
204  is_robot_considered[i] = True
205 
206  selection = lcsm.select_candidates(nb_candidates, is_robot_considered)
207  self.assertEqual(len(selection), nb_candidates)
208 
209 
210 if __name__ == "__main__":
211  unittest.main()