Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
2 captures
13 Jun 22 - 14 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
1
Question by Jaetriel · May 30, 2021 at 12:51 PM · mobileworld spacereal-timeworldpos

Moving in Unity with real world coordinates (latitude-longitude to 3d position)

So, I've got an Arduino device getting data from an external GPS and sending the lat long coordinates to Unity via bluetooth. What I'm struggling with is how exactly to visualize movement in the real world in Unity, so let's say I move 5m forward I'd want my character to move forward as well. I scoured the web for a way to convert these lat and long values to a xyz vector:

 private Vector3 PolarToCartesian(float latitude, float longitude)
 {
         //an origin vector, representing lat,lon of 0,0. 
         Vector3 origin = new Vector3(0, 0, 1);
         //build a quaternion using euler angles for lat,lon
         Quaternion rotation = Quaternion.Euler(latitude, longitude, 0);
         Vector3 point = rotation * origin;
 
         return point;
 }

and this seems to be working fine, but when I enter some coordinates as start coordinates, and then tell the character to move to coordinates that are 1.5km away in the real world, the calculations in Unity return pretty much the exact same vector and the character just doesn't move, i.e if I take the start of a street in Vienna with coords 48.195932, 16.339999 this gives me a vector of (0.2, -0.7, 0.6). Taking the coordinates of the end of that same street 48.202385, 16.361278, the difference is so small that I get pretty much the same vector. Any ideas as to how to go about solving this, maybe it's just a scaling issue with the numbers I'm getting an Unity units or am I looking at it from a completely wrong angle here?

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image andresmqa · Jul 20, 2021 at 06:34 AM 0
Share

I am looking for the same question. Have been you @Jaetriel found any solution?,I am looking for the same question. Have been you found any solution?

avatar image oscarAbraham andresmqa · Jul 20, 2021 at 07:15 AM 0
Share

I've done this kind of thing before, but I don't remember using Quaternion.Euler. It seems to be right, though; and even if it isn't, I believe results would just be inverted.

Maybe the problem here is that you're expecting point to be in a real-world scale? Latitude and Longitude are just angles; you're getting the position on a spherical world with a diameter of 2. You would need to multiply point by the real radius of the Earth, which is 6,371 kilometers.

If things are still too imprecise, it could be because you're using floats? Using doubles would give you more precision, although I don't expect it to be necessary for most common cases. Also, doubles don't work with Unity's quaternion.

There are libraries for this sort of thing, though. Some of them even consider that the Earth is not a perfect sphere. I'd really recommend you to look for a good one if you're doing lots of geolocation stuff. You know, why reinvent the wheel? That said, if you just want a quick simple solution in repo form, this library has the same API than System.Device.Location.GeoCoordinate, which is normally not available in Unity.

1 Reply

· Add your reply
  • Sort: 
avatar image
0

Answer by andrew-lukasik · Jul 20, 2021 at 01:47 PM


This will resolve your issue, just make sure to enable _originFromPlayerPosition. The solution is to increase scale, math precision and implement floating origin to avoid floating-point rendering/transform issues.


left to right:

  • 3d game world space

  • debug 2d coordinates

  • debug 3d spherical coordinates

geographical to cartesian coordinates

 // src*: https://gist.github.com/andrew-raphael-lukasik/26d14f6c9abd0c410d83305222ca829b
 using UnityEngine;
 using Math = System.Math;
 
 public class GeoCoordToCart : MonoBehaviour
 {
 
     [SerializeField] Vector3 _worldSize = new Vector3(100,0,100);
     [SerializeField] Vector3 _worldOrigin = new Vector3(0,0,0);
 
     [SerializeField] bool _originFromPlayerPosition = false;
     [SerializeField] GeoCoord _playerPosition = new GeoCoord{ label="Player 0" , latitude=48.195932 , longitude=16.339999 };
 
     [SerializeField] float _worldPointSize = 1f;
     [SerializeField][Min(0.01f)] float _gizmoScale = 10f;
 
 
     #if UNITY_EDITOR
     void OnValidate ()
     {
         if( _originFromPlayerPosition )
         {
             UnityEditor.Undo.RecordObject( this , "Origin From Player Position" );
             MoveOrigin( _playerPosition );
         }
     }
     void OnDrawGizmos ()
     {
         Vector3 origin = transform.position;
         
         // draw sphere:
         Gizmos.color = Color.cyan;
         Gizmos.DrawWireSphere( origin , _gizmoScale );
         Gizmos.color = new Color(0,1,1,0.05f);
         Gizmos.DrawSphere( origin , _gizmoScale );
 
         // draw rect:
         Gizmos.color = Color.cyan;
         Vector2 rect = new Vector2( _gizmoScale*4f , _gizmoScale*2f );
         Vector3 rectCenterWorld = origin - Vector3.right*_gizmoScale*4f;
         Gizmos.DrawWireCube( rectCenterWorld , new Vector3(rect.x,rect.y,0) );
 
         // draw game world bounds:
         Gizmos.DrawWireCube( _worldOrigin , _worldSize );
 
         for( int i=_coordinates.Length-1 ; i!=-1 ; i-- )
         {
             var coord = _coordinates[i];
 
             // sphere:
             {
                 Vector3 spherePoint = coord.ToVector3UnitSphere();
                 Vector3 worlPos = origin + spherePoint*_gizmoScale;
 
                 Gizmos.color = Color.yellow;
                 Gizmos.DrawSphere( worlPos , _gizmoScale*0.01f );
                 UnityEditor.Handles.Label( worlPos , coord.ToString() );
             }
 
             // rect:
             {
                 Vector2 v2point = coord.ToVector2();
                 Vector3 worlPos = rectCenterWorld + Vector3.Scale(v2point,rect*0.5f);
 
                 Gizmos.color = Color.yellow;
                 Gizmos.DrawSphere( worlPos , _gizmoScale*0.01f );
                 UnityEditor.Handles.Label( worlPos , coord.ToString() );
             }
 
             // game world:
             {
                 Vector3 v3point = coord.ToVector3();
                 Vector3 worlPos = _worldOrigin + Vector3.Scale(v3point,_worldSize*0.5f);
 
                 Gizmos.color = Color.green;
                 Gizmos.DrawCube( worlPos , new Vector3(_worldPointSize,_worldPointSize,_worldPointSize) );
                 UnityEditor.Handles.Label( worlPos , coord.ToString() );
             }
         }
     }
     #endif
 
     void MoveOrigin ( GeoCoord coord ) => _worldOrigin = -Vector3.Scale( coord.ToVector3() , _worldSize*0.5f );
 
     [SerializeField] GeoCoord[] _coordinates = new GeoCoord[]{
         new GeoCoord{ label="" , latitude=0 , longitude=0 } ,
         new GeoCoord{ label="Reykjavík" , latitude=64.1335484 , longitude=-21.9224813 } ,
         new GeoCoord{ label="Kraków" , latitude=50.0468548 , longitude=19.9348336 } ,
         new GeoCoord{ label="Paris" , latitude=48.8589507 , longitude=2.2770204 } ,
         new GeoCoord{ label="Buenos Aires" , latitude=-34.6156625 , longitude=-58.503338 } ,
         new GeoCoord{ label="Ho Chi Minh" , latitude=10.7553411 , longitude=106.4150395 } ,
         new GeoCoord{ label="İstanbul" , latitude=41.0054958 , longitude=28.8720965 } ,
         new GeoCoord{ label="Nairobi" , latitude=-1.3030364 , longitude=36.7773568 } ,
         new GeoCoord{ label="Dublin" , latitude=53.3244431 , longitude=-6.3857857 } ,
         new GeoCoord{ label="London" , latitude=51.5287718 , longitude=-0.2416804 } ,
         new GeoCoord{ label="New York" , latitude=40.6976637 , longitude=-74.119764 } ,
         new GeoCoord{ label="Starbase" , latitude=25.9884963 , longitude=-97.1632233 } ,
         new GeoCoord{ label="Vancouver" , latitude=49.2578263 , longitude=-123.1939434 } ,
         new GeoCoord{ label="Honolulu" , latitude=21.1579153 , longitude=-158.5605044 } ,
         new GeoCoord{ label="Mumbai" , latitude=19.0825223 , longitude=72.7411016 } ,
         new GeoCoord{ label="Tehran" , latitude=35.6970118 , longitude=51.2097352 } ,
         new GeoCoord{ label="Hongkong" , latitude=22.3529913 , longitude=113.9876156 } ,
         new GeoCoord{ label="Sydney" , latitude=-33.8479255 , longitude=150.6511036 } ,
         new GeoCoord{ label="Dakar" , latitude=14.7110139 , longitude=-17.5360369 } ,
         new GeoCoord{ label="Natal" , latitude=-4.8730191 , longitude=-34.9832028 } ,
         new GeoCoord{ label="Ushuaia" , latitude=-54.8228355 , longitude=-68.3797813 } ,
         new GeoCoord{ label="Caracas" , latitude=10.4683841 , longitude=-66.9605778 } ,
         new GeoCoord{ label="Cape Town" , latitude=-33.9152193 , longitude=18.3751883 } ,
         new GeoCoord{ label="Якутск" , latitude=62.0312622 , longitude=129.5613624 } ,
         new GeoCoord{ label="Roma" , latitude=41.9099856 , longitude=12.3955715 } ,
         new GeoCoord{ label="Gibraltar" , latitude=36.129508 , longitude=-5.3708525 } ,
         new GeoCoord{ label="Longyearbyen" , latitude=79.2639353 , longitude=4.3014832 } ,
         new GeoCoord{ label="Lima" , latitude=-12.0185972 , longitude=-77.1280131 } ,
         new GeoCoord{ label="Santiago" , latitude=-33.4727088 , longitude=-70.7702586 } ,
         new GeoCoord{ label="Atqasuk" , latitude=70.539337 , longitude=-157.9874001 } ,
         new GeoCoord{ label="Douala" , latitude=4.0359007 , longitude=9.6715926 } ,
         new GeoCoord{ label="Stazione Mario Zucchelli" , latitude=-74.6958608 , longitude=164.0881707 } ,
         new GeoCoord{ label="Alert" , latitude=82.5058286 , longitude=-62.5571841 } ,
 
         new GeoCoord{ label="Vienna p0" , latitude=48.195932 , longitude=16.339999 } ,
         new GeoCoord{ label="Vienna p1" , latitude=48.202385 , longitude=16.361278 } ,
     };
     
 }
 
 [System.Serializable]
 public struct GeoCoord
 {
     public string label;
     public double latitude;
     public double longitude;
     public override string ToString () => this.label;
     public Vector2 ToVector2 () => new Vector2( (float) Math.Sin( this.longitude * Deg2Rad * 0.5 ) , (float) Math.Sin( this.latitude * Deg2Rad ) );
     public Vector3 ToVector3 ( float elevation = 0 ) => new Vector3( (float) Math.Sin( this.longitude * Deg2Rad * 0.5 ) , elevation , (float) Math.Sin( this.latitude * Deg2Rad ) );
     public Vector3 ToVector3UnitSphere () => Quaternion.Euler(0,-(float)this.longitude,0) * ( Quaternion.Euler(-(float)this.latitude,0,0) * Vector3.forward );
     const double Deg2Rad = Math.PI / 180.0;
 }

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image andrew-lukasik · Jul 20, 2021 at 05:17 PM 0
Share

Here is an example. Scale is set to 1 000 000+ floating origin results in (+/-) 100 units of distance between those coordinates. Naturally, with some additional math, you can calculate an exact scale that will match 1 unit with 10 or 100 meters of real world distance.

1 unit - 1 meter probably won't be a good idea since geolocation offers no such precision in 2021. But one can compensate for that if your really need it, I guess.

alt text

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

171 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Are real-time reflection probes working with specular convolution on mobile devices? 0 Answers

Is Using Coroutines Actually Faster Than Update? 1 Answer

Prevent mesh normals for being normalized when building for mobile? 0 Answers

Delta touch trembling 0 Answers

Adjusting Unity scene for smartphones and tablets? 1 Answer


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges