Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Geo-localised objects in AR core.

Discussion in 'AR' started by rguenon, Jul 12, 2018.

  1. rguenon

    rguenon

    Joined:
    Jul 2, 2018
    Posts:
    7
    Hi.

    I am trying to place geo-localized augmented object using ARCore.

    To do so, I would need the scene Z axis to point north which I didn't found how to do (without breaking the tracking).

    I tried to place the objects relatively to the camera but I couldn’t get a good "north direction" by comparing the camera angle and the compass.

    Would anyone have some hint on how to do so?

    Thank you in advance for your answers.
     
  2. JVaughan

    JVaughan

    Joined:
    Feb 6, 2013
    Posts:
    23
    *Bumping this thread*. Cloud anchors are nice but sometimes we need something much more persistent.
     
  3. danielesuppo

    danielesuppo

    Joined:
    Oct 20, 2015
    Posts:
    331
    Place objects in georeferenced position, as child of a transform that you can rotate to point the north.
    Hope this help
     
  4. rguenon

    rguenon

    Joined:
    Jul 2, 2018
    Posts:
    7
    I managed to get a good-enough geo-localised placement.

    Some tricks I used:
    I placed the objects relatively to the camera. To do so, I use UTM projection coordinates to get a cartesian space with the same units as the “ARCore world”.

    I don’t use the compass but the gyroscope. The angle between the gyroscope and the north doesn’t change so it is usable (Although I read somewhere that it can be dependent on the captor) and it is easier to compare it with the angle of the Camera in the Unity scene.

    So, using the gyroscope and the GPS, I can have a north direction, and a vector between the camera and the geo-localised object, allowing me to place it at the right place.


    With some filtering to de-noise the captor, I have an object placed in the AR view with the same precision as the GPS (around 5 or 6 meters most of the time).
     
  5. danielesuppo

    danielesuppo

    Joined:
    Oct 20, 2015
    Posts:
    331
    It's a really good idea to use gyroscope in place of compass, maybe do you have some advice on how to get north from it?
    About gps, are you actually using iPhone? I have a Samsung S8 and gps "precision" is around 5 up to 20 meters (!), despite the accuracy reported by the sensor...
     
  6. rguenon

    rguenon

    Joined:
    Jul 2, 2018
    Posts:
    7
    As the Gyroscope is pointing to the north (I got a (0,0,0) angle when pointing north), what I do is calculate the delta angle between the camera/phone and the north.

    Here is the code I use (there is probably a cleaner and better way to do it, without using the transform, but it works):


    Code (CSharp):
    1. Vector3 previousObjectAngle = transform.eulerAngles;
    2.  
    3. transform.localRotation = Input.gyro.attitude;
    4. transform.Rotate(0f, 0f, 180f, Space.Self); // Swap "handedness" of quaternion from gyro.
    5. transform.Rotate(90f, 180f, 0f, Space.World); // Rotate to make sense as a camera pointing out the back of your device.
    6.  
    7. float deltaAngle = Mathf.DeltaAngle(transform.eulerAngles.y, transform.eulerAngles.y);
    8.  
    9. transform.eulerAngles = previousObjectAngle;
    10.  
    To get a stable position in ARCore, you might want to de-noise the angle before using it (I use lerp. It does the trick).


    I use a Samsung S9, but the 5-6 meters GPS precision was measured on a cleared ground. It goes around 20-30 meters if I go near tall buildings, trees or obstacles.
     
  7. yeidy17

    yeidy17

    Joined:
    Jul 31, 2017
    Posts:
    1

    Hi!

    I don't understand what you say. First, where did you place the code, in the Start function or in the Update?

    which is the result of this float deltaAngle = Mathf.DeltaAngle(transform.eulerAngles.y, transform.eulerAngles.y);? it returns the value of transform.eulerAngles.y (I think)

    And for what is used the variable deltaAngle? Yo calculate the deltaAngle value but you're not using it.

    Can you show me the full script that you used to calculate it?

    Thank you very much (sorry for my bad english).
     
  8. rguenon

    rguenon

    Joined:
    Jul 2, 2018
    Posts:
    7
    Hi.

    I iterated a lot since I post this code.
    I can't show the full script, as there is a lot more going on in it, but I will try to explain how it works:

    What I do, is to place a Geo-localised object relative to the camera.
    To do so, we need to:
    -Geo-localised the camera.
    -Being able to express the difference in position between the camera and the Geo-localised object in the Unity space.

    To Geo-localised the camera, I simply use the GPS from the smartphone.We can then deduce the difference in position between the smartphone and the object.

    The tricky part is the second part: from this difference in position in the real space, we need to deduce the difference in position in the Unity space.

    First, we convert the GPS and the Geo-localised (which are both in standard lat-lon, format => wgs84 system) into UTM coordinates.
    UTM coordinates are interesting because it uses an orthonormal space, and the unit is the meter (same as AR-Core. how lucky...). (Proj4Net may be a good place to start if you want to do that).

    Using UTM coordinates, we can deduce the position difference in the Unity Space.
    We shall however be looking to the "true world" north in the Unity space before translating our object by this difference, which is why we need the deltaAngle: the angle between the Unity Space Forward vector and the North vector.

    So, this line of code
    float deltaAngle = Mathf.DeltaAngle(myCamera.transform.eulerAngles.y, target.eulerAngles.y);//where "myCamera" is the camera, controled by ArCore.
    is the angle between the Unity space forward and the north.

    We may use it like this:
    someObject.transform.eulerAngle = new Vector3(0, deltaAngle,0);

    By doing so, We are making the object look into the north direction.
     
    Last edited: Jun 21, 2019
    cryingcavecat, grobm and yeidy17 like this.
  9. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    @rguenon thanks for posting your solution, when I try it the target object doesn't seem to point north, it points in the direction the phone was pointing when starting the scene.

    Is the code below on the right track?

    Thanks

    Code (CSharp):
    1.     public Transform target;
    2.     public Gyroscope gyro;
    3.  
    4.     void Start()
    5.     {
    6.         gyro = Input.gyro;
    7.         gyro.enabled = true;
    8.     }
    9.     void Update()
    10.     {
    11.         target.localRotation = gyro.attitude;
    12.         target.Rotate(0f, 0f, 180f, Space.Self); // Swap "handedness" of quaternion from gyro.
    13.         target.Rotate(90f, 180f, 0f, Space.World); // Rotate to make sense as a camera pointing out the back of your device.
    14.      
    15.         float deltaAngle = Mathf.DeltaAngle(target.eulerAngles.y, target.eulerAngles.y);
    16.      
    17.         target.eulerAngles = new Vector3(0,deltaAngle,0);
    18.     }
     
    Last edited: Jun 15, 2019
  10. rguenon

    rguenon

    Joined:
    Jul 2, 2018
    Posts:
    7
    My bad, there is a mistake in the code I posted.
    Indeed, Mathf.DeltaAngle(target.eulerAngles.y, target.eulerAngles.y) will always return 0, so no wonder your object is pointing to 0.


    We are comparing the camera angle in Unity to the angle return by the compasse, so the right line is:
    float deltaAngle = Mathf.DeltaAngle(myCamera.transform.eulerAngles.y, target.eulerAngles.y);
    where "myCamera" is the camera, controled by ArCore.

    Here is the corrected complete code:

    Code (CSharp):
    1.     public Transform target;
    2.     public Gyroscope gyro;
    3.  
    4.     void Start()
    5.     {
    6.         gyro = Input.gyro;
    7.         gyro.enabled = true;
    8.     }
    9.     void Update()
    10.     {
    11.         target.localRotation = gyro.attitude;
    12.         target.Rotate(0f, 0f, 180f, Space.Self); // Swap "handedness" of quaternion from gyro.
    13.         target.Rotate(90f, 180f, 0f, Space.World); // Rotate to make sense as a camera pointing out the back of your device.
    14.  
    15.         float deltaAngle = Mathf.DeltaAngle(myCamera.transform.eulerAngles.y, target.eulerAngles.y);//where "myCamera" is the camera, controled by ArCore.
    16.  
    17.         target.eulerAngles = new Vector3(0,deltaAngle,0);
    18.     }
    With this, the target should look to the north.
     
    Last edited: Jun 20, 2019
    jfillingham-mt likes this.
  11. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    @rguenon ah nice, works great. North in this case seems to be whatever direction the phone was pointing in when the applications starts (I guess this is how the gyro initialises?)
     
  12. rguenon

    rguenon

    Joined:
    Jul 2, 2018
    Posts:
    7
    Sory, I did the same mistake in my previous post (damn copy-past).
    Could you try changing the line 15
    float deltaAngle = Mathf.DeltaAngle(target.eulerAngles.y, target.eulerAngles.y);
    to
    float deltaAngle = Mathf.DeltaAngle(myCamera.transform.eulerAngles.y, target.eulerAngles.y);//where "myCamera" is the camera, controled by ArCore.
     
    enhawk likes this.
  13. enhawk

    enhawk

    Joined:
    Aug 22, 2013
    Posts:
    833
    No problems, managed to catch that one. Seems to point in the direction the phone is pointed in when starting up, not north.
     
  14. rguenon

    rguenon

    Joined:
    Jul 2, 2018
    Posts:
    7
    It's probably a problem with the angle sign.

    Could you try this?
    target.eulerAngles = new Vector3(0,-deltaAngle,0);