Search code examples
c#unity-game-enginetrilateration

3d Trilateration in C#


How to make the GPS algorithm to get a point based on three known points and their distances?


Solution

  • It is made in Unity, so it uses the Vector3 and Mathf classes, but it would be easy to remove those dependencies using a 3-sized array for each point and the standart Math class.

    static float sqr(float a)
    {
        return a * a;
    }
    static float norm(Vector3 a)
    {
        return Mathf.Sqrt(sqr(a.x) + sqr(a.y) + sqr(a.z));
    }
    static float dot(Vector3 a, Vector3 b)
    {
        return a.x * b.x + a.y * b.y + a.z * b.z;
    }
    static Vector3 vector_cross(Vector3 a, Vector3 b)
    {
        return new Vector3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);
    }
    
    public static Vector3[] Trilaterate(Vector3 p1, float r1, Vector3 p2, float r2, Vector3 p3, float r3)
    {
        Vector3 ex = (p2 - p1) / norm(p2 - p1);
        float i = dot(ex, (p3 - p1));
        Vector3 a = ((p3 - p1) - (ex * i));
        Vector3 ey = (a / norm(a));
        Vector3 ez = vector_cross(ex, ey);
        float d = norm(p2 - p1);
        float j = dot(ey, p3 - p1);
    
        float x = (sqr(r1) - sqr(r2) + sqr(d)) / (2 * d);
        float y = (sqr(r1) - sqr(r3) + sqr(i) + sqr(j)) / (2 * j) - (i / j) * x;
    
        float b = sqr(r1) - sqr(x) - sqr(y);
    
        // floating point math flaw in IEEE 754 standard
        // see https://github.com/gheja/trilateration.js/issues/2
        if (Mathf.Abs(b) < 0.0000000001)
        {
            b = 0;
        }
    
        float z = Mathf.Sqrt(b);
    
        // no solution found
        if (float.IsNaN(z))
        {
            return new Vector3[] { Vector3.zero };
        }
    
        Vector3 aa = p1 + ((ex * x) + (ey * y));
        Vector3 p4a = (aa + (ez * z));
        Vector3 p4b = (aa - (ez * z));
    
        return new Vector3[] { p4a, p4b };
    }
    

    It is a direct translation of the JS version from gheja, all credits to them: https://github.com/gheja/trilateration.js/blob/master/trilateration.js