2

I have implemented the trilateration positioning algorithm in Python, and so far the results look quite off because of the computed distances are affected by signal interference and so it looks like this:

current

when it should be looking something like this:

expected

So I was thinking about scaling the circles at the same time using a constant factor until they all intersect at one point (which would be optimal) or until the sum of their mutual distances is minimum. Given the XY coordinates of the three circles in 2D-space, as well as their FSPL-computed distances from the reference point (which is the center of one of the circles), the function should return the best scaling factor that minimizes the error. It should be something like this:

def find_best_scaling_constant(p1, p2, p3, r1, r2, r3):
  # some magic here
  return scalingConstant

find_best_scaling_constant((0.00, 0.00), (3.15, -0.47), (4.90, 7.00), 1.12, 1.77, 0.18)

I'm not a mathematician so I don't know if this logic makes sense, but if someone has a comment or a better idea, please share them. It would be of great help!

SalmaFG
  • 2,022
  • 3
  • 23
  • 36
  • This approach seems strange - do you want to fit own value of light speed (fundamental constant)? Perhaps you have got wrong values for radii. – MBo May 23 '19 at 11:17
  • 1
    this might help you find the closest distance between 3 points (one on each circle).: https://math.stackexchange.com/questions/2870952/find-the-smallest-sum-distance-among-three-points-on-three-circles – Raphael May 23 '19 at 11:17
  • @MBo the values of the radii are computed based on the detected signal strength at the access points (the centers of the circles) which is not very accurate because of obstacles and reflection. In the first image the receiver was actually sitting right next to the blue access point which is why its radius is so small. But it was also being detected by the other 2 access points, so they should be intersecting if there was no error. This is why I thought about scaling them because the ratios of the radii are relatively correct. – SalmaFG May 23 '19 at 11:24

1 Answers1

4

Let the circles have centers with coordinates:

enter image description here

and let the corresponding radii, you have computed, be:

enter image description here

respectively. So it looks like you are looking for the point enter image description here and a scaling factor with the following property:

enter image description here

Equivalently, we need to to find a point enter image description here in the plane which is the common intersection point of the three circles, obtained by re-scaling the radii of the original circles by a common factor k, or in mathematical notation, we need to solve the system

enter image description here

It is clear that the systems above and the property written before the system are equivalent.

To simplify things, square both sides of each equation from the system:

enter image description here

By Pythagoras' theorem, write

enter image description here

That is why, in explicit formulas, the system of three squared equations above, is in fact the quadratic system of equations:

enter image description here

which, after moving the term from the right-hand side of each equation to the left-hand side, becomes:

enter image description here

Expand all the squared differences in each equation and reorder the terms:

enter image description here

To simplify this system, subtract the second equation from the first, then subtract the third equation from the second and keep one of the quadratic equations, let's say keep the first quadratic equation:

enter image description here

The idea for finding the solution of this system, is the following:

enter image description here

To simplify the notation and the expressions, we can use a bit of notation from linear algebra. Define the following two by two matrix and two by one column-vectors:

enter image description here

and when we multiply the latter matrix equation by the inverse matrix of M:

enter image description here

Let us also write in matrix notation

enter image description here

enter image description here

enter image description here

enter image description here

And finally, the algorithm for finding the intersection point of the three circles, after scaling with an appropriate scaling factor, can be formulated as follows:

enter image description here enter image description here

Observe that the quadratic equation has two solutions for z. The one I chose, with minus, is the first point of intersection whenever the three circles are external to each and with initial non-intersecting radii. There is also a second intersection point which is the one corresponding to a plus solution for z. If you have the information from a fourth tower available, then you will be able to pick the right point and possibly you may be even able to linearize the problem completely. But with this available data only, you have two solutions.

I tested the algorithm with the following hand-made example:

x1 = 0;  y1 = 0;  r1 = sqrt(13)/3;
x2 = 5;  y2 = 1;  r2 = sqrt(13)/3;
x3 = 3;  y3 = 7;  r3 = sqrt(17)/3;

and it ouputs the right location

x = 2;  y = 3;  

and scaling factor k = 3.

I implemented it in Matlab/Octave because I am comfortable with the linear algebra there:

function [xy, k] = location_scaled(x1, y1, r1, x2, y2, r2, x3, y3, r3)
        
        M = 2*[x2 - x1  y2 - y1; 
               x3 - x2  y3 - y2];
        A = [r1^2 - r2^2; 
             r2^2 - r3^2];
        B = [x2^2 + y2^2 - x1^2 - y1^2; 
             x3^2 + y3^2 - x2^2 - y2^2];
        A = M\A;
        B = M\B;
        
        a = A'*A;
        b = 2*B'*A - 2*[x1  y1]*A - r1^2;
        c = [x1 y1]*[x1; y1] - 2*[x1  y1]*B + B'*B;
        
        k = (- b - sqrt(b^2 - 4*a*c)) / (2*a);
        
        xy = k*A + B;
        k = sqrt(k);
        
end

And here is the python version:

import numpy as np

def location_scaled(x1, y1, r1, x2, y2, r2, x3, y3, r3):

        M = 2*np.array([[x2 - x1,  y2 - y1], 
                        [x3 - x2,  y3 - y2]])
        A = np.array([r1**2 - r2**2, 
                      r2**2 - r3**2])
        B = np.array([x2**2 + y2**2 - x1**2 - y1**2, 
                      x3**2 + y3**2 - x2**2 - y2**2])

        M = np.linalg.inv(M)
        A = M.dot(A)
        B = M.dot(B)
        x1_y1 = np.array([x1, y1])

        a = A.dot(A)
        b = 2*B.dot(A) - 2*x1_y1.dot(A) - r1**2
        c = x1*x1 + y1*y1 - 2*x1_y1.dot(B) + B.dot(B)

        k = (- b - np.sqrt(b*b - 4*a*c)) / (2*a);

        return k*A + B, np.sqrt(k)
Futurologist
  • 1,874
  • 2
  • 7
  • 9
  • Thanks for your answer! Could you explain how you got the terms `r1^2`, `r2^2` and `r3^2` in the quadratic equations? I understand the rest of the expressions in those equations are the distances as derived from the Pythagorean theorem. – SalmaFG May 26 '19 at 13:02
  • @SalmaFG I added an edit with some extra explanations. Look at it and let me know if that's what you are asking about. The terms ```r1^2, r2^2, r3^2``` come from the three radii ```r1, r2, r3``` of the three circles that you are given, if I understand correctly the assumptions of the problem you have posted. – Futurologist May 26 '19 at 16:14
  • Yes this helps, I will test it as soon as I can and let you know! – SalmaFG May 27 '19 at 23:01
  • I am implementing the equations like you said but I came across a problem when the radii are of the same length. I get a division by 0 in the `DET` because of `(rj^2 - ri^2)`. Are you sure about this expression? I tried to solve the system of equations by hand to double check this but I got stuck. How did you manage to do it? – SalmaFG May 30 '19 at 08:30
  • @SalmaFG You are right. When two of the radii (or all three) are equal, there is a division by zero in the formulas I wrote. The equations up to the End of Edit is correct and general, it applies even to equal radii. However, to simplify things, I divided by the difference rj^2 - ri^2, because I thought that in realistic calculations it is unlikely to get ri = rj (but now when I think about it, it could be that ri^2 - rj^2 is a very small number, so it is still not good to divide by it). – Futurologist May 30 '19 at 13:33
  • @SalmaFG However, this can be fixed, it is a matter of multiplying the equations by appropriate rk^2 - rl^2 instead of dividing by rj^2 - ri^2. I will look at it and write an edit later today. – Futurologist May 30 '19 at 13:35
  • I agree, it is highly unlikely that 2 radii are exactly the same. But also in cases when they are not, I got gigantic numbers for a scaling factor. Btw, I really appreciate all your help so far :) – SalmaFG May 30 '19 at 22:10
  • @SalmaFG I edited my post. I wrote the derivations of the equations for most relevant cases. I suggest you test it with three circles of reasonable locations and radii, before testing it for more degenerate cases. – Futurologist May 31 '19 at 01:42
  • I implemented the equations and it works now for both cases! I tried both and found that Case 1 really does cover both like you said :) The equations do work though when a solution exists, otherwise it returns some number as a scaling factor and there is no way to know if it is the correct solution or not unless I draw the circles with the scaled radii and see if they intersect. Is there is a mathematical way to know? – SalmaFG Jun 01 '19 at 13:24
  • @SalmaFG I am glad it works. I like when things work out. In terms of existence of a solution, since this is a linear system of equations, in Case 1 if ```det``` is not zero, then there exists a unique solution. In Case 2, if the denominator ```a12 * b23 - a23 * b12``` is not zero, then there exists a unique solution. This are theorems from the algebra of linear systems (linear algebra). – Futurologist Jun 01 '19 at 18:16
  • I just tested this but unfortunately, it doesn't seem to work. I will post my code in case you want to try it yourself. – SalmaFG Jun 01 '19 at 19:37
  • @SalmaFG You have a typo in the first three expressions of your code. It should be ```r12 = r2**2 - r1**2``` and ```r23 = r3**2 - r2**2``` and ```r31 = r1**2 - r3**2``` I copied an pasted your code in my post with these correction. – Futurologist Jun 01 '19 at 23:15
  • Oops! I'm surprised it worked though. I actually just tried making the corrections and testing it again on different cases and it doesn't work anymore. – SalmaFG Jun 02 '19 at 00:10
  • @SalmaFG I found the issue. I should have known better. The idea and the equations are correct, but I thought (although I should have known better) we could solve the problem as a linear system. However, it cannot be done like that, because one of the equations is redundant and the quantity ```det = 0```. So the linear system is underdetermined, which may imply that it is not enough to solve the system by linear methods, we need a quadratic equation. Now I have the correct method for solution and I tested it, but will have to spend some time writing it. – Futurologist Jun 02 '19 at 14:20
  • I found this SciPy library for nonlinear systems. I don't understand the concept yet but I'm still reading about it. It may be useful: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.least_squares.html – SalmaFG Jun 02 '19 at 14:31
  • @SalmaFG no need for that. I will post a Matlab code that works (I hope you can convert it to Python). Later I will add more edits. – Futurologist Jun 02 '19 at 14:44
  • I'm working on the python conversion but my Matlab is very rusty so it may take a while. – SalmaFG Jun 03 '19 at 19:45