PreprintPDF Available

Reference Positioning Engine & Measurements Database for Indoor Time-Delay Wi-Fi Client Positioning

Preprints and early-stage research may not have been peer reviewed yet.

Abstract and Figures

The following whitepaper describes a reference positioning engine (PE) and time-delay measurements database that can be used for the development and performance evaluation of passive, time-delay based, Wi-Fi scalable location systems. The database includes fine-time measurements (FTM) timestamps that were collected in an indoor Wi-Fi venue. As a turnkey for using this database, a reference Matlab code of a positioning engine (PE) that can be executed by a Wi-Fi client station, is provided. The reference PE demonstrates the usage of the database and enables to analyze the performance of the PE using additional information included in the database files.
Content may be subject to copyright.
Reference Positioning Engine & Measurements
Database for Indoor Time-Delay Wi-Fi Client
Leor Banin, Ofer Bar-Shalom, Nir Dvorecki, and Yuval Amizur
The following whitepaper describes a reference positioning engine (PE) and time-delay measure-
ments database that can be used for the development and performance evaluation of passive, time-
delay based, Wi-Fi scalable location systems. The database includes fine-time measurements (FTM)
timestamps that were collected in an indoor Wi-Fi venue. As a turnkey for using this database, a reference
Matlabrcode of a positioning engine (PE) that can be executed by a Wi-Fi client station, is provided.
The reference PE demonstrates the usage of the database and enables to analyze the performance of
the PE using additional information included in the database files.
Index Terms
Geolocation, Positioning, Position Estimation, Location Estimation, Indoor navigation, Fine timing
measurement, FTM, Time delay estimation, WLAN, Wi-Fi, IEEE 802.11
The following paper outlines the Matlabrcode of a reference positioning engine (PE) that
uses time delay measurements for estimating and tracking the position of a client receiver. The
receiver is assumed to be equipped with IEEE802.11 WLAN (Wi-Fi) chipset that is capable
of fine-timing measurements [1]. To test the PE’s performance, the Matlab code is provided
Copyright c
2018 Intel Corporation. The Matlabrsource code is provided under BSD 3-Clause license.
L. Banin, O. Bar-Shalom, N. Dvorecki and Y. Amizur are with Intel’s Location Core Division, 94 Em Hamoshavot Rd., Petah
Tikva 49527, Israel.,,,
along with a set of files that contain time delay measurements collected in an indoor venue.
The files contain both real-life time delay timestamps of Wi-Fi units operating in the venue
that were collected passively by a client that was roaming within the venue. Additional files,
containing synthetic measurements generated using a network simulator, enable the testing of
network capabilities that are currently not supported by the real Wi-Fi hardware available, but
are planned to be part of the future IEEE802.11az standard. The measurement files consist of
all the information required for enabling the analysis of PE performance and the accuracy of
its position estimates, (for which “ground truth” (reference) position information of the client
receiver is included). The Wi-Fi network deployed in the venue consists of broadcasting stations
(bSTA), which periodically broadcast measurement frames at a rate of 5Hz. These frames enable
the other bSTA to measure their times of arrival (ToA) and publish their measurement results in
their subsequent broadcasting events. This passive location mode is called “collaborative time
of arrival” (CToA). A detailed description of this concept can be found in [3]. The client station
that passively listens to the network broadcast transmissions and measures their ToA is called
a “CToA station” (cSTA). These terms are used within the code. It should be emphasized that
even though the terms used throughout the document correspond to so-called “non-trigger-based
scalable location”, the positioning engine implementation is generic and supports both “trigger-
based” (TB HEz-Multi User ranging) and “non-trigger-based” (VHTz-Single User/SU ranging).
See [2] for details on these protocols. The remainder of this paper is organized as follows.
Section II contains an annotated listing of the Matlabrcode included in the files provided.
Section III contains a detailed description of the measurement data included in the database.
Section IV-A describes the contents of the software package, its installation and its usage. Finally,
Section V provides some numerical examples of the performance measures that can be obtained
by executing the PE code on the given inputs.
A. The MainPE.m Function
The function MainPE.mis the main function used for executing the environment. The function
receives as an input a description of the environment configuration file, which includes all the
information for executing the test: the name of the *.csv measurement file, configuration
parameters of the test venue and so on. The MainPE function first extracts the test configuration
parameters, then extracts the measurement table out of the *.csv file provided, executes the
positioning engine, and then plots the results.
function mainPE(configMfile)
3if exist(’configMfile’,’var’)
configFunc = str2func(configMfile);
configFunc = @testConfig;
cfg = configFunc();
9[measTable, bPos, refPos] = ReadFile(cfg); % Read measurements file
[posEst,pValid] = RunPE(cfg,measTable); % Run PE
11 % pValid - are the entries produced for every packet received by the client
posMat = posEst(:,pValid)’;
13 refPosMat = refPos(pValid,:);
PlotResults(cfg,posMat,bPos,refPosMat) % plot results
15 end
Listing 1. The MainPE.m Function Listing
Following is the listing of the testConfig.m script. Multiple scripts are included in the code
distribution, each is targeted for running a different test configuration.
1function cfg = testConfig()
% % 6rsp @ 5hz, Real data set
3% % Tx time is randomly spread.
cfg.measFile = ’RD.csv’; = cfg.measFile(1:end-4);
cfg.initPos = [-1.5; 7; 1.7];
7% file contain measurement from 6 bSTA, we remove 2 of them.
cfg.bSTA2remove = [1,6]; % for using all bSTAs: cfg.bSTA2remove = [];
9% value must be the equal or bigger than the biggest bSTA id used.
cfg.maxSTAid = 6;
11 cfg.disableClkTracking = 0;
% Map image filename, xMinMax, yMinMax
13 cfg.mapFile = ’arc_map.png’;;
cfg.xMinMax = [-44.5301, 6.7192];
15 cfg.yMinMax = [-15.3423, 35.9070];
Listing 2. The testConfig.m Function Listing
B. The RunPE.m Function
The function RunPE.m is the function that executes the EKF-based PE. The function loops
over all the measurements. The function prepares each measurement to be fed into an EKF-based
PE for processing. A measurement is defined as,
z= (ToAj+νj)(ToDi+νi)(1)
where ToAjdenotes the timestamp corresponding to the time of arrival measured by the jth
receiver, and ToDidenotes the timestamp corresponding to the time of departure measured by
the ith transmitter. As each timestamp is reported at the local clock of the measuring unit, the
scalars νi, νj, are introduced. These scalars correspond to the clock offsets of the jth receiver and
ith transmitter that are measured w.r.t. to the client clock. By definition, if the ToA is measured
by the client directly then, νj0. This process is implemented by lines 24-57 of the following
listing. Depending on the type of the measurement, the EKF is called on line 59 or 61 with the
appropriate parameters.
The RunPE loops over all the measurements contained in the measurements table. The first
action in the loop is to ensure proper initialization of the EKF states and variables. The bSTAs
clock offsets states must be initialized prior to the processing of any measurements that involve
these bSTAs. As seen from lines 15-21, the first measurement used for initializing the clock offset
states, is a measurement of a packet that was received by the client directly. This initializes the
clock offset state of the transmitting bSTA with some rather coarse accuracy (as the distance
between the client and the bSTA is neglected at this stage). The initialization of the additional
offsets states is implemented in lines 24-47, which implement the initialization phase of all the
offsets for all the other bSTA at multiple scenarios of measurement types and the order they
arrive. Any measurement, which is used for state initialization, is discarded afterwards and is
not used for further states updating.
2function RunPE(cfg, measTable)
measN = size(measTable,1);
4KF = KFclass; % Kalman Filter Constructor
INIT_KF = 1; % KF Initialization flag
6lastPacketId = -999;
lastTxid = -999;
8staOffsetInit = zeros(6,1); % vector to indicate if offset was init
posEst = nan(3,measN);
10 pValid = false(measN,1);
initPos = cfg.initPos;
12 for k = 1:measN
14 if INIT_KF
if type==0 % Rx by cSTA
16 KF.initKF(rxTime,initPos);
INIT_KF = 0;
18 initOffset = txTime - rxTime;
20 staOffsetInit(txId) = 1;
22 continue;
24 if staOffsetInit(txId)==0 || (rxId>0 && staOffsetInit(rxId)==0)
if rxId>0 && staOffsetInit(txId)==0 && staOffsetInit(rxId)==0
26 % bSTA to bSTA - both not init --> cannot do anything
28 elseif rxId < 0 && staOffsetInit(txId)==0
% bSTA to Client - init bSTA
30 initOffset = rxTime - txTime + KF.Xoffset(txId);
32 staOffsetInit(txId) = 1;
34 elseif staOffsetInit(txId)==0 && staOffsetInit(rxId)==1
% for k = 1:measN% bSTA to bSTA - tx not init
36 initOffset = txTime - rxTime + KF.Xoffset(rxId);
38 staOffsetInit(txId) = 1;
40 elseif staOffsetInit(txId)==1 && staOffsetInit(rxId)==0
% bSTA to bSTA - rx not init
42 initOffset = rxTime - txTime + KF.Xoffset(txId);
44 staOffsetInit(rxId) = 1;
46 end
48 % Every packet is defined uniquely by its packetId and txId
% If the new measurement differ from the last packet
50 % the time of new packet is obtained using KF.GetKFtime
if packetId ˜= lastPacketId || txId ˜= lastTxid % detect new packet
52 kfTime = KF.GetKFtime(txTime,txId); % convert txTime to cSTA clock
lastPacketId = packetId;
54 lastTxid = txId;
56 % prepare the measurement for KF
meas = rxTime - txTime;
58 if type % bSTA to bSTA
posEst(:,k) = KF.Run(meas,kfTime,staTx,staRx,’BSTA_TO_BSTA’); % Run KF
60 else % bSTA to cSTA
posEst(:,k) = KF.Run(meas,kfTime,staTx,[],’RX_BY_CSTA’); % Run KF
62 pValid(k) = true;
64 end % INIT_KF
% ----------------------------------------
66 % Outlier filtering code may be added here
% ----------------------------------------
68 end % for k = 1:measN
% ------------------------------------------------------------------------
72 function [pId,type,txId,rxId,txTime,rxTime,staTx,staRx] = ParseMeasLine(measLine)
% line Format: packetId,type,txId,rxId,txPos,rxPos,txTime,rxTime,refPos
74 pId = measLine(1);
type = measLine(2);
76 txId = measLine(3);
rxId = measLine(4);
78 txTime = measLine(11);
rxTime = measLine(12);
80 %----------------------------------------------------------
staTx.index = txId; % Transmitting bSTA ID
82 staTx.pos = measLine(5:7)’; % Transmitting bSTA position
staRx.index = rxId; % Receiver bSTA ID (not used if client)
84 staRx.pos = measLine(8:10)’; % Receiver bSTA position (not used if client)
86 end
88 function c = isClient(id)
90 end
Listing 3. The RunPE.m Function Listing
C. The KFClass.m Class
The EKF code is implemented in an object-oriented fashion. Class-based object-oriented
programming defines an object constructor, which is a special type of subroutine called to create
an object. The EKF object constructor is initialized on line no. 4 of the RunPE.m function using
the code line KF = KFclass(cfg);. This instantiates an object called KF, supporting the
properties and methods defined by KFClass, which are implemented in KFClass.m. Such
object has the following properties:
2X% States vector
P% States covariance matrix
4sysNoisePos % position system noise
sysNoiseClk % clock system noise
6t% KF time
stateN % number of KF states
8clkN % number of bSTA clocks being tracked
statePerClk % number of states per clock
10 Xoffset_Index % clock offsets states index subvector
Xdrift_Index % clock drifts states index subvector
12 Xoffset % clock offsets states subvector
Xdrift % clock drifts states subvector
14 NO_CLK_TRACKING % Flag to effectively disable clock tracking
Listing 4. The KFclass Properties Listing
The class properties are addressed by KFclass object constructor subroutine.
1function obj = KFClass(cfg)
obj.clkN = cfg.maxSTAid; % should be init to the maximal bSTA index
3obj.stateN = 3 + 2*obj.clkN; % Total number of filter states
obj.Xoffset_Index = 3 + 1:obj.statePerClk:obj.stateN;
5obj.Xdrift_index = 3 + 2:obj.statePerClk:obj.stateN;
obj.sysNoiseClk = [1e-15, 0.01e-6] .ˆ2; % Set system noise covariance matrix
7% values for clock offset and drift.
obj.sysNoisePos = [1.0, 1.0, 0.1] .ˆ2; % Set system noise covariance matrix
9% values for the client position.
% --------------------------------------------
11 % Outlier filtering code may be added here...
% --------------------------------------------
13 end
Listing 5. The KFClass Method Constructor Listing
As was describe in [3], the EKF system model is defined by the following recursive equation,
xk=Fkxk1+wk, k 0(2)
where the index kdenotes the discrete time-step. The vector xkdenotes an N×1states vector,
which describes the parameters being estimated and tracked by the filter. The states vector for the
client-mode consists of the client’s position coordinates and per-bSTA clock parameters (clock
offset and clock offset change rate/drift). The size of the EKF state vector is thus: N= 3 + 2M,
where Mdenotes the number of bSTAs being received by the cSTA (both directly and indirectly),
pk,[xk, yk, zk]T
νm,k ,[νm,k,˙νm,k]T
1,k, . . . , ˜
M,k ]T
The vector wkdenotes a random N×1model noise vector, which described the uncertainties
in the system model and has the following statistical properties:
The system-model noise covariance, Qkis assumed to have the following structure:
Qk= ∆t·
Qp,k 0
0 IM˜
where denotes Kronecker multiplication and,
Qp,k ,
x0 0
0 ˜σ2
0 0 ˜σ2
c,k ,
0 ˙σ2
1) EKF Initialization: The EKF initialization phase occurs before the first execution of the
EKF (i.e., before the Run method is called for the first time). During this phase, the initial
values of the filter states vector and its corresponding covariance matrix are set. The filter states
covariance matrix is defined as follows,
where ¯
xk,E{xk}. When the filter is initialized the state-covariance matrix is assumed to be,
0 IM˜
where σν,0,σ2
˙ν,0denote the initial values for the standard deviations of the clock offsets and
drifts, and ˜
Pp,0denotes the initial value of states covariance matrix given by,
x,00 0
0 0 σ2
1function obj = initKF(obj,initTs,initPos)
obj.t = initTs; % Initialize EKF time
3Xinit = zeros(obj.stateN,1);
Xinit(1:3) = initPos; % Initialize EKF client position states
5ErrSigma = 10e-3; % Initialize clock offset STD
PPMsigma = 100e-6; % Initialize clock drift STD
7latSigma = 10; % Initialize horizontal position STD
Zsigma = 0.5; % Initialize vertical position STD
9PinitPerClk = diag([...
11 PPMsigma...
13 PinitPerPos = diag([...
15 latSigma...
17 ].ˆ2);
Pinit = obj.BuildBigMat(PinitPerPos,PinitPerClk);
19 % init KF:
obj.X = Xinit; % initialize the KF states vector
21 obj.P = Pinit; % initialize the KF states covariance matrix
% ---- Update easy-access vectors ------
23 obj.Xoffset = obj.X(obj.Xoffset_Index);
obj.Xdrift = obj.X(obj.Xdrift_index);
25 % --------------------------------------
Listing 6. The initKF Method Listing
2) EKF Prediction: The EKF time as well as EKF states, are predicted according to the ToA
of the received packet. The predicted state-vector is defined as,
The predicted covariance estimate:
The method predictKF implements the EKF prediction step. It receives a handle to the
KFClientClass, the states transition matrix, Fk, and the system noise covariance matrix
Qk. Equations (12)-(13) are realized by the method predictKF.
function predictKF(obj,F,Q)
2obj.X = F *obj.X; % calculate X_k/k-1
obj.P = F *obj.P *F’ + Q; % calculate P_k/k-1
Listing 7. The predictKF Method Listing
The dynamic system-model linear transfer function denoted by Fk, is an N×Nblock-diagonal
matrix defined as follows.
0 IM˜
where tcorresponds to the elapsed time between two consecutive discrete time steps and,
1 ∆t
0 1
The states transition matrix, Fk, is generated using the CreateF method as follows.
function F = CreateF(obj,dt)
2FperPos = eye(3); % per position
FperClk = [1 dt ; 0 1 ]; % per tracked bSTA clock
4F= obj.BuildBigMat(FperPos,FperClk);
Listing 8. The CreateF Method Listing
The system noise covariance matrix, Qk, is created using the method CreateQ as follows.
function Q = CreateQ(obj, dt)
3QperPos = diag( dt *obj.sysNoisePos );
if obj.NO_CLK_TRACKING && dt > 10e-3
5% setting high system noise, making the offset and drift
% states to have a very little on the updated outcome..
7obj.X(obj.Xoffset_Index) = obj.X(obj.Xoffset_Index) + 1e-6*randn(obj.clkN,1);
QperClk = diag( [1e-6 1e-6].ˆ2 );
QperClk = diag( dt *obj.sysNoiseClk );
11 end
Q= obj.BuildBigMat(QperPos,QperClk);
13 end
Listing 9. The CreateQ Method Listing
The CreateQ method includes a mechanism that effectively disables the clock tracking of
the EKF for measurements that are separated (in time) by 10ms or more. This mechanism is
implemented in lines 4-8 of the method. This effect is achieved by adding a relatively large
random noise to the clock offset with a standard deviation of 1µsec and setting the filter clock
offset and drift system-model noise to relative large levels of 1µs and 1 ppm, respectively.
The CreateQ and CreateF methods use the BuildBigMat method as a utility for
constructing the larger matrices, which correspond to all the states.
1function out = BuildBigMat(obj,posMat,clkMat)
out = zeros(obj.stateN);
3out(1:3,1:3) = posMat;
for k = 1:obj.clkN
out(s:s+1,s:s+1) = clkMat;
Listing 10. The BuildBigMat Method Listing
3) EKF Measurement Model: The EKF measurement model is defined as,
zk=h(xk) + vk(16)
where zkis a ToF measurement. The function h(xk)denotes the nonlinear measurement model
transfer function, and vkdenotes the additive measurement noise that has the following statistical
E{vk}= 0
mδkj (17)
where δkj denotes the Kronecker delta.
The method CreateR generates the respective measurement noise variance according to the
measurement type, measType.
function R = CreateR(obj,measType)
2if strcmp(measType, ’BSTA_TO_BSTA’)% bSTA to bSTA
R = (3e-9)ˆ2;
4elseif strcmp(measType,’RX_BY_CSTA’)% Rx by client
R = (6e-9)ˆ2; ’RX_BY_CSTA’)% higher meas. var. since client is mobile
Listing 11. The CreateR Method Listing
The noise-free measurement models for bSTA cSTA and bSTA bSTA are given by (18)
and (19), respectively.
h(xk) = 1
cpkqi∥ − νi,k (18)
hl(xk) = 1
cqjqi+νj,k νi,k (19)
Since the measurement transfer function, h(·)is nonlinear, it cannot be applied to estimate the
measurements covariance matrix directly. Instead we linearize h(·)by replacing it with its first
order Taylor series expansion, calculated around ˆ
xk|k1) + Hk·(xkˆ
where the notation, ˆ
xn|mrepresents the estimate of xat time ngiven observations up to and
including time mn. The matrix Hkdenotes the Jacobian of the measurement model function
vector h(·), which is a J×Nmatrix defined as,
∂x2· · · ∂h1
∂x2· · · ∂hJ
[Hk]ij ∂hi
The method CreateH generates the linearized measurement model matrix lines (a line per
1function H = CreateH(obj,type,staTx,staRx)
H = zeros(1,obj.stateN);
3if strcmp(type,’RX_BY_CSTA’)
H(1:3)= (obj.X(1:3)’ - staTx.pos’)/norm (obj.X(1:3)’ - staTx.pos’)/3e8;
5H(4 + (staTx.index-1)*obj.statePerClk) = -1; % ToD
elseif strcmp(type,’BSTA_TO_BSTA’)
7H(4 + (staRx.index-1)*obj.statePerClk) = 1; % ToA
H(4 + (staTx.index-1)*obj.statePerClk) = -1; % ToD
Listing 12. The CreateH Method Listing
The Jacobian is obtained by calculating the partial derivatives of (18)-(19) w.r.t. to the states
vector. Equations (22)-(23) define compact expressions for the matrix Hklines, depending on the
measurement type. Equation (22) defines the matrix line entry for a bSTAcSTA measurement,
while (23) defines the corresponding line for the bSTAbSTA measurement case.
where eidenotes the ith column of an M×Midentity matrix and ˜
e1= [1,0]T. Equations
(22)-(23) are realized by the CreateHx method. Notice that since the measurements are fed
into the EKF one by one (and not as a vector of measurements), the matrix Hkis never used
as a “matrix”, but only as a line-vector, according to the current measurement type.
function hi = CreateHx(obj,type,staTx,staRx)
2if strcmp(type,’RX_BY_CSTA’)
Xpos = obj.X(1:3)’;
4hi = norm(Xpos - staTx.pos’)/3e8 - obj.Xoffset(staTx.index);
elseif strcmp(type,’BSTA_TO_BSTA’)
6tof = norm(staTx.pos - staRx.pos)/3e8;
hi = obj.Xoffset(staRx.index) - obj.Xoffset(staTx.index) + tof;
Listing 13. The CreateHx Method Listing
The timestamps associated with a packet are translated into the client’s local timebase using the
method KF.GetKFtime. This method is called from the RunPE.m function (see line 52)
1function KFtime = GetKFtime(obj,localTime,index)
KFtime = localTime - obj.Xoffset(index);
Listing 14. The GetKFtime Method Listing
D. EKF Update
The measurements included in the received packet are updated according to the new EKF
predicted time. The update is done per individual measurement (as opposed to joint updating a
vector of measurements), such that a matrix inverse in (26) is not required. The measurement
innovation (i.e., the measurement residual) is obtained using,
For a vector of measurements, the innovation covariance matrix is calculated using,
The near-optimal Kalman filter gain is obtained using,
Using (26), the updated state estimate is calculated as,
And the updated estimate covariance,
Pk|k= (IKkHk)Pk|k1(28)
Equations (26)-(28) are executed by calling the following updateKF method.
1function updateKF(obj,z,H,R,hi)
K = obj.P *H’ / (H *obj.P *H’ + R); % calculate K - filter gain
3obj.X = obj.X + K*(z - hi); % calculate X - Update states
obj.P = obj.P - K *H*obj.P; % calculate P - Update states covariance
Listing 15. The updateKF Method Listing
The Run method is called per measurement and executes the EKF algorithm, which is detailed
in [3].
1function posEst = Run(obj,z,t,staTx,staRx,measType)
dt = max(0,t - obj.t); % time difference from last update
3obj.t = obj.t + dt; % update current KF time
5F = obj.CreateF(dt); % generate the states transition matrix
Q = obj.CreateQ(dt); % generate the system noise covariance matrix
7obj.predictKF(F,Q); % Do KF prediction
9% ---- Update easy-access vectors ------
obj.Xoffset = obj.X(obj.Xoffset_Index); % Clock offsets vector
11 obj.Xdrift = obj.X(obj.Xdrift_index); % Clock drift vector
% --------------------------------------
H = obj.CreateH(measType,staTx,staRx);
15 hi = obj.CreateHx(measType,staTx,staRx); % generate the linearized meas. matrix
R = obj.CreateR(measType); % generate meas. noise covariance matrix
% ------------------------------------------------
19 % Measurement outlier filtering may come here...
% ------------------------------------------------
obj.updateKF(z,H,R,hi); % Do KF update
23 % ---- Update easy-access vectors ------
obj.Xoffset = obj.X(obj.Xoffset_Index); % Clock offsets vector
25 obj.Xdrift = obj.X(obj.Xdrift_index); % Clock drift vector
% --------------------------------------
27 posEst = obj.X(1:3); % updated current position estimation vector
end % function Run
Listing 16. The Run Method Listing
As seen in lines 51-55 of RunPE, the system updates the EKF time variable (kfTime, by calling
the method GetKFtime) only once per transmitted packet, (which is uniquely identified by its
packet ID, packetId, and its transmitter ID, txId). This condition effectively causes the
EKF states’ prediction to be done only once per transmitted packet. Only the first measurement
associated with the packet that is fed into the EKF will have a t= (kfTimekkfTimek1)>
0(see line 6 in Run method). For each additional measurement corresponding to that packet,
GetKFtime is not called and thus, kfTime is not updated. Consequently, t= (kfTimek
kfTimek1)0. As the states’ prediction relies on the values of Fkand Qk, (see line 12
in Run method), both of which depend on t, having t= 0 effectively disables the states’
prediction, and enables only the states’ update per measurement.
E. Outlier Rejection
The EKF code contains no outlier measurement rejection mechanisms, but only “hooks” to
places where such mechanisms might be added into the code. Examples of EKF outlier rejection
mechanisms are described in e.g., [5, Chapter 15.2].
F. Performance Visualization
The following function implements the results visualization and enables to present the posi-
tioning error and the trajectories of the cSTA on a map of the venue. The architectural blueprint
map of the test venue is provided as *.png file named ’arc_map.png’. Additional maps may
be added similarly in future releases of this database. The positioning error statistics is presented
by means of the empirical cumulative distribution function (ECDF) of the norm between the
estimated position and its ground-truth reference.
2function PlotResults(cfg,posMat,bPos,refPos)
% Plot Ref. and Estimated Trajectories on Map
4figure(cfg.MapFigNum);clf;hold on;axis equal
ImgData = imread(cfg.mapFile);
6FloorPlan = image(ImgData, ...
’XData’, cfg.xMinMax, ...
8’YData’, fliplr(cfg.yMinMax));
axis([-12, 6.7, -5 28])
10 uistack(FloorPlan, ’bottom’);
12 plot(posMat(:,1),posMat(:,2),’b.’,’MarkerSize’,6,’MarkerFaceColor’,’b’)
14 plot(bPos(:,1),bPos(:,2),’ro’,’MarkerSize’,8,’LineWidth’,3);
axis([min(cfg.xMinMax), max(cfg.xMinMax), -5 25])
16 xlabel(’x [m]’)
ylabel(’y [m]’)
18 title(cfg.measFile)
grid on; axis equal; box on
20 leg1 = legend(’$\hat\mathbf{p}$’,’$\mathbf{p}$’,’bSTA’,’Location’,’southwest’);
% Plot Positioning Error Empirical CDF (ECDF)
24 Nsamp = length(posMat(:,1));
posErr = zeros(Nsamp,1);
26 for kk = 1:Nsamp
posErr(kk) = norm(posMat(kk,:)-refPos(kk,:));
28 end
[X,Y] = CalcEcdf(posErr);
30 figure; hold on;grid on; box on
32 xlabel(’Position Error [m]’)
ylabel(’CDF [%]’)
34 title(cfg.measFile)
function [x,y] = CalcEcdf(x)
38 N = length(x);
x = sort(x);
40 y = (1:N)/N*100;
42 end
Listing 17. The PlotResults Function Listing
The reference code of the PE is distributed along with several measurements files. These files
enable the code users to evaluate the performance of the reference PE and additional PEs that
can accept the measurement format. The measurements files included are listed in Section IV-B3.
Additional files may be added in the future. Each file is a *.csv file format that spreads over
14 columns (A-N), where each line represents a measurement with the following data format
(the text in (Courier) font refers to the naming of that parameter in the reference code):
Column A - packet identification (pId)
Column B - packet type (type): 0 - bSTAbSTA, 1 - bSTAclient (cSTA)
Column C - Transmitting bSTA identification (txId)
Column D - Receiving bSTA identification (rxId)
Columns E-G - Transmitting bSTA position coordinates (x,y,z) (txPos)
Columns H-J - Receiving bSTA position coordinates (x,y,z) (rxPos)
Column K - Broadcast packet time of transmission (txTime) at the time-base of the
Column L - Broadcast packet time of reception (rxTime) at the time-base of the receiver
Columns M-O - Client receiver ground truth (reference) position (x,y,z) coordinates (refPos)
The database includes a single file with real-measurements collected from the network and 4
files containing simulated measurements. The simulated measurements were generated using
skewed-clock modeling as described in [4]. It should be emphasized that this model assumes
only Gaussian-distributed errors (on the clock and the measurement noise), but does not include
any biases or other effects resulting from the physical propagation channel (e.g. shadowing,
multipath reflections etc.). Namely, the timestamps were generated under a line-of-sight (LoS)
assumption between all the receivers, and thus correspond to the geometric distance between the
transmitters and the receivers. The files currently contained in the database are the following:
RD.csv - real-data (RD) measurements file containing measurements of 6 bSTAs, broad-
casting measurement frames at a rate of 5Hz, where the transmission time of each bSTA is
randomly spread over time.
SD.csv - simulated-data (SD) measurements file containing measurements of 6 bSTAs,
broadcasting measurement frames at a rate of 5Hz. The clock drifts were simulated with
¨ν=0.01ppm/sec, ˜σ=3ns, ¯σ=6ns (see [4]). The bSTA broadcasts transmission times are
randomly spread.
SDMU.csv - IEEE 802.11az multi-user ranging simulated-data measurements file contain-
ing measurements of 6 bSTAs, broadcasting measurement frames at a rate of 5Hz. The
clock drifts were simulated with ¨ν=0.01ppm/sec, ˜σ=3ns, ¯σ=6ns. The bSTA broadcasts
transmission times are all time-aligned with minimal spacing of about 50µs.
SDSMU.csv - IEEE 802.11az multi-user ranging simulated-data measurements file con-
taining measurements of 6 bSTAs, broadcasting measurement frames at a rate of 5Hz. The
clock drifts were simulated with ¨ν=0.01ppm/sec, ˜σ=3ns, ¯σ=6ns. The bSTA broadcasts
transmission times are aligned in two groups (Split MU): [1,2,5] are 100ms offset from
The following section describes the how to install and execute the simulation environment.
A. Download Information
The package may be downloaded from the Intel’s repository on the GitHub website:
B. Software Installation
To install the software, simply create a folder on your PC’s local drive and copy all the files into it. The folder
should contain the following files:
1) Package Code Files:
1) MainPE.m - contains the main function to run the simulation environment.
2) configFunc - contains a function for extracting the test configuration.
3) ReadFile.m - contains a function for reading the *.csv measurement files.
4) RunPE.m - a function that implements the .
5) KFclass.m - contains a class of methods implementing the EKF.
6) PlotResults.m - contains a function that implements the results visualization (trajectory plotting and
2) Test Configuration Files:
1) testConfig.m - executes the default real-data (RD) measurements file (RD.csv).
2) testConfigSD.m - executes the simulated-data (SD) measurements file (SD.csv).
3) testConfigSD_NT.m - executes the simulated-data (SD) measurements file (SD.csv), but with no time-
tracking (NT). This effect is acheived by manipulating the model-noise covariance matrix in the method
4) testConfigSDMU.m - executes the simulated-data of passive multi-user (MU) ranging measurements file
5) testConfigSDMU_NT.m - executes the simulated-data of passive multi-user (MU) ranging measurements
file (SDMU.csv), but with no time-tracking (NT).
3) Supplementary Files:
1) RD.csv - real-data (RD) measurements file.
2) SD.csv - simulated-data (SD) measurements file
3) SDMU.csv - IEEE 802.11az multi-user ranging simulated-data.
4) SDSMU.csv - IEEE 802.11az multi-user ranging simulated-data.
5) arc_map.png - an architectural blueprint figure of the test venue.
6) - an text file containing the BSD-3-Clause license terms.
7) - a text file describing the repository contents.
C. Software Execution
The code was tested on MatlabrR2016b (but may also run on its earlier versions).
To execute the code:
1) Set current Matlabrto the folder to which the *.zip was extracted (or add that folder to the Matlabr
search path).
2) In the MatlabrCommand Window type: main(TesConfigFileName),
where TesConfigFileName denotes the name of the Test Configuration *.m file.
The following options are presently supported:
mainPE() - executes the PE with the RD.csv measurements file .
mainPE(’testConfigSD’) - executes the PE with the SD.csv measurements file.
mainPE(’testConfigSDMU’) - executes the PE with the SDMU.csv measurements file.
mainPE(’testConfigSDSMU’) - executes the PE with the SDSMU.csv measurements file.
mainPE(’testConfigSDMU_NT’) - executes the PE with the SDMU.csv measurements file, but without
clock tracking.
mainPE(’testConfigSDSMU_NT’) - executes the PE with the SDSMU.csv measurements file, but
without clock tracking.
The following section provides performance examples of the reference PE when operated on the input mea-
surements files included in the database. The output is generally available as depicted in Fig. 2, which includes a
plot of the estimated and reference client trajectories on the venue’s blueprint map, along with the positioning
errors’ empirical cumulative distribution functions (ECDF). The bSTAs are located as shown in Fig. 1. For
-10 -5 0 5
x [m]
y [m]
Fig. 1. bSTA Positions
the following tests, the measurements coming from bSTA#1 and bSTA#6 were ignored by enabling the line
cfg.bSTA2remove = [1,6]; on testConfig.m. To enable measurements of all bSTAs this line should
be modified as cfg.bSTA2remove = [];. Other combinations of bSTAs may be enabled accordingly. Fig. 2
provides an illustration of the expected output when using SD.csv as an input.
Fig. 3 compares the positioning error ECDF of all the simulated-data cases.
Fig. 3 compares the positioning error ECDF of the real measured data - with and without outlier rejection. As
explained, the simulated data (SD) is generated using Gaussian-distributed additive errors. Due the nature of these
errors, outliers and range-bias errors are not present in this data-set. Consequently, the EKF, which is optimized
for the Gaussian-case, performs well (as indicated by the “SD” and “SDMU” cases). For the case of split-MU,
there are two pairs of MU AP + bSTA. The inferior performance exhibited for the case where the EKF does not
track the clock offsets and drifts (“NT”), can be mainly attributed to the poor resulting geometry of the two pairs.
Enabling the data from the two additional bSTAs improves the results to the level of “SDMU”.
-10 -5 0 5
x [m]
y [m]
Position Error [m]
CDF [%]
Fig. 2. Reference and Estimated Trajectories for SD.csv
0 1 2 3 4 5 6 7 8
Position Error [m]
CDF [%]
Fig. 3. Comparison of Positioning Error CDFs for Simulated Data
As can be seen from Fig. 4, the positioning accuracy using the real-measured data is somewhat inferior compared
to the simulated data. As aforementioned, the performance degradation is mainly attributed to the outliers and range-
biases, which are introduced, by nature, in real-network measured data, but do not exist in the model generating the
simulated data. The outliers may be filtered-out using outlier-rejection mechanisms that can be applied to the EKF
code. An example of the resulting performance using some mild, heuristic outlier-rejection is depicted in Fig. 4 for
Position Error [m]
CDF [%]
RD + outlier rejection
Fig. 4. Comparison of Positioning Error CDFs for Simulated Data
We presented a reference Matlabrimplementation of a positioning engine for indoor time-delay Wi-Fi client
positioning. The positioning engine is based on a linearized version of the well-known Kalman filter algorithm.
The source code is provided along with a measurements database for assessing and developing time-delay based
Wi-Fi client positioning systems.
[1] IEEE Std 802.11TM-2016 (Revision of IEEE Std 802.11-2012) - Part 11: Wireless LAN Medium Access Control (MAC)
and Physical Layer (PHY) Specifications, IEEE 802.11 Working Group, December 7th, 2016.
[2] P802.11azTM/D0.1 Draft Standard for Information Technology - Telecommunications and Information Exchange Between
Systems Local and Metropolitan Area Networks - Specific Requirements Part 11: Wireless LAN Medium Access Control
(MAC) and Physical Layer (PHY) Specifications - Amendment 8: Enhancements for Positioning, IEEE 802.11 Working
Group, November, 2017.
[3] L. Banin, O. Bar-Shalom, N. Dvorecki and Y. Amizur, “High-Accuracy Indoor Geolocation using
Collaborative Time of Arrival - Whitepaper,” doc.: IEEE 802.11-17/1387R0, Sept. 2017, [available online:
[4] L. Banin, O. Bar-Shalom, N. Dvorecki and Y. Amizur, “Wi-Fi Positioning using Collaborative Time of Arrival (CToA),
IEEE Trans. on Wireless Communications, under review, Jan. 2018.
[5] P. D. Groves, Principles of GNSS, Inertial, and Multisensor Integrated Navigation Systems, Artech House Boston-London,
ResearchGate has not been able to resolve any citations for this publication.
Full-text available
Collaborative time of arrival (CToA) is the next generation, indoor geolocation protocol, which is designed for enabling scalability of the existing IEEE802.11/Wi-Fi-based, geolocation systems. The protocol leverages on the IEEE802.11 fine timing measurements (FTM) capabilities, enabled in state-ofthe-art Wi-Fi chipsets, and supports two concurrent operation modes; the CToA “client-mode” enables “GPS-like” operation indoors, and allows an unlimited number of clients to privately estimate their position and navigate indoors, without exposing their presence to the network. The CToA “network-mode” is designed for large-scale asset-tracking applications, and enables a centric positioning server to pinpoint objects equipped with wireless, Wi-Fi-based, low-power electronic tags (e-Tags). The CToA protocol is a broadcast-based protocol that operates over an un-managed network, built out of cheap, unsynchronized units called “CToA broadcasting stations” (bSTA). The bSTAs, which are stationed at known locations, periodically broadcast a unique beacon transmission and publish its time of departure (ToD). Neighbor bSTA units and clients that receive the beacon broadcast, measure and log its time of arrival (ToA). Every bSTA publishes its most recent timing measurement log as part of its next beacon broadcast. CToA clients combine their own ToA measurements with those published by the bSTAs, in order to estimate and track their location. CToA e-Tag clients act similar to bSTAs, and simply wake-up sporadically to broadcast a CToA beacon. The ToA of that broadcast is measured and logged by the receiving bSTAs similarly to beacons broadcast by other bSTAs. The timing measurement report is then delivered to a centric positioning server that can estimate and track the location of numerous CToA-based e-Tags, simultaneously. The paper outlines the principles of the CToA protocol and the mathematical background of the position estimation algorithms. In addition, performance examples as well as theoretical analysis of the expected positioning accuracy are provided.
Full-text available
Capturing a wave of innovation and creativity in the field, this greatly expanded edition of Principles of GNSS, Inertial, and Multisensor Integrated Navigation Systems combines a comprehensive review of the latest navigation and positioning technologies with clear explanations of their underlying principles and details on how to integrate technologies for maximum accuracy and reliability. Global navigation satellite systems (GNSS), inertial navigation, terrestrial radio positioning, odometry, pedestrian dead reckoning, magnetic heading determination, image-based navigation, and map matching are explained alongside a host of other technologies suitable for air, land, sea, underwater, indoor, and space navigation and positioning. As well as providing in-depth coverage of INS/GNSS and multisensor integration, the book describes fault detection and integrity monitoring, discusses design and testing, and incorporates the latest thinking on context-dependent and cooperative positioning. The accompanying DVD includes MATLAB® INS/GNSS simulation software, extensive appendices, worked examples, and problems. Providing expert guidance for engineers, researchers, educators, and students in navigation and positioning, this book helps readers: - Design, develop, and debug INS/GNSS, and multisensor integrated navigation systems; - Select the right combination of technology and sensors to meet the requirements of particular navigation or positioning applications; - Make more informed engineering and application decisions by better understanding the characteristics, performance, and errors of different positioning technologies.
11-2012) -Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications, IEEE 802.11 Working Group
IEEE Std 802.11 TM -2016 (Revision of IEEE Std 802.11-2012) -Part 11: Wireless LAN Medium Access Control (MAC) and Physical Layer (PHY) Specifications, IEEE 802.11 Working Group, December 7th, 2016.
Wi-Fi Positioning using Collaborative Time of Arrival (CToA)
  • L Banin
  • O Bar-Shalom
  • N Dvorecki
  • Y Amizur
L. Banin, O. Bar-Shalom, N. Dvorecki and Y. Amizur, "Wi-Fi Positioning using Collaborative Time of Arrival (CToA)," IEEE Trans. on Wireless Communications, under review, Jan. 2018.
Execution The code was tested on Matlab R2016b (but may also run on its earlier versions)
  • C Software
C. Software Execution The code was tested on Matlab R2016b (but may also run on its earlier versions).