• 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.

FSXA Most efficient way to code a switch

Messages
407
Country
ca-britishcolumbia
I've made a three position autopilot switch for my DC-8. The first position is "off", the next is "yaw damper on" and the last position is "autopilot on". The yaw damper stays on in the autopilot on position.

The way I have it now is with an animation from 0 to 50. So far, I have only coded the yaw damper. When the local variable gets to 25 or higher, the yaw damper is turned on using the YAW_DAMPER_ON event. It switches off in the same manner using YAW_DAMPER_OFF when the local variable is less than 25.

I'm now wondering if I have created a gauge that will be checking every cycle to see whether or not to turn the yaw damper on and off, and that really I should use the YAW_DAMPER_SET or YAW_DAMPER_TOGGLE events. Am I right in thinking the latter way would use less resources? How do I code the event to happen when the local variable passes through a specified value? Or is it fine the way it is?
 
Placing evaluations like that is a terrific way to generate a "race" condition. By that I mean a continuous firing of event(s) that will cripple the sim.

Best practice is to only use event commands within the mouse routine. This way will guarantee that they only get fired one time. For example, here is the XML script for a fuel selector knob. Note in particular the last four lines where the desired event is fired based on the control L:var's value:
Code:
    <MouseRect>
      <Cursor>Hand</Cursor>
      <TooltipText>Fuel Select Left</TooltipText>
      <MouseFlags>LeftSingle+RightSingle+Wheel</MouseFlags>
      <CallbackCode>
        (M:Event) 'LeftSingle' scmp 0 ==
        (M:Event) 'WheelDown' scmp 0 == or
             if{ (L:FuelSelectLeft, enum) -- 0 max (>L:FuelSelectLeft, enum) }
 
        (M:Event) 'RightSingle' scmp 0 ==
        (M:Event) 'WheelUp' scmp 0 ==
             if{ (L:FuelSelectLeft, enum) ++ 3 min (>L:FuelSelectLeft, enum) }
 
        (L:FuelSelectLeft,enum) 0 == if{ 0 (&gt;K:FUEL_SELECTOR_SET) }
        (L:FuelSelectLeft,enum) 1 == if{ 2 (&gt;K:FUEL_SELECTOR_SET) }
        (L:FuelSelectLeft,enum) 2 == if{ 9 (&gt;K:FUEL_SELECTOR_SET) }
        (L:FuelSelectLeft,enum) 3 == if{ 15 (&gt;K:FUEL_SELECTOR_SET) }
      </CallbackCode>
    </MouseRect>
In your case the conditions would be controlled thusly:
Code:
      (L:MyKnob,enum) 0 == if{ (>K:YAW_DAMPER_OFF) }
      (L:MyKnob,enum) 1 == if{ (>K:YAW_DAMPER_ON)  (>K:AUTOPILOT_OFF) }
      (L:MyKnob,enum) 2 == if{ (>K:AUTOPILOT_ON) }
 
No problem. I've re-edited several times to simplify the scheme and make it easier to read.

Most important of all is to always use _ON, _OFF, or _SET versions of events whenever they are available. "Toggle" events are far too easy to 'get out of synch', which will really flummox everyone. :banghead:
 
Toggles are good for keyboard commands... not much else. Don't use them for switches. Even buttons usually are on/off not toggle, even if you cant notice it at first look.
 
But what happens when the user uses a key command to turn the autopilot off? Or uses a key command to turn the yaw damper on or off?

As they are most likely to do on an approach where the last thing they want to be doing is mousing about looking for a switch. Your L var and what is happening in the sim will become disconnected.

In this particular case I would try something like this in the Animation code:
Code:
       <Animation>
            <Parameter>
                <Code>
(A:AUTOPILOT MASTER,bool)
if{ 50 }
els{
  (A:AUTOPILOT YAW DAMPER,bool)
  if{ 25 }
  els{ 0 }
}
</Code>
                <Lag>25</Lag>
            </Parameter>
        </Animation>

If the AP is on then it will animate to keyframe 50 and assume the Yaw damper is also on (see below for more on how to ensure the yaw damper is on).

If the AP is off it will check if the yaw damper is on or off and set the switch to either 25 or 0 depending on the situation.

If you want to ensure everything is in line and doing what it is supposed to do you can add a validation routine to an XML gauge to check if the AP is on and the Yaw Damper is off and if so turn the Yaw damper back on. Like:

(A:AUTOPILOT MASTER,bool) (A:AUTOPILOT YAW DAMPER,bool) ! and if{ (&gt;K:YAW_DAMPER_ON) }

This will check 18 frames per second if you have it in a XML gauge. It is not very processor intensive and will only fire the YAW DAMPER ON if it is in a position it shouldn't be. Compared to using tens of thousands of trig functions to draw a bunch of polygons on screen every single frame it has miniscule effect.

You could throw the above line into the Animation Code if you really do not want to use a separate XML gauge but this would be a last resort option.

The mouse rect function could look something like this (borrowing Bill's original code he posted earlier)

Code:
<MouseRect>
      <Cursor>Hand</Cursor>
      <TooltipText>Fuel Select Left</TooltipText>
      <MouseFlags>LeftSingle+RightSingle+Wheel</MouseFlags>
      <CallbackCode>
        (M:Event) 'LeftSingle' scmp 0 ==
        (M:Event) 'WheelDown' scmp 0 == or
             if{
                     (A:AUTOPILOT MASTER,bool)
                       if{ (&gt;K:AP_MASTER) }
                        els{ (&gt;K:YAW_DAMPER_OFF) }
               }
        (M:Event) 'RightSingle' scmp 0 ==
        (M:Event) 'WheelUp' scmp 0 == or
             if{
                  (A:AUTOPILOT YAW DAMPER,bool) !
                 if{ (&gt;K:YAW_DAMPER_ON) }
                  els{
                       (A:AUTOPILOT MASTER,bool) !
                       if{ (&gt;K:AP_MASTER) }
                         }
              }
      </CallbackCode>
    </MouseRect>

Left click will check if the AP is ON, if so it will turn it off (and we assume our validation code will have already set the yaw damper to on). If the AP is already OFF then we can assume the yaw damper is either on or off. It makes no difference as if it is ON we just turn it off. If it is off we can still turn it off again without anything bad happening.

Right click checks the Yaw damper is OFF. remember, our validation routine will only allow the yaw damper to be off if the AP is off. If it is off then turn it on. Otherwise the yaw damper is ON. The AP can then be either on or off. If it is off then turn the AP on.

I like to use AP_MASTER toggle as I think (can't remember exactly) AUTOPILOT_OFF and AUTOPILOT_ON generate a contenterrorlogging report in P3D for some silly reason.

Using the above will keep your AP switch in sync with anything the user key commands as well as avoiding any L vars.

Disclaimer: This code has not been tested in sim, it may contain syntax (most likely) or logic errors (I hope not).
 
If you are concerned with potential loss of synchronization of the 3d switch because of a keyboard command, you could trap the keyboard command and then set the switch's L:var accordingly.
Code:
     <Keys>
        <OnEvent="AP_MASTER">(L:AUTOPILOT MASTER,bool) ! if{ 25 (>L:MyAP_Knob,enum) } els{ 50 (>L:MyAP_Knob,enum) }</On>
     </Keys>
 
Using the above will keep your AP switch in sync with anything the user key commands as well as avoiding any L vars.

As a general rule, you shouldn't tie the animation of switches directly to (A) variables, as there are big chances they will get out of sync if electrical condition is a factor.

In your example:


Code:
<Animation>
  <Parameter>
    <Code>
       (A:AUTOPILOT MASTER,bool)
       if{ 50 }
       els{
             (A:AUTOPILOT YAW DAMPER,bool)
             if{ 25 }
             els{ 0 }
            }
    </Code>
    <Lag>25</Lag>
  </Parameter>
</Animation>

the switch may be manually positioned in any of the three positions, regardless of the current electrical status.
BUT, in a cold and dark situation, with BATT/DC/AC off, (A:AUTOPILOT MASTER,bool) will be 0, resulting in the switch not being able to respond to mouse clicks.

So, the best for animations is to use LVars to reflect the status of switches (ON/OFF/ETC) which in most cases will be independent of the system's status they control, and manage the behavior of systems that depend on those switches within a regular panel gauge.

Tom
 
Last edited:
A good point Tom

I did say "In this particular case" as I thought we could get away with using A vars but as you say the AP switch is turned off when the power is cut (I had assumed it would work like the A vars light switches). As a general rule, I like to use an A var first if that will do the job (eg light switchs, magnetoes etc) and I will only use an L var is a last resort (all the APs I have ever done have had soft keys to control the AP rather than a hardware switch).

Bottom line is the OP will need some sort of gauge code to handle user key inputs and have those reflected in his L var.

He could try Bill's <Key> system. The only limitation of that system is you must be in the VC for it to work. If you are in an exterior view the key commands won't be captured.
 
I implemented Anthony's first suggestion (code was flawless) before reading the last posts, and it works as expected.

But I see now that I am going to have to give some more thought to this (and not just with respect to the AP) before settling on any given approach.
 
One way to look at it is 'a switch is a switch'. In your home a switch will move to any position it is designed. But if there's a power cut then the expected result of moving the switch might not happen.
A/c electrical systems are very complex. Dependant on what bus is live etc etc.
I have a very complex anti-ice panel with switches and magnetic eyes. The magnetic eyes cross-line if the switches are off. BUT, not always as they can be cross-lined by other factors. Many of my switches therefore have 'off-site' variables that do nothing but detect the switch position and then act or not as the case maybe.
Doing a full on electrical failure regime in the VC10 is quite a nightmare!
vololiberista
 
It's a pity about the AP turning off when the electrical system turns off otherwise the solution would have been good.

I can see though that this will require some more thought.

For example, if you use the L var to store the switch state, what happens if the switch is set to AP and Yaw damper ON and the electrical system is off. If the electrics are then turned on do you need to notice that event and then turn the AP on (via a K event)?

Plus, if the electricals is turned off the AP master is turned off so how do you identify if the AP master going off was caused by a user input (which would need you to change the L var switch) or via the loss of electrical power (where you would leave the L var switch alone)?

I had to make a combined Master Battery/Generator switch, I also decided to model the aircraft behaviour where the generator would only come on when the RPM was above 1100. I ended up with 60 lines of XML code to handle user key inputs as well as ensuring the switch and generator would work properly.
 
Pretty much the only way to work out how the AP or yaw dampers are affected or not by a power supply or lack of is to do a flow chart. Include your battery supply / APU / and buses. In your flight or technical manuel you should find what instruments and controls are affected by power disruption and whether or not there is a backup. So test your switch position (check if it is the only switch for that purpose) and work back to the various power sources and then build in your xml code to account for one or other power supply failure. It's very slow work as it has to be done for every control / gauge etc.
On the VC10 it's even more complicated as that a/c has a split system. Whilst some of the control surfaces are hydraulicaly operated they are also electrically controlled. Each hydraulicaly controlled surface is operated from its own reservoir which if depleted forces the control surface to go to a neutral position. But the signal to move the control surface is electrical (in this scenario the electrical signal to move the control surface would have no affect). And then some control surfaces are electrical only. These are directly linked to the AP so when the AP is flying the a/c it is 100% FBW. In this manner the VC10 was the precursor to today's modern fly by wire systems.
vololiberista
 
Back
Top