• Which the release of FS2020 we see an explosition of activity on the forun and of course we are very happy to see this. But having all questions about FS2020 in one forum becomes a bit messy. So therefore we would like to ask you all to use the following guidelines when posting your questions:

    • Tag FS2020 specific questions with the MSFS2020 tag.
    • Questions about making 3D assets can be posted in the 3D asset design forum. Either post them in the subforum of the modelling tool you use or in the general forum if they are general.
    • Questions about aircraft design can be posted in the Aircraft design forum
    • Questions about airport design can be posted in the FS2020 airport design forum. Once airport development tools have been updated for FS2020 you can post tool speciifc questions in the subforums of those tools as well of course.
    • Questions about terrain design can be posted in the FS2020 terrain design forum.
    • Questions about SimConnect can be posted in the SimConnect forum.

    Any other question that is not specific to an aspect of development or tool can be posted in the General chat forum.

    By following these guidelines we make sure that the forums remain easy to read for everybody and also that the right people can find your post to answer it.

MSFS [SOLVED] stepping through the C:fs9gps: flight plan

Messages
244
Country
unitedkingdom
Programming a MSFS html nav intrument I'm stepping though the waypoints in the loaded flightplan by the standard process(?):
  • writing C:fs9gps:FlightPlanWaypointIndex, and then
  • reading e.g. C:fs9gps:FlightPlanWaypointIdent for each waypoint.
There seem to be MAJOR MSFS quirks with a simple flightplan .pln FILE for a simple triangle [1.Airport, 2.WP1, 3.WP2, 4.same Airport] I do not remember from FSX - can anyone comment:
  • On load, the sim is adding additional waypoints into the fs9gps data i.e. 3.TIMECRUIS, 4.TIMEDCNT. I know what these are for (getting the plane to/from the cruise altitude) but I don't remember the actual flight plan being modified before and will need to skip this stuff for my VFR (glider!) flight where the altitudes are garbage.
  • The waypoint data for FlightPlanWaypointIndex=0 seems unreliable, i.e. at the start of the flight it contains the start Airport, but AFTER CYCLING ROUND the [C:fs9gps:FlightPlanWaypointsNumber] set of waypoints, the info for the waypoint at [0] is all null (i.e. Ident, Lat, Long). Note I am only modifying FlightPlanWaypointIndex, not FlightPlanIsActiveWaypoint, and sitting at the start Airport.
  • Selecting a waypoint by writing e.g. {3 -> C:fs9gps:FlightPlanWaypointIndex}, and then {true -> C:fs9gps:FlightPlanIsActiveWaypoint} does NOT result in the any of the "GPS" variables being updated for the selected waypoint (e.g. "GPS WP DISTANCE") although those do remain set for waypoint[0].
Small detail - are the waypoints supposed to be [0..WaypointsNumber-1] or [1..WaypointsNumber]? I've tested both and I'm finding waypoint data at [0..WaypointsNumber] which is bizarre.

Am I doing something stupid? Or has my memory from FSX decayed over the past decade? Any hints / clues / comments MUCH appreciated.
 
Last edited:
Messages
244
Country
unitedkingdom
Here's what I think is the answer to my own question... found in this excellent guide : https://www.robbiemcelrath.com/fs/guides/gps

There is a gauge update DELAY after setting C:fs9gps:FlightPlanWaypointIndex before the change takes effect and the values such as C:fs9gps:FlightPlanWaypointIdent become updated for the selected waypoint.

I'm think in FSX the updated data was available in the same gauge update cycle as the index change, but in MSFS this is not the case.

So on my gauge, flightplan waypointindex:0 was OK (because this was pre-loaded on flight start), selecting waypointindex:1 and then immediately reading FlightPlanWaypointIdent would actually return the existing data for waypointindex:0 (the start airport) while in the background the fs9gps engine was updating to waypointindex:1. When the NEXT waypoint was selected (waypointindex:2) and FlightPlanWaypointIdent read immediately after(i.e. in the same gauge update cycle), this would still contain the ident value for waypointindex:1 and so on.

That is why, on a flightplan that should have had indexes 0..6, I seemed able to read waypointindex:7 - following that FlightPlanWaypointIndex update I was then actually immediately reading the data (e.g. Ident) for waypointindex:6 while my index update was causing fs9gps in the background to update the values on the NEXT cycle to NULL (the correct values for waypointindex:7 for my 0..6 flightplan). And when I rotated to waypointindex:0 after this, I read these NULL's so it seemed like the data for waypointindex:0 had 'disappeared'.

AFAIK there is no way to know how long to wait before you can be sure it is safe to read FlightPlanWaypoint<property> after updating FlightPlanWaypointIndex but my guess is waiting a single update cycle should be ok for this specific example.
 
Messages
244
Country
unitedkingdom
Having re-programmed my gauge I can confirm the FlightPlanWaypointXXXX data is retrieved fine after a 1-update-cycle delay (from writing FlightPlanWaypointIndex). 1 cycle is easy to implement just by setting a local 'flightplan_request' boolean and returning immediately after writing FlightplanWaypointIndex, and on the next cycle detecting 'flightplan_request' is true, reading the values, and setting flightplan_request to false.

I'm still puzzled with MSFS 'additional' waypoints TIMECRUIS and TIMEDSCNT though. Anyone know how to stop those being added? I can skip them in my code but how many other 'additional' waypoints are there? Frankly it's annoying MSFS modifies the actual flightplan, really there should be an internal structure representing the flight plan as loaded, and another for however the sim wants to manipulate it. Whatever.
 
Messages
1,564
Country
thailand
I'm think in FSX the updated data was available in the same gauge update cycle as the index change, but in MSFS this is not the case.

AFAIK there is no way to know how long to wait before you can be sure it is safe to read FlightPlanWaypoint<property> after updating FlightPlanWaypointIndex but my guess is waiting a single update cycle should be ok for this specific example.

First off, we're talking MSFS 2020 here and I'm about to answer FSX so keep that in mind, but as far as FSX is concerned, you can't assume that a single cycle skip - one that may be implemented simply as a bool ! check, is sufficient delay to retrieve information from the database before you start using it.

There are ways to tell when data have been retrieved from the database and there's always the option to wait three or four cycles before trying to utilize a variable that is returned from the database. I've been stung assuming a single skip was sufficient only to learn the hard way that I needed three. And the length of delay may be variable depending on what's going on in the sim and what you have asked for from the gps module.

I'd assume that the fs9gps engine has been changed/updated in MSFS 2020 although I haven't tried to check. It certainly changed from FS9 to FSX and then again in P3D when LM added SID/STAR variables. All along the way, the developers did a poor to non-existent job of documenting the module. From what I read in here, MS/Asobo is in the same frame of mind right now. So, Asobo may have added things like TIMECRUIS and TIMEDSCNT, and others. Dunno.

Just keep plugging away and I'm sure you'll discover some things. But I'm with Dai and I'm not ready or willing to dive into MSFS 2020 for a while.

Bob
 
Messages
244
Country
unitedkingdom
My 'ultimate' solution (easier to code with Javascript than XML, so thanks Asobo) is to use an 'in gauge' data structure to store a copy of the flightplan. In the Update() code I check whether a flightplan is 'active', and if that status *changes* (including flightplan active on startup) then I request the waypoint count and waypoint[0] (and flag a request outstanding). When waypoint[0] arrives (in subsequent Update() calls, so far always the immediate next one) then I store that in my local structure and request waypoint[1] and so on.

If I get a MSFS-generated waypoint called "TIMEDSCNT" or "TIMECRUIS" then I simply skip it (I don't want these in my application). All the gauge code uses the 'local' array of waypoints which can be enriched with leg distance etc (which never change) so the code is nice and zippy. I notice the MSFS 'flightplan display' window skips these waypoints also (but the map display doesn't).

MSFS doesn't return the actual elevation/altitude you put in the flightplan (except for VOR's maybe?) which is a pita for me. I support an optional user waypoint id format of "NAME+ALT" (e.g. "PRTON+235") - in this case my gauge will display "PRTON" and use 235 feet as the elevation for that waypoint (otherwise it falls back to whatever MSFS reports)
 
Messages
244
Country
unitedkingdom
OK my final HTML/JS gauge solution was to stop using fs9gps and upgrade this technique to the "MSFS2020" way and use Coherent.call("GET_FLIGHTPLAN"):

For all the clues needed, Asobo original example is in asobo-vcockpits-instruments/html_ui/Pages/VCockpit/Instruments/Shared/FlightElements/FlightPlanManager.js:

Code:
        Coherent.call("GET_FLIGHTPLAN").then((flightPlanData) => {
            let index = flightPlanData.flightPlanIndex;
            if (flightPlanData.cruisingAltitude != this._cruisingAltitude) {
                this._cruisingAltitude = flightPlanData.cruisingAltitude;
                if (this.onCruisingAltitudeChanged) {
                    this.onCruisingAltitudeChanged();
                }
            }
            this._activeWaypointIndex = flightPlanData.activeWaypointIndex;
            this._departureWaypointSize = Math.max(0, flightPlanData.departureWaypointsSize);
            this._runwayIndex = flightPlanData.originRunwayIndex;
            this._departureRunwayIndex = flightPlanData.departureRunwayIndex;
            this._departureProcIndex = flightPlanData.departureProcIndex;
            this._departureEnRouteTransitionIndex = flightPlanData.departureEnRouteTransitionIndex;
            this._departureDiscontinuity = flightPlanData.departureDiscontinuity;
            this._arrivalWaypointSize = Math.max(0, flightPlanData.arrivalWaypointsSize);
            this._arrivalProcIndex = flightPlanData.arrivalProcIndex;
            this._arrivalTransitionIndex = flightPlanData.arrivalEnRouteTransitionIndex;
            this._arrivalDiscontinuity = flightPlanData.arrivalDiscontinuity;
            this._approachIndex = flightPlanData.approachIndex;
            this._approachTransitionIndex = flightPlanData.approachTransitionIndex;
            this._lastIndexBeforeApproach = flightPlanData.lastIndexBeforeApproach;
            this._isDirectTo = flightPlanData.isDirectTo;
            if (!this._directToTarget) {
                this._directToTarget = new WayPoint(this.instrument);
                this._directToTarget.infos = new IntersectionInfo(this.instrument);
            }
            this._directToTarget.icao = flightPlanData.directToTarget.icao;
            this._directToTarget.infos.icao = this._directToTarget.icao;
            this._directToTarget.ident = flightPlanData.directToTarget.ident;
            if (!this._directToTarget.ident) {
                this._directToTarget.ident = this._directToTarget.icao.substr(7);
            }
            this._directToTarget.infos.ident = this._directToTarget.ident;
            this._directToTarget.infos.coordinates = new LatLongAlt(flightPlanData.directToTarget.lla);
            this._directToOrigin = new LatLongAlt(flightPlanData.directToOrigin);
            if (!this._waypoints[index]) {
                this._waypoints[index] = [];
            }
            this._loadWaypoints(flightPlanData.waypoints, this._waypoints[index], (wps) => {
                this._waypoints[index] = wps;
            });
        });
FSX/MSFS flightplans are potentially hugely complicated, but for my purposes I simply needed to iterate flightPlanData.waypoints and collect the ident, lat, long ,alt into my own data structure.

The FlightPlanManager.js _loadWaypoints() function shows the various properties available for each waypoint as you iterate flightPlanData.waypoints, for example:
Code:
                   waypointData.icao;
                   waypointData.ident;
                   waypointData.ident;
                   new LatLongAlt(waypointData.lla);
                   waypointData.lla.lat;
                   waypointData.lla.long;
                   waypointData.lla.alt * 3.2808;
                   waypointData.altitudeMode;
                   wp.bearingInFP = isFinite(waypointData.heading) ? waypointData.heading : 0;
                   waypointData.distance;
                   waypointData.cumulativeDistance;
                   waypointData.estimatedTimeOfArrival;
                   waypointData.estimatedTimeEnRoute;
                   waypointData.cumulativeEstimatedTimeEnRoute;
                   waypointData.estimatedTimeEnRoute;
                   waypointData.airwayIdent;
                   waypointData.speedConstraint;
                   waypointData.transitionLLas;
                   waypointData.magvar;

If you do NOT have a flightplan loaded, the .then() part of the Coherent.call still gets called, but in that case flightPlanData.waypoints.length == 0.
 
Messages
531
Country
france
[ EDIT after a bug fix in my code ]

I came to the exact same conclusion as you : I have created my own flight plan structure, which mainly consists of an array of waypoints in which I can add/remove the waypoints I wish. It works, but the problem is that if I want to have the plane automatically fly the programmed flight plan, I would like to use the MSFS autopilot to do this (using GPS DRIVES NAV1), which means the MSFS flight plan MUST be consistent with my own flight plan.
This is why I tried using Coherent.call("ADD_WAYPOINT") and Coherent.call("REMOVE_WAYPOINT") like they are used in FlightPlanManager.js but these functions did not seem to work as expected for the following reasons:
  • Sometimesarrival airport disppears
  • The active waypoint is not correctly updated
Just like you, I still wonder if these functions should be used with index numbering from 0 to n-1 or from 1 to n.
If you used one of these functions, I would be happy to know if you were more successful than I was :)

Eric
 
Last edited:
Messages
244
Country
unitedkingdom
Sorry Eric - not needing the autopilot, and with my own nav gauges, I haven't needed to reverse any in-flight changes BACK into what MSFS thinks the flightplan is. TBH my life would have been a lot simpler if MSFS had allowed me to read the flightplan XML file with no interpretation by Asobo/MSoft code at all.

It seems the MSFS autopilot is still the FSX code (there are other clues that is the case, including a dependency on vars in flight_model.cfg that are no longer in the Asobo flight model), so have you tried the C:fs9gps:FlightPlanNewWaypoint... crapola to see if that injects the waypoint into the internal structure the autopilot sees? Then maybe another Coherent.call("GET_FLIGHTPLAN") would get the updated copy back into your code.

The GET_FLIGHTPLAN call is clearly getting the flightplan AFTER some autopilot code has already messed with it, because the returned data includes additional autopilot waypoints like TIMECRUIS and TIMEDCNT.

I'm not sure which class FlightPlanManager extends (I'm at 'work', if that's a fair term to use for university employment) but in case there are issues related to callbacks/listeners have you tried having your instrument extend the same class (rather than BaseInstrument)? For my original map-based nav gauge I did not need to add the 'listener' code, but in a subsequent restructuring of the code into a separate re-usable module that listener code (as FlightPlanManager) was necessary.
 
Messages
531
Country
france
Thanks for your reply.
Again, after many trials and errors, I think I could guess how this system works. If only I could have a good documentation instead...
Anyway, I found a workaround that looks OK and my flight plan management now looks OK.

BTW, I don't use the Asobo FlighrPlanManager and my class does not inherit from it. Consequently, I don't have the TIMECRUIS and TILEDCNT points created and I am happy with this 🙂
 
Messages
244
Country
unitedkingdom
I don't use FlightPlanManager at all either, just Coherent.call("GET_FLIGHTPLAN").then(...) from my own class extending BaseInstrument. I've definitely had those generated waypoints in the returned flightPlanData.waypoints and filter them out, to the extent after some MSFS update a while back my code detected the new TIMEVERT inserted waypoint so I had to add that to the list of waypoints I filter out.

Code:
                // in the "GET_FLIGHTPLAN" then(...) code:
               ...
                if (flightPlanData.waypoints.length > 1) {
                    for (let i=0; i<flightPlanData.waypoints.length; i++) {
                        let fp_wp = flightPlanData.waypoints[i];
                        this.add_waypoint_from_flightplan(fp_wp);
                    }
                }
              ...

// Here the start of the add_waypoint_from_flightplan() function:

    // For each MSFS flightplan waypoint, add it to this.task.waypoints[ ]
    add_waypoint_from_flightplan(fp_wp) {
        console.log("add_waypoint_from_flightplan", fp_wp.ident, fp_wp);
        if ( fp_wp.ident.startsWith("TIMECRUIS") || fp_wp.ident.startsWith("TIMEDSCNT") || fp_wp.ident.startsWith("TIMEVERT") ) {
            console.log("add_waypoint_from_flightplan skipping",fp_wp.ident);
            return;
        }
       ...
I found a workaround
do tell...
 
Messages
531
Country
france
I am surprised because I am in the exact same situation as you: I don't use the FlightPlanManager, my class extends BaseInstrument and I just use Coherent.call("GET_FLIGHTPLAN"), so I don't really understand why I don't have these waypoints...

Regarding my workaround, it is hard to tell without providing my whole code :)
To make a long story short, I used Coherent.call("SET_ORIGIN") and Coherent.call("SET_DESTINATION") for the departure and arrival airports, then I realized these functions add the waypoints for these 2 airports. When you create the flight plan from scratch, this is good, but not when you import it from the MSFS flight plan, it duplicates 2 waypoints that already exist: the departure and the arrival airports.
It took me some time to understand this and I just solved it by adding a flag that call these 2 functions ONLY when you create a flight plan from scratch and not when you import it. It seems to work fine, as much as my tests can tell.
 
Messages
244
Country
unitedkingdom
cool.. it's possible I'm not getting those waypoints any more - maybe the filter code did it's job earlier on and an update has changed things. I'll keep an eye on the messages in the debugger and report back if the 'skipping' message still appears in there.
 
Top