def _gpsSolve(self, user: User) -> Point: def _error(x, c, r): return sum([(np.linalg.norm(x - c[i]) - r[i])**2 for i in range(len(c))]) [beacon_centers, beacon_distance] = self._getBeaconsData(user) if not self._isEnoughBeacons(beacon_centers): return Point(0, 0) length = len(beacon_centers) distances_sum = sum(beacon_distance) # compute weight vector for initial guess weight_vector: List[float] = [ ((length - 1) * distances_sum) / (distances_sum - d) for d in beacon_distance ] # get initial guess of point location x0: List[float] = [ sum([ weight_vector[i] * beacon_centers[i].x for i in range(length) ]), sum([ weight_vector[i] * beacon_centers[i].y for i in range(length) ]), ] centers_f: List[List[float]] = [[bc.x, bc.y] for bc in beacon_centers] # optimize distance from signal origin to border of spheres found_location = minimize( _error, np.array(x0), args=(centers_f, beacon_distance), method="Nelder-Mead", ).x return Point(found_location[0], found_location[1])
def testAddHole(self): hole_geometry = HoleGeometry( [Point(0.3, 0.3), Point(0.3, 0.5), Point(0.5, 0.3)], self.cellId) self.cellGeometry.addHole(hole_geometry) self.assertEqual(1, len(self.cellGeometry.holes))
def testLocationByRSSI(self): location = Point(1, 3) self.assertAlmostEqual( location.distance(self.beacon.location), self.beacon.getDistanceByRSSI(self.beacon.getRSSI(location)), 1, )
def testStringify(self): transition_points = [Point(0, 0), Point(0, 1)] transition_geometry = TransitionGeometry(transition_points) self.assertEqual( f"Transition: [{transition_points[0].x}, {transition_points[0].y}]" + f"[{transition_points[1].x}, {transition_points[1].y}]", transition_geometry.__str__(), )
def testAddHoleWrongId(self): hole_geometry = HoleGeometry( [Point(0.3, 0.3), Point(0.3, 0.5), Point(0.5, 0.3)], self.cellId + "bad") with self._caplog.at_level(logging.INFO): self.cellGeometry.addHole(hole_geometry) assert (f"Hole is member of: {hole_geometry.memberOf} " + f"while cell id is: {self.cellId}" in self._caplog.text)
def getCellGeometries(project_data: any) -> List[CellGeometry]: """Get Cell geometries from a project data Args: project_data (any): Project json data Returns: List[CellGeometry]: List of cells from project file """ cell_geometries: List[CellGeometry] = [] cell_geometry = list( project_data[ParserJsonKeys.geometry_container.value][ ParserJsonKeys.cell_geometry.value]) cell_properties = list( project_data[ParserJsonKeys.property_container.value][ ParserJsonKeys.cell_properties.value]) for cell in cell_geometry: cell_points: List[Point] = [] cell_name: str = ParserJSON.getCellName(cell["id"], cell_properties) for points in cell["points"]: x = points["point"]["x"] y = points["point"]["y"] cell_points.append(Point(x, y)) cell_geometries.append( CellGeometry(cell["id"], cell_name, cell_points)) return cell_geometries
class UserTest(unittest.TestCase): location = Point(1, 1) user = User(location) def testInit(self): self.assertEqual(self.location, self.user.location)
def getRSSI( self, location: Point, scale: float = 1, is_wall: bool = False, noise: bool = False, ) -> float: """Calculate RSSI on given location Args: location (Location): scale (float, optional): Floor scale. Defaults to 1. is_wall (bool, optional): Is wall on a way. Defaults to False. noise (bool, optional): Should noise be added to a signal. Defaults to False. Returns: float: RSSI in dB """ # Distance = 10 ^ ((Measured Power — RSSI) / (10 * N)) distance = location.distance(self.location, scale) if is_wall: n = self.n_wall else: n = self.n signal_strength: float = -10 * n * math.log10(distance) + self.rssi_1 if noise: signal_strength += np.random.normal(0, self.noise_var) logging.debug(f"{self} for {location} RSSI: {signal_strength:4.2f}") return signal_strength
def testDistance(self): test_point = Point(0.3, 0.3) self.assertEqual(0.3, self.transitionGeometry.getDistance(test_point)) test_point = Point(0.3, 0.5) self.assertEqual(0.5, self.transitionGeometry.getDistance(test_point)) test_point = Point(0.9, -0.9) self.assertEqual(0.1, self.transitionGeometry.getDistance(test_point)) test_point = Point(1.3, 0.3) self.assertEqual(round(0.3 * 2**0.5, 4), self.transitionGeometry.getDistance(test_point)) test_point = Point(1.3, 0.3) self.assertEqual(round(0.3 * 2**0.5, 6), self.transitionGeometry.getDistance(test_point, 6))
class PointTest(unittest.TestCase): point = Point(1, 2) def testInit(self): self.assertEqual(1, self.point.x) self.assertEqual(2, self.point.y) def testEquability(self): point2: Point = Point(1, 2) self.assertTrue(point2, self.point) def testString(self): self.assertTrue(self.point.__str__(), "Point [1; 2]") def testAdd(self): point2: Point = Point(2, 1) point2 = point2 + self.point self.assertEqual(3, point2.x) self.assertEqual(3, point2.y) def testAddOneArg(self): point2: Point = Point(2, 1) point2 += self.point self.assertEqual(3, point2.x) self.assertEqual(3, point2.y) def testSub(self): point2: Point = Point(2, 1) point2 = point2 - self.point self.assertEqual(1, point2.x) self.assertEqual(-1, point2.y) def testSubOneArg(self): point2: Point = Point(2, 1) point2 -= self.point self.assertEqual(1, point2.x) self.assertEqual(-1, point2.y) def testDistance(self): point2: Point = Point(1, 1) point3: Point = Point(0, 1) self.assertEqual(1, self.point.distance(point2)) self.assertEqual(math.sqrt(2), self.point.distance(point3)) def testDict(self): point_dict = {"point": {"x": self.point.x, "y": self.point.y}} self.assertDictEqual(self.point.getDict(), point_dict)
def testIsInsideWithHole(self): hole_geometry = HoleGeometry( [ Point(0.3, 0.3), Point(0.3, 0.5), Point(0.5, 0.5), Point(0.5, 0.3) ], self.cellId, ) self.cellGeometry.addHole(hole_geometry) self.assertFalse(self.cellGeometry.isPointInside(Point(0.4, 0.4))) self.assertTrue(self.cellGeometry.isPointInside(Point(0.2, 0.2)))
class BeaconTest(unittest.TestCase): beacon = Beacon(Point(1, 1)) def testInit(self): self.assertEqual(Point(1, 1), self.beacon.location) def testRSSI_1m(self): location = Point(1, 2) self.assertEqual(self.beacon.rssi_1, self.beacon.getRSSI(location)) def testRSSI_2m(self): location = Point(1, 3) self.beacon.rssi_1 = -69 self.assertAlmostEqual(-75, self.beacon.getRSSI(location), 1) def testRSSI_2mWall(self): location = Point(1, 3) self.beacon.rssi_1 = -69 self.assertGreater(-75, self.beacon.getRSSI(location, is_wall=True)) def testRSSI_2mNoise(self): location = Point(1, 3) numpy.random.seed(0) self.beacon.rssi_1 = -69 self.assertLess(-75 - self.beacon.getRSSI(location, noise=True), 10) def testLocationByRSSI(self): location = Point(1, 3) self.assertAlmostEqual( location.distance(self.beacon.location), self.beacon.getDistanceByRSSI(self.beacon.getRSSI(location)), 1, ) def testDict(self): beacon_type = Beacon.beaconType.get(BeaconTypeEnum.GENERIC) beacon_dict = {"points": self.beacon.location.getDict()} for k, v in beacon_type.__dict__.items(): beacon_dict[k] = v self.assertDictEqual(self.beacon.getDict(), beacon_dict)
def testClosestPointOnSegment(self): segment = [Point(0, 0), Point(1, 0)] self.assertEqual( segment[0], getClosestPointOnSegment(Point(-1, 0), segment), ) self.assertEqual( segment[1], getClosestPointOnSegment(Point(2, 0), segment), ) self.assertEqual( Point(0.5, 0), getClosestPointOnSegment(Point(0.5, 2), segment), )
def getTransitionGeometries(project_data: any) -> List[TransitionGeometry]: """Get transitions from a project file Args: project_data (any): Project json data Returns: List[TransitionGeometry]: List of transitions geometries from the project file """ transition_geometries: List[TransitionGeometry] = [] transition_geometry = list( project_data[ParserJsonKeys.geometry_container.value][ ParserJsonKeys.transition_geometry.value]) for transition in transition_geometry: transition_points: List[Point] = [] for points in transition["points"]: x = points["point"]["x"] y = points["point"]["y"] transition_points.append(Point(x, y)) transition_geometries.append(TransitionGeometry(transition_points)) return transition_geometries
def getHolesGeometries(project_data: any) -> List[HoleGeometry]: """Get holes from a project file Args: project_data (any): Project json data Returns: List[HoleGeometry]: List of holes geometries from the project file """ hole_geometries: List[HoleGeometry] = [] hole_geometry = list( project_data[ParserJsonKeys.geometry_container.value][ ParserJsonKeys.hole_geometry.value]) for hole in hole_geometry: hole_point: List[Point] = [] for points in hole["points"]: x = points["point"]["x"] y = points["point"]["y"] hole_point.append(Point(x, y)) hole_geometries.append(HoleGeometry(hole_point, hole["holeOf"])) return hole_geometries
def getBeaconGeometries(project_data: any) -> List[Beacon]: """Get beacons from project file Args: project_data (any): Project json data Returns: List[Beacon]: List of beacons from the project file """ beacon_geometries: List[Beacon] = [] beacon_geometry = list( project_data[ParserJsonKeys.geometry_container.value][ ParserJsonKeys.beacon_geometry.value]) for beacon in beacon_geometry: for points in beacon["points"]: x = points["point"]["x"] y = points["point"]["y"] beacon_location = Point(x, y) beacon_type = BeaconType(beacon["rssi_1"], beacon["n"], beacon["n_wall"], beacon["noise_var"]) beacon_geometries.append(Beacon(beacon_location, beacon_type)) return beacon_geometries
def testRSSI_2mNoise(self): location = Point(1, 3) numpy.random.seed(0) self.beacon.rssi_1 = -69 self.assertLess(-75 - self.beacon.getRSSI(location, noise=True), 10)
def testRSSI_2mWall(self): location = Point(1, 3) self.beacon.rssi_1 = -69 self.assertGreater(-75, self.beacon.getRSSI(location, is_wall=True))
def testRSSI_2m(self): location = Point(1, 3) self.beacon.rssi_1 = -69 self.assertAlmostEqual(-75, self.beacon.getRSSI(location), 1)
def testRSSI_1m(self): location = Point(1, 2) self.assertEqual(self.beacon.rssi_1, self.beacon.getRSSI(location))
def testInit(self): self.assertEqual(Point(1, 1), self.beacon.location)
def testClosestPoint(self): test_point = Point(0.3, 0.5) closes_point = Point(0.3, 0) self.assertEqual(closes_point, self.transitionGeometry.getClosestPoint(test_point))
def testIsInside(self): self.assertTrue(self.cellGeometry.isPointInside(Point(0.5, 0.5))) self.assertFalse(self.cellGeometry.isPointInside(Point(5, 5))) self.assertTrue(self.cellGeometry.isPointInside(Point(0.5, 1)))
def testAddHoleOutsideOfCell(self): hole_geometry = HoleGeometry( [Point(2, 3), Point(3, 5), Point(5, 2)], self.cellId) with self._caplog.at_level(logging.INFO): self.cellGeometry.addHole(hole_geometry) assert f"Please check if hole fits inside." in self._caplog.text
def testClosestSegment(self): self.assertEqual( 0, self.transitionGeometry._getClosestSegmentId(Point(-1, 0)))
class LocationTest(unittest.TestCase): cellId = "C1" cellName = "cellName" cellPoints = [Point(0, 0), Point(0, 1), Point(1, 1), Point(1, 0)] cellGeometry = CellGeometry(cellId, cellName, cellPoints) @pytest.fixture(autouse=True) def inject_fixtures(self, caplog): self._caplog = caplog def testInit(self): self.assertEqual(self.cellId, self.cellGeometry.id) self.assertEqual(self.cellName, self.cellGeometry.name) self.assertEqual(self.cellPoints, self.cellGeometry.points) def testStringify(self): self.assertEqual( f"Cell: {self.cellName} Points: " + f"[{self.cellPoints[0].x}, {self.cellPoints[0].y}]" + f"[{self.cellPoints[1].x}, {self.cellPoints[1].y}]" + f"[{self.cellPoints[2].x}, {self.cellPoints[2].y}]" + f"[{self.cellPoints[3].x}, {self.cellPoints[3].y}]", self.cellGeometry.__str__(), ) def testAddHole(self): hole_geometry = HoleGeometry( [Point(0.3, 0.3), Point(0.3, 0.5), Point(0.5, 0.3)], self.cellId) self.cellGeometry.addHole(hole_geometry) self.assertEqual(1, len(self.cellGeometry.holes)) def testAddHoleWrongId(self): hole_geometry = HoleGeometry( [Point(0.3, 0.3), Point(0.3, 0.5), Point(0.5, 0.3)], self.cellId + "bad") with self._caplog.at_level(logging.INFO): self.cellGeometry.addHole(hole_geometry) assert (f"Hole is member of: {hole_geometry.memberOf} " + f"while cell id is: {self.cellId}" in self._caplog.text) def testAddHoleOutsideOfCell(self): hole_geometry = HoleGeometry( [Point(2, 3), Point(3, 5), Point(5, 2)], self.cellId) with self._caplog.at_level(logging.INFO): self.cellGeometry.addHole(hole_geometry) assert f"Please check if hole fits inside." in self._caplog.text def testIsInside(self): self.assertTrue(self.cellGeometry.isPointInside(Point(0.5, 0.5))) self.assertFalse(self.cellGeometry.isPointInside(Point(5, 5))) self.assertTrue(self.cellGeometry.isPointInside(Point(0.5, 1))) def testIsInsideWithHole(self): hole_geometry = HoleGeometry( [ Point(0.3, 0.3), Point(0.3, 0.5), Point(0.5, 0.5), Point(0.5, 0.3) ], self.cellId, ) self.cellGeometry.addHole(hole_geometry) self.assertFalse(self.cellGeometry.isPointInside(Point(0.4, 0.4))) self.assertTrue(self.cellGeometry.isPointInside(Point(0.2, 0.2)))
def testSubOneArg(self): point2: Point = Point(2, 1) point2 -= self.point self.assertEqual(1, point2.x) self.assertEqual(-1, point2.y)
def testDistance(self): point2: Point = Point(1, 1) point3: Point = Point(0, 1) self.assertEqual(1, self.point.distance(point2)) self.assertEqual(math.sqrt(2), self.point.distance(point3))
def testSub(self): point2: Point = Point(2, 1) point2 = point2 - self.point self.assertEqual(1, point2.x) self.assertEqual(-1, point2.y)
class LocationTest(unittest.TestCase): transitionPoints = [Point(0, 0), Point(1, 0), Point(1, -1)] transitionGeometry: TransitionGeometry def setUp(self): self.transitionGeometry = TransitionGeometry(self.transitionPoints) def testInit(self): self.assertEqual(self.transitionPoints, self.transitionGeometry.points) def testStringify(self): transition_points = [Point(0, 0), Point(0, 1)] transition_geometry = TransitionGeometry(transition_points) self.assertEqual( f"Transition: [{transition_points[0].x}, {transition_points[0].y}]" + f"[{transition_points[1].x}, {transition_points[1].y}]", transition_geometry.__str__(), ) def testSegments(self): segments = [] for i in range(1, len(self.transitionPoints)): segments.append( [self.transitionPoints[i - 1], self.transitionPoints[i]]) self.assertEqual(segments, self.transitionGeometry.segments) def testDistance(self): test_point = Point(0.3, 0.3) self.assertEqual(0.3, self.transitionGeometry.getDistance(test_point)) test_point = Point(0.3, 0.5) self.assertEqual(0.5, self.transitionGeometry.getDistance(test_point)) test_point = Point(0.9, -0.9) self.assertEqual(0.1, self.transitionGeometry.getDistance(test_point)) test_point = Point(1.3, 0.3) self.assertEqual(round(0.3 * 2**0.5, 4), self.transitionGeometry.getDistance(test_point)) test_point = Point(1.3, 0.3) self.assertEqual(round(0.3 * 2**0.5, 6), self.transitionGeometry.getDistance(test_point, 6)) def testClosestSegment(self): self.assertEqual( 0, self.transitionGeometry._getClosestSegmentId(Point(-1, 0))) def testClosestPointOnSegment(self): segment = [Point(0, 0), Point(1, 0)] self.assertEqual( segment[0], getClosestPointOnSegment(Point(-1, 0), segment), ) self.assertEqual( segment[1], getClosestPointOnSegment(Point(2, 0), segment), ) self.assertEqual( Point(0.5, 0), getClosestPointOnSegment(Point(0.5, 2), segment), ) def testClosestPoint(self): test_point = Point(0.3, 0.5) closes_point = Point(0.3, 0) self.assertEqual(closes_point, self.transitionGeometry.getClosestPoint(test_point)) def testDict(self): transition_dict = { "points": [p.getDict() for p in self.transitionPoints] } self.assertDictEqual(transition_dict, self.transitionGeometry.getDict())