Discrepancy in GPS co-ordinates between Esri LocationDisplay GPS co-ordinates and System.Device.Location.GeoCoordinateWatcher

536
10
02-13-2024 06:36 AM
DaveMorrow
New Contributor II

 

What reason would there be a discrepancy in location between Esri maps using default Windows Location Services, getting a GPS signal (i.e. not a default wi-fi location) and Windows Location Services getting a location using Powershell?

Our application in UWP uses the below code to enable GPS location in Esri using Windows Location Services (default).

 

C# code below

 

Map.LocationDisplay.IsEnabled = true;

Map.LocationDisplay.DataSource.LocationChanged += (sender, eventArgs) => OnDeviceLocationChanged(sender, eventArgs);

private void OnDeviceLocationChanged(object sender, Location e)

{

_ = Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>

{

logger.Info($"Current Device Location:

Easting = { position.Easting}

Northing = { position.Northing}");

});

}

 

The log entry generated using Esri data is below.

Device Location: Easting = 631010.XXXXXXXXX Northing = 143140.XXXXXXXXX

 

Using a converter (https://gridreferencefinder.com/) to convert to Lat and Long, result is Lat

51.14 , long 1.30

 

Using System.Device.Location.GeoCoordinateWatcher using the powershell script below to capture GPS coordinates at the same time returns Lat 51.25, Long 0.514)

 

Powershell code below

 

Add-Type -AssemblyName System.Device

$GeoWatcher = New-Object System.Device.Location.GeoCoordinateWatcher

$GeoWatcher.Start()

 

while (($GeoWatcher.Status -ne 'Ready') -and ($GeoWatcher.Permission -ne 'Denied')) {

    Start-Sleep -Milliseconds 100 #Wait for discovery.

 

$GeoWatcher.Position.Location | Select Latitude,Longitude

 

See: https://learn.microsoft.com/en-us/dotnet/api/system.device.location.geocoordinatewatcher?view=netfra...

 

DaveMorrow_0-1707835596549.png

 

 

0 Kudos
10 Replies
MichaelDavis3
Occasional Contributor III

Your Powershell coordinates are in Lat/Long and your AGSLocation coordinates are in Web Mercator. 

Sorry - misread the original post.  Not sure what the discrepancy is however I've noticed on a few occasions that the AGSLocation objects in my maps seem to start general and then "snap" to a more accurate location after a few seconds.

0 Kudos
dotMorten_esri
Esri Notable Contributor

What LocationDatasource are you using? I'm a bit surprised you're not getting WGS84 Lat/Long values if you're using the default datasource.
Whatever spatial reference you're getting it in, the conversion might be using different datum transforms than what you're comparing to online.

0 Kudos
DaveMorrow
New Contributor II

Hi, We are using the default datasource which I believe is returning WGS84 Lat/Long but we log the Easting and Northing (X and Y values from MapPoint projected to BritishNationalGrid). This isn't the issue.

Pasting these into gridreferencefinder.com shows a valid location and is normally correct. However, in this instance the location was wrong! But Powershell was reporting the correct location (when converted).

Normally they are both the same location, as you would expect.

So the question is why is Powershell returning a different location to ArcGis if they are using the same GPS source.

Does ArcGisRuntime use the same underlying method as our Powershell script does via System.Device.Location.GeoCoordinateWatcher to get the GPS coordinates and is there any logic (e.g. caching etc.) that occurs that would affect the locations from being the same/correct?

Thanks

0 Kudos
dotMorten_esri
Esri Notable Contributor

 but we log the Easting and Northing

Just to rule out any projection differences, could you instead verify that the original unprojected coordinate matches what you see in powershell? The projection used in Runtime might not match 100% the one you compare with online (or use Runtime to convert your powershell-based location using the same reprojection code and datum transformation steps).

 

We use the newer GeoLocator, (GeoCoordinateWatcher is based on a deprecated underlying location API) but there are various accuracy settings that might affect it too (we explicitly set it to high), and you seem to just be pulling the coordinate from the location. The very first location we get might be up to an hour old (the property on the location will indicate that and the dot on the map will be gray), but next location event should be "fresh".

0 Kudos
DaveMorrow
New Contributor II

Hi,

I'm comfortable that the projection is correct (it works the rest of the time).

In this instance the location determined was the initial result from the Esri LocationDisplay and did not get a subsequent LocationChanged event, so quite probably not "fresh". But this was over an 4.5hr period (see below). I note that the location is consistent too, suggesting stale/cached data. This was resolved on restart of the UWP application hosting the Esri map.

10:57:49|Easting = 631010.123456789 Northing = 143140.123456789
12:50:06|Easting = 631010.123456789 Northing = 143140.123456789
12:56:42|Easting = 631010.123456789 Northing = 143140.123456789
14:39:52|Easting = 631010.123456789 Northing = 143140.123456789
15:13:32|Easting = 631010.123456789 Northing = 143140.123456789
15:34:13|Easting = 631010.123456789 Northing = 143140.123456789

Yet, the Powershell script was returning correct location at the same time as above.

Presumably both APIs should return the same co-ordinates.

But if there is caching then this could result in different results at the same time. Is this cached by the Esri Runtime or the underlying API?

Can we programmatically determine if the location is Fresh and/or flush the cache or force a fresh read?

Thanks

Dave

0 Kudos
dotMorten_esri
Esri Notable Contributor

Can we programmatically determine if the location is Fresh

You can use the IsLastKnown property to check whether it is an old cached location. You can also look at the timestamp.

Presumably both APIs should return the same co-ordinates.

We're not using the same API. You're using GeoCoordinateWatcher which is built on the older Windows Location APIs that has been deprecated. We're using WinRT's more modern GeoLocator in the Windows.Devices.Geolocation APIs, which might also be pulling from IP, WiFi, Celltowers etc to get a quick first location fix. You should be able to tell the origin of the location in the AdditionalSourceProperties property, although it is a bit dependent on your system's Location driver whether that'll get populated. The HorizontalAccuracy property might also be an indication of what kind of location fix you got.

 

I'm comfortable that the projection is correct (it works the rest of the time).

I just wanted to rule this out completely. It's a lot easier to troubleshoot if we remove all the extra stuff, just in case - grid transformations can be finicky and a web site is not guaranteed to use the exact same transformation data or calculation as the Maps SDK, and even the Maps SDK can be configured to perform the transformations differently depending on scenario.

 

0 Kudos
DaveMorrow
New Contributor II

Hi,

I’ve been looking at the additional properties and as you say they depend on underlying API and driver to provide details. I’ve had mixed results but mainly LocationSource is returning Wifi even when using GPS dongle and doesn't always provide any other clue. Most importantly we’re unable to force any refresh of cache or only use GPS to get accurate read.

Our issue is that Windows Location Services used as default in Esri has been unreliable – a combination of slow to update and inaccurate location (e.g. WiFi or cached location).

It was during investigating this that we noticed Powershell script was returning more accurate location results (not cached).

We’re are now looking at replacing with direct call to the GPS device via COM Port, e.g.

var port = new System.IO.Ports.SerialPort("COM3", 9600);

NmeaLocationDataSource serialPortDatasource = NmeaLocationDataSource.FromStreamCreator(

    onStart: (ds) =>

    {

        port.Open();

        return Task.FromResult(port.BaseStream);

    },

    onStop: (ds) =>

    {

        port.Close();

        return Task.CompletedTask;

    }

);

MyMapView.LocationDisplay.DataSource = serialPortDatasource;

MyMapView.LocationDisplay.IsEnabled = true; // This will trigger onStart to get called

 

However, within UWP some calls are restricted. And we’ve had COM ports being reassigned when Windows restart or windows/driver updates.

Obviously I’d rather not write code to identify the correct port but it seems this may be needed.

Any thoughts or suggestions on best approach to implement GPS location reliably and accurately would be appreciated.

0 Kudos
dotMorten_esri
Esri Notable Contributor

You could also consider replacing your system's location driver with a NMEA based one. Of course that requires system-wide install and managing the connection outside your app. Windows won't "just" use a GPS dongle as its system location without some configuration/driver setup.


Wrt UWP and serial ports, there's plenty of device information APIs to help you find the "right" port based on device ids. https://learn.microsoft.com/en-us/uwp/api/windows.devices.serialcommunication?view=winrt-22621

The device information will allow you to identify the same device regardless of it's assigned portname dynamically. The UWP version of the NMEA constructor takes that device information object directly as an input: https://developers.arcgis.com/net/api-reference/api/uwp/Esri.ArcGISRuntime/Esri.ArcGISRuntime.Locati...


 

0 Kudos
DaveMorrow
New Contributor II

I realised I hadn't installed the GPSComplete GPSDirect middleware driver (as this had been uninstalled for testing) so Windows Location Service couldn't use the GPS device and was actually getting WiFi as a position source. When I reinstalled the driver I do then get GNSS as a PositionSource.

I also get IP as the PositionSource when Wifi is disabled. So now we can use this to assist in troubleshooting. 🙂

 

But we're still looking at bypassing Windows Location Service as there is no control over the above to disable IP or Wifi options only for location purposes and force use of GPS device.

 

The examples you give for finding the Serial Device assume no other serial devices are installed and potentially fail if another (non-GPS) serial device installed?

 

SerialDevice.GetDeviceSelector takes a portName as parameter or returns all serial devices so does require a known static COM Port.

SerialDevice.GetDeviceSelector Method (Windows.Devices.SerialCommunication) - Windows UWP applicatio...

 

An alternative in the documentation using SerialDevice.GetDeviceSelectorFromUsbVidPid can identify device by vendor and product Id would require configuration per GPS device.

SerialDevice.GetDeviceSelectorFromUsbVidPid(UInt16, UInt16) Method (Windows.Devices.SerialCommunicat...

var selector = SerialDevice.GetDeviceSelectorFromUsbVidPid(vid, pid);            

var devices = await DeviceInformation.FindAllAsync(selector);            

var item = devices.FirstOrDefault();

 

What is the best option to identify a GPS serial device on UWP application without known static COM port address and with other non-GPS serial devices installed?

 

0 Kudos