How to calculate waypoint altitude for VNAV code

#1
Hi everyone

I have a question regarding calculating waypoint altitudes.

I'm trying to get a countdown time to reaching the Top of Descent waypoint for an advisory VNAV piece of XML code for a GA aircraft. I've already got the angle-to-waypoint, vertical track error in feet, and desired spot altitude successfully expressed via trigonometry as L:vars, but I'm stuck with one area.

I'd like to do something like this (schematically):

"FlightPlanWaypointETA (or similar)" would become visible if "GPS WP PREV ALT" is the same as "GPS WP NEXT ALT" and "GPS WP AFTER-THE-NEXT-ONE ALT" is lower than both of them. This would indicate that we're on the final level segment before the top of descent.

But how might one calculate the altitude of the waypoint *after* the active waypoint? There is no variable that I can see, either in the Simulation Variables or GPS Variables set, that can access that directly.

One idea I had would be to briefly make the waypoint after the current one active, and get the altitude that way, but if it's driving the autopilot, then it would mess things up. The other would be to label the waypoint "ToD" or similar in the flightplan, and then have the ETA variable become visible when the next waypoint string is "ToD". But then you'd have to ensure that every plan had the Top of Descent waypoint labelled as "ToD", which is a bit restrictive.

This thread (http://www.fsdeveloper.com/forum/showthread.php?t=427905) gave me a suggestion, but I would like my code to do the calculations automatically, without involving mouse clicks.

Does anyone have any ideas on this?

Many thanks and kind regards,

David
 
#2
Hey, David!

I'm not familiar with gps variables, but just an idea:

Instead of the mouse click event mentioned in the other thread, you could just use a different trigger event.
For example, whenever your active waypoint changes.

I'm sure the gps gurus will join in with some better ideas soon ;)

Best regards,
Steven
 
#3
Thanks Steven

Actually, I got figured it out this morning, and it's ended up being based on waypoint indexing.

The code was relatively simple after all:

Code:
    <Macro Name="NextWPAlt">
      <MacroValue>
	(A:GPS IS ACTIVE FLIGHT PLAN,bool) 1 == if{ (A:GPS FLIGHT PLAN WP INDEX,number) 1 + (&gt;@c:FlightPlanWaypointIndex) (@c:FlightPlanWaypointAltitude,feet) }
      </MacroValue>
...and the script to go with it:

Code:
(A:GPS IS ACTIVE FLIGHT PLAN,bool) 1 ==
	  if{
	  @NextWPAlt (&gt;L:GPSNextWPAlt,feet) }
So then I was able to use the L:var to trigger the "we're going to descend on the next leg" code, which activated the timer, displayed using the A:GPS WP ETE variable.

The VNAV code is all very inelegant at the moment, even though it all works, but I'll clean it up and post it here sometime soon. If anyone's interested, they can use it for their FMCs or GPSs.

All the best,

David
 
Last edited:
#4
Code:
    <Macro Name="NextWPAlt">
      <MacroValue>
	(A:GPS IS ACTIVE FLIGHT PLAN,bool) 1 == if{ (A:GPS FLIGHT PLAN WP INDEX,number) 1 + (&gt;@c:FlightPlanWaypointIndex) (@c:FlightPlanWaypointAltitude,feet) }
      </MacroValue>
Hello David,

Did you double check the values that FlightPlanWaypointAltitude returns?

Bob
 
#5
Hello Bob

Yes, I have checked. I originally came up with this VNAV code a couple of years ago, and have used it to drive the autopilot on many flights since then, including a pitch-for-speed, constant-thrust mode (rather than autothrottle) by using the autopilot climb/descent rate. I just recently dusted it off and applied it to a different gauge. I can see what's happening to the waypoint altitudes by looking at the output of the (A:GPS WP NEXT ALT,feet) variable, while slewing through a whole flight plan.

The whole waypoint altitude business is where one of FS's quirks comes in.

Because FSX (and therefore its default flight planner) wasn't really designed with native VNAV capabilities in mind, one has to edit the flight plans made by the default planner. The WorldPosition entry of each ATCWaypoint section in each flightplan has some quirks that need ironing out before the plan will work properly with VNAV.

For example, each VOR, airport, and NDB used as a waypoint will give their MSL surface altitude by default, while each user waypoint (WP1, WP2, etc.) will give the flight plan altitude by default. Finally, each intersection used as a waypoint will give an altitude of zero by default. It's a real dog's breakfast.

So all that has to be ironed out, by manually putting in realistic altitudes for each waypoint in the .pln files (opening them using Notepad or similar).

Another quirk is that the altitude of the waypoints before the top-of-climb and after the top-of-descent follow a 3-4 degree profile (which I think may depend on where the nearest waypoint is that the simulator decides can be used as the ToC or ToD waypoint). What this means is that I can't get a departure waypoint altitude below that profile (i.e. waypoints at 1000 feet 10 miles out from the departure airport will not be honoured by the sim), but I can put one above the profile, and its altitude will be honoured. For the descent waypoints, the situation is less clear. I've yet to experiment fully with those, but putting in an approximate altitude will cause them to go to an altitude representing the 3-4 degree descent path, so it's not a big issue anyway. Suffice to say, it all works, although SID and STAR crossing heights will probably not be exactly honoured. Instrument approach waypoint altitudes will also display correctly, because each waypoint in each procedure (including the transitions) has an AT or PLUS altitude associated with it.

The whole thing also means that every plan would have to have at least two waypoints enroute, representing ToC and ToD.

All the best,

David
 
#6
Hi everyone

For anyone who's interested, here's the VNAV code, as promised.

1) Firstly, the calculations:
Code:
   <Element>
      <Select>
         <Value>(A:GPS IS ACTIVE WAY POINT,bool) 1 ==
            	if{
		(A:GPS WP NEXT ALT,feet) (A:INDICATED ALTITUDE,feet) - (&gt;L:HeightToWpt,feet)
		(A:GPS WP DISTANCE,feet) (&gt;L:DistanceToWpt,feet)
		(L:HeightToWpt,feet) (L:DistanceToWpt,feet) /
		(&gt;L:Valueholder,feet)
		(L:Valueholder,feet) atg
		(&gt;L:AngleToWPT,radians)
		(A:GPS WP NEXT ALT,feet) (A:GPS WP PREV ALT,feet) - (&gt;L:WPTHeightDiff,feet)
		(L:WPTHeightDiff,feet) (L:GPSLegDistance,nmiles) 6076.1155 * /
		(&gt;L:Valueholdertwo,feet)
		(L:Valueholdertwo,feet) atg
		(&gt;L:AngleBetweenWPT,radians)
		(A:GPS WP DISTANCE,feet) (L:AngleBetweenWPT,radians) cos / (&gt;L:HypotenuseToWPT,feet)
		(L:HypotenuseToWPT,feet) sqr (A:GPS WP DISTANCE,feet) sqr - (&gt;L:AltRemainingSqrd,feet)
		(L:AltRemainingSqrd,feet) sqrt (&gt;L:AltRemaining,feet)
		(L:HeightToWpt,feet) sqr (A:GPS WP DISTANCE,feet) sqr + (&gt;L:TriangleHypotenuseCsqrd,feet)
		(L:TriangleHypotenuseCsqrd,feet) sqrt (&gt;L:TriangleHypotenuseC,feet)
		(L:AltRemaining,feet) sqr (A:GPS WP DISTANCE,feet) sqr + (&gt;L:TriangleHypotenuseBsqrd,feet)
		(L:TriangleHypotenuseBsqrd,feet) sqrt (&gt;L:TriangleHypotenuseB,feet)
		(L:AngleToWPT,radians) (L:AngleBetweenWPT,radians) - (&gt;L:Angleholder,radians)
		(L:Angleholder,radians) cos (&gt;L:AngleholderCos,radians)
		(L:TriangleHypotenuseB,feet) (L:TriangleHypotenuseC,feet) * 2 * (L:AngleholderCos,radians) * (&gt;L:equationholder,number)
		(L:TriangleHypotenuseBsqrd,feet) (L:TriangleHypotenuseCsqrd,feet) + (L:equationholder,number) - (&gt;L:VertTrackErrorSqr,feet)
		(L:VertTrackErrorSqr,feet) sqrt (&gt;L:VertTrackError,feet)
		}
         </Value>
      </Select>
   </Element>
2) Next, the macros:
Code:
    <Update>
      <Script>
	  (A:GPS IS ACTIVE FLIGHT PLAN,bool) 1 ==
	  if{
	  @LegDistance (&gt;L:GPSLegDistance,nmiles) }
	  (A:GPS IS ACTIVE FLIGHT PLAN,bool) 1 ==
	  if{
	  @NextWPAlt (&gt;L:GPSNextWPAlt,feet) }
        </Script>
    </Update>

    <Macro Name="LegDistance">
      <MacroValue>
	(A:GPS IS ACTIVE FLIGHT PLAN,bool) 1 == if{ (A:GPS FLIGHT PLAN WP INDEX,number) (&gt;@c:FlightPlanWaypointIndex) (@c:FlightPlanWaypointDistance,nmiles) }
      </MacroValue>
    </Macro>
    <Macro Name="NextWPAlt">
      <MacroValue>
	(A:GPS IS ACTIVE FLIGHT PLAN,bool) 1 == if{ (A:GPS FLIGHT PLAN WP INDEX,number) 1 + (&gt;@c:FlightPlanWaypointIndex) (@c:FlightPlanWaypointAltitude,feet) }
      </MacroValue>
    </Macro>
3) Here is the string for showing the nominal point altitude:
Code:
<String>VNV Alt %((L:AngleToWPT,radians) (L:AngleBetweenWPT,radians) &lt;)%{if}%((A:Indicated Altitude, feet) (L:VertTrackError,feet) - )%!d!%{else}%((A:Indicated Altitude, feet) (L:VertTrackError,feet) + )%!d!%{end}'</String>
4) Finally, here is the string which shows ETE to the next waypoint at which VNAV will be required:
Code:
                        <Element>
				<Visible>(A:GPS WP NEXT ALT,feet) (A:GPS WP PREV ALT,feet) == (A:GPS WP NEXT ALT,feet) (L:GPSNextWPAlt,feet) != &amp;&amp; (A:GPS IS ACTIVE FLIGHT PLAN, bool) 1 == &amp;&amp;</Visible>
				<Position X="0" Y="0" />
				<FormattedText X="220" Y="24" Font="Tahoma" FontSize="20" Adjust="Center" VerticalAdjust="Top" Color="#0F0F0F"
					Bright="Yes">
					<String>VNV in %((A:GPS IS ACTIVE WAY POINT, bool))%{if}%((A:GPS WP ETE, minutes) flr 100 %)%!02d!:%((A:GPS WP ETE, seconds) flr 60 %)%!02d!</String>
				</FormattedText>
			</Element>

The most useful output variables are as follows. (L:AngleToWPT,degrees) shows the angle to the next waypoint, based on your current altitude. (L:VertTrackError,feet) shows the vertical track error, in feet. This indicates how far your aircraft is above or below the nominal VNAV profile, but note that this variable is absolute value -- it will not provide a negative number (if you want a negative number, you'd have to get a minus sign to display by comparing L:AngleToWPT and L:AngleBetweenWPT). Finally, the nominal altitude at which the aircraft should be can be displayed using the code in Section 3 above.

Hope this is useful to someone.

All the best,

David
 
Last edited:
#7
Hi everyone

Just a couple of observations related to waypoint altitudes.

I've been experimenting with VFR plans made using the default planner in FSX, and I've found that you get more flexibility with having edited waypoint altitudes honoured if your set the cruise altitude very low. Because the cruise altitude is not used by default ATC regarding VFR flights, you can set it to 100 feet or something like that, and then the pre-ToC and post-ToD altitude smoothing (mentioned in a previous post) doesn't occur.

That means that you can freely set altitudes with such a modified VFR plan. An example might be departing the field, climbing over a restricted area, then going under a TCA shelf or similar, then climbing again to cruise altitude, to reach final descent later on. In this case, the waypoint altitudes will be honoured, and the code will display advisory VNAV information to help you avoid the areas of airspace.

Anyway, perhaps this is useful to someone.

All the best,

David
 
Top