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

[SOLVED] Creating a Proper Yaw Damper

Messages
232
Country
us-kentucky
Hi all,

In pursuit of my perfect 747, I am interested in creating a proper yaw damper.

The real 747 has a yaw damper that acts as both a dutch roll counteract-er and also helps to coordinate turns, regardless of whether the autopilot is engaged or not.

As far as I can understand, the default yaw damper of flight sim does nothing more than limit the total amount of rudder travel. While this is realistic to an extent, that's not *all* the yaw damper should do.

My question is, using XML, is it possible to create a gauge that will automatically adjust the rudder position (limited by 6 degrees of total rudder travel) to coordinate turns, or, more precisely, keep the ball centered.

I think I can use the A:Turn coordinator ball, and K:Rudder set variables, but I'm not entirely sure how to combine them together to produce the effect I want.

Thanks!
 

Heretic

Resource contributor
Messages
6,830
Country
germany
(Nearly) Everything's possible in XML.

For a start, you need a variable display gauge (e.g. Blackbox3 or similar) that diplays "A:Turn Coordinator Ball" and "A:RUDDER PEDAL POSITION", go for a test flight and note the value range the variables take during turns and while counteracting with rudder input.

Your gauge then contains something akin to "if turn coordinator value is greater than [xy], set rudder to turncoordinator value times [something] times [something to attian an output from -16383 to 16383 for K:RUDDER_SET]" and "if turn coordinator value is lower than [xy], set rudder to turncoordinator value times [something] times [something to attian an output from -16383 to 16383 for K:RUDDER_SET]".
Note that positive and negative output ranges. I always forget which yields what result, but that should be easy to find out for you (because you have a display gauge).
 
Messages
232
Country
us-kentucky
Hi Bjoern,

I think I understand what you're saying, but I have some questions.

Will your code ensure that the ball becomes centered during turns? I understand that it will deflect the rudder in the direction the turn coordinator is falling, but how will it know how much rudder to deflect?

How can I impose limits so that only so much rudder gets used?

Lastly, if statements are still unfamiliar territory for me in XML. What I'm thinking is that I would create an if statement that essentially says "if the turn coordinator position (which ranges from -1.00 to 1.00, full left and full right) is greater or less than 0.xx (small value very close to zero), activate the rest of the code." Would this be a good way to do it, and what would the syntax of that look like?

Thanks for the valued input!
 

Roy Holmes

Resource contributor
Messages
1,803
Country
us-virginia
It is quite possible that the default yaw damper is as good as it can be without a pretty sophisticated implementation using rate gyros, some form of PID and some complex damping algorithms.
Just opposing yaw with rudder would work if there was no inertia. The 747 has more inertia than most airplanes. A simple mechanism could easily get out of phase with the natural yaw and create dynamically unstable directional stability.
There are some flight conditions where you want yaw, such as landing in a crosswind. However, Dutch roll is most prevalent at high altitudes where inertial effects are large and aerodynamic effects are low. So the code could be inoperative at low to medium altitudes.
In Dutch roll conditions the degree of yaw is small compared to the roll induced by the yaw, but it is better to attack the problem by reducing the prime cause, the yaw.
Of course, you can design out Dutch roll by appropriate values in the air file. And, it does not follow that a sim model of a 747 will have Dutch roll because the real one does. In a 747 the yaw damper has triple redundancy so Dutch roll is minimal at all times, therefore the fde designer should design it out of the flight model. And so you basically just need a yaw damper switch which does nothing.
Finally, the 747 yaw dampers do not move the rudder pedals, they move the rudder only, so how would you achieve that with a simple mechanism that moves the rudder pedal position.
Roy
 

Heretic

Resource contributor
Messages
6,830
Country
germany
Will your code ensure that the ball becomes centered during turns? I understand that it will deflect the rudder in the direction the turn coordinator is falling, but how will it know how much rudder to deflect?

That's for you to find out.

How can I impose limits so that only so much rudder gets used?

Translate the turn coordinator ball deviation into appropriate rudder input. Again, it's for you to find out just how much you'll need.

Lastly, if statements are still unfamiliar territory for me in XML. What I'm thinking is that I would create an if statement that essentially says "if the turn coordinator position (which ranges from -1.00 to 1.00, full left and full right) is greater or less than 0.xx (small value very close to zero), activate the rest of the code." Would this be a good way to do it, and what would the syntax of that look like?

Your assumption about what the code should do is plausible, but I'm not going to write it for you, you'll have to do that yourself. Otherwise you'll be denied the crucial "A-ha!" moment and we'll both have wasted our time.
If you need examples for "if" evaluations, dig around the forums or dissect some other XML gauges. Write something up, test it and then post if it doesn't work. I'll correct it.
 
Messages
232
Country
us-kentucky
Welcome back to this one more than two years later, lol...

I finally decided to come back to this after doing some basic reading and studying a few XML gauges. I am just beginning to understand the syntax that I have attempted but I have a feeling that it will look like total garbage to anyone with experience in this. Either way, here's my very first college try with it.

This code does not work unfortunately after some testing but I'm not surprised. I found myself really dumbfounded with how to get the calculations to work in XML.

My idea was to set the Rudder Pedal Position (read from 0 to +/- 1.0 in the sim) to 1.67 times the value of the Turn Coordinator Ball position (also read as 0 to +/- 1.0). That seemed to be a good ratio to me. I understand that the Rudder Set variable has a range of -16384 to 16384 in accordance with the minimum and maximum deflection, but there was ultimately where I was dumbfounded. I'll worry about trying to limit how much rudder authority it has, failure scenarios, etc. after I can just get the dang thing working.

Please do not laugh at me! I have never been a programmer! And don't just give me the answer either. I'd really like to learn where I went wrong and what I need to do/read/understand to improve. :)

Code:
<Gauge Name="Yaw Damper" Version="0.1">
   <Element>
      <Select>
         <Value>
            (A:TURN COORDINATOR BALL, position) s0 0.01 >= if{
            1
            (>K:RUDDER_SET) -1.67 l0*
            }
    }
                (A:TURN COORDINATOR BALL, position) s0 -0.01 <= if{
            1
            (>K:RUDDER_SET) 1.67 l0*
            }
    }
        els{
            (>K:RUDDER_SET) 0 l0*
            }
    }
        </Value>
      </Select>
   </Element>
</Gauge>
 

tgibson

Resource contributor
Messages
11,338
Country
us-california
So you have confirmed through testing (i.e. printing out the number on screen) that the turn coordinator ball position is -/+ 1.0? I'll assume you have done that.

First, the l0* probably should have a space: l0 * I always put spaces between any operators (like * ).

Second, your intended code is setting the rudder to deflect 1.67/16384 of full deflection - virtually none at all.

Third, you are not loading (>K:Rudder_Set) with the proper value (you are loading it with either 1 or a number that is on the stack). For the proper code you probably need something like:

XML:
-1.67 l0 * 16384 *  16383 min (>K:Rudder_Set)

and

XML:
0 (>K:Rudder_Set)

The 16383 min prevents the value from becoming greater than 16383 (full deflection).

Hope this helps,
 
Messages
232
Country
us-kentucky
Hey Tom, didn't know you knew XML at all. The amount of knowledge you have of FS never ceases to amaze.

Are you saying my code should look like this?

Code:
<Gauge Name="Yaw Damper" Version="0.1">
   <Element>
      <Select>
         <Value>
            (A:TURN COORDINATOR BALL, position) s0 0.01 >= if{
            1
            -1.67 l0 * 16384 *  16383 min (>K:Rudder_Set)
            }
    }
                (A:TURN COORDINATOR BALL, position) s0 -0.01 <= if{
            1
            1.67 l0 * 16384 *  16383 min (>K:Rudder_Set)
            }
    }
        els{
            0 (>K:Rudder_Set)
            }
    }
        </Value>
      </Select>
   </Element>
</Gauge>\

If so, I find that it does not work either.
 
Messages
2,077
Country
us-ohio
First.... TURN COORDINATOR BALL is a value of -127 to +127...
Second... I see too many closing curly braces...
Third...

Your code reads:

IF (TURN COORDINATOR BALL >= 0.01) THEN
set Rudder_Set to (-1.67*TURN COORDINATOR BALL*16384) or 16383, whichever is lower.

IF (TURN COORDINATOR BALL <= -0.01) THEN
set Rudder_Set to (1.67 * TURN COORDINATOR BALL * 16384) or 16383, whichever is lower.

ELSE
set Rudder_Set to 0

In both THEN statements you are testing to ensure you select the value lower than the POSITIVE value of 16383... which for the negative values you want to test for max of -16383, not min of 16383.

I will also point out that AXIS_RUDDER_SET (if assigned) will override any input you place in RUDDER_SET.
 
Messages
232
Country
us-kentucky
Ah, I see. Simple mistake there.

Also I am not sure how you get that the TURN COORDINATOR BALL has +/-127 range. My BlackBox3 gauge reads +/- 1.0 for that. In any case, I will trust your guidance.

My code now reads:

Code:
<Gauge Name="Yaw Damper" Version="0.1">
   <Element>
      <Select>
         <Value>
            (A:TURN COORDINATOR BALL, position) s0 0.01 &gt if{
            1
            -1.67 l0 * 16384 *  -16383 max (>K:Axis_Rudder_Set)
            }
            (A:TURN COORDINATOR BALL, position) s0 -0.01 &lt if{
            1
            1.67 l0 * 16384 *  16383 min (>K:Axis_Rudder_Set)
            }
        els{
            0 (>K:Axis_Rudder_Set)
            }
        </Value>
      </Select>
   </Element>
</Gauge>

I am still not seeing any result in Flight Simulator though. Am I just not using the right equation? I feel like I must be making some kind of newbie error here.

Thanks for all the help and input. Even through the frustration of things not working, it is very enjoyable to learn.
 
Messages
1,564
Country
thailand
1) Missing semicolons after &gt and &lt. This is the reason your gauge isn't working.
2) Drop the 1s after if{ They're pushed to the bottom of the stack and not used by the formula. There's a Stack wiki in the FSD Gauges Wiki. You might want to become familiar with it
3) Are you sure you want the 0 (>K:Axis_Rudder_Set)?

I feel like I must be making some kind of newbie error here. I'd say it's a lack of practice and thoroughness of q/c'ing your code. Can be hard to spot your own mistakes sometimes. To learn this stuff, test, test, and re-test.

Bob
 
Last edited:
Messages
232
Country
us-kentucky
I read the SDK documentation. Did you? :)

Fair enough, for some reason I didn't think that the Panel SDK contained information on XML variables. I now stand corrected

Progress has been made! Though it still does not work as intended. The gauge is now deflecting the rudder, and is doing so at a reasonable amount of deflection! So that is better than we were.
Problem is that the deflection seems reversed. The rudder consistently deflects in the opposite direction intended. I have tried reversing the signs and positions of just about everything here, I am not sure what else to change there.

I reduced my ratio to 0.012598 because approximately 10% deflection of the ball (12.7 out of 127 units) corresponds to 4 degrees of rudder in the approach condition, which is the limit of the yaw damper. 4 degrees / 25 degrees total = 0.16, and 0.16 * 16384 = 2621.44. So, my final equation is x * 12.7 * 16384 = 2621.44. x = 0.012598

Here is my code:

Code:
<Gauge Name="Yaw Damper" Version="0.1">
   <Element>
      <Select>
         <Value>
            (A:TURN COORDINATOR BALL,position 128) s0 1 >=
            if{
            0.012598 l0 * 16384 *  -16383 max (&gt;K:RUDDER_SET)
            }
            (A:TURN COORDINATOR BALL,position 128) s1 -1 &lt;=
            if{
            0.012598 l1 * 16384 *  16383 min (&gt;K:RUDDER_SET)
            }
            els{ 0 }
        </Value>
      </Select>
   </Element>
</Gauge>

EDIT: Nevermind! I remembered one of the most basic math principles of multiplying by -1, and added that to my code. It now works as intended. Thank you everyone for your input! Here is the fixed code for those interested:
Code:
<Gauge Name="Yaw Damper" Version="0.1">
   <Element>
      <Select>
         <Value>
            (A:TURN COORDINATOR BALL,position 128) s0 1 >=
            if{
            0.012598 l0 * 16384 * -1*  -16383 max (&gt;K:RUDDER_SET)
            }
            (A:TURN COORDINATOR BALL,position 128) s1 -1 &lt;=
            if{
            0.012598 l1 * 16384 * -1*  16383 min (&gt;K:RUDDER_SET)
            }
            els{ 0 }
        </Value>
      </Select>
   </Element>
</Gauge>
 
Last edited:
Messages
258
Country
ireland
Chris, I believe you may an incorrect unit there - position 128. I cannot find a P3D SDK Units document but my FS2004 doc doesn't have 'position 128' as a unit. Obviously it still works but...

Walter
 
Messages
232
Country
us-kentucky
Chris, I believe you may an incorrect unit there - position 128. I cannot find a P3D SDK Units document but my FS2004 doc doesn't have 'position 128' as a unit. Obviously it still works but...

Walter

Walter,

I didn't know of it either until WarpD pointed out that it was in the SDK.


I imagine you might be able to get away with the standard position unit, but what I have works so I see no reason to change it. :)

Chris
 
Messages
258
Country
ireland
I certainly learn something new every single day on these forums. I have just updated my Stearman Turn and Bank Instrument to use the Unit Position 128. Thanks for the free glimpse into the depths of the SDK.
 
Messages
1,564
Country
thailand
I imagine you might be able to get away with the standard position unit, but what I have works so I see no reason to change it. :)


You can't get away with that - not unless you change your comparison operand also. Position 128 values are 128 times the corresponding Position values, so changing units will have a significant impact on your formula. As you know, (A:TURN COORDINATOR BALL, position) ranges from -1 to +1. The equivalent position 128 values range from -128 to +128. Your current formula uses position 128 units and adjusts the rudder (>K:RUDDER_SET) when Ball position 128 exceeds abs 1, which is essentially continuous rudder set. But if you use position units with no change to the comparison operand, you won't set the rudder unless Ball position equals 1, which is no rudder set at all. Big difference.

Bob
 
Messages
232
Country
us-kentucky
Just as an appendix to this, I have a question...

Is it possible to simulate a yaw rate gyro using this XML gauge? I.e. is it possible to detect the yaw rate as the variable rather than the turn ball coordinator? My yaw damper happily reacts to sideslips and skids rather well but it is reactive rather than proactive as most real yaw dampers are. Real yaw dampers detect yaw rate to arrest the onset of a slip rather than waiting for one to develop.

I have attempted using the ROTATION VELOCITY BODY Z variable available in SimConnect just to see if it was available in FS9, but it returns zero at all times.

I thought about jury-rigging something that would react to the turn ball coordinator (i.e. if the turn ball coordinator position is decreasing or increasing relative to zero, deflect the rudder in the direction of the trend) but I couldn't find anything definitive in the SDK that would demonstrate how to do this.

Any potential further insight into this?
 
Messages
35
The rotation and acceleration parameters are FUBAR. They return nonsense.

You need a proportional controller. If the side-slip is greater than zero, apply an additive rudder input until it is nulled.
 
Top