├── LICENSE.md ├── README.md ├── Trilateration.png ├── circles.m ├── estimate_distance.m └── trilateration_estimation.m /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Joao Dias 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # WiFi RSS based trilateration with MATLAB 2 | MATLAB code that enables position estimation using trilateration technique based on the observed WiFi RSS. 3 | 4 | ## Example of Use 5 | Let's assume that the test room is a 10 by 10 meters room (100 square meters) with a WiFi AP (Access Point) in each corner, so 4 APs in total. 6 | First a distance estimation is necessary for all the WiFi APs. 7 | In order to get these distances you need to have the observed RSS (Received Signal Strength) vector containing all the WiFi RSS values for all WiFi APs. 8 | 9 | Example of an input vector. 10 | If you are in position (3, 4.5): 11 | ``` 12 | -53.6 %from AP1 13 | -53.2 %from AP2 14 | -55 %from AP3 15 | -65.2 %from AP4 16 | ``` 17 | Then, this vector should be used as input to estimate_distance.m function: 18 | ``` 19 | >> estimate_distance(RSS) 20 | ``` 21 | 22 | The function will return a vector with estimated distances (d) between the current position and the APs. You should then create a matrix with the APs position. In this example case: 23 | ``` 24 | >> X = [0, 0; 0,10; 10,0; 10,10] 25 | ``` 26 | Now you should be ready to estimate a position based on these values: 27 | ``` 28 | >> trilateration_estimation( X, d, 3, 4.5, 0, 10, 0, 10 ) 29 | ``` 30 | -------------------------------------------------------------------------------- /Trilateration.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joaodias/WiFi-RSS-based-trilateration-with-MATLAB/40bdc2501f6a62bc049d9f9556301d14f28da3bb/Trilateration.png -------------------------------------------------------------------------------- /circles.m: -------------------------------------------------------------------------------- 1 | function [ h ] = circles(x,y,r,varargin) 2 | % h = circles(x,y,r,varargin) plots circles of radius r at points x and y. 3 | % x, y, and r can be scalars or N-D arrays. 4 | % 5 | % Chad Greene, March 2014. Updated August 2014. 6 | % University of Texas Institute for Geophysics. 7 | % 8 | %% Syntax 9 | % circles(x,y,r) 10 | % circles(...,'points',numberOfPoints) 11 | % circles(...,'rotation',degreesRotation) 12 | % circles(...,'ColorProperty',ColorValue) 13 | % circles(...,'LineProperty',LineValue) 14 | % h = circles(...) 15 | % 16 | %% Description 17 | % 18 | % circles(x,y,r) plots circle(s) of radius or radii r centered at points given by 19 | % x and y. Inputs x, y, and r may be any combination of scalar, 20 | % vector, or 2D matrix, but dimensions of all nonscalar inputs must agree. 21 | % 22 | % circles(...,'points',numberOfPoints) allows specification of how many points to use 23 | % for the outline of each circle. Default value is 1000, but this may be 24 | % increased to increase plotting resolution. Or you may specify a small 25 | % number (e.g. 4 to plot a square, 5 to plot a pentagon, etc.). 26 | % 27 | % circles(...,'rotation',degreesRotation) rotates the shape by a given 28 | % degreesRotation, which can be a scalar or a matrix. This is useless for 29 | % circles, but may be desired for polygons with a discernible number of corner points. 30 | % 31 | % circles(...,'ColorProperty',ColorValue) allows declaration of 32 | % 'facecolor' or 'facealpha' 33 | % as name-value pairs. Try declaring any fill property as name-value pairs. 34 | % 35 | % circles(...,'LineProperty',LineValue) allows declaration of 'edgecolor', 36 | % 'linewidth', etc. 37 | % 38 | % h = circles(...) returns the handle(s) h of the plotted object(s). 39 | % 40 | % 41 | %% EXAMPLES: 42 | % 43 | % Example 1: 44 | % circles(5,10,3) 45 | % 46 | % % Example 2: 47 | % x = 2:7; 48 | % y = [5,15,12,25,3,18]; 49 | % r = [3 4 5 5 7 3]; 50 | % figure 51 | % circles(x,y,r) 52 | % 53 | % % Example 3: 54 | % figure 55 | % circles(1:10,5,2) 56 | % 57 | % % Example 4: 58 | % figure 59 | % circles(5,15,1:5,'facecolor','none') 60 | % 61 | % % Example 5: 62 | % figure 63 | % circles(5,10,3,'facecolor','green') 64 | % 65 | % % Example 6: 66 | % figure 67 | % h = circles(5,10,3,'edgecolor',[.5 .2 .9]) 68 | % 69 | % % Example 7: 70 | % lat = repmat((10:-1:1)',1,10); 71 | % lon = repmat(1:10,10,1); 72 | % r = .4; 73 | % figure 74 | % h1 = circles(lon,lat,r,'linewidth',4,'edgecolor','m','facecolor',[.6 .4 .8]); 75 | % hold on; 76 | % h2 = circles(1:.5:10,((1:.5:10).^2)/10,.12,'edgecolor','k','facecolor','none'); 77 | % axis equal 78 | % 79 | % % Example 8: Circles have corners 80 | % This script approximates circles with 1000 points. If all those points 81 | % are too complex for your Pentium-II, you can reduce the number of points 82 | % used to make each circle. If 1000 points is not high enough resolution, 83 | % you can increase the number of points. Or if you'd like to draw 84 | % triangles or squares, or pentagons, you can significantly reduce the 85 | % number of points. Let's try drawing a stop sign: 86 | % 87 | % figure 88 | % h = circles(1,1,10,'points',8,'color','red'); 89 | % axis equal 90 | % % and we see that our stop sign needs to be rotated a little bit, so we'll 91 | % % delete the one we drew and try again: 92 | % delete(h) 93 | % h = circles(1,1,10,'points',8,'color','red','rot',45/2); 94 | % text(1,1,'STOP','fontname','helvetica CY',... 95 | % 'horizontalalignment','center','fontsize',140,... 96 | % 'color','w','fontweight','bold') 97 | % 98 | % figure 99 | % circles([1 3 5],2,1,'points',4,'rot',[0 45 35]) 100 | % 101 | % 102 | % TIPS: 103 | % 1. Include the name-value pair 'facecolor','none' to draw outlines 104 | % (non-filled) circles. 105 | % 106 | % 2. Follow the circles command with axis equal to fix distorted circles. 107 | % 108 | % See also: fill, patch, and scatter. 109 | 110 | %% Check inputs: 111 | 112 | assert(isnumeric(x),'Input x must be numeric.') 113 | assert(isnumeric(y),'Input y must be numeric.') 114 | assert(isnumeric(r),'Input r must be numeric.') 115 | 116 | if ~isscalar(x) && ~isscalar(y) 117 | assert(numel(x)==numel(y),'If neither x nor y is a scalar, their dimensions must match.') 118 | end 119 | if ~isscalar(x) && ~isscalar(r) 120 | assert(numel(x)==numel(r),'If neither x nor r is a scalar, their dimensions must match.') 121 | end 122 | if ~isscalar(r) && ~isscalar(y) 123 | assert(numel(r)==numel(y),'If neither y nor r is a scalar, their dimensions must match.') 124 | end 125 | 126 | %% Parse inputs: 127 | 128 | % Define number of points per circle: 129 | tmp = strcmpi(varargin,'points')|strcmpi(varargin,'NOP')|strcmpi(varargin,'corners')|... 130 | strncmpi(varargin,'vert',4); 131 | if any(tmp) 132 | NOP = varargin{find(tmp)+1}; 133 | tmp(find(tmp)+1)=1; 134 | varargin = varargin(~tmp); 135 | else 136 | NOP = 1000; % 1000 points on periphery by default 137 | end 138 | 139 | % Define rotation 140 | tmp = strncmpi(varargin,'rot',3); 141 | if any(tmp) 142 | rotation = varargin{find(tmp)+1}; 143 | assert(isnumeric(rotation)==1,'Rotation must be numeric.') 144 | rotation = rotation*pi/180; % converts to radians 145 | tmp(find(tmp)+1)=1; 146 | varargin = varargin(~tmp); 147 | else 148 | rotation = 0; % no rotation by default. 149 | end 150 | 151 | % Be forgiving if the user enters "color" instead of "facecolor" 152 | tmp = strcmpi(varargin,'color'); 153 | if any(tmp) 154 | varargin{tmp} = 'facecolor'; 155 | end 156 | 157 | %% Begin operations: 158 | 159 | % Make inputs column vectors: 160 | x = x(:); 161 | y = y(:); 162 | r = r(:); 163 | rotation = rotation(:); 164 | 165 | % Determine how many circles to plot: 166 | numcircles = max([length(x) length(y) length(r) length(rotation)]); 167 | 168 | % Create redundant arrays to make the plotting loop easy: 169 | if length(x)