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

Simple Animation the Hard Way

Paul Domingue

Resource contributor
Messages
1,532
Country
us-california
I just spent a week creating what I thought would be a simple animation job and boy was I wrong. I was making linked biplane ailerons. Without any good pictures of how the system worked I had to figure it out from what I had. First trying to find the proper pivot points was a bit confusing until I realized that the attach points between the two ailerons were not as to be expected since they had to be at the same position in an equivalent arc.

Working on the left wings I created the animation for the ailerons with frames 0, 50 and 100 swinging through a 60 degree arc, -30 to +30 (later I had to change that to 50 degrees) and assigned the stock (l_aileron_percent_key) animation to them. The linkage rod was attached to the top aileron and I used the Lookat Constraint to keep it lined up with the bottom aileron attachment mount.

Everything was working great in Max but not so in the sim. The rod was swinging back and forth only lining up at frames 0, 50 and 100. After checking all the usual culprits, axis alignment, scaling and linear rotation and with all that good and no satisfactory results in the sim I tried assigning the (lever_stick_l_r) animation to no avail.

I then decided I would write my own XML code for the linkage rod animation. It still didn't work! I then wrote another little bit of XML code to display a 2d gauge with the numerical readouts of both the (AILERON LEFT DEFLECTION PCT) and my code results side by side.

While watching the animation in the sim and the custom gauge readout I noticed that the linkage rod was actually rotating in the opposite direction as the ailerons.....Ah ha! I went back and assigned the (r_aileron_percent_key) to the left linkage rod then back in the sim but no joy. I was sure that I was on the right track with the opposite aileron control but there was still a problem.

Several times during the week I was tempted to post the problem on the forum but hesitated because I was determined to figure this out for myself. So I'm sitting there moving the joystick side to side and just watching what was happening and about to give up and ask for help when I finally noticed what was happening. The linkage rod was out of phase with the ailerons between 0 and 50 and 50 and 100. Bingo! I went back and animated the ailerons through 50 degrees with 2 degree increments at every 4th frame (25 iterations) and collapsed the linkage rod Lookat Constraint with 25 iterations using the right aileron control for the left linkage rod and it worked perfectly.

I may not be the smartest guy in the world and someone else may have figured this out faster but for you people who are just starting out in modeling this is the type of thing you will run up against. I hope this will save others the work I went through.

Paul
 
Moral of the story/basic rules for linking two animations:
- If using constraints, collapse their keyframes before exporting or once the animation is finalized
- Linear controllers all the way



Several times during the week I was tempted to post the problem on the forum but hesitated because I was determined to figure this out for myself.

Well, creating a new thread usually puts my problem-solving skills into overdrive and I usually manage to find an answer myself within hours. So it would not have been the worst idea to simply post here when you ran into the wall the first time. Or you throw in the towel for the day just to find that someone already provided a possible solution to your problem in the thread.
 
Moral of the story/basic rules for linking two animations:
- If using constraints, collapse their keyframes before exporting or once the animation is finalized
- Linear controllers all the way

Those are the first things I do in every instance and then double check if the results aren't correct.

So it would not have been the worst idea to simply post here when you ran into the wall the first time.

If I'm stonewalled this is where I come running but in this case I have had enough animation experience to know it had to be an engineering and mathematical problem and I would learn more by solving it myself. Besides, if I had posted, Fr. Bill (n4gix) might have posted one of his professorial enigmatic answers that always leave me scratching my head for a while until I figure out what he said. o_O :)
 
I don't trust l_aileron_percent_key.

Code:
    <PartInfo>
        <Name>l_aileron_percent_key</Name>
        <AnimLength>100</AnimLength>
        <Animation>
            <Parameter>
                <Sim>
                    <Variable>AILERON LEFT DEFLECTION PCT</Variable>
                    <Scale>-1</Scale>
                    <Units>percent</Units>
                    <Bias>50</Bias>
                </Sim>
            </Parameter>
        </Animation>
    </PartInfo>

You see the scale looks wrong to me. If Aileron left deflection pct is returning values between -100 and 100 then the above code will only display the values between -50 and 50. The bias offset of +50 means that at keyframe you should be seeing 50% deflection, keyframe 50 is no deflection and keyframe 100 is 50% deflection the other way. Where's the 50 to 100% deflection keyframes?

At least that's what it looks like to me.

I prefer this code:
Code:
<Animation name="ailerons_anim" guid="F654C323-C12B-4eb0-BE07-DD3E88F34598" type="Sim" typeParam2="ailerons_anim" length="210" typeParam="AutoPlay" />
<PartInfo>   
    <Name>ailerons_anim</Name>
    <AnimLength>210</AnimLength>
    <Animation>
        <Parameter>
            <Code>
                (A:AILERON POSITION,percent) 110 +
            </Code>
        </Parameter>
    </Animation>
</PartInfo>

Keyframe 0 is a no deflection position (so that my model is always zeroed at 0 keyframes). Keyframe 10 is 100% deflection. Keyframe 110 is no deflection and keyframe 210 is 100% deflection the other way.
 
I don't trust l_aileron_percent_key.

You see the scale looks wrong to me. If Aileron left deflection pct is returning values between -100 and 100 then the above code will only display the values between -50 and 50. The bias offset of +50 means that at keyframe you should be seeing 50% deflection, keyframe 50 is no deflection and keyframe 100 is 50% deflection the other way. Where's the 50 to 100% deflection keyframes?

At least that's what it looks like to me.

I like your code so if you don't mind I like to test it and use it even though I have my problem solved. I have programmed several 3d gauges for my models but I am very much a novice and have a lot to learn.

Thanks
 
When the ailerons are undeflected (rudder is the same), the animation is at key 50. When you push the stick fully left it goes to key 0, right is key 100.
The scale and bias work to that end and the code is correct.

BTW, I modeled a DH Rapide which has ailerons on both wings and I used l_aileron_key for the left upper wing and l_aileron_percent_key for the lower left. It made things easier at the time though with hindsight it was not necessary.
Roy
 
I don't trust l_aileron_percent_key.

Code:
                    <Variable>AILERON LEFT DEFLECTION PCT</Variable>
                    <Scale>-1</Scale>
Your interpretation of the <Scale> parameter is faulty. All it is doing is inverting the values returned from the <Variable> token.

As Roy stated, normal animation keys are 0 - 50 - 100. The <Scale> inverts the 0 and 100 positions, so that up becomes down, and down becomes up.
scale: Scales from simvar units to event units
It seems to be a silly way of doing things, but that's only because they (ACES) were working from an ancient system and had to maintain 'backwards compatibility' with previous methods.
 
Last edited:
The little 2d gauge I made helps me a lot in evaluating the end results of my code. I will probably write a larger piece of code to display a multitude of variables which will give me a lot of practice.

I include the code for people learning like myself. Just add it to your panel .cfg as a new window. The background .bmp is a 100 x 80 pixel image set at RGB 1,1,1. Edit lines 8 and 10 as needed. Edit lines 19 and 40 for the sim variables and code you are working on.
Code:
<?xml version="1.0" encoding="UTF-8"?>
<SimBase.Document
  Type="AceXML"
  version="1,0"
  id="Test Gauge">
  <Descr>AceXML Document</Descr>
  <Filename>TestG1.xml</Filename>
  <SimGauge.Gauge id="Gauge" ArtDirectory="D:\Program Files (x86)\Microsoft Games\Microsoft Flight Simulator X\Gaugesl\PDTest">
  <FloatPosition>0.000,0.000</FloatPosition>
  <Image id="TestG1background.bmp" Name="TestG1background.bmp">
  <Transparent>True</Transparent>
  </Image>
  <Element id="Fixed Text">
  <FloatPosition>5.000,10.000</FloatPosition>
  <GaugeText id="GaugeText">
  <FontColor>gold</FontColor>
  <FontFace>Arial</FontFace>
  <FontHeight>13</FontHeight>
  <GaugeString>Variable Name</GaugeString>
  <Size>90,15</Size>
  <Transparent>True</Transparent>
  </GaugeText>
  </Element>
  <Element id="Output Box">
  <FloatPosition>5.000,40.000</FloatPosition>
  <Rectangle id="Rectangle">
  <LineWidth>1</LineWidth>
  <Width>90</Width>
  <Height>24</Height>
  <LineColor>darkslateblue</LineColor>
  <FillColor>black</FillColor>
  </Rectangle>
  </Element>
  <Element id="Display Text">
  <FloatPosition>10.000,44.000</FloatPosition>
  <GaugeText id="GaugeText">
  <FontColor>red</FontColor>
  <FontFace>Courier</FontFace>
  <FontHeight>16</FontHeight>
  <GaugeString>%((Sim Variable))%!03d!  %((My Code)%!03d!</GaugeString>
  <Size>90,16</Size>
  <Transparent>True</Transparent>
  <VerticalAlign>CENTER</VerticalAlign>
  </GaugeText>
  </Element>
  </SimGauge.Gauge>
</SimBase.Document>
 
Your interpretation of the <Scale> parameter is faulty. All it is doing is inverting the values returned from the <Variable> token.

As Roy stated, normal animation keys are 0 - 50 - 100. The <Scale> inverts the 0 and 100 positions, so that up becomes down, and down becomes up.

It seems to be a silly way of doing things, but that's only because they (ACES) were working from an ancient system and had to maintain 'backwards compatibility' with previous methods.

But Bill, this is my point. I think the Scale should be -0.5 (like it is with the aileron trim pct default animation). This (and the bias offset) will convert the -100 to 100 range that is returned from the aileron percentage variable into a key range of 0 - 50 - 100.

If you want to see something scary load up the default C172 in FSX and put in a gauge that shows the value of the aileron percentage. Then move your ailerons. The default C172 reaches the limits of its animation when the aileron percentage is between -50 and 50. You can keep moving your stick beyond this range to -100 and 100 but the ailerons on the C172 do not move when you are within the 50 to 100 range. This is why I do not trust the default animations.

If you don't want to check it for yourself I have attached a picture showing the C172 aileron deflection and the values coming from FSX for aileron deflection. I have put a yellow dot next to the aileron position values to help you spot them easier (ignore the left aileron percentage value which is showing 0, I must have put in a typo there so it isn't showing a proper value). Now look at the actual position of the animated aileron in the two screenshots. It hasn't moved. The top pic shows full deflection (20 deg up for the left aileron) and the bottom pic just over half deflection (10.69 deg up) but the aileron is in the same position.
aileron.jpg
.
 
Have you tried these tests with other stock models? It's possible whatever the SDK prescribes has not been followed for the C172. It may not have been built for FSX originally....
 
Other models? Well I just tried the default DC3, Learjet and Baron and the ailerons, rudder and elevator all exhibit the same problem, full range of control surface reached around halfway in joystick movement. Although with the learjet it's hard to tell as it uses spoilerons so I don't know if they are supposed to stop early.

Try it for yourself, load up the Baron, switch to an exterior view and try to get the yoke, ailerons and elevator all in view. The yoke in the cockpit will still move at the ends of the range of movement after the ailerons and elevator have stopped moving.

Here's a screenshot of the Baron. You can see the yoke is more rotated in the left pic than in the right pic but the aileron is still in the same position.

Baronaileron.jpg


I first discovered this problem years ago when I used the stock animation for the rudder in a plane and I noticed that the animation would stop before I had moved my pedals all the way.

The problem is in the scaling of some of the stock animations in the modeldef as supplied in the SDK.

Consider this code for the rudder pedals. Note that the scale is 50 and bias is 50. If rudder pedal position returns a value from -1 to 1 (which I think it does) then multiply by the scale (50) and add the bias (50) and you get a range of 0 to 100 with the centre position being 50 which is fine.

Code:
    <PartInfo>
        <Name>lever_pedals_l_r</Name>
        <AnimLength>100</AnimLength>
        <Animation>
            <Parameter>
                <Sim>
                    <Variable>RUDDER PEDAL POSITION</Variable>
                    <Units>part</Units>
                    <Scale>50</Scale>
                    <Bias>50</Bias>
                </Sim>
            </Parameter>
        </Animation>
        <MouseRect>
            <TooltipText>Rudder pedals (%((A:RUDDER PEDAL POSITION, percent) s0)%{if}%(l0 abs)%!d!%% %(l0 0 &gt;)%{if}right%{else}left%{end}%{else}straight%{end})</TooltipText>
        </MouseRect>
    </PartInfo>

But here is the rudder percent key which has no scale. Rudder deflection pct returns -100 to 100 (this I know) so if we do the maths we multiply by the scale (defaults to 1) and add the bias (50) and you get a range of -50 to 150 with the centre being 50. Obviously you can't animate keyframe -50 and no one animates to keyframe 150 when they use this code (as the animlength suggests it only goes up to 100 keyframes) so the animation keyframes are usually 0, 50 and 100. When the values fall outside this range then FSX uses the outer limit keyframes. So when the rudder deflection pct is between 50 and 100 the keyframe used is always 100 and when the rudder deflection pct is between -50 and -100 the keyframe 0 is used.

Code:
    <PartInfo>
        <Name>rudder_percent_key</Name>
        <AnimLength>100</AnimLength>
        <Animation>
            <Parameter>
                <Sim>
                    <Variable>RUDDER DEFLECTION PCT</Variable>
                    <Units>percent</Units>
                    <Bias>50</Bias>
                </Sim>
            </Parameter>
        </Animation>
    </PartInfo>
 
Anthony,
The SDK definition of bias:
"If the value returned and scaled does not fall into the desired range for the keyframes (for example, the range -50 to +50), then a bias can be added to all values to indicate which keyframe to use. A bias of 50 in this example will adjust the range to 0 to 100."
The rudder is animated from 0, full left through 50 centered to 100, full right. But you really want it -50 to 50. Add the 50 bias and you get 0 to 100.
Whatever, it works perfectly for me using my test gauge and noting rudder deflection versus pedal deflection.
Roy
 
Roy, I know what bias does and I know what scale does.

The formula (not counting the max and min limits) used in <Sim> calculations is A:VAR * SCALE + BIAS.

In the case of the stock animation l_aileron_percent_key the SCALE is -1 and the BIAS is 50 so the <Sim> calculation can be written as:

AILERON LEFT DEFLECTION PCT * -1 + 50

Now, lets plug in some numbers for AILERON LEFT DEFLECTION PCT and see what the result is:
-100 * -1 + 50 = 150
-50 * -1 + 50 = 100
0 * -1 + 50 = 50
50 * -1 + 50 = 0
100 * -1 + 50 = -50

AILERON LEFT DEFLECTION PCT returns values between -100 and 100, not -50 and 50 so whenever AILERON LEFT DEFLECTION PCT is less than -50 and greater than 50 than keyframes generated will fall below 0 and above 100 respectively.

The first screenshot I posted demonstrates this. The value of AILERON RIGHT DEFLECTION PCT in the top picture is -99.99 and in the bottom picture it is -53.44. Now, don't forget that this is for the RIGHT aileron and not the LEFT (due to a typo in the gauge the LEFT value is not shown properly). We can deduce that the value of AILERON LEFT DEFLECTION PCT would be 99.99 and 53.44 though.

So let's plug these numbers in the l_aileron_percent_key <Sim> calculation and see what we get:
99.99 * -1 + 50 = -49.99
53.44 * -1 + 50 = -3.44

As you can see the values are below zero so the 0 keyframe animation is used (full up).

I stress here that the problem is that the values coming from the DEFLECTION PCT variables for the control surfaces are in the range of -100 to 100. If you want these to animate within 100 keyframes then you must scale them by 0.5 and not 1 for them to work. Most of the stock animations for the aileron, rudder and elevator are using 1 or -1 as the scale and I think this is wrong.
 
Anthony,
I have a different understanding of how bias is applied by the simulator.
When you animate ailerons using the stock AILERON XXX DEFLECTION PCT and 100 frames,
Frame zero has the left aileron fully down, frame 50 has it centered and frame 100 has it fully up. In the sim these deflections are reversed by the scale being -1.
If you look at the model when it is in the sim, the aileron animation is at frame 50 because that is what bias does, it adds bias to the undeflected state. As the SDK says "a bias can be added to all values to indicate which keyframe to use."
It does not matter whether you use percent, percent over 100, position or part, what matters here is that you have 100 animation frames and the bias sets the animation at frame 50 when there are no control deflection inputs.
Roy
 
n4gix explained this to me a long time ago but I have forgotten so could one of you fill in this code for me so I can try to understand both points of the argument.
Convert this:
Code:
<Sim>
  <Variable>AILERON LEFT DEFLECTION PCT</Variable>
  <Scale>-1</Scale>
  <Units>percent</Units>
  <Bias>50</Bias>
</Sim>
To this: please
Code:
   <Code>
      (A:AILERON LEFT DEFLECTION PCT, percent) Fill in the blank
   </Code>
 
Assuming the AnimLength is 100

<Code>
(A:AILERON LEFT DEFLECTION PCT, percent) -1 * 50 +
</Code>

The scale of -1 is there because stick left needs left aileron up. For a rudder no scale is needed because pedal left = rudder left. A quirk of the sim.

Another example is a VSI with 140 frames <Code>(A:VERTICAL SPEED, ft/min) 100 / 70 + </Code> The 70 puts you at frame 70 for level flight.

Think about zero input, what frame do you want displayed. The result of the calculation in the .mdl code is the frame displayed for the variable input value.
Roy
 
Paul,
The <Sim> calculation can be expressed in reverse polish notation as:

(A:VARIABLE, UNITS) SCALE * BIAS +

which in this case can be written as:
<Code>
(A:AILERON LEFT DEFLECTION PCT, percent) -1 * 50 +
</Code>

In normal mathematics it can be written as:
(A:VARIABLE, UNITS) * SCALE + BIAS
or in this case:
(A:AILERON LEFT DEFLECTION PCT, percent) * -1 + 50

The problem is (A:AILERON LEFT DEFLECTION PCT, percent) returns values between -100 and 100 which is a total range of 200 (I've shown this in the first pic I posted of the C172, AILERON R DEF PCT: -99.99). As the SCALE is -1 it will only invert the value of (A:AILERON LEFT DEFLECTION PCT, percent), negative becomes positive and vice versa, it will not reduce the total range of 200.

So the results you will get from inputting values in the range -100 to 100:
(A:AILERON LEFT DEFLECTION PCT, percent) -1 * 50 +
are 150 to -50 (-100 * -1 + 50 = 150, 100 * -1 + 50 = -50, see post #14 for more examples).

If you want results between 0 and 100 (for 100 keyframes of animation) then you need to scale the output of (A:AILERON LEFT DEFLECTION PCT, percent) and reduce the range of values from 200 to 100. This code will reduce the range and invert the positive and negative values (change has been bolded):
<Code>
(A:AILERON LEFT DEFLECTION PCT, percent) -0.5 * 50 +
</Code>
 
Getting down to basics, the sim actually has one, and only one internal token variable for ailerons (found in the FSX_gauges.h file):
Code:
AILERON_DEFLECTION,     //  radians
Note carefully that there is no distinction between left or right ailerons, just one token that's returned in radians.

When ACES started the XML schema, they came up with some truly whacky new XML parameters all based off of that lonely C token variable, including this one:
Code:
  <PartInfo>
    <Name>average_aileron_key</Name>
    <AnimLength>100</AnimLength>
    <Animation>
      <Parameter>
        <Sim>
          <Variable>AILERON AVERAGE DEFLECTION</Variable>
          <Units>percent</Units>
          <Scale>0.5</Scale>
          <Bias>0</Bias>
        </Sim>
      </Parameter>
    </Animation>
  </PartInfo>
To be perfectly honest, I didn't even know about this one until just now! What is interesting is that although it has an animation length of 100 frames, there's no distinction for right or left, and...

...no Bias at all! This appears to me as a completely useless bit of XML script... :eek:

The most straightforward and easy to interpret XML script is this one, since it uses 'gradians' for the units. This incidentally is the one I use for my models:
Code:
  <PartInfo>
    <Name>l_aileron_key</Name>
    <AnimLength>100</AnimLength>
    <Animation>
      <Parameter>
        <Sim>
          <Variable>AILERON LEFT DEFLECTION</Variable>
          <Scale>-1</Scale>
          <Units>grads</Units>
          <Bias>50</Bias>
        </Sim>
      </Parameter>
    </Animation>
  </PartInfo>
 
Thanks Roy and Anthony. I understand the reverse polish notation but what I didn't know was that scale was a multiple and that bias was an addition.
Let me see if I have this right.

From AILERON LEFT DEFLECTION PCT WE GET -100 to +100 % deflection
Animation length = 100 frames.
Mathematical laws require that multiplications are calculated first so I assume the sim is doing this as well.
(-100 * -1) +50 = 150 (frame 100)
(-50 * -1) +50 = 100 (frame 100)
(0 * -1) + 50 = 50 (frame 50)
(50 * -1) +50 = 0 (frame 0)
(100 * -1) +50 = -50 (frame 0)
So by this we are seeing full deflection negative or positive at 50% stick movement right or left. This would explain why the yoke will continue to rotate after full aileron deflection. In this case I would have to agree with what Anthony is saying.

Edit: Bill, I didn't see your post when I posted this but shouldn't the same thing apply?
 
Back
Top