added multipath reflections as well
This commit is contained in:
parent
f607778a22
commit
0f86737da0
|
|
@ -6,11 +6,11 @@ import matplotlib.pyplot as plt
|
|||
|
||||
from libs.consts import COLORMAP_MIN
|
||||
from libs.consts import COLORMAP_MAX
|
||||
from libs.spacemap import SpaceMap
|
||||
|
||||
|
||||
def plotSpace(
|
||||
space_map: SpaceMap,
|
||||
space_map,
|
||||
space_rays = None,
|
||||
cminmax: tuple = (COLORMAP_MIN, COLORMAP_MAX)
|
||||
):
|
||||
'''
|
||||
|
|
@ -30,8 +30,14 @@ def plotSpace(
|
|||
vmin=cminmax[0],
|
||||
vmax=cminmax[1]
|
||||
)
|
||||
ax1.set_xlim([0,64])
|
||||
ax1.set_ylim([0,64])
|
||||
plt.colorbar()
|
||||
|
||||
if space_rays:
|
||||
for each in space_rays:
|
||||
ax1.plot([each.start.x / 0.1, each.end.x / 0.1], [each.start.y / 0.1, each.end.y / 0.1], 'b-')
|
||||
|
||||
ax2 = fig.add_subplot(1, 2, 2)
|
||||
ax2.set_title("reflection loss")
|
||||
plt.imshow(
|
||||
|
|
@ -42,6 +48,8 @@ def plotSpace(
|
|||
vmin=cminmax[0],
|
||||
vmax=cminmax[1]
|
||||
)
|
||||
ax2.set_xlim([0,64])
|
||||
ax2.set_ylim([0,64])
|
||||
plt.colorbar()
|
||||
|
||||
# plt.show()
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ from libs.consts import MAX_RANGE
|
|||
from libs.consts import NOISE_FLOOR
|
||||
from libs.consts import FLOAT_TOLERANCE
|
||||
from libs.models import log_gamma_dist
|
||||
from libs.plotting import plotSpace
|
||||
|
||||
|
||||
class SpaceBlock():
|
||||
|
|
@ -20,6 +21,14 @@ class SpaceBlock():
|
|||
self.has_transmitter = False
|
||||
self.loss_penetration = 0.0
|
||||
self.loss_reflection = -100.0
|
||||
self.orientation = None
|
||||
# backup linked list
|
||||
self.left = None # <-
|
||||
self.right = None # ->
|
||||
self.up = None # ^
|
||||
self.down = None # v
|
||||
self.top = None # . (3d on top)
|
||||
self.bottom = None # o (3d underneath)
|
||||
|
||||
def __mul__(self, val):
|
||||
return SpaceBlock(self.x * val, self.y * val, self.z * val)
|
||||
|
|
@ -106,6 +115,12 @@ class SpaceBlock():
|
|||
self.loss_penetration = penetration
|
||||
self.loss_reflection = reflection
|
||||
|
||||
def setOrientation(self, orientation=0.0):
|
||||
self.orientation = orientation
|
||||
|
||||
def getOrientation(self):
|
||||
return self.orientation
|
||||
|
||||
def getLoss(self):
|
||||
return [self.loss_penetration, self.loss_reflection]
|
||||
|
||||
|
|
@ -159,11 +174,22 @@ class SpaceRay():
|
|||
def __str__(self):
|
||||
return (
|
||||
"SpaceRay(start = {0}, end = {1}): ".format(self.start, self.end) +
|
||||
"pwr_init = {0:.2f}, pwr_end = {1:.2f}, ".format(self.init_pwr, self.ending_pwr) +
|
||||
"loss_start = {0:.2f}, loss_end = {1:.2f}\n".format(self.starting_loss, self.ending_loss) +
|
||||
"pwr_init = {0}, pwr_end = {1}, ".format(self.init_pwr, self.ending_pwr) +
|
||||
"loss_start = {0}, loss_end = {1}\n".format(self.starting_loss, self.ending_loss) +
|
||||
" <- prev_ray = {}".format(self.prev_ray)
|
||||
)
|
||||
|
||||
def __iter__(self):
|
||||
self.__prev_ray = self
|
||||
return self
|
||||
|
||||
def __next__(self):
|
||||
if self.__prev_ray is None:
|
||||
raise StopIteration
|
||||
tmp = self.__prev_ray
|
||||
self.__prev_ray = self.__prev_ray.prev_ray
|
||||
return tmp
|
||||
|
||||
def getAngle(self, degree=False):
|
||||
if self.angle_theta is None:
|
||||
self.angle_theta = np.arctan2(
|
||||
|
|
@ -215,7 +241,8 @@ class SpaceRay():
|
|||
self.reflection_blks = []
|
||||
step_blk = SpaceBlock(self.getAngleThetaCos(), self.getAngleThetaSin()) * space_map.bs
|
||||
early_stop_flag = False
|
||||
for i in range(1, int(self.getDistance() / space_map.bs)):
|
||||
# reflect_blk_min_gap = 2
|
||||
for i in range(2, int(self.getDistance() / space_map.bs) - 1):
|
||||
next_blk = self.start + step_blk * i
|
||||
# assume 2D
|
||||
x_idx, y_idx = [int(x) for x in (next_blk / space_map.bs).round()]
|
||||
|
|
@ -306,6 +333,12 @@ class SpaceMap():
|
|||
y = self.bs * (j + 0.5)
|
||||
for i in range(self.map.shape[0]):
|
||||
self.map[i, j] = SpaceBlock(self.bs * (i + 0.5), y)
|
||||
for j in range(self.map.shape[1]):
|
||||
for i in range(self.map.shape[0]):
|
||||
self.map[i, j].up = self.map[i, j+1] if j < self.map.shape[1]-1 else None
|
||||
self.map[i, j].down = self.map[i, j-1] if j > 0 else None
|
||||
self.map[i, j].left = self.map[i-1, j] if i < 0 else None
|
||||
self.map[i, j].right = self.map[i+1, j] if i < self.map.shape[0]-1 else None
|
||||
|
||||
# propagation
|
||||
self.env_gamma = 2.0
|
||||
|
|
@ -326,6 +359,9 @@ class SpaceMap():
|
|||
for i in range(self.map.shape[0]):
|
||||
self.setLoss(i, j, penetrations[i ,j], reflections[i, j])
|
||||
|
||||
def setOrientation(self, i, j, orientation):
|
||||
self.map[i, j].setOrientation(orientation)
|
||||
|
||||
def setLoss(self, i, j, penetration, reflection):
|
||||
self.map[i, j].setLoss(penetration, reflection)
|
||||
self.__loss_p[i, j] = penetration
|
||||
|
|
@ -341,7 +377,7 @@ class SpaceMap():
|
|||
def setEnvGamma(self, val: float):
|
||||
self.env_gamma = val
|
||||
|
||||
def traceRay(self, tx_power: float, tx_loc: SpaceBlock, rx_loc: SpaceBlock):
|
||||
def traceRay(self, tx_power: float, tx_loc: SpaceBlock, rx_loc: SpaceBlock, debug: bool = False):
|
||||
def getPathFromRay(ray, stop_blk):
|
||||
path = SpaceRay(ray.start, stop_blk)
|
||||
# prevent 0 distance
|
||||
|
|
@ -385,6 +421,38 @@ class SpaceMap():
|
|||
sig_pwr += np.power(10, path.getEndingPower() / 10.0)
|
||||
return 10.0 * np.log10(sig_pwr)
|
||||
|
||||
def removeRedundantPaths(paths):
|
||||
paths_len = len(paths)
|
||||
duplicated_ones = {}
|
||||
# calcualte pair-wise distance
|
||||
for i in range(paths_len):
|
||||
for j in range(i + 1, paths_len):
|
||||
if abs(paths[i].start - paths[j].start) < 2.0 * self.bs:
|
||||
if i not in duplicated_ones:
|
||||
duplicated_ones[i] = [0, []]
|
||||
duplicated_ones[i][0] += 1
|
||||
duplicated_ones[i][1].append(j)
|
||||
if j not in duplicated_ones:
|
||||
duplicated_ones[j] = [0, []]
|
||||
duplicated_ones[j][0] += 1
|
||||
duplicated_ones[j][1].append(i)
|
||||
# removal
|
||||
to_be_removed = []
|
||||
while len(duplicated_ones) > 0:
|
||||
idx = sorted(list(duplicated_ones.keys()), key=lambda x: duplicated_ones[x][0], reverse=True)[0]
|
||||
for target_idx in duplicated_ones[idx][1]:
|
||||
if target_idx not in to_be_removed:
|
||||
to_be_removed.append(target_idx)
|
||||
duplicated_ones[idx][0] -= 1
|
||||
duplicated_ones[target_idx][0] -= 1
|
||||
if duplicated_ones[target_idx][0] == 0:
|
||||
del duplicated_ones[target_idx]
|
||||
continue
|
||||
del duplicated_ones[target_idx][1][duplicated_ones[target_idx][1].index(idx)]
|
||||
del duplicated_ones[idx]
|
||||
for each in sorted(to_be_removed, reverse=True):
|
||||
del paths[each]
|
||||
|
||||
# # round
|
||||
# rx_loc = ((rx_loc / self.bs).round() + 0.5) * self.bs
|
||||
# fake_init_ray = SpaceRay(None, None)
|
||||
|
|
@ -418,14 +486,21 @@ class SpaceMap():
|
|||
continue
|
||||
ref_blk = ray.reflection_blks[0]
|
||||
path = getPathFromRay(ray, ref_blk)
|
||||
# too weak
|
||||
if path is None or path.getEndingPower() < NOISE_FLOOR:
|
||||
continue
|
||||
# penetrated ray
|
||||
ray_p = getRayFromPath(path, ray.getAngle(), t='penetrate')
|
||||
if ray_p is not None:
|
||||
rays.append(ray_p)
|
||||
# ray_r = getRayFromPath(path, path.getAngle() + 0.5 * np.pi, t='reflect')
|
||||
# ray_r = getRayFromPath(path, path.getAngle() - 0.5 * np.pi, t='reflect')
|
||||
|
||||
# reflected ray
|
||||
if ref_blk.getOrientation() is None:
|
||||
# if no orientation info provided, cannot calculate reflected ray
|
||||
continue
|
||||
ray_r = getRayFromPath(path, 2.0 * ref_blk.getOrientation() - path.getAngle() , t='reflect')
|
||||
if ray_r is not None:
|
||||
rays.append(ray_r)
|
||||
# clean up for too nearby paths
|
||||
removeRedundantPaths(rx_loc_paths)
|
||||
return aggreatePower(rx_loc_paths), rx_loc_paths
|
||||
|
||||
|
||||
|
||||
|
|
@ -16,15 +16,21 @@ from libs.plotting import plotSpace
|
|||
|
||||
def test():
|
||||
spacemap = SpaceMap(width=6.4, length=6.4, block_size=0.1)
|
||||
for i in range(10, 40):
|
||||
spacemap.setLoss(i, 10, penetration=-5.0, reflection=-80.0)
|
||||
spacemap.setLoss(i, 20, penetration=-5.0, reflection=-80.0)
|
||||
# add walls
|
||||
for i in range(0, 64):
|
||||
spacemap.setLoss(i, 10, penetration=-5.0, reflection=-100.0)
|
||||
spacemap.setOrientation(i, 10, orientation=0.0)
|
||||
spacemap.setLoss(i, 50, penetration=-50.0, reflection=-10.0)
|
||||
spacemap.setOrientation(i, 50, orientation=0.0)
|
||||
plotSpace(spacemap, cminmax=(-50, 0.0))
|
||||
rx_loc = SpaceBlock(6.25, 3.2)
|
||||
rx_loc_rss, rx_loc_paths = spacemap.traceRay(0.0, SpaceBlock(0.0, 0.0), rx_loc)
|
||||
multipaths = []
|
||||
for path in rx_loc_paths:
|
||||
print(path)
|
||||
print(rx_loc_rss)
|
||||
print("found path: {}".format(path))
|
||||
multipaths.extend(list(path))
|
||||
print("rss = {:.6f}dB".format(rx_loc_rss))
|
||||
plotSpace(spacemap, space_rays=multipaths, cminmax=(-50, 0.0))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
|
|
|||
Loading…
Reference in New Issue