2 % (C) 2008 Gergely Imreh <imrehg@gmail.com>
8 % Crude Octave3 code to attempt to find GSM tower positions
9 % using log from Cell Locator:
10 % http://repo.or.cz/w/CellLocator.git
11 % http://projects.openmoko.org/projects/rocinante/
13 % Very rough, trying to fit free-space propagation model to
14 % recorded signal. Also visualizing log data.
20 % Parameters to modify
23 logfile = 'log_cells.csv';
24 % Clean up before use! Remove headers, and possible invalid lines
26 % Which GSM cell to check
28 % it is the number in the order of the cells listed in logfile
29 % cellcheck = [1..number-of-different-cellid]
31 % Whether to plot: 0/1
36 disp('Parameters ==============')
37 disp(['Logfile: ',logfile])
38 disp(['Cell to check : ' num2str(cellcheck)])
47 %% Parsing log into separate variables
55 % Received signal level
57 % MCC/MNC numbers for the network
61 %% Getting all distinct CellID numbers
62 cidlist = unique(cid);
63 % Sometimes there's unknown cellid logged as '0' - omit
65 cidlist = cidlist(2:end);
67 disp(['Number of cells in log: ' num2str(length(cidlist))])
68 disp(['MCC,MNC: ' num2str(mcc) ',' num2str(mnc)]);
70 if (cellcheck < 1) or (cellcheck > length(cidlist))
71 disp('Invalid cell number - no such cell to check')
75 % plot complete logged GPS track
87 %%%%% In loop to allow for later extending to batch procession
88 %%%%% Currently only one at a time: need of visual inspection of data for each cell
89 for k = cellcheck:cellcheck
93 disp(['MCC,MNC,CellID: ' num2str(mcc) ',' num2str(mnc) ',' num2str(id)])
95 %% Number of logged points
96 nlog = length(cid(cid == id));
97 disp(['Logged points: ' num2str(nlog)])
99 %% Select logged parameters for just this cell
100 clat = lat(cid == id);
101 clon = lon(cid == id);
102 crxl = rxl(cid == id);
104 basestations = unique(cbs);
105 disp(["Base stations: " num2str(basestations')])
107 %% Turn RxL (dB) into signal scale
108 csig = 10.^(crxl/10);
110 % Calculate all signal compared to maximum recorded
111 crxlnorm = max(crxl)-crxl;
112 % Distance scaling power: d^(-dsq) : dsq=2 is free space propagation
114 %%%% scale factor only for plotting, that should be handled more cleverly...
117 %% Approximate distance scale:
118 % RxL (dB) -> Signal (relative) -> Distance (with assumed scaling)
119 ds = 1./(10.^(crxlnorm/10)).^(1/dsc);
122 %% Plot data recorded for given cell
124 % - circles around logged positions
125 % - circle radius is inversely proportional to signal strength
126 % ---> tower 'close': small circle; tower 'far': big circle
131 c1 = dist(l)*cos(linspace(0,2*pi))+clon(l);
132 c2 = dist(l)*sin(linspace(0,2*pi))+clat(l);
139 %% For fitting, guess the tower position close to the max recorded signal
140 %% an add random offset
141 [maxsig maxsignum] = max(crxl);
143 fitofflon = offsetm*rand-offsetm/2;
144 fitofflat = offsetm*rand-offsetm/2;
145 b_in = [clon(maxsignum)+fitofflon clat(maxsignum)+fitofflat 0.01];
147 %% use the RxL for fitting...
148 [yhat, b_est] = leasqr([clon clat],crxl,b_in,"gsmsurf",0.00001,3000);
149 disp(['Fitted tower coordinates (Lat/Lon): ' num2str(b_est(2)) ',' num2str(b_est(1))]);
151 % Residual sum of squares (for fit quality purposes: smaller the better!
152 RSSin = sum((gsmsurf([clon clat],b_in)-crxl).^2);
153 RSSest = sum((gsmsurf([clon clat],b_est)-crxl).^2);
154 disp(['RSS: ' num2str(RSSin) ' -> ' num2str(RSSest)])
156 %%% Put fitted tower position on map: big red X
158 plot(b_est(1),b_est(2),'rx','MarkerSize',32);
159 xlabel(['CellID:' num2str(id) '/ RSS: ' num2str(RSSest) ' / Pos: ' num2str([b_est(1) b_est(2)])])
164 %% To assess fit quality:
169 r = sqrt((clon-lon0).^2 + (clat-lat0).^2);
170 % yhat = yhat./log(10)*10;
171 plot(r,crxl,'@',r,yhat,'x')
172 % plot(r,lcsig,'@',r,yhat,'x')
174 xlabel(['Distance from fitted tower position / CellID:' num2str(id) ])
177 disp(['GSMPOS: ' num2str(mcc) ',' num2str(mnc) ',' num2str(id) ',' num2str(b_est(1)) ',' num2str(b_est(2)) ])
178 disp(['OpenLayers: ' num2str(b_est(1)) '|' num2str(b_est(2)) '|cell ' num2str(id) '|mcc ' num2str(mcc) ' mnc ' num2str(mnc) '|icon_blue.png|24,24|0,-24'])
180 end % function gsmfit
184 %%% Additional sub-routines
187 function yhat = gsmsurf(X,b)
188 %% Signal propagation surface according to propagation assumption
190 %% Assumed distance scaling: d^(-dsc): dsc=2 is free-space propagation
192 %%%%% Separating input parameters into variables
193 % proposed cell position
196 % tower output scale factor - "signal at tower" - purely for fitting
200 % Distance from checked centre
201 r = sqrt((X(:,1)-lon0).^2 + (X(:,2)-lat0).^2);
203 yhat = 10*log(s0*r.^(-dsc))/log(10);