Swarm-SLAM  1.0.0
C-SLAM Framework
scancontext_utils.py
Go to the documentation of this file.
1 # Adapted from https://github.com/gisbi-kim/PyICP-SLAM/blob/master/utils/ScanContextManager.py
2 
3 import numpy as np
4 np.set_printoptions(precision=4)
5 
6 import time
7 from scipy import spatial
8 
9 
10 def xy2theta(x, y):
11  if (x >= 0 and y >= 0):
12  theta = 180/np.pi * np.arctan(y/x)
13  elif (x < 0 and y >= 0):
14  theta = 180 - ((180/np.pi) * np.arctan(y/(-x)))
15  elif (x < 0 and y < 0):
16  theta = 180 + ((180/np.pi) * np.arctan(y/x))
17  elif ( x >= 0 and y < 0):
18  theta = 360 - ((180/np.pi) * np.arctan((-y)/x))
19  return theta
20 
21 
22 def pt2rs(point, gap_ring, gap_sector, num_ring, num_sector):
23  x = point[0]
24  y = point[1]
25  # z = point[2]
26 
27  if(x == 0.0):
28  x = 0.001
29  if(y == 0.0):
30  y = 0.001
31 
32  theta = xy2theta(x, y)
33  faraway = np.sqrt(x*x + y*y)
34 
35  idx_ring = np.divmod(faraway, gap_ring)[0]
36  idx_sector = np.divmod(theta, gap_sector)[0]
37 
38  if(idx_ring >= num_ring):
39  idx_ring = num_ring-1 # python starts with 0 and ends with N-1
40 
41  return int(idx_ring), int(idx_sector)
42 
43 
44 def ptcloud2sc(ptcloud, sc_shape, max_length):
45  num_ring = sc_shape[0]
46  num_sector = sc_shape[1]
47 
48  gap_ring = max_length/num_ring
49  gap_sector = 360/num_sector
50 
51  enough_large = 500
52  sc_storage = np.zeros([enough_large, num_ring, num_sector])
53  sc_counter = np.zeros([num_ring, num_sector])
54 
55  num_points = ptcloud.shape[0]
56  for pt_idx in range(num_points):
57  point = ptcloud[pt_idx, :]
58  if np.isnan(point[0]) or np.isnan(point[1]) or np.isnan(point[2]):
59  # Reject spurious points
60  continue
61  point_height = point[2] + 2.0 # for setting ground is roughly zero
62 
63  idx_ring, idx_sector = pt2rs(point, gap_ring, gap_sector, num_ring, num_sector)
64 
65  if sc_counter[idx_ring, idx_sector] >= enough_large:
66  continue
67  sc_storage[int(sc_counter[idx_ring, idx_sector]), idx_ring, idx_sector] = point_height
68  sc_counter[idx_ring, idx_sector] = sc_counter[idx_ring, idx_sector] + 1
69 
70  sc = np.amax(sc_storage, axis=0)
71 
72  return sc
73 
74 
75 def sc2rk(sc):
76  return np.mean(sc, axis=1)
77 
78 def distance_sc(sc1, sc2):
79  num_sectors = sc1.shape[1]
80 
81  # repeat to move 1 columns
82  _one_step = 1 # const
83  sim_for_each_cols = np.zeros(num_sectors)
84  for i in range(num_sectors):
85  # Shift
86  sc1 = np.roll(sc1, _one_step, axis=1) # columne shift
87 
88  #compare
89  sum_of_cossim = 0
90  num_col_engaged = 0
91  for j in range(num_sectors):
92  col_j_1 = sc1[:, j]
93  col_j_2 = sc2[:, j]
94  if (~np.any(col_j_1) or ~np.any(col_j_2)):
95  # to avoid being divided by zero when calculating cosine similarity
96  # - but this part is quite slow in python, you can omit it.
97  continue
98 
99  cossim = np.dot(col_j_1, col_j_2) / (np.linalg.norm(col_j_1) * np.linalg.norm(col_j_2))
100  sum_of_cossim = sum_of_cossim + cossim
101 
102  num_col_engaged = num_col_engaged + 1
103 
104  # save
105  if num_col_engaged == 0:
106  sim_for_each_cols[i] = 0.0
107  else:
108  sim_for_each_cols[i] = sum_of_cossim / num_col_engaged
109 
110  yaw_diff = np.argmax(sim_for_each_cols) + 1 # because python starts with 0
111  sim = np.max(sim_for_each_cols)
112  dist = 1 - sim
113 
114  return dist, yaw_diff
def distance_sc(sc1, sc2)
def ptcloud2sc(ptcloud, sc_shape, max_length)
def pt2rs(point, gap_ring, gap_sector, num_ring, num_sector)