Jump to content
The simFlight Network Forums

Creating FsLatLonPoint via other thread 'lag'


Recommended Posts

Hi,

 

I'm currently developing an application with Pete Dowson's DLL.

I just upgraded to Client 3.0 beta, which works for now as expected.

 

sidenote - I upgraded because I needed the WeatherServices, however I'm getting errors on that: 'METAR for xxxx is not available now'. - But that is not the issue for this topic :)

 

My issue is, that I'm trying to make use of the FsLatLonQuadrilateral interface, and just like the UserGuide.pdf, I am creating 4 FsLatLonPoints, but there is the issue:

I'm doing this on another thread (backgroundworker c#) and it takes about 30 seconds (25 seconds to be exact) to create them, after which the backgroundworker kind of crashes, without error, just exitcode 259.

 

I believe this is because it is trying to access the main thread or something to process the FsLatLonPoints? Like it is really 'creating' points in fsx?

 

In the main thread they just work fine.

 

The reason I use it on a background worker is because it does some processes which require information from an database and work with that data... Basically I have a list of points and I want to check if they are within a distance of the airplane.

 

Suggestions?

Can I find the source code on this somewhere?

Link to comment
Share on other sites

HI,

 

The FSLonLatPoints are only local-memory structs and all the calculations are done by locally by the DLL. Nothing is created in FSX/FSUIPC.

 

It certainly shouldn't take 25 seconds to new up 4 instances of these. I'll try it here on a background thread and see if I can see the problem. It does sound like some kind of cross-threading blocking.

 

I'll get back to you with my findings and hopefully a fix.

 

Paul

Link to comment
Share on other sites

I've replicated what you are doing (as far as I can tell) and I can't see any problems.

 

Below is the short test form I set up that creates a quad using FSLatLonPoints and then tests the player's position. There are two buttons, one runs on the main thread and the other on a background worker thread. Both come back instantly.

 

I think there is something else in your code that is causing the issues; the DLL itself seems quite happy with being called from other threads.

using FSUIPC;
using System.Threading;
       // Form is called 'frmBackgroundThread' 
       // Two button on the form called 'btnMainThread' and 'btnBackgroundThread'        
       // Test will return 'true' when on runway at EGJJ 

        private Offset<long> playerLatitude = new Offset<long>(0x0560);
        private Offset<long> playerLongitude = new Offset<long>(0x0568);

        public frmBackgroundThread()
        {
            InitializeComponent();
        }

        private void frmBackgroundThread_Load(object sender, EventArgs e)
        {
            FSUIPCConnection.Open();
        }

        private void frmBackgroundThread_FormClosing(object sender, FormClosingEventArgs e)
        {
            FSUIPCConnection.Close();
        }

        private void btnMainThread_Click(object sender, EventArgs e)
        {
            bool testResult = createAndTestQuad();
            MessageBox.Show("result on main thread was: " + testResult.ToString());
        }

        private void btnBackgroundThread_Click(object sender, EventArgs e)
        {
            BackgroundWorker bw = new BackgroundWorker();
            bw.DoWork += bw_DoWork;
            bw.RunWorkerCompleted += bw_RunWorkerCompleted;
            bw.RunWorkerAsync();
        }

        void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            MessageBox.Show("result from background thread was: " + e.Result.ToString());
        }

        private void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            e.Result = createAndTestQuad();
        }

        private bool createAndTestQuad()
        {
            FsLatLonPoint NE = new FsLatLonPoint(new FsLatitude(49, 20d), new FsLongitude(-2, -10d));
            FsLatLonPoint NW = new FsLatLonPoint(new FsLatitude(49, 20d), new FsLongitude(-2, -20d));
            FsLatLonPoint SE = new FsLatLonPoint(new FsLatitude(49, 10d), new FsLongitude(-2, -10d));
            FsLatLonPoint SW = new FsLatLonPoint(new FsLatitude(49, 10d), new FsLongitude(-2, -20d));
            FsLatLonQuadrilateral quad = new FsLatLonQuadrilateral(NE, NW, SE, SW);
            FSUIPCConnection.Process();
            FsLatitude testLat = new FsLatitude(this.playerLatitude.Value);
            FsLongitude testLon = new FsLongitude(this.playerLongitude.Value);
            FsLatLonPoint testPoint = new FsLatLonPoint(testLat, testLon);
            return quad.ContainsPoint(testPoint);
        }

If you need any more help with this let me know,

 

Regards,

 

Paul

Link to comment
Share on other sites

        private bool createAndTestQuad()
        {
            FsLatLonPoint NE = new FsLatLonPoint(new FsLatitude(49, 20d), new FsLongitude(-2, -10d));
            FsLatLonPoint NW = new FsLatLonPoint(new FsLatitude(49, 20d), new FsLongitude(-2, -20d));
            FsLatLonPoint SE = new FsLatLonPoint(new FsLatitude(49, 10d), new FsLongitude(-2, -10d));
            FsLatLonPoint SW = new FsLatLonPoint(new FsLatitude(49, 10d), new FsLongitude(-2, -20d));
            FsLatLonQuadrilateral quad = new FsLatLonQuadrilateral(NE, NW, SE, SW);
            FSUIPCConnection.Process();
            FsLatitude testLat = new FsLatitude(this.playerLatitude.Value);
            FsLongitude testLon = new FsLongitude(this.playerLongitude.Value);
            FsLatLonPoint testPoint = new FsLatLonPoint(testLat, testLon);
            return quad.ContainsPoint(testPoint);
        }

 

Why you have a FSUIPCConnection.Process() there?

What I should add is that, while that is working on the background, a timer, with interval 200, is also running at the same time. (processing data back and fort to/from fsx)

 

In the meantime I already got it fixed. by I re-creating the Quadrilateral class a bit and got away with it. I think, somehow, the FsLatLonPoint still wants to be processed or something, it is probably waiting in queue it looks like, I don't know,, after doing this I've got my results within a milliseconds.

Oh and btw, why do you do +90.0 and +180.0 on the lat/lon Degrees inside ContainsPoint() Method?  

 

Thanks for your time though, well done on that DLL, very useful.

Edited by ruudfaessen
Link to comment
Share on other sites

The process() call in my test form is just to update the player location (this.playerLatitude and this.playerLongitude). I just wanted to check that it was okay calling Process() and accessing offsets on a different thread.

 

Most of the internal trigonometry involving lon/lat uses values that are offset by 180 (lon) or 90 (lat) degrees so that there are no negative values to deal with. So for example the longitude runs from 0 to 360 degrees instead of -180 to +180. It's many years since I wrote this but I'm guessing it kept the maths formulas more simple.

 

Glad to hear you've sorted your problem.

 

Paul

Link to comment
Share on other sites

Paul, altrough you have solved my problem for this, I have a more off-topic question regarding the WeatherServices, it doesn't work, I get back the error: FSUIPC Error #11: FSUIPC_ERR_TIMEOUT. Weather station xxxx is currently unavailable or is invalid.

Where xxx is a valid airport where my aircraft was parked at that moment.

I've tried it in two ways:

FSUIPC.FSUIPCConnection.Process();
WeatherServices ws = FSUIPCConnection.WeatherServices;
            string weather1 = ws.GetMetarAtLocation("LSZH");
            FsWeather weather = ws.GetWeatherAtLocation(Convert.ToDouble(airport.Latitude_deg), Convert.ToDouble(airport.Longitude_deg));
            foreach (FsWindLayer wl in weather.WindLayers)
            {
                double direction = wl.Direction;
                double speed = wl.SpeedKnots;
            }
Link to comment
Share on other sites

The error is thrown because FSUIPC did not receive the weather from SimConnect within the time limit. The default time limit is only 1 second. This was okay on the airports I tested on, but it seems some stations take much much longer to respond.

 

To increase the waiting time set ws.LocationReadTimeout to the number of milliseconds to wait. I found 20 seconds was a better setting, but you can go higher if you want. Just remember that if the station really is out of range it will keep trying for the whole timeout.

FSUIPC.FSUIPCConnection.Process();
WeatherServices ws = FSUIPCConnection.WeatherServices;
ws.LocationReadTimeout = 20000; // try 20 seconds.
string weather1 = ws.GetMetarAtLocation("LSZH");
FsWeather weather = ws.GetWeatherAtLocation(Convert.ToDouble(airport.Latitude_deg), Convert.ToDouble(airport.Longitude_deg));
foreach (FsWindLayer wl in weather.WindLayers)
{
   double direction = wl.Direction;
   double speed = wl.SpeedKnots;
}

Paul

Link to comment
Share on other sites

  • 2 weeks later...

I've replicated what you are doing (as far as I can tell) and I can't see any problems.

 

Below is the short test form I set up that creates a quad using FSLatLonPoints and then tests the player's position. There are two buttons, one runs on the main thread and the other on a background worker thread. Both come back instantly.

 

I think there is something else in your code that is causing the issues; the DLL itself seems quite happy with being called from other threads.

If you need any more help with this let me know,

 

Regards,

 

Paul

 

 

Hi,

i would like to ask you why there is a difference, for example with distances and Bearing, between your DLL functions you are using with the FSUIPCClientExample and the real world Mathe calculation that is giving the right result.

 

Aircraft world position Lat/Lon from FSUipc offsets (single offsets) or with Simconnect

Destination Lat/Lon from a external dBase

 

Example Difference:

LOWG to EGLL

Distance in nm = 677 - Km = 1255 - BRG 296° initial

Your FS-DLL calculation is:

Distance in nm = 732 - Km = 1356 - BRG 289° initial

I checked my data with some Web distance calculators that confirmed my results.

I think that the difference is due to a different conversion from N/W/E to a lat / lon with 6 decimals, let us say less accurate.

The real world distance calculation

 

   Function distance(ByVal lat1, ByVal lon1, ByVal lat2, ByVal lon2, ByVal unit

) As Double

        ''lat1, lat2 - Double values with 6 decimals

        Dim theta As Double = 0

        Dim dist As Double = 0

        theta = lon1 - lon2

        dist = Math.Sin(deg2rad(lat1)) * Math.Sin(deg2rad(lat2)) + Math.Cos(deg2rad(lat1)) * Math.Cos(deg2rad(lat2)) * Math.Cos(deg2rad(theta))

        dist = acos(dist)

        dist = rad2deg(dist)

        distance = dist * 60 * 1.1515

        Select Case UCase(unit)

            Case "K"

                distance = distance * 1.609344

            Case "N"

                distance = distance * 0.8684

        End Select

    End Function

THE BEARING FUNCTION (all Mathe as per ED Williams Pilot Mathe)

http://williams.best.vwh.net/avform.htm

 

       'get distance into d

        d = distance_radians(d)

        'calc bearing

        If Math.Sin(BlonRad - AlonRad) < 0 Then

            dn = (Math.Sin(d) * Math.Cos(AlatRad))

            If dn = 0 Then dn = 1      'not the correct way but it helps otherwhise stop calc.

            tc1 = acos((Math.Sin(BlatRad) - Math.Sin(AlatRad) * Math.Cos(d)) / dn)

        Else

            dn = (Math.Sin(d) * Math.Cos(AlatRad))

            If dn = 0 Then dn = 1

            tc1 = 2 * pi - acos((Math.Sin(BlatRad) - Math.Sin(AlatRad) * Math.Cos(d)) / dn)

        End If

        'rad into degrees

        tc1 = rad2deg(tc1)  'RESULT  <= 0 = 360°

        ''''convert to what we need

        '' 'Course deviation from actual aircraft position

        '' adjust HeadingDifference

        '' less MagVariation

 

Appreciate you kind comments.

Many thanks and best regards,

Raimund

.

Link to comment
Share on other sites

Hi Raimund,

 

I'm pretty sure I'm using different formulas than you posted. It's likely that the current formulas are either fundamentally inaccurate or, as you suggest, there could be a rounding problem.

 

Let me check it out over the next few days and I'll get back to you with a fix or further comments.

 

Regards,

 

Paul

Link to comment
Share on other sites

Hi Raimund,

 

The formula I was using for distance and bearing were not the 'great circle' ones you posted and linked to.

 

I'm not sure how you got my DLL to say the distance between LOWG and EGLL is 732NM. I tried with this code and it came back only 3 NM over.

            FsLatLonPoint LOWG = new FsLatLonPoint(new FsLatitude(46.991067), new FsLongitude(15.439628));            FsLatLonPoint EGLL = new FsLatLonPoint(new FsLatitude(51.4775), new FsLongitude(-0.461388));            double distance = LOWG.DistanceFromInNauticalMiles(EGLL);

I only mention this in case you've got something wrong in your code.

 

Anyway, I've replaced the formulas with those from the web page you linked to. New version is attached.

 

Using the same code above it now reports 677NM and 299 degrees, which is consistent with this web page:

 

http://www.ig.utexas.edu/outreach/googleearth/latlong.html

 

Thanks for reporting this and linking to the formulas.

 

Paul

 

 

FSUIPCClient3.0_BETA.zip

FSUIPCClient3.0_BETA.zip

Link to comment
Share on other sites

Hi Raimund,

 

The formula I was using for distance and bearing were not the 'great circle' ones you posted and linked to.

 

I'm not sure how you got my DLL to say the distance between LOWG and EGLL is 732NM. I tried with this code and it came back only 3 NM over.

            FsLatLonPoint LOWG = new FsLatLonPoint(new FsLatitude(46.991067), new FsLongitude(15.439628));
            FsLatLonPoint EGLL = new FsLatLonPoint(new FsLatitude(51.4775), new FsLongitude(-0.461388));
            double distance = LOWG.DistanceFromInNauticalMiles(EGLL);

I only mention this in case you've got something wrong in your code.

 

Anyway, I've replaced the formulas with those from the web page you linked to. New version is attached.

 

Using the same code above it now reports 677NM and 299 degrees, which is consistent with this web page:

 

http://www.ig.utexas.edu/outreach/googleearth/latlong.html

 

Thanks for reporting this and linking to the formulas.

 

Paul

Hi Paul,

 

I did not use your DLL for calculating as i'm only using the Mathe Formulas by Ed Williams for all calculations.

 

I noticed the difference using your FSUIPCClientExample.VB that is using your DLL.

Sitting at LOWG your example program is calculating distance + Bearing to EGLL.

 

As far as the Bearing is concerned (296 / 299) the difference is the MagVariation, depending on what we want as result.

 

In fact, as example, the RWY-Heading(35C) of LOWG is 349 considering the MagVariation or 346(less MagV).

 

There is a "lateral deviation formula" that could be very useful for calculating a "restricted" deviation result, example to a Rwy or else.

crs_AD = Heading in Rad

crs_AB = Back-Course (example of a Rwy) in Rad

 

XTD_Dev = Math.Asin(Math.Sin(Distance) * Math.Sin(crs_AB - crs_AD))

XTD_Dev = rad2deg(XTD_Dev)

 

'Restrict area / result

If XTD_Dev < 0.6 And XTD_Dev > -0.6 then

    'do something

    'also a ILS signal would be within this result even if not aligned but heading towards

Else

    'do something

End If

 

This formula should not be used for calculating a Fly-To Bearing Difference.

To mention that there is a big difference in calculating a Bearing-To and calculating for example a Rwy-Approach that would need more calculation for getting the Bearing-Difference.

 

'calc Position/Wpt aligned with Heading/Rwy at same distance of Apl to Rwy

tc = RunwayBackCourse + MagVariation

tc = deg2rad(tc)

d2 = distance in Km

lat = Math.Asin(Math.Sin(lat2) * Math.Cos(d2 / EarthR) + Math.Cos(lat2) * Math.Sin(d2 / EarthR) * Math.Cos(tc))

lon = lon2 + Atan2((Math.Sin(tc) * Math.Sin(d2 / EarthR) * Math.Cos(lat2)), (Math.Cos(d2 / EarthR) - Math.Sin(lat2) * Math.Sin(lat2)))

 

 

In fact a Rwy-Approach, example a FS-ILS Autopilot Appr is moving the Apl more "lateral" L/R while the pure Mathe-Calc is moving the Apl along a smooth angle to the Center Approach-Heading. Considering the speed and change of the actual apl position the difference is quite obvious and requesting to start alignmend at a certain distance for any system in use.

 

Your contribution is really great. Thanks.

 

regards,

Raimund

.

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use. Guidelines Privacy Policy We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.