Nobody Told You Wi-Fi Could Do This.
we all know the limitations of GPS in indoor Positioning.The satellite signals ended up getting blocked by indoor walls while on other…
Nobody Told You Wi-Fi Could Do This.

we all know the limitations of GPS in indoor Positioning.The satellite signals ended up getting blocked by indoor walls while on other hands the proper or professional solutions like Ultra-Lite beacons and dedicated BLE structure costs thousands of dollars and required professional setup and efforts but what if we can replicate all that just at a $9 hardware ?
That what i built . The ESP-32 Which is an microcontroller by “Espressif Systems” is the perfect choice for this project as it comes with a Wi-Fi And Bluetooth module inbuilt it has an integrated 2.4Ghz Wi-Fi (802.11 b/g/n) support which is the sole for this project.
Core Idea: Turning Signal Strength Into Distance
Every Wi-fi signal brodcast a free parameters or information attached with it which is the RSSI(Signal Strentgh) which gets weakear as you get far from the access point a phenomenon described by the “log-distance path model”:

Log-Distance Path Model
Where:
• d = Estimated Distance
• A= Reference RSSI at 1 metre
• RSSI= Current Signal Strength
• N= Path Loss Exponent
if we know the distance between any of three points we can calculate the actual position using the “Trilateration ”concept the same concept GPS uses to find the actual location but the what make it harder for us to that is the noise in signal strength which is there because of the intervention of humans , reflections , or other available network and to overcome this we uses something known as the “Kalman Filter”
System Architecture
The Hardware setup is simple :
- 3x stationary anchor nodes , each broadcasting a unique Wi-Fi SSID
- 1x ESP-32 capturing the signal strength strength
Node 1
*
/ \
/ \
/ \
/ 📍 \
/ ESP-32 \
/ \
*---------------*
Node 2 Node 3
Calibrating the Path Loss Model
The Esp-32 was placed at exactly 1,2,3 and 4 meters from a anchor and a total of 50 sample were collected at each distance respectively . a mean of each value is take their respective distances.

RSSI Captured At 1 Meter

RSSI Captured At 2 Meter

RSSI Captured At 3 Meter

RSSI Captured At 4 Meter
The path-loss equation in linear form :

this becomes standard linear regression y=Mx which can be solved by solving:

where :

The above matrix operation and calculation of mean of RSSI for all the distance can be done using python here is how:
# finding "A" and "N" with taking sample of 50 rssi values for 4 different distance
# mathmatical realtion between rssi and distance is
# RSSI=A−10Nlog10(d)
# where "A" is mean of 50 values of rssi taken at distance of 1m
# "N" is environment-specific path-loss exponent
import raw_data as rd
import numpy as np
average_rssai=[]
raw_values=[rd.one_meter,rd.two_meter,rd.three_meter,rd.four_meter]
temp=0
#Taking Average Or Mean Of Raw RSSI Values
for key in raw_values:
temp=sum(key)/len(key)
average_rssai.append(temp)
print("The Average RSSI Found To Be:- ",average_rssai)
temp_list=average_rssai
average_rssai=[
(1,temp_list[0]), #One Meter
(2,temp_list[1]), #Two Meter
(3,temp_list[2]), #Three Meter
(4,temp_list[3]) #Four Meter
]
distance = np.array([x[0] for x in average_rssai])
mean_rssai = np.array([x[1] for x in average_rssai])
#matrix M with first column as 1 and second column as 10log(d) where log is base to 10
M=np.column_stack((
np.ones(len(distance)),
10*np.log10(distance)
))
#least square method
MT=M.T
MTM=MT @ M
MTy=MT @ mean_rssai
x = np.linalg.solve(MTM, MTy)
A = x[0]
n = -x[1]
print("A =", A)
print("n =", n)
after solving equation using the above python code we have the:
A= -61.92dBm
N=1.64
Note: — “ the lower value of N indicates the short distances in a lab environment, reflective surfaces like floors and walls”
Kalman Filtering The RSSI
The Kalman **Filter **is what solves the most important problem of noise in captured RSSI signals . every RSSI stream gets its own instance of filter using the Kalman Filter class.
class KalmanFilter:
def __init__(self, q=0.01, r=4, p=1):
self.q = q
self.r = r
self.p = p
self.x = None
def update(self, measurement):
# First measurement
if self.x is None:
self.x = measurement
self.p = self.p + self.q
# Kalman Gain
k = self.p / (self.p + self.r)
self.x = self.x + k * (measurement - self.x)
self.p = (1 - k) * self.p
return self.x
The Ratio of q/r is 0.0025 and which sets the importance for internal model 400 times more than the measured value which produces very smooth rssi stream for Trilateration. here is how much it helped in smoothing the raw stream.

Raw Vs Kalman Filter For Network 1

Raw Vs Kalman Filter For Network 2

Raw Vs Kalman Filter For Network 3
Trilateration On Filter Stream
with distance estimated from three anchor, target lies at the intersection of the 3 circle which is formed by taking their coordinates as centre and distances as the radius

Where N Varies From 0 To 3
Subtracting equations pairwise eliminates the squared unknowns and yields a linear system solved in closed form:
#d1 d2 and d3 are distances of anchors calculated after using kalman filter on raw rssi
def trilateration(x1, y1, d1,
x2, y2, d2,
x3, y3, d3):
#EQ1(After Subtracting Circle Eq)
A = 2 * x2 - 2 * x1
B = 2 * y2 - 2 * y1
C = d1**2 - d2**2 - x1**2 + x2**2 - y1**2 + y2**2
#EQ2(After Subtracting Circle Eq)
D = 2 * x3 - 2 * x2
E = 2 * y3 - 2 * y2
F = d2**2 - d3**2 - x2**2 + x3**2 - y2**2 + y3**2
dn = (A * E - B * D)
#Zero Divsion Prevension
if dn == 0:
return None
x = (C * E - F * B) / dn
y = (A * F - D * C) / dn
return (x, y)
Results
Over the 118 measurement session, the system tracked the target node moving gradually from (1.99, 0.84) to (1.85, 0.94) metres — a total displacement of about 17 cm.
The position estimates clustered tightly along the x-axis (1.71 to 1.99 m) with slightly more spread along y (0.84 to 1.03 m).That asymmetry is directly traceable to TestNetwork2’s noisy RSSI, which was the primary driver of y-axis uncertainty.


Limitations And Drawbacks
- The calibration of N or the path loss constant was a fixed values while in real rooms it varies with direction and obstacle density.
- A fourth anchor with an overdetermined least-squares solution would make the system significantly more accurate .
- Fixed Kalman Parameters in real rooms it should estimate own its own by taking the real sample variance
Try It Yourself
All the source code , raw data and and results are open-source
- GitHub:- Indoor-Positioning-System-Application-On-ESP32
- (Zenodo): DOI: 10.5281/zenodo.20310320
메타데이터
- post_id
- c28c4e3f8398
- slug
- nobody-told-you-wi-fi-could-do-this-c28c4e3f8398
- url
- https://medium.com/@dev.harshit_67278/nobody-told-you-wi-fi-could-do-this-c28c4e3f8398
- canonical_url
- https://medium.com/@dev.harshit_67278/nobody-told-you-wi-fi-could-do-this-c28c4e3f8398
- author_url
- https://medium.com/@dev.harshit_67278
- status
- ok
- fetched_at
- 2026-07-11 01:06:15