4 sys.path.append(
'/home/lajoiepy/Documents/projects/c-slam/c-slam-ws/install/cslam/lib/python3.8/site-packages/')
7 from cslam.mac.utils
import Edge
8 from cslam.mac.mac
import MAC
11 from timeit
import default_timer
as timer
19 nb_poses (int): nb of poses in graph
20 nb_candidate_edges (int): nb of loop edges to generate
23 list(EdgeInterRobot), dict(EdgeInterRobot): edges in the graph
30 while len(candidate_edges.values()) < nb_candidate_edges:
32 random.choice(range(nb_poses)), fixed_weight)
33 candidate_edges[(edge.robot0_keyframe_id, edge.robot1_keyframe_id)] = edge
35 return fixed_edges_list, list(candidate_edges.values())
39 """Build graph with multiple robots
42 nb_poses (int): nb of poses in graph
43 nb_candidate_edges (int): nb of loop edges to generate
44 max_nb_robots (int): nb of robots
47 list(EdgeInterRobot), dict(EdgeInterRobot): edges in the graph
53 for i
in range(max_nb_robots - 1):
56 fixed_edges_list.append(edge)
61 while len(candidate_edges.values()) < nb_candidate_edges:
62 robot0_id = random.choice(range(max_nb_robots))
63 robot1_id = random.choice(
64 list(set(range(max_nb_robots)) - set([robot0_id])))
66 random.choice(range(nb_poses)), robot1_id,
67 random.choice(range(nb_poses)), fixed_weight)
68 if edge.robot0_id < edge.robot1_id:
69 candidate_edges[(edge.robot0_id, edge.robot0_keyframe_id, edge.robot1_id, edge.robot1_keyframe_id)] = edge
71 candidate_edges[(edge.robot1_id, edge.robot1_keyframe_id, edge.robot0_id, edge.robot0_keyframe_id)] = edge
74 return fixed_edges_list, list(candidate_edges.values())
78 """Unit tests for algebraic connectivity maximization
82 """Test simple single robot graph
86 nb_candidate_edges = 50
88 nb_poses, nb_candidate_edges)
90 nb_candidates_to_choose = 10
93 ac.set_graph(fixed_edges_list, candidate_edges_list)
95 is_robot_considered = {0:
True}
96 selection = ac.select_candidates(nb_candidates_to_choose,
98 greedy_initialization=
False)
100 self.assertEqual(len(selection), nb_candidates_to_choose)
103 """Test the greedy weight initialization
105 nb_candidates_to_choose = 10
107 nb_candidate_edges = 50
109 nb_poses, nb_candidate_edges)
110 weights = np.random.rand(nb_candidate_edges)
113 for e
in range(len(candidate_edges_list)):
114 candidate_edges_list[e] = ac.replace_weight(candidate_edges_list[e],
117 ac.set_graph(fixed_edges_list, candidate_edges_list)
118 is_robot_considered = {0:
True}
119 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
120 ac.compute_offsets(is_robot_included)
121 edges = ac.rekey_edges(ac.candidate_edges.values(), is_robot_included)
122 w_init = ac.greedy_initialization(nb_candidates_to_choose, edges)
123 self.assertAlmostEqual(
124 np.sum(weights[w_init.astype(bool)]),
125 np.sum(np.sort(weights)[-nb_candidates_to_choose:]))
128 """Test that adding measurements after solving works
132 nb_candidate_edges = 50
133 nb_candidates_to_choose = 10
135 nb_poses, nb_candidate_edges)
137 ac.set_graph(fixed_edges_list, candidate_edges_list)
140 is_robot_considered = {0:
True}
141 selection0 = ac.select_candidates(nb_candidates_to_choose,
143 greedy_initialization=
False)
144 self.assertEqual(len(selection0), nb_candidates_to_choose)
148 for i
in range(nb_add_edges):
149 ac.add_candidate_edge(
151 random.choice(range(nb_poses)), 1.0))
152 selection1 = ac.select_candidates(nb_candidates_to_choose,
154 greedy_initialization=
False)
155 self.assertEqual(len(selection1), nb_candidates_to_choose)
157 selection2 = ac.select_candidates(nb_candidates_to_choose + 2,
159 greedy_initialization=
False)
160 self.assertEqual(len(selection2), nb_candidates_to_choose + 2)
161 for i
in range(nb_add_edges):
162 ac.add_candidate_edge(
164 random.choice(range(nb_poses)), 1.0))
165 selection3 = ac.select_candidates(nb_candidates_to_choose + 2,
167 greedy_initialization=
False)
168 self.assertEqual(len(selection3), nb_candidates_to_choose + 2)
171 """Test that loop closures can be fixed
175 nb_candidate_edges = 50
176 nb_candidates_to_choose = 10
178 nb_poses, nb_candidate_edges)
180 ac.set_graph(fixed_edges_list, candidate_edges_list)
183 is_robot_considered = {0:
True}
184 selection0 = ac.select_candidates(nb_candidates_to_choose,
186 greedy_initialization=
False)
187 self.assertEqual(len(selection0), nb_candidates_to_choose)
191 for i
in range(nb_add_edges):
194 random.choice(range(nb_poses)), 1.0))
195 selection1 = ac.select_candidates(nb_candidates_to_choose,
197 greedy_initialization=
False)
198 self.assertEqual(len(selection1), nb_candidates_to_choose)
201 """Test that we can remove candidates from consideration
205 nb_candidate_edges = 50
206 nb_candidates_to_choose = 10
208 nb_poses, nb_candidate_edges)
210 ac.set_graph(fixed_edges_list, candidate_edges_list)
213 candidates_edges_before = ac.candidate_edges.copy()
214 is_robot_considered = {0:
True}
215 selection0 = ac.select_candidates(nb_candidates_to_choose,
217 greedy_initialization=
False)
218 self.assertEqual(len(selection0), nb_candidates_to_choose)
222 self.assertIn(e, list(candidates_edges_before.values()))
225 self.assertEqual(len(test), nb_candidates_to_choose)
227 nb_candidates0 = len(ac.candidate_edges)
230 ac.remove_candidate_edges(list(ac.candidate_edges.values())[:nb_candidates_to_choose])
231 nb_candidates1 = len(ac.candidate_edges)
232 self.assertGreaterEqual(nb_candidates0,
233 nb_candidates1 + nb_candidates_to_choose - 1)
234 self.assertLessEqual(nb_candidates0,
235 nb_candidates1 + nb_candidates_to_choose + 1)
238 """Test that we can remove candidates from consideration
243 nb_candidate_edges = 10
245 nb_candidates_to_choose = 3
247 nb_poses, nb_candidate_edges, max_nb_robots)
250 max_nb_robots=max_nb_robots)
251 ac.set_graph(fixed_edges_list, candidate_edges_list)
252 candidates_edges_before = ac.candidate_edges.copy()
255 is_robot_considered = {}
256 for i
in range(max_nb_robots):
257 is_robot_considered[i] =
True
258 selection0 = ac.select_candidates(nb_candidates_to_choose,
260 greedy_initialization=
False)
261 self.assertEqual(len(selection0), nb_candidates_to_choose)
264 self.assertIn(e, list(candidates_edges_before.values()))
266 nb_candidates0 = len(ac.candidate_edges)
269 existant_edge = [list(ac.candidate_edges.values())[0]]
271 ac.remove_candidate_edges(existant_edge)
272 nb_candidates1 = len(ac.candidate_edges)
273 self.assertEqual(nb_candidates0, nb_candidates1 + 1)
275 ac.remove_candidate_edges(inexistant_edge)
276 nb_candidates2 = len(ac.candidate_edges)
277 self.assertEqual(nb_candidates0, nb_candidates2 + 1)
280 """Test that we can declare candidate fixed if they are successfully
285 nb_candidate_edges = 50
286 nb_candidates_to_choose = 10
288 nb_poses, nb_candidate_edges)
290 ac.set_graph(fixed_edges_list, candidate_edges_list)
292 candidates_edges_before = ac.candidate_edges.copy()
295 is_robot_considered = {0:
True}
296 selection0 = ac.select_candidates(nb_candidates_to_choose,
298 greedy_initialization=
False)
299 self.assertEqual(len(selection0), nb_candidates_to_choose)
302 self.assertIn(e, list(candidates_edges_before.values()))
305 ac.candidate_edges_to_fixed(selection0)
307 self.assertNotIn(e, list(ac.candidate_edges.values()))
309 selection1 = ac.select_candidates(nb_candidates_to_choose,
311 greedy_initialization=
False)
314 self.assertIn(e, list(candidates_edges_before.values()))
316 for e0
in selection0:
317 for e1
in selection1:
318 self.assertFalse(e0.robot0_keyframe_id == e1.robot0_keyframe_id
319 and e0.robot1_keyframe_id == e1.robot1_keyframe_id)
322 """Test connectivity check
327 nb_candidate_edges = 10
329 is_robot_considered = {}
330 for i
in range(max_nb_robots):
331 is_robot_considered[i] =
True
334 nb_poses, nb_candidate_edges, max_nb_robots)
337 max_nb_robots=max_nb_robots)
338 ac.set_graph(fixed_edges_list, candidate_edges_list)
340 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
342 for r
in is_robot_included:
343 self.assertTrue(is_robot_included[r])
345 is_robot_considered[1] =
False
347 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
348 for r
in is_robot_included:
349 if is_robot_considered[r]:
350 self.assertTrue(is_robot_included[r])
352 self.assertFalse(is_robot_included[r])
354 is_robot_considered[1] =
True
359 nb_candidate_edges = 10
362 nb_poses, nb_candidate_edges, max_nb_robots)
365 for i
in range(len(fixed_edges_list)):
366 if fixed_edges_list[i].robot0_id == 0
or fixed_edges_list[
368 to_delete.append(fixed_edges_list[i])
370 fixed_edges_list.remove(e)
373 for i
in range(len(candidate_edges_list)):
374 if candidate_edges_list[i].robot0_id == 0
or candidate_edges_list[
376 to_delete.append(candidate_edges_list[i])
378 candidate_edges_list.remove(e)
381 max_nb_robots=max_nb_robots)
382 ac.set_graph(fixed_edges_list, candidate_edges_list)
384 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
386 for r
in is_robot_included:
388 self.assertFalse(is_robot_included[r])
390 self.assertTrue(is_robot_included[r])
393 """Test connectivity check
398 nb_candidate_edges = 10
401 nb_poses, nb_candidate_edges, max_nb_robots)
404 max_nb_robots=max_nb_robots)
405 ac.set_graph(fixed_edges_list, candidate_edges_list)
407 is_robot_considered = {}
408 for i
in range(max_nb_robots):
409 is_robot_considered[i] =
True
410 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
411 ac.compute_offsets(is_robot_included)
413 nb_poses = ac.nb_poses
414 self.assertEqual(ac.offsets[0], 0)
415 self.assertEqual(ac.offsets[1], ac.offsets[0] + nb_poses[0])
416 self.assertEqual(ac.offsets[2], ac.offsets[1] + nb_poses[1])
417 self.assertEqual(ac.offsets[3], ac.offsets[2] + nb_poses[2])
418 self.assertEqual(ac.offsets[4], ac.offsets[3] + nb_poses[3])
422 for i
in range(len(fixed_edges_list)):
423 if fixed_edges_list[i].robot0_id == 0
or fixed_edges_list[
425 to_delete.append(fixed_edges_list[i])
427 fixed_edges_list.remove(e)
430 for i
in range(len(candidate_edges_list)):
431 if candidate_edges_list[i].robot0_id == 0
or candidate_edges_list[
433 to_delete.append(candidate_edges_list[i])
435 candidate_edges_list.remove(e)
438 max_nb_robots=max_nb_robots)
439 ac.set_graph(fixed_edges_list, candidate_edges_list)
441 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
442 ac.compute_offsets(is_robot_included)
444 self.assertEqual(ac.offsets[0], 0)
445 self.assertEqual(ac.offsets[1], 0)
446 self.assertEqual(ac.offsets[2], ac.offsets[1] + nb_poses[1])
447 self.assertEqual(ac.offsets[3], ac.offsets[2] + nb_poses[2])
448 self.assertEqual(ac.offsets[4], ac.offsets[3] + nb_poses[3])
452 for i
in range(len(fixed_edges_list)):
453 if fixed_edges_list[i].robot0_id == 3
or fixed_edges_list[
455 to_delete.append(fixed_edges_list[i])
457 fixed_edges_list.remove(e)
460 for i
in range(len(candidate_edges_list)):
461 if candidate_edges_list[i].robot0_id == 3
or candidate_edges_list[
463 to_delete.append(candidate_edges_list[i])
465 candidate_edges_list.remove(e)
469 fixed_edges_list.append(edge)
472 max_nb_robots=max_nb_robots)
473 ac.set_graph(fixed_edges_list, candidate_edges_list)
475 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
476 ac.compute_offsets(is_robot_included)
478 self.assertEqual(ac.offsets[0], 0)
479 self.assertEqual(ac.offsets[1], 0)
480 self.assertEqual(ac.offsets[2], ac.offsets[1] + nb_poses[1])
481 self.assertEqual(ac.offsets[3], 0)
482 self.assertEqual(ac.offsets[4], ac.offsets[2] + nb_poses[2])
485 """Test key changes between C-SLAM system and solver
489 nb_candidate_edges = 10
492 nb_poses, nb_candidate_edges, max_nb_robots)
495 max_nb_robots=max_nb_robots)
496 ac.set_graph(fixed_edges_list, candidate_edges_list)
498 is_robot_considered = {}
499 for i
in range(max_nb_robots):
500 is_robot_considered[i] =
True
501 is_robot_included = ac.check_graph_disconnections(is_robot_considered)
503 ac.compute_offsets(is_robot_included)
504 rekeyed_fixed_edges = ac.rekey_edges(ac.fixed_edges, is_robot_included)
505 self.assertEqual(len(ac.fixed_edges), 2)
506 rekeyed_fixed_edges.extend(ac.fill_odometry())
507 self.assertEqual(len(rekeyed_fixed_edges),
508 max_nb_robots * (nb_poses - 1) + 2)
509 rekeyed_candidate_edges = ac.rekey_edges(ac.candidate_edges.values(),
511 values = list(ac.candidate_edges.values())
512 for i
in range(len(values)):
514 r = rekeyed_candidate_edges[i]
515 self.assertEqual(r.i, e.robot0_keyframe_id + e.robot0_id * 10)
516 self.assertEqual(r.j, e.robot1_keyframe_id + e.robot1_id * 10)
518 recovered_edges = ac.recover_inter_robot_edges(rekeyed_candidate_edges,
520 for i
in range(len(values)):
522 r = recovered_edges[i]
523 self.assertEqual(r.robot0_keyframe_id, e.robot0_keyframe_id)
524 self.assertEqual(r.robot1_keyframe_id, e.robot1_keyframe_id)
527 """Test graph with multi-robot edges
532 nb_candidate_edges = 100
534 nb_candidates_to_choose = 10
536 nb_poses, nb_candidate_edges, max_nb_robots)
539 max_nb_robots=max_nb_robots)
540 ac.set_graph(fixed_edges_list, candidate_edges_list)
542 is_robot_considered = {}
543 for i
in range(max_nb_robots):
544 is_robot_considered[i] =
True
547 selection = ac.select_candidates(nb_candidates_to_choose,
549 greedy_initialization=
False)
550 self.assertEqual(len(selection), nb_candidates_to_choose)
552 self.assertLess(s.robot0_keyframe_id, nb_poses)
553 self.assertGreaterEqual(s.robot0_keyframe_id, 0)
554 self.assertLess(s.robot1_keyframe_id, nb_poses)
555 self.assertGreaterEqual(s.robot0_keyframe_id, 0)
556 self.assertGreaterEqual(s.robot0_id, 0)
557 self.assertGreaterEqual(s.robot1_id, 0)
558 self.assertLess(s.robot0_id, max_nb_robots)
559 self.assertLess(s.robot1_id, max_nb_robots)
562 """Test graph with multi-robot edges
567 nb_candidate_edges = 100
569 nb_candidates_to_choose = 10
571 nb_poses, nb_candidate_edges, max_nb_robots)
574 max_nb_robots=max_nb_robots)
575 ac.set_graph(fixed_edges_list, candidate_edges_list)
577 is_robot_considered = {}
578 for i
in range(max_nb_robots):
579 is_robot_considered[i] =
True
582 selection = ac.select_candidates(nb_candidates_to_choose,
584 greedy_initialization=
False)
585 self.assertEqual(len(selection), nb_candidates_to_choose)
594 max_nb_robots=max_nb_robots)
598 self.assertEqual(len(ac.candidate_edges.values()), 1)
601 self.assertEqual(len(ac.candidate_edges.values()), 2)
604 self.assertEqual(len(ac.candidate_edges.values()), 2)
605 self.assertAlmostEqual(
606 ac.candidate_edges[(e2.robot0_id, e2.robot0_keyframe_id, e2.robot1_id,
607 e2.robot1_keyframe_id)].weight, 0.2)
610 if __name__ ==
"__main__":
def test_remove_candidate0(self)
def test_greedy_initilization(self)
def test_remove_candidate1(self)
def test_multi_robot_edges0(self)
def test_multi_robot_edges1(self)
def test_add_measurements(self)
def test_compute_offsets(self)
def test_simple_graph(self)
def test_fixed_loop_closures(self)
def test_candidate_to_fixed(self)
def test_check_graph_disconnections(self)
def build_multi_robot_graph(nb_poses, nb_candidate_edges, max_nb_robots)
def build_simple_graph(nb_poses, nb_candidate_edges)