added multipath reflections as well

This commit is contained in:
HappyZ 2019-05-22 22:12:57 -05:00
parent f607778a22
commit 0f86737da0
3 changed files with 105 additions and 16 deletions

View File

@ -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()

View File

@ -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

View File

@ -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__":