1

My program isn't making use of any geographical data, but I'm hoping that the users experience in the subject can help me with my current issue.

The project I am working is trying to locate a user in an indoor environment using bluetooth low energy beacons (I know the issues surround BLE). My environment could have N number of beacons in it and I'm wanting my program to pick the best (read closest) three and trilaterate the users position based on them. All of this I'm trying to visualise inside Unity.

However, my math isn't that great and I did try to transpose the data from the wiki however, I'm not sure if I have done the calculations correctly. For one, in my project, the calculations only work as long as my beacons are above 0 on the Y axis. Likewise, the point at which it determines the player to be is totally different dependant on the order in which the beacons are place. Am I doing something wrong?

public GameObject sphere1, sphere2, sphere3, player;
float rad1, rad2 ,rad3;
float x;
float y;
Vector3 P1, P2, P3, V;
bool yRot = false;
float angle = 0;

// Update is called once per frame
void LateUpdate () 
{   
    TrilaterationCalc(sphere1,sphere2,sphere3,player);
}

void OnGUI()
{
    GUI.Label(new Rect(10, 560, 200, 180), "Sphere1 size: " + sphere1.transform.localScale.ToString());
    GUI.Label(new Rect(10, 580, 200, 180), "Sphere2 size: " + sphere2.transform.localScale.ToString());
    GUI.Label(new Rect(10, 600, 200, 180), "Sphere3 size: " + sphere3.transform.localScale.ToString());
}


static Vector3 RotateAroundPoint(Vector3 point , Vector3 pivot, Quaternion angle)
{
    //Center the point around the origin
    Vector3 finalPos = point - pivot;

    //Rotate the point.
    finalPos = angle * finalPos;

    //Move the point back to its original offset. 
    finalPos += pivot;

    return finalPos;
}

void TrilaterationCalc(GameObject sph1, GameObject sph2, GameObject sph3, GameObject user)
{
    //Find the offset to set P1 to the origin
    V = -sphere1.transform.position;

    //Set the 3 points and apply offset
    P1 = sph1.transform.position + V;
    P2 = sph2.transform.position + V;
    P3 = sph3.transform.position + V;

    //Apply rotation if P2 doesn't lie on the 
    if(P2.y != 0 || P2.x < P1.x)
    {   
        //Angle between
        if(P2.y > P1.y)
        {
            angle  = -Vector3.Angle(Vector3.right,P2);
        }
        else
        {
            angle = Vector3.Angle(Vector3.right,P2);
        }
        //Rotate P2 to X-axis and apply same rotation to 
        P2 = RotateAroundPoint(P2,P1,Quaternion.Euler(0, 0, angle));
        P3 = RotateAroundPoint(P3,P1,Quaternion.Euler(0, 0, angle));
        yRot = true;
    }
    else
    {
        yRot = false;
    }

    //Get the Radius of each sphere 
    rad1 = sph1.renderer.bounds.extents.x * sph1.renderer.bounds.extents.x;
    rad2 = sph2.renderer.bounds.extents.x * sph2.renderer.bounds.extents.x;
    rad3 = sph3.renderer.bounds.extents.x * sph3.renderer.bounds.extents.x;

    //Get the distance 
    float d =  Vector3.Distance(P1,P2);

    //Get x and y of point 3
    float i = P3.x;
    float j = P3.y;

    //Set the X and Y of P4
    x = (rad1 - rad2 + (d*d)) / (d*2);
    y = (rad1 - rad3 + (i*i) + (j*j)) / ((j*2) - ((i/j)*P1.x));

    //Set Player Pos depend on if rotated
    if(!yRot)
    {
        //Set User Position
        user.transform.position = new Vector3(x,y,0) - V;
    }
    else
    {
        //Set initial P4
        Vector3 P4 = new Vector3(x,y,0);

        //Rotate back and unapply to offset
        P4 = (RotateAroundPoint(P4,P1,Quaternion.Euler(0, 0, -angle))) - V;

        //Set User Position
        user.transform.position = P4;
    }

}
N0xus
  • 111
  • 3
  • 1
    Page 3 (III. TRILATERATION) "Accurate Mobile Robot Localization in indoor environments using Bluetooth" http://www.cse.iitm.ac.in/~ravi/papers/Ashwin_ICRA10.pdf – Mapperz Apr 04 '14 at 13:44
  • See also http://gis.stackexchange.com/a/98100/3195 – Martin F May 27 '14 at 20:06

0 Answers0