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 timestep 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: TimeStepping 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).
 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.
 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.
 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.
 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.
 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 pointcounter from N to N+1,
so that N+1 becomes the “current” point.
 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 windtunnel mode. (For some possible
nonbasic features see item E and
item F.)

We run the script, including any propertysetting directives.
In basic windtunnel mode, we assume the script sets all relevant
positions and rates for point N. See item C for more on this.
 We calculate forces, moments, and accelerations for point N,
by evaluating the aerodynamic functions, based on the current
positions and rates.
 We print results to the output file.
 We advance the time variable (t). Similarly we advance the
pointcounter 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 nonzero, 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
windtunnel 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 windtunnel 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 nonwindtunnel 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 earthfixed 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 earthfixed frame.
 I.
We want setting of each variable to be independent, and
to commute with the setting of other variables, in the earthfixed
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 bodyfixed reference frame. Other
representations are derived from this bodyfixed 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 noninertial 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
leadingorder centrifugal and Coriolis terms associated with the
rotation of the body frame of reference.
However, everyone should beware that only the leadingorder 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 highprecision 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 noninertial
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 earthfixed 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 noncommutativity as just an extreme version
of the previous problem: Setting the attitude corresponds to a
nearinfinite rate of attitude change, and would require nearinfinite
correction terms in the equation of motion. The "none" integrator
cannot handle any nonzero rate, let alone a nearinfinite rate.
Also item F would require windtunnel mode to use nonnull
integrators.
To summarize: we have seen numerous reasons why windtunnel 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 earthfixed 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 variablesetting functions. Each such
function should set both the bodyframe 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”
www.av8n.com/physics/vectorintro.htm