Copyright © 2008 jsd

1  Musings about the Design of a Wind Tunnel Simulator

The basic idea is to start with the JSBSim simulator, and make minor modifications so as to implement wind tunnel mode.

A.    Let’s review the principles of operation in the normal integrator mode, where we time-step the equations of motion. We will discuss it from two points of view, namely what should happen, and what actually happens in the current (July 2008) code. Note that what we call “time stepping” is called “propagation” in the code.
Figure 1: Time-Stepping the Equation of Motion

As an “induction hypothesis” we assume that we already have valid position and rate data for the old point N. Our tasks include advancing to the new point N+1, and printing out the results (not necessarily in that order).

  1. We evaluate the aerodynamics functions at point N. These functions take as input the positions and rates at point N, and produce as outputs the forces and accelerations. That is, we calculate the second derivatives as a function of the zeroth derivatives and the first derivatives.
  2. We should print out the results. This is the appropriate place to do so, because it is the first time we have full information about point N, namely the positions, rates, and forces. This is what should happen, but not what the current code actually does, as far as I can tell.
  3. We integrate to find the rate at point N+1, shown in blue in the figure, calculated from the rate at point N and the acceleration at point N.
  4. We integrate to find the position at point N+1. This is slightly tricky, because we could use the old rate (shown by the slope of the red line) and/or the new rate (shown by the slope of the blue line). In the example shown in figure 1, the old rate is an overestimate of the average rate, whereas the new rate is an underestimate of the average rate. The average rate is the average over the interval from point N to point N+1, as shown by slope of the dashed green line in the figure.
  5. We advance the time variable. This can be considered another example of integrating the equations of motion, according to the rule t = ∫dt. This may seem almost trivial, but we mustn’t forget to do it. Similarly we advance the point-counter from N to N+1, so that N+1 becomes the “current” point.
  6. At this point the current code prints out the results. This is somewhat problematic, because we don’t have force or acceleration data for the new current point (N+1). Those variables still have data from point N hanging around.

B.    Here are the proposed principles of operation for wind tunnel mode. You can compare and contrast this with the conventional integrator mode (item A). We start by describing basic wind-tunnel mode. (For some possible non-basic features see item E and item F.)
  1. We run the script, including any property-setting directives. In basic wind-tunnel mode, we assume the script sets all relevant positions and rates for point N. See item C for more on this.
  2. We calculate forces, moments, and accelerations for point N, by evaluating the aerodynamic functions, based on the current positions and rates.
  3. We print results to the output file.
  4. We advance the time variable (t). Similarly we advance the point-counter from N to N+1.

C.    In wind tunnel mode, if any position or any rate is not set by the script, it remains stuck at its previous value. Being stuck may seem weird, especially if the rates are non-zero, but it is not completely unphysical, for reasons discussed in item D.

D.    In wind tunnel mode, there is no requirement that the new positions and rates be related to the old positions and rates via any equation of motion. This is not as unphysical as it might seem. For example, if we have unchanging positions and nonzero rates, it might correspond to the flight path shown in figure 2.
Figure 2: Position and Rate Remaining Stuck

E.    As a creeping feature, we could have a fancy wind-tunnel mode where the script just sets the positions, and we calculate rates by differentiation so that the rates are consistent with the positions, and with the equations of motion. I’m not sure this is desirable or even practical.

F.    Alternatively, as a creeping feature, we could have a fancy wind-tunnel mode where the script specifies the rates, and we calculate the positions by integration, so that the positions are consistent with the rates and with the equations of motion. I’m not sure this is worth the trouble.

We would need to offer a choice of integration methods, just as the existing code does in non-wind-tunnel mode.

G.    It pays to be flexible about reference frames. Some things are more natural in one reference frame, and some things are more natural in another. JSBSim already does a lot of switching between reference frames. This is as it should be, and always will be.

H.    The natural reference frame for the user interface for a wind tunnel is an earth-fixed frame such as ECEF. Physically, the wind tunnel uses a jig to hold the aircraft in a given attitude relative to the earth. Therefore the software needs to have a mode that dictates attitude ... in the earth-fixed frame.

I.    We want setting of each variable to be independent, and to commute with the setting of other variables, in the earth-fixed frame.

J.    In the existing code, many crucial variables cannot be set from a script. Implementing wind tunnel mode will require making these things settable.

K.    In the existing code, the fundamental representation of velocities etc. uses a body-fixed reference frame. Other representations are derived from this body-fixed representation, and rarely (if ever) the other way around. This choice of frame has the advantage that is natural from a pilot’s point of view.

One disadvantage is that it is not an inertial frame. Doing physics in a non-inertial frame is tricky, but it can be done. In particular, the equations of motion contain must contain correction terms for the centrifugal field, for Coriolis effects, et cetera.

Another disadvantage is that, simply put, it is not the ECEF frame, i.e. it is not the natural frame for the wind tunnel user interface, as mentioned in item H.

L.    JSBSim does in fact have code to implement the leading-order centrifugal and Coriolis terms associated with the rotation of the body frame of reference.

However, everyone should beware that only the leading-order terms are implemented, and there are lots of other terms. Some of the unimplemented terms are not very small compared to the implemented terms.

For one thing, the familiar centrifugal and Coriolis terms only cover the case of steady rotation around a fixed axis. If the rotation rate is changing, or if the rotation axis is changing, all bets are off.

I reckon the existing code is good enough for ordinary aircraft and for ground vehicles, but a stated goal of the JSBSim project is to be able to handle spacecraft. I suspect that if you want to accurately model a spacecraft or a high-precision inertial navigation system, the equation of motion code would need major repairs.

I don’t want to make a big deal out of all this. I’m just saying that there is a price to be paid whenever you choose to use a non-inertial reference system.

M.    The existing null integrator (which the code calls the "none" integrator) is an odd duck. There is, as far as I can tell, no documentation as to what it is supposed to do, so we must consider various hypotheses:

One hypothesis is that the null integrator is supposed to represent a vehicle subjected to no forces, such as a freely floating space capsule. Alas, the "none" integrator, as implemented in the existing code, does not correctly represent this. It is implemented using zero lines of code, which means that it leaves out the centrifugal and Coriolis terms that the correct equation of motion must have (even in the absence of applied forces).

Another hypothesis is that the null integrator might leave the aircraft attitude frozen in some earth-fixed frame. This is wishful thinking; it is not what happens. In particular, if the aircraft attitude is changing (due to natural angular motion and/or due to being set by the script) then the aircraft’s momentum vector will magically change. That is, in the absence of forces, the vector’s projection onto the body axes will remain constant, but the actual physical momentum will change ... in violation of the most sacred basic laws of physics.

Remember that the momentum vector has physical and geometric reality, quite independent of its projection onto any set of axes. See reference 1 for details on this.

This also means that if you use a script to set the aircraft velocity and then set the attitude, you get a different result than if you did things in the other order, in violation of the commutativity objective expressed in item I.

You can optionally view non-commutativity as just an extreme version of the previous problem: Setting the attitude corresponds to a near-infinite rate of attitude change, and would require near-infinite correction terms in the equation of motion. The "none" integrator cannot handle any nonzero rate, let alone a near-infinite rate.

Also item F would require wind-tunnel mode to use non-null integrators.

To summarize: we have seen numerous reasons why wind-tunnel mode cannot be implemented simply by selecting the null integrator.

2  Next Steps

Here’s how I see things going forward:

The most crucial change is to arrange that in the “propagate” step, in wind tunnel mode, we use something other than the body frame. Using the body frame is inconsistent with the goal of letting scripts set the body attitude. An earth-fixed frame is the logical choice (although almost any frame other than the body frame would be acceptable).

This does not require a major rewrite. The changes affect only wind tunnel mode; ordinary integrator mode is completely unaffected. The code changes are confined to a couple of existing functions and the new “set” functions.

Basically I’m hoping to add a couple of lines in FGFDMExec.cpp, which take effect only in wind tunnel mode, to convert the body frame projections to ECEF projections before running the script, and to convert ECEF to body frame after the dust settles.

There should also be some conditionals in FGPropagate.cpp to avoid futile calculations.

The printouts need to be rescheduled to the proper point in the cycle.

We also need to write the variable-setting functions. Each such function should set both the body-frame projections and the ECEF projections, not one or the other.

I reckon there should be a variable somewhere to specify whether we are in wind tunnel mode or not. I think this should be a new, separate variable, not entangled with the existing enumeration of integrators (eIntegrateType), since as discussed in item F there are situations where wind tunnel mode needs integrators.

3  References

John Denker,
“Introduction to Vectors”
Copyright © 2008 jsd