def drawToAnimation(self): """ Draw. Assuming that the human is standing. Parameters ---------- """ listPlanes = [] if self.chair and self.table: listPlanes.append(self.chair.getPartition(Ps=1)) listPlanes.append(self.table.getPartition(Ps=1)) listPlanes = list(flatten(listPlanes)) alphas = [1 for plane in listPlanes] fig, ax = draw(xlim=[0, self.room.L], ylim=[0, self.room.W], zlim=[0, self.room.H], planes=listPlanes, enablevect=False, alphas=alphas) fig, ax = draw(figure=fig, axes=ax, vectors=[self.led], colors='blue') return fig, ax
def draw(self, displayRoom=False, displayReflectivity=False): """ Draw. Parameters ---------- displayRoom: bool displayReflectivity: bool """ if displayRoom: if displayReflectivity: alphas = [ 0.5 * plane.reflectivity for plane in self.listPlanes ] else: alphas = [1 for plane in self.listPlanes] fig, ax = draw(xlim=[0, self.room.L], ylim=[0, self.room.W], zlim=[0, self.room.H], planes=self.listPlanes, vectors=Vector(coord=self.human.normalVect, refPoint=self.human.ctrPoint, which='cartesian'), enablevect=False, alphas=alphas) else: listPlanes = [] listPlanes.append(self.human.listPlanes) if self.chair and self.table: listPlanes.append(self.chair.getPartition(Ps=1)) listPlanes.append(self.table.getPartition(Ps=1)) listPlanes = list(flatten(listPlanes)) if displayReflectivity: alphas = [0.5 * plane.reflectivity for plane in listPlanes] else: alphas = [1 for plane in listPlanes] fig, ax = draw(xlim=[0, self.room.L], ylim=[0, self.room.W], zlim=[0, self.room.H], planes=listPlanes, vectors=Vector(coord=self.human.normalVect, refPoint=self.human.ctrPoint, which='cartesian'), enablevect=False, alphas=alphas) fig, ax = draw(figure=fig, axes=ax, circles=[self.human.pd, self.pd], scales=5e3, vectors=[self.human.led, self.led]) return fig, ax
def getPartition(self, Ps=1, delta=None): planes = [] if delta == None: planes.append(self.head.getPartition(Ps=Ps)) planes.append(self.body.getPartition(Ps=Ps)) planes.append(self.leg.getPartition(Ps=Ps)) else: if delta > 0.15: delta = 0.15 planes.append(self.head.getPartition(delta=delta)) planes.append(self.body.getPartition(delta=delta)) planes.append(self.leg.getPartition(delta=delta)) planes = list(flatten(planes)) return planes
def getPartition(self, Ps=1, delta=None): """ Partition all objects. Parameters ---------- Ps: list List of number of partition of each side. delta: list Define the partition based on partition lengths Returns ------- list: A list of partitioned planes. Each plane is an instant of RectPlane_py. """ planes = [] if delta == None: planes.append(self.head.getPartition(Ps=Ps)) planes.append(self.body.getPartition(Ps=Ps)) if self.leg: planes.append(self.leg.getPartition(Ps=Ps)) if self.chair: planes.append(self.chair.getPartition(Ps=Ps)) if self.table: planes.append(self.table.getPartition(Ps=Ps)) else: if delta > 0.15: delta = 0.15 planes.append(self.head.getPartition(delta=delta)) planes.append(self.body.getPartition(delta=delta)) if self.leg: planes.append(self.leg.getPartition(delta=delta)) if self.chair: planes.append(self.chair.getPartition(delta=delta)) if self.table: planes.append(self.table.getPartition(delta=delta)) planes = list(flatten(planes)) return planes
def calc(self, LEDs, PDs, blockingObj, reflectingObj, partitionDist=speed_of_light * 1e-9, numReflections=3, verbose=False): """ Calcute the CIR. Parameters ---------- LEDs: list List of LEDs. But, currently supports 1 LED. PDs: list List of PDs. Currently supports 1 PD. blockingObj: list List of blocking objects. reflectingObj: list List of reflecting objects, for example a room. The naming is due to we might need a genera case when we can do the assumptions of infinite room such that what matters most are the ceiling and the floor. Note that the blockingObj will also be treated as a relfecting object. partitionDist: double, optional Delta distance based on which we partition a plane (the default value is 1ns * c, c: speed of light). The default value is c*timesampling, timesampling is assumed to 1ns by default. See Schulze's paper. numReflections: inf or integer, optional Denoting the number of reflections (the default is 3). """ # Transform into list if not isinstance(LEDs, list): LEDs = [LEDs] if not isinstance(PDs, list): PDs = [PDs] if not isinstance(blockingObj, list): blockingObj = [blockingObj] if not isinstance(reflectingObj, list): reflectingObj = [reflectingObj] # Currently support 1 LED and 1 PD assert len(LEDs) == 1 and len(PDs) == 1 # Partition assuming that all obj in reflectingObj # has the getPartition method reflectingPlanes = [] for obj in reflectingObj: reflectingPlanes.append(obj.getPartition(delta=partitionDist)) # don't forget to include blockingObj as reflecting objects for obj in blockingObj: reflectingPlanes.append(obj.getPartition(delta=partitionDist)) # flatten the list reflectingPlanes = list(flatten(reflectingPlanes)) # Partition blockingObj blockingPlanes = [] for obj in blockingObj: # The number of partition on each side is one blockingPlanes.append(obj.getPartition(Ps=1)) blockingPlanes = list(flatten(blockingPlanes)) # Get simple planes simpleReflectingPlanes = [ plane.getSimplePlane() for plane in reflectingPlanes ] simpleBlockingPlanes = [ plane.getSimplePlane() for plane in blockingPlanes ] emitters = [led.getSimplePointSource() for led in LEDs] collectors = [pd.getSimpleBareDetector() for pd in PDs] # Get the farthest vertix from origin dummyPlanes = [] for obj in reflectingObj: dummyPlanes.append(obj.getPartition(Ps=1)) dummyPlanes = list(flatten(dummyPlanes)) # Assuming each dummyPlane has the vertixes attributes # Collect all vertices verts = np.array(list(flatten([plane.verts for plane in dummyPlanes ]))).reshape(-1, 3) # Calculate norm relative to origin listOfNorm = list(map(lambda v: np.linalg.norm(v), verts)) outerVert = verts[listOfNorm.index(max(listOfNorm))] if verbose: print("> Calculating CIR......(wait)") self.ht_los, self.ht_diff = calcCIRTimeDom(self.timeSampling, numReflections, outerVert, emitters[0], collectors[0], simpleReflectingPlanes, simpleBlockingPlanes) if verbose: print("> Finish calculating CIR :)") self.t = np.arange(self.ht_los.size) * self.timeSampling return self.ht_los, self.ht_diff
def updateListPlanesAndCheckValidity(self): # Get all planes self.listPlanes = [] self.listPlanes.append(self.human.listPlanes) self.listPlanes.append(self.room.listPlanes) if self.chair and self.table: self.listPlanes.append(self.chair.getPartition(Ps=1)) self.listPlanes.append(self.table.getPartition(Ps=1)) self.listPlanes = list(flatten(self.listPlanes)) # Get blocking object self.blockingObj = [] if self.chair: self.blockingObj.append(self.chair) if self.table: self.blockingObj.append(self.table) if self.human: self.blockingObj.append(self.human) # Validate whether a vertice is NOT out of bounds roomVerts = np.append(self.room.listPlanes[0].verts, self.room.listPlanes[1].verts).reshape([-1, 3]) delaunay = Delaunay(roomVerts) verts = np.array( list(flatten([plane.verts.tolist() for plane in self.listPlanes]))).reshape([-1, 3]) if self.human.led: verts = np.append(verts, self.human.led.loc).reshape([-1, 3]) elif self.human.pd: verts = np.append(verts, self.human.pd.loc).reshape([-1, 3]) # # Check feasibility of human # verts = np.array(list(flatten([plane.verts.tolist() for plane in self.human.listPlanes]))).reshape([-1,3]) # # Check feasibility of chair # verts = np.array(list(flatten([plane.verts.tolist() for plane in self.chair.getPartition(Ps=1)]))).reshape([-1,3]) # # Check feasibility of table # verts = np.array(list(flatten([plane.verts.tolist() for plane in self.table.getPartition(Ps=1)]))).reshape([-1,3]) # # Check feasibility of LED # verts = self.human.led.loc # # Check feasibility of PD # verts = self.human.pd.loc self.isValid = np.alltrue(delaunay.find_simplex(verts) >= 0) # Check whether the human intersects with the furniture if self.chair and self.table: chairVerts = np.append(self.chair.listPlanes[0].verts, self.chair.listPlanes[1].verts).reshape( [-1, 3]) tableVerts = np.append( self.tableAsCube.listPlanes[0].verts, self.tableAsCube.listPlanes[1].verts).reshape([-1, 3]) verts = np.array( list( flatten([ plane.verts.tolist() for plane in self.human.listPlanes ]))).reshape([-1, 3]) if self.human.led: verts = np.append(verts, self.human.led.loc).reshape([-1, 3]) elif self.human.pd: verts = np.append(verts, self.human.pd.loc).reshape([-1, 3]) self.isValid = np.alltrue( Delaunay(chairVerts).find_simplex(verts) < 0) and np.alltrue( Delaunay(tableVerts).find_simplex(verts) < 0)
def __init__(self, roomDim, humanLoc, humanDirection, chairLoc=None, chairDirection=0, mode='rx', activity='calling', position='standing'): # Assertion checks assert len(roomDim) == 3 and np.alltrue(np.array(roomDim) > 0) assert mode.lower() == 'tx' or mode.lower() == 'rx',\ ("'mode' is not recognized! Should be either 'tx' or 'rx'") assert activity.lower() == 'calling' or activity.lower() == 'reading' or activity.lower() == 'usbdongle',\ ("'activity' is not recognized! Should be either 'calling', 'reading' or 'usbdongle'") assert position.lower() == 'standing' or position.lower() == 'sitting',\ ("'mode' is not recognized! Should be either 'standing' or 'sitting'") assert not(activity.lower() == 'usbdongle' and position.lower()=='standing'),\ ("cannot choose the `usbdongle` aciticity and the `standing` position.") # Human and other elements self.human = Human(loc=humanLoc, direction=humanDirection, mode=mode, activity=activity, position=position) # Room # Reflectivities # Except the floor, which is modeled as a pinewood, other # parts are modeled with plasters rho_keys = ['b', 't', 's', 'n', 'e', 'w'] if mode.lower() == 'tx': # IR-LED (uplink) rho_vals = [0.92, 0.83, 0.83, 0.83, 0.83, 0.83] elif mode.lower() == 'rx': # VL-LED (downlink) rho_vals = [0.54, 0.76, 0.76, 0.76, 0.76, 0.76] reflectivities = { rho_keys[i]: rho_vals[i] for i in range(len(rho_keys)) } self.room = Room(dimensions=roomDim, identity=1, reflectivities=reflectivities) # A chair and a table self.chair, self.table, self.tableAsCube = None, None, None if chairLoc: self.chair = Cube(Vector( np.array([1, np.deg2rad(90), np.deg2rad(0)])), ctrPoint=np.array([0, 0, 0.2]), dimensions=[0.4, 0.4, 0.4], reflectivities={ 'p0': 0.04, 'p1': 0.04, 'p2': 0.04, 'p3': 0.04, 'p4': 0.04, 'p5': 0.04 }) self.chair = self.chair.rotate(chairDirection, np.array([0, 0, 1])) self.chair = self.chair.translate( np.array([*chairLoc, 0]) + self.chair.ctrPoint) Rd = getRodriguesMtx(chairDirection, np.array([0, 0, 1])) shiftedVect = ( Rd @ np.array([0.2, 0, 0]).reshape(3, 1)).reshape(-1) self.chair = self.chair.translate(shiftedVect + self.chair.ctrPoint) # The table's location is defined based on self.table = Cube(Vector( np.array([1, np.deg2rad(90), np.deg2rad(0)])), ctrPoint=np.array([0, 0, 0.3]), dimensions=[0.6, 1.2, 0.9], reflectivities={ 'p0': 0.04, 'p1': 0.04, 'p2': 0.04, 'p3': 0.04, 'p4': 0.04, 'p5': 0.04 }) self.table = self.table.rotate(chairDirection, np.array([0, 0, 1])) self.table = self.table.translate( np.array([*chairLoc, 0]) + self.table.ctrPoint) Rd = getRodriguesMtx(chairDirection, np.array([0, 0, 1])) shiftedVect = (Rd @ np.array([1, 0, 0]).reshape(3, 1)).reshape(-1) self.table = self.table.translate(shiftedVect + self.table.ctrPoint) # The table is modeled a simple plane self.tableAsCube = self.table self.table = self.table.listPlanes[2] # LED or PD self.led, self.pd = None, None if mode.lower() == 'rx': self.led = PointSource( np.pi, 0, np.array([self.room.L / 2, self.room.W / 2, self.room.H]), m=-np.log(2) / np.log(np.cos(np.deg2rad(40.)))) elif mode.lower() == 'tx': self.pd = BareDetector( np.pi, 0, np.array([self.room.L / 2, self.room.W / 2, self.room.H]), area=1e-4, FoV=np.deg2rad(85)) # Get all planes self.listPlanes = [] self.listPlanes.append(self.human.listPlanes) self.listPlanes.append(self.room.listPlanes) if self.chair and self.table: self.listPlanes.append(self.chair.getPartition(Ps=1)) self.listPlanes.append(self.table.getPartition(Ps=1)) self.listPlanes = list(flatten(self.listPlanes)) # Get blocking object self.blockingObj = [] if self.chair: self.blockingObj.append(self.chair) if self.table: self.blockingObj.append(self.table) if self.human: self.blockingObj.append(self.human) # Validate whether a vertice is NOT out of bounds roomVerts = np.append(self.room.listPlanes[0].verts, self.room.listPlanes[1].verts).reshape([-1, 3]) delaunay = Delaunay(roomVerts) verts = np.array( list(flatten([plane.verts.tolist() for plane in self.listPlanes]))).reshape([-1, 3]) if self.human.led: verts = np.append(verts, self.human.led.loc).reshape([-1, 3]) elif self.human.pd: verts = np.append(verts, self.human.pd.loc).reshape([-1, 3]) # # Check feasibility of human # verts = np.array(list(flatten([plane.verts.tolist() for plane in self.human.listPlanes]))).reshape([-1,3]) # # Check feasibility of chair # verts = np.array(list(flatten([plane.verts.tolist() for plane in self.chair.getPartition(Ps=1)]))).reshape([-1,3]) # # Check feasibility of table # verts = np.array(list(flatten([plane.verts.tolist() for plane in self.table.getPartition(Ps=1)]))).reshape([-1,3]) # # Check feasibility of LED # verts = self.human.led.loc # # Check feasibility of PD # verts = self.human.pd.loc self.isValid = np.alltrue(delaunay.find_simplex(verts) >= 0) # Check whether the human intersects with the furniture if self.chair and self.table: chairVerts = np.append(self.chair.listPlanes[0].verts, self.chair.listPlanes[1].verts).reshape( [-1, 3]) tableVerts = np.append( self.tableAsCube.listPlanes[0].verts, self.tableAsCube.listPlanes[1].verts).reshape([-1, 3]) verts = np.array( list( flatten([ plane.verts.tolist() for plane in self.human.listPlanes ]))).reshape([-1, 3]) if self.human.led: verts = np.append(verts, self.human.led.loc).reshape([-1, 3]) elif self.human.pd: verts = np.append(verts, self.human.pd.loc).reshape([-1, 3]) self.isValid = np.alltrue( Delaunay(chairVerts).find_simplex(verts) < 0) and np.alltrue( Delaunay(tableVerts).find_simplex(verts) < 0)
def calc(self, LEDs, PDs, blockingObj, reflectingObj, partitionDist=speed_of_light * 1e-9, numReflections=math.inf, verbose=False): """ Calcute the CIR. Parameters ---------- LEDs: list List of LEDs. But, currently supports 1 LED. PDs: list List of PDs. Currently supports 1 PD. blockingObj: list List of blocking objects. reflectingObj: list List of reflecting objects, for example a room. The naming is due to we might need a genera case when we can do the assumptions of infinite room such that what matters most are the ceiling and the floor. Note that the blockingObj will also be treated as a relfecting object. partitionDist: double (optional) Delta distance based on which we partition a plane. The default value is c*timesampling, timesampling is assumed to 1ns by default. See Schulze's paper. numReflections: inf or integer (optional) Denoting the number of reflections. """ # Transform into list if not isinstance(LEDs, list): LEDs = [LEDs] if not isinstance(PDs, list): PDs = [PDs] if not isinstance(blockingObj, list): blockingObj = [blockingObj] if not isinstance(reflectingObj, list): reflectingObj = [reflectingObj] # Currently support 1 LED and 1 PD assert len(LEDs) == 1 and len(PDs) == 1 # Partition assuming that all obj in reflectingObj # has the getPartition method reflectingPlanes = [] for obj in reflectingObj: reflectingPlanes.append(obj.getPartition(delta=partitionDist)) # don't forget to include blockingObj as reflecting objects for obj in blockingObj: reflectingPlanes.append(obj.getPartition(delta=partitionDist)) # flatten the list reflectingPlanes = list(flatten(reflectingPlanes)) # Partition blockingObj blockingPlanes = [] for obj in blockingObj: # The number of partition on each side is one blockingPlanes.append(obj.getPartition(Ps=1)) blockingPlanes = list(flatten(blockingPlanes)) # Get simple planes simpleReflectingPlanes = [ plane.getSimplePlane() for plane in reflectingPlanes ] simpleBlockingPlanes = [ plane.getSimplePlane() for plane in blockingPlanes ] emitters = [led.getSimplePointSource() for led in LEDs] collectors = [pd.getSimpleBareDetector() for pd in PDs] if verbose: print("> Calculating CIR......(wait)") if len(self.H_f) != 0: # self.Hf_los,self.Hf_diff = calcCIRFreqDom_fromMtx(self.f, # emitters[0],collectors[0],simpleReflectingPlanes, # self.H_f,self.t_f,self.r_f,self.H_los,blockingplanes=simpleBlockingPlanes) self.Hf_los, self.Hf_diff = calcCIRFreqDom_fromMtx( self.f, self.Nplanes, self.reflectivities, self.H_f, self.t_f, self.r_f, self.H_los) else: self.Hf_los, self.Hf_diff = calcCIRFreqDom(self.f, emitters[0], collectors[0], simpleReflectingPlanes, simpleBlockingPlanes) if verbose: print("> Finish calculating CIR :)") return self.Hf_los, self.Hf_diff
def getArrayMobility(randomMobModel='rwp', activity='walking', dimensions=(0, 1), velocityMinMax=(0.1, 1), waitTimeMax=1., excludedArea=1., minSamples=30): """ Obtain arrays of locations, velocities, time instances, directions, and changes of polar and azimuth angles of orientation of the UE. Parameters ---------- randomMobModel: {'rwp','rd','lw'} 'rwp': random waypoint 'rd' : random direction 'lw' : Levy-walk activity: {'sitting','standing','walking'} self-explanotory dimensions: tuple(2,) Areas of mobility of the human. Ex: dimensions = (roomLength,roomWidth) velocityMinMax: tuple(2,) The minimum and maximum of velocities. waitTimeMax: double The maximum waiting time in seconds. excludedArea: double Area that will be excluded during simulation. Currently, it is as simple as a circle centered at the origin. Therefore, it is now only suitable for the simple office environment. minSamples: double The minimum number of generated samples. Default is 30. """ assert randomMobModel.lower() in {'rwp', 'rd', 'lw'} assert activity.lower() in {'sitting', 'standing', 'walking'} assert len(dimensions) == len(velocityMinMax) == 2 assert waitTimeMax >= 0 assert excludedArea >= 0 if activity.lower() == 'walking': if randomMobModel.lower() == 'rwp': rmm = RandomWaypoint(1, dimensions=dimensions, velocity=velocityMinMax, wt_max=waitTimeMax) elif randomMobModel.lower() == 'rd': rmm = RandomDirection(1, dimensions=dimensions, velocity=velocityMinMax, wt_max=waitTimeMax) elif randomMobModel.lower() == 'lw': rmm = TruncatedLevyWalk(1, dimensions=dimensions, WT_MAX=waitTimeMax) # Make an iterable object from rmm rmmIter = iter(rmm) while True: arrayLoc = [] arrayVel = [] arrayTime = [0] while True: loc = next(rmmIter) if np.linalg.norm(loc) < excludedArea: break else: arrayLoc.append(np.array(loc)) arrayVel.append(np.array(rmm.velocity)) for i in range(len(arrayLoc) - 1): if arrayVel[i] == 0: deltaTime = 0 else: deltaTime = np.linalg.norm(arrayLoc[i + 1] - arrayLoc[i]) / arrayVel[i] arrayTime.append(arrayTime[i] + deltaTime) arrayVel = np.array(list(flatten(arrayVel))) arrayTime = np.array(list(flatten(arrayTime))) arrayLoc = np.array(list(flatten(arrayLoc))).reshape((-1, 2)) if arrayLoc.shape[0] >= minSamples: break arrayDir = [] for i in range(arrayLoc.shape[0] - 1): arrayDir.append(getDirection(arrayLoc[i], arrayLoc[i + 1])) arrayDir.append(arrayDir[-1]) arrayDir = np.array(arrayDir) ro = RandomOrientation('walking') arrayTheta0, arrayOmega0 = ro.genSamples(arrayTime) else: # {'sitting','standing'} ro = RandomOrientation(activity) arrayTime = np.arange(minSamples) * 0.001 # 1 ms resolution arrayTheta0, arrayOmega0 = ro.genSamples(arrayTime) arrayLoc, arrayVel, arrayDir = [], [], [] return { 'arrayLoc': arrayLoc, 'arrayVel': arrayVel, 'arrayTime': arrayTime, 'arrayDir': arrayDir, 'arrayTheta0': arrayTheta0, 'arrayOmega0': arrayOmega0 }