]> git.mxchange.org Git - flightgear.git/commitdiff
Merge branch 'fredb/msvc-cleanup'
authorTim Moore <timoore33@gmail.com>
Thu, 6 May 2010 09:06:24 +0000 (11:06 +0200)
committerTim Moore <timoore33@gmail.com>
Thu, 6 May 2010 09:06:24 +0000 (11:06 +0200)
38 files changed:
acinclude.m4
docs-mini/README.effects
src/AIModel/AIAircraft.cxx
src/AIModel/AIAircraft.hxx
src/ATC/trafficcontrol.cxx
src/ATC/trafficcontrol.hxx
src/ATCDCL/ATC.cxx
src/ATCDCL/ATCmgr.cxx
src/Aircraft/replay.cxx
src/Airports/apt_loader.cxx
src/Airports/dynamics.cxx
src/Airports/groundnetwork.cxx
src/Airports/groundnetwork.hxx
src/Airports/runwayprefs.cxx
src/Autopilot/xmlauto.cxx
src/Autopilot/xmlauto.hxx
src/Environment/environment.cxx
src/Environment/environment.hxx
src/Environment/environment_mgr.cxx
src/Input/FGCommonInput.cxx
src/Input/FGDeviceConfigurationMap.cxx
src/Input/FGEventInput.cxx
src/Input/FGJoystickInput.cxx
src/Input/FGKeyboardInput.cxx
src/Input/fgjs.cxx
src/Instrumentation/airspeed_indicator.cxx
src/Instrumentation/airspeed_indicator.hxx
src/Instrumentation/dme.cxx
src/Main/fg_commands.cxx
src/Main/main.cxx
src/Main/viewer.cxx
src/Main/viewer.hxx
src/Network/jsclient.cxx
src/Traffic/Schedule.cxx
utils/Modeller/normalmap.cxx
utils/Modeller/texture.cxx
utils/TerraSync/terrasync.cxx
utils/js_server/js_server.cxx

index 7822c2a4db3a9e4c8a6d715cea208b00d81d354b..56618780a265959929128a0b6c29f354f095dc5a 100644 (file)
@@ -663,3 +663,159 @@ if test "x$want_boost" = "xyes"; then
 fi
 
 ])
+
+# pkg.m4 - Macros to locate and utilise pkg-config.            -*- Autoconf -*-
+# 
+# Copyright © 2004 Scott James Remnant <scott@netsplit.com>.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+#
+# As a special exception to the GNU General Public License, if you
+# distribute this file as part of a program that contains a
+# configuration script generated by Autoconf, you may include it under
+# the same distribution terms that you use for the rest of that program.
+
+# PKG_PROG_PKG_CONFIG([MIN-VERSION])
+# ----------------------------------
+AC_DEFUN([PKG_PROG_PKG_CONFIG],
+[m4_pattern_forbid([^_?PKG_[A-Z_]+$])
+m4_pattern_allow([^PKG_CONFIG(_PATH)?$])
+AC_ARG_VAR([PKG_CONFIG], [path to pkg-config utility])dnl
+if test "x$ac_cv_env_PKG_CONFIG_set" != "xset"; then
+       AC_PATH_TOOL([PKG_CONFIG], [pkg-config])
+fi
+if test -n "$PKG_CONFIG"; then
+       _pkg_min_version=m4_default([$1], [0.9.0])
+       AC_MSG_CHECKING([pkg-config is at least version $_pkg_min_version])
+       if $PKG_CONFIG --atleast-pkgconfig-version $_pkg_min_version; then
+               AC_MSG_RESULT([yes])
+       else
+               AC_MSG_RESULT([no])
+               PKG_CONFIG=""
+       fi
+               
+fi[]dnl
+])# PKG_PROG_PKG_CONFIG
+
+# PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND])
+#
+# Check to see whether a particular set of modules exists.  Similar
+# to PKG_CHECK_MODULES(), but does not set variables or print errors.
+#
+#
+# Similar to PKG_CHECK_MODULES, make sure that the first instance of
+# this or PKG_CHECK_MODULES is called, or make sure to call
+# PKG_CHECK_EXISTS manually
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_EXISTS],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+if test -n "$PKG_CONFIG" && \
+    AC_RUN_LOG([$PKG_CONFIG --exists --print-errors "$1"]); then
+  m4_ifval([$2], [$2], [:])
+m4_ifvaln([$3], [else
+  $3])dnl
+fi])
+
+
+# _PKG_CONFIG([VARIABLE], [COMMAND], [MODULES])
+# ---------------------------------------------
+m4_define([_PKG_CONFIG],
+[if test -n "$$1"; then
+    pkg_cv_[]$1="$$1"
+ elif test -n "$PKG_CONFIG"; then
+    PKG_CHECK_EXISTS([$3],
+                     [pkg_cv_[]$1=`$PKG_CONFIG --[]$2 "$3" 2>/dev/null`],
+                    [pkg_failed=yes])
+ else
+    pkg_failed=untried
+fi[]dnl
+])# _PKG_CONFIG
+
+# _PKG_SHORT_ERRORS_SUPPORTED
+# -----------------------------
+AC_DEFUN([_PKG_SHORT_ERRORS_SUPPORTED],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])
+if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+        _pkg_short_errors_supported=yes
+else
+        _pkg_short_errors_supported=no
+fi[]dnl
+])# _PKG_SHORT_ERRORS_SUPPORTED
+
+
+# PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND],
+# [ACTION-IF-NOT-FOUND])
+#
+#
+# Note that if there is a possibility the first call to
+# PKG_CHECK_MODULES might not happen, you should be sure to include an
+# explicit call to PKG_PROG_PKG_CONFIG in your configure.ac
+#
+#
+# --------------------------------------------------------------
+AC_DEFUN([PKG_CHECK_MODULES],
+[AC_REQUIRE([PKG_PROG_PKG_CONFIG])dnl
+AC_ARG_VAR([$1][_CFLAGS], [C compiler flags for $1, overriding pkg-config])dnl
+AC_ARG_VAR([$1][_LIBS], [linker flags for $1, overriding pkg-config])dnl
+
+pkg_failed=no
+AC_MSG_CHECKING([for $1])
+
+_PKG_CONFIG([$1][_CFLAGS], [cflags], [$2])
+_PKG_CONFIG([$1][_LIBS], [libs], [$2])
+
+m4_define([_PKG_TEXT], [Alternatively, you may set the environment variables $1[]_CFLAGS
+and $1[]_LIBS to avoid the need to call pkg-config.
+See the pkg-config man page for more details.])
+
+if test $pkg_failed = yes; then
+        _PKG_SHORT_ERRORS_SUPPORTED
+        if test $_pkg_short_errors_supported = yes; then
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors "$2" 2>&1`
+        else 
+               $1[]_PKG_ERRORS=`$PKG_CONFIG --print-errors "$2" 2>&1`
+        fi
+       # Put the nasty error message in config.log where it belongs
+       echo "$$1[]_PKG_ERRORS" >&AS_MESSAGE_LOG_FD
+
+       ifelse([$4], , [AC_MSG_ERROR(dnl
+[Package requirements ($2) were not met:
+
+$$1_PKG_ERRORS
+
+Consider adjusting the PKG_CONFIG_PATH environment variable if you
+installed software in a non-standard prefix.
+
+_PKG_TEXT
+])],
+               [AC_MSG_RESULT([no])
+                $4])
+elif test $pkg_failed = untried; then
+       ifelse([$4], , [AC_MSG_FAILURE(dnl
+[The pkg-config script could not be found or is too old.  Make sure it
+is in your PATH or set the PKG_CONFIG environment variable to the full
+path to pkg-config.
+
+_PKG_TEXT
+
+To get pkg-config, see <http://pkg-config.freedesktop.org/>.])],
+               [$4])
+else
+       $1[]_CFLAGS=$pkg_cv_[]$1[]_CFLAGS
+       $1[]_LIBS=$pkg_cv_[]$1[]_LIBS
+        AC_MSG_RESULT([yes])
+       ifelse([$3], , :, [$3])
+fi[]dnl
+])# PKG_CHECK_MODULES
index f6d2b3159eb69d7f4d8e765b44c78089c09cd88c..c46d392c2466044511c90a1b266764d1b43ec06a 100644 (file)
@@ -35,19 +35,37 @@ and, or, equal, less, less-equal
 glversion - returns the version number of OpenGL
 extension-supported - returns true if an OpenGL extension is supported
 property - returns the boolean value of a property
+float-property - returns the float value of a property, useful inside equal, less or less-equal nodes
 shader-language - returns the version of GLSL supported, or 0 if there is none.
 
 The proper way to test whether to enable a shader-based technique is:
+       <predicate>
+         <and>
+               <property>/sim/rendering/shader-effects</property>
+               <less-equal>
+                 <value type="float">1.0</value>
+                 <shader-language/>
+               </less-equal>
+         </and>
+       </predicate>
+
+There is also a property set by the user to indicate what is the level 
+of quality desired. This level of quality can be checked in the predicate
+like this :
     <predicate>
       <and>
         <property>/sim/rendering/shader-effects</property>
-        <less-equal>
-          <value type="float">1.0</value>
-          <shader-language/>
-        </less-equal>
+       <less-equal>
+         <value type="float">2.0</value>
+         <float-property>/sim/rendering/quality-level</float-property>
+       </less-equal>
+       <!-- other predicate conditions -->
       </and>
     </predicate>
-
+    
+The range of /sim/rendering/quality-level is [0..5]
+ * 2.0 is the threshold for relief mapping effects,
+ * 4.0 is the threshold for geometry shader usage.
 
 A technique can consist of several passes. A pass is basically an Open
 Scene Graph StateSet. Ultimately all OpenGL and OSG modes and state
@@ -60,11 +78,11 @@ can be based on a parameter in the parameters section of the
 effect. For example, effects that support transparent and opaque
 geometry could have as part of a technique:
 
-      <blend>
-        <active><use>blend/active</use></active>
-        <source>src-alpha</source>
-        <destination>one-minus-src-alpha</destination>
-      </blend>
+         <blend>
+               <active><use>blend/active</use></active>
+               <source>src-alpha</source>
+               <destination>one-minus-src-alpha</destination>
+         </blend>
 
 So if the blend/active parameter is true blending will be activated
 using the usual blending equation; otherwise blending is disabled.
@@ -75,84 +93,87 @@ Values of Technique Attributes
 Values are assigned to technique properties in several ways:
 
        * They can appear directly in the techniques section as a
-        constant. For example:
-      <uniform>
-        <name>ColorsTex</name>
-        <type>sampler-1d</type>
-        <value type="int">2</value>
-      </uniform>
-        * The name of a property in the parameters section can be
-        referenced using a "use" clause. For example, in the technique
-        section: 
-      <material>
-        <ambient><use>material/ambient</use></ambient>
-      </material>
-        Then, in the parameters section of the effect:
-  <parameters>
-    <material>
-      <ambient type="vec4d">
-        0.2 .2 0.2 1.0
-      </ambient>
-    </material>
-  </parameters>
-
-        It's worth pointing out that the "material" property in a
-        technique specifies part of OpenGL's state, whereas "material"
-        in the parameters section is just a name, part of a
-        hierarchical namespace.
-
-        * A property in the parameters section doesn't need to contain
-        a constant value; it can also contain a "use" property. Here
-        the value of the use clause is the name of a node in an
-        external property tree which will be used as the source of a
-        value. If the name begins with '/', the node is in
-        FlightGear's global property tree; otherwise, it is in a local
-        property tree, usually belonging to a model [NOT IMPLEMENTED
-        YET]. For example:
-  <parameters>
-    <chrome-light><use>/rendering/scene/chrome-light</use></chrome-light>
-  </parameters>
-        The type is determined by what is expected by the technique
-        attribute that will ultimately receive the value. [There is
-        no way to get vector values out of the main property system
-        yet; this will be fixed shortly.] Values that are declared
-        this way are dynamically updated if the property node
-        changes.
+               constant. For example:
+               <uniform>
+                       <name>ColorsTex</name>
+                       <type>sampler-1d</type>
+                       <value type="int">2</value>
+               </uniform>
+               * The name of a property in the parameters section can be
+               referenced using a "use" clause. For example, in the technique
+               section:
+               <material>
+                       <ambient><use>material/ambient</use></ambient>
+               </material>
+               Then, in the parameters section of the effect:
+               <parameters>
+                       <material>
+                               <ambient type="vec4d">0.2 0.2 0.2 1.0</ambient>
+                       </material>
+               </parameters>
+
+               It's worth pointing out that the "material" property in a
+               technique specifies part of OpenGL's state, whereas "material"
+               in the parameters section is just a name, part of a
+               hierarchical namespace.
+
+               * A property in the parameters section doesn't need to contain
+               a constant value; it can also contain a "use" property. Here
+               the value of the use clause is the name of a node in an
+               external property tree which will be used as the source of a
+               value. If the name begins with '/', the node is in
+               FlightGear's global property tree; otherwise, it is in a local
+               property tree, usually belonging to a model [NOT IMPLEMENTED
+               YET]. For example:
+               <parameters>
+                       <chrome-light><use>/rendering/scene/chrome-light</use></chrome-light>
+               </parameters>
+               The type is determined by what is expected by the technique
+               attribute that will ultimately receive the value. [There is
+               no way to get vector values out of the main property system
+               yet; this will be fixed shortly.] Values that are declared
+               this way are dynamically updated if the property node
+               changes.
 
 OpenGL Attributes
 -----------------
 
 The following attributes are currently implemented in techiques:
 alpha-test - children: active, comparison, reference
-         Valid values for comparision:
-             never, less, equal, lequal, greater, notequal, gequal,
-             always 
+                Valid values for comparision:
+                        never, less, equal, lequal, greater, notequal, gequal,
+                        always 
 
 blend - children: active, source, destination, source-rgb,
-         source-alpha, destination-rgb, destination-alpha
-         Each operand can have the following values:
-             dst-alpha, dst-color, one, one-minus-dst-alpha,
-             one-minus-dst-color, one-minus-src-alpha,
-             one-minus-src-color, src-alpha, src-alpha-saturate,
-             src-color, constant-color, one-minus-constant-color,
-             constant-alpha, one-minus-constant-alpha, zero
+                source-alpha, destination-rgb, destination-alpha
+                Each operand can have the following values:
+                        dst-alpha, dst-color, one, one-minus-dst-alpha,
+                        one-minus-dst-color, one-minus-src-alpha,
+                        one-minus-src-color, src-alpha, src-alpha-saturate,
+                        src-color, constant-color, one-minus-constant-color,
+                        constant-alpha, one-minus-constant-alpha, zero
 
 cull-face - front, back, front-back
 
 lighting - true, false
 
 material - children: active, ambient, ambient-front, ambient-back, diffuse,
-         diffuse-front, diffuse-back, specular, specular-front,
-         specular-back, emissive, emissive-front, emissive-back, shininess,
-         shininess-front, shininess-back, color-mode
+                diffuse-front, diffuse-back, specular, specular-front,
+                specular-back, emissive, emissive-front, emissive-back, shininess,
+                shininess-front, shininess-back, color-mode
 
 polygon-mode - children: front, back
-        Valid values:
-              fill, line, point
+               Valid values:
+                         fill, line, point
 
 program
-        vertex-shader
-        fragment-shader
+               vertex-shader
+               geometry-shader
+               fragment-shader
+               attribute
+               geometry-vertices-out: integer, max number of vertices emitted by geometry shader
+               geometry-input-type - points, lines, lines-adjacency, triangles, triangles-adjacency
+               geometry-output-type - points, line-strip, triangle-strip
 
 render-bin - (OSG) children: bin-number, bin-name
 
@@ -162,25 +183,25 @@ shade-model - flat, smooth
 
 texture-unit - has several child properties:
        unit - The number of an OpenGL texture unit
-        type - This is either an OpenGL texture type or the name of a
-        builtin texture. Currently supported OpenGL types are 1d, 2d,
-        3d which have the following common parameters:
+               type - This is either an OpenGL texture type or the name of a
+               builtin texture. Currently supported OpenGL types are 1d, 2d,
+               3d which have the following common parameters:
                image (file name)
-                filter
-                mag-filter
-                wrap-s
-                wrap-t
-                wrap-r
-        The following builtin types are supported:
-                white - 1 pixel white texture
-                noise - a 3d noise texture
-        environment
-                mode
-                color
+                       filter
+                       mag-filter
+                       wrap-s
+                       wrap-t
+                       wrap-r
+               The following built-in types are supported:
+                       white - 1 pixel white texture
+                       noise - a 3d noise texture
+               environment
+                       mode
+                       color
 uniform
-        name
-        type - float, float-vec3, float-vec4, sampler-1d, sampler-2d,
-        sampler-3d
+               name
+               type - float, float-vec3, float-vec4, sampler-1d, sampler-2d,
+               sampler-3d
 
 vertex-program-two-side - true, false
 
@@ -211,8 +232,49 @@ those parameters in its "techniques" section. The derived effect
 overrides any default values that might be in the base effect's
 parameters section.
 
+Generate
+--------
+
+Often shader effects need tangent vectors to work properly. These 
+tangent vectors, usually called tangent and binormal, are computed 
+on the CPU and given to the shader as vertex attributes. These 
+vectors are computed on demand on the geometry using the effect if 
+the 'generate' clause is present in the effect file. Exemple :
+
+       <generate>
+               <tangent type="int">6</tangent>
+               <binormal type="int">7</binormal>
+               <normal type="int">8</normal>
+       </generate>
+
+Valid subnodes of 'generate' are 'tangent', 'binormal' or 'normal'.
+The integer value of these subnode is the index of the attribute 
+that will hold the value of the vec3 vector.
+
+The generate clause is located under PropertyList in the xml file.
+
+In order to be available for the vertex shader, these data should 
+be bound to an attribute in the program clause, like this :
+
+       <program>
+               <vertex-shader>my_vertex_shader</vertex-shader>
+               <attribute>
+                       <name>my_tangent_attribute</name>
+                       <index>6</index>
+               </attribute>
+               <attribute>
+                       <name>my_binormal_attribute</name>
+                       <index>7</index>
+               </attribute>
+       </program>
+
+attribute names are whatever the shader use. The index is the one 
+declared in the 'generate' clause. So because generate/tangent has 
+value 6 and my_tangent_attribute has index 6, my_tangent_attribute 
+holds the tangent value for the vertex.
+
 Default Effects in Terrain Materials and Models
----------------------------------------
+-----------------------------------------------
 
 Effects for terrain work in this way: for each material type in
 materials.xml an effect is created that inherits from a single default
@@ -233,12 +295,12 @@ variation possible from the OSG model loaders than from the terrain
 system. The parameters created are: 
 
        * material active, ambient, diffuse, specular, emissive,
-        shininess, color mode
-        * blend active, source, destination
-        * shade-model
-        * cull-face
-        * rendering-hint
-        * texture type, image, filter, wrap-s, wrap-t
+               shininess, color mode
+               * blend active, source, destination
+               * shade-model
+               * cull-face
+       * rendering-hint
+       * texture type, image, filter, wrap-s, wrap-t
 
 Specifying Custom Effects
 -------------------------
@@ -260,3 +322,30 @@ Examples
 
 The Effects directory contains the effects definitions; look there for
 examples. Effects/crop.eff is a good example of a complex effect.
+
+Application
+-----------
+
+To apply an effect to a model or part of a model use:
+
+       <effect>
+               <inherits-from>Effects/light-cone</inherits-from>
+               <object-name>Cone</object-name>
+       </effect>
+
+where <inherits-from> </inherits-from> contains the path to the effect you want to apply.
+The effect does not need the file extension.
+
+NOTE:
+
+Chrome, although now implemented as an effect, still retains the old method of application:
+
+       <animation>
+                       <type>shader</type>
+                       <shader>chrome</shader>
+                       <texture>glass_shader.png</texture>
+                       <object-name>windscreen</object-name>
+       </animation>
+
+in order to maintain backward compatibility.
+
index 2bf71b3b18b96b35a66462bce9f0fe2c9e282e97..0a8c1d5460ff0f3217ba64ad41208e3678ad0c6b 100644 (file)
@@ -80,6 +80,7 @@ FGAIAircraft::FGAIAircraft(FGAISchedule *ref) : FGAIBase(otAircraft) {
     headingError = 0;
 
     holdPos = false;
+    needsTaxiClearance = false;
 
     _performance = 0; //TODO initialize to JET_TRANSPORT from PerformanceDB
     dt = 0;
@@ -663,9 +664,8 @@ bool FGAIAircraft::handleAirportEndPoints(FGAIFlightPlan::waypoint* prev, time_t
     //cerr << trafficRef->getCallSign() << " has passed waypoint " << prev->name << " at speed " << speed << endl;
     if (prev->name == "PushBackPoint") {
         dep->getDynamics()->releaseParking(fp->getGate());
-        time_t holdUntil = now + 120;
-       fp->setTime(holdUntil);
-       //cerr << _getCallsign() << "Holding at pushback point" << endl;
+        AccelTo(0.0);
+        setTaxiClearanceRequest(true);
     }
 
     // This is the last taxi waypoint, and marks the the end of the flight plan
index 6a53e5a2bf32238b4c61fa6f81e5bfd6a179507e..7e65d0df51294732c4543a3dcff5c4461fc50f54 100644 (file)
@@ -70,6 +70,8 @@ public:
 
     void announcePositionToController(); //TODO have to be public?
     void processATC(FGATCInstruction instruction);
+    void setTaxiClearanceRequest(bool arg) { needsTaxiClearance = arg; };
+    bool getTaxiClearanceRequest() { return needsTaxiClearance; };
     FGAISchedule * getTrafficRef() { return trafficRef; };
 
     virtual const char* getTypeString(void) const { return "aircraft"; }
@@ -150,6 +152,7 @@ private:
     const char * _getTransponderCode() const;
 
     bool reachedWaypoint;
+    bool needsTaxiClearance;
     time_t timeElapsed;
 
     PerformanceData* _performance; // the performance data for this aircraft
index f9c2fee4e5fc6ef900774085e07a755e1f5fe533..98b2ab46e9ab3a1dcb9373ce4b5596ef600571f1 100644 (file)
@@ -340,11 +340,27 @@ FGATCInstruction::FGATCInstruction()
   alt     = 0;
 }
 
+
 bool FGATCInstruction::hasInstruction()
 {
   return (holdPattern || holdPosition || changeSpeed || changeHeading || changeAltitude || resolveCircularWait);
 }
 
+/***************************************************************************
+ * FGATCController
+ *
+ **************************************************************************/
+
+
+
+
+FGATCController::FGATCController() 
+{
+     dt_count = 0; 
+     available = true; 
+     lastTransmission = 0;
+}
+
 string FGATCController::getGateName(FGAIAircraft *ref) 
 {
     return ref->atGate();
@@ -370,6 +386,7 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
 
     //double commFreqD;
     sender = rec->getAircraft()->getTrafficRef()->getCallSign();
+    //cerr << "transmitting for: " << sender << "Leg = " << rec->getLeg() << endl;
     switch (rec->getLeg()) {
         case 2:
         case 3:
@@ -449,6 +466,12 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
                taxiFreqStr = formatATCFrequency3_2(taxiFreq);
                text = receiver + ". Switching to " + taxiFreqStr + ". " + sender;
                break;
+           case MSG_INITIATE_CONTACT:
+                text = receiver + ". With you. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_INITIATE_CONTACT:
+                text = receiver + ". Roger. " + sender;
+                break;
            case MSG_REQUEST_PUSHBACK_CLEARANCE:
                text = receiver + ". Request push-back. " + sender;
                break;
@@ -457,9 +480,30 @@ void FGATCController::transmit(FGTrafficRecord *rec, AtcMsgId msgId, AtcMsgDir m
                break;
            case MSG_HOLD_PUSHBACK_CLEARANCE:
                 text = receiver + ". Standby. " + sender;
-                 break;
-            default:
-                 text = sender + ". Transmitting unknown Message";
+                break;
+           case MSG_REQUEST_TAXI_CLEARANCE:
+                text = receiver + ". Ready to Taxi. " + sender;
+                break;
+           case MSG_ISSUE_TAXI_CLEARANCE:
+                text = receiver + ". Cleared to taxi. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_TAXI_CLEARANCE:
+                text = receiver + ". Cleared to taxi. " + sender;
+                break;
+           case MSG_HOLD_POSITION:
+                text = receiver + ". Hold Position. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_HOLD_POSITION:
+                text = receiver + ". Holding Position. " + sender;
+                break;
+           case MSG_RESUME_TAXI:
+                text = receiver + ". Resume Taxiing. " + sender;
+                break;
+           case MSG_ACKNOWLEDGE_RESUME_TAXI:
+                text = receiver + ". Continuing Taxi. " + sender;
+                break;
+           default:
+                 text = text + sender + ". Transmitting unknown Message";
                   break;
     }
     double onBoardRadioFreq0 = fgGetDouble("/instrumentation/comm[0]/frequencies/selected-mhz");
@@ -691,8 +735,6 @@ FGATCInstruction FGTowerController::getInstruction(int id)
 FGStartupController::FGStartupController() :
   FGATCController()
 {
-    available        = false;
-    lastTransmission = 0;
 }
 
 void FGStartupController::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
@@ -874,7 +916,7 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
              available = false;
         }
      }
-     // Note: The next two stages are only necessesary when Startup control is
+     // Note: The next four stages are only necessesary when Startup control is
      //  on a different frequency, compared to ground control
      if ((state == 4) && available){
         if (now > startTime+130) {
@@ -885,20 +927,36 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
              available = false;
         }
      }
+     if ((state == 5) && available){
+        if (now > startTime+140) {
+            transmit(&(*i), MSG_INITIATE_CONTACT, ATC_AIR_TO_GROUND);
+            i->updateState();
+            lastTransmission = now;
+             available = false;
+        }
+     }
+     if ((state == 6) && available){
+        if (now > startTime+150) {
+            transmit(&(*i), MSG_ACKNOWLEDGE_INITIATE_CONTACT, ATC_GROUND_TO_AIR);
+            i->updateState();
+            lastTransmission = now;
+             available = false;
+        }
+     }
 
 
      // TODO: Switch to APRON control and request pushback Clearance.
      // Get Push back clearance
-     if ((state == 5) && available){
-        if (now > startTime+160) {
+     if ((state == 7) && available){
+        if (now > startTime+180) {
             transmit(&(*i), MSG_REQUEST_PUSHBACK_CLEARANCE, ATC_AIR_TO_GROUND);
             i->updateState();
             lastTransmission = now;
              available = false;
         }
      }
-     if ((state == 6) && available){
-        if (now > startTime+180) {
+     if ((state == 8) && available){
+        if (now > startTime+200) {
             if (i->pushBackAllowed()) {
                  i->allowRepeatedTransmissions();
                  transmit(&(*i), MSG_PERMIT_PUSHBACK_CLEARANCE, ATC_GROUND_TO_AIR);
@@ -911,7 +969,7 @@ void FGStartupController::update(int id, double lat, double lon, double heading,
              available = false;
         }
      }
-     if ((state == 6) && available){
+     if ((state == 9) && available){
           i->setHoldPosition(false);
      }
 }
index f97e7cf22928549228599d065cade4fd519c0aaa..d069a5b84120af9e5fa2773b4f13383c0b3f7dde 100644 (file)
@@ -129,6 +129,7 @@ public:
   void setLeg(int lg) { leg = lg;};
   int getId() { return id;};
   int getState() { return state;};
+  void setState(int s) { state = s;}
   FGATCInstruction getInstruction() { return instruction;};
   bool hasInstruction() { return instruction.hasInstruction(); };
   void setPositionAndHeading(double lat, double lon, double hdg, double spd, double alt);
@@ -210,7 +211,10 @@ typedef vector<ActiveRunway>::iterator ActiveRunwayVecIterator;
  *************************************************************************************/
 class FGATCController
 {
-private:
+protected:
+  bool available;
+  time_t lastTransmission;
+
   double dt_count;
 
 
@@ -220,18 +224,27 @@ private:
 public:
   typedef enum {
       MSG_ANNOUNCE_ENGINE_START,
-      MSG_REQUEST_ENGINE_START, 
+      MSG_REQUEST_ENGINE_START,
       MSG_PERMIT_ENGINE_START,
       MSG_DENY_ENGINE_START,
       MSG_ACKNOWLEDGE_ENGINE_START,
       MSG_REQUEST_PUSHBACK_CLEARANCE,
-      MSG_PERMIT_PUSHBACK_CLEARANCE, 
+      MSG_PERMIT_PUSHBACK_CLEARANCE,
       MSG_HOLD_PUSHBACK_CLEARANCE,
-      MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY } AtcMsgId;
+      MSG_ACKNOWLEDGE_SWITCH_GROUND_FREQUENCY,
+      MSG_INITIATE_CONTACT,
+      MSG_ACKNOWLEDGE_INITIATE_CONTACT,
+      MSG_REQUEST_TAXI_CLEARANCE,
+      MSG_ISSUE_TAXI_CLEARANCE,
+      MSG_ACKNOWLEDGE_TAXI_CLEARANCE,
+      MSG_HOLD_POSITION,
+      MSG_ACKNOWLEDGE_HOLD_POSITION,
+      MSG_RESUME_TAXI,
+      MSG_ACKNOWLEDGE_RESUME_TAXI } AtcMsgId;
   typedef enum {
       ATC_AIR_TO_GROUND,
       ATC_GROUND_TO_AIR } AtcMsgDir;
-  FGATCController() { dt_count = 0;};
+  FGATCController();
   virtual ~FGATCController() {};
   virtual void announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentRoute,
                                double lat, double lon,
@@ -284,8 +297,6 @@ class FGStartupController : public FGATCController
 {
 private:
   TrafficVector activeTraffic;
-  bool available;
-  time_t lastTransmission;
   //ActiveRunwayVec activeRunways;
   
 public:
index 68963fe929f7e9ff571c5e7641f89e76ff75cc19..10fb8971545d1b770ee226d835043493bfa6bf16 100644 (file)
@@ -59,6 +59,7 @@ FGATC::FGATC() :
 {
        SGSoundMgr *smgr = globals->get_soundmgr();
        _sgr = smgr->find("atc", true);
+        _sgr->tie_to_listener();
 
        _volume = fgGetNode("/sim/sound/atc/volume", true);
        _enabled = fgGetNode("/sim/sound/atc/enabled", true);
index 9e5085adbdb8bb2d4f9bd6741abafb54026a22fa..19053adef5f712342dfc2fd0ce18fdaa15ed441d 100644 (file)
@@ -59,7 +59,14 @@ AirportATC::AirportATC() :
 FGATCMgr::FGATCMgr() :
     initDone(false),
     atc_list(new atc_list_type),
-    last_in_range(false)
+#ifdef ENABLE_AUDIO_SUPPORT
+    voiceOK(false),
+    voice(true),
+#else
+    voice(false),
+#endif
+    last_in_range(false),
+    v1(0)
 {
 }
 
@@ -89,30 +96,6 @@ void FGATCMgr::init() {
         // Is this still true after the reorganization of the event managar??
         // -EMH-
     
-#ifdef ENABLE_AUDIO_SUPPORT 
-    // Load all available voices.
-    // For now we'll do one hardwired one
-    
-    v1 = new FGATCVoice;
-    try {
-        voiceOK = v1->LoadVoice("default");
-        voice = true;
-    } catch ( sg_io_exception & e) {
-        voiceOK  = false;
-        SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : " << e.getFormattedMessage().c_str());
-        voice = false;
-        delete v1;
-        v1 = 0;
-    }
-    
-    /* I've loaded the voice even if /sim/sound/pause is true
-    *  since I know no way of forcing load of the voice if the user
-    *  subsequently switches /sim/sound/audible to true.
-        *  (which is the right thing to do -- CLO) :-) */
-#else
-    voice = false;
-#endif
-
     // Initialise the ATC Dialogs
     //cout << "Initing Transmissions..." << endl;
     SG_LOG(SG_ATC, SG_INFO, "  ATC Transmissions");
@@ -421,6 +404,31 @@ FGATCVoice* FGATCMgr::GetVoicePointer(const atc_type& type) {
     if(voice) {
         switch(type) {
         case ATIS: case AWOS:
+#ifdef ENABLE_AUDIO_SUPPORT
+            // Delayed loading fo all available voices, needed because the
+            // soundmanager might not be initialized (at all) at this point.
+            // For now we'll do one hardwired one
+
+            /* I've loaded the voice even if /sim/sound/pause is true
+             *  since I know no way of forcing load of the voice if the user
+             *  subsequently switches /sim/sound/audible to true.
+             *  (which is the right thing to do -- CLO) :-)
+             */
+            if (!voiceOK && fgGetBool("/sim/sound/working")) {
+                v1 = new FGATCVoice;
+                try {
+                    voiceOK = v1->LoadVoice("default");
+                    voice = voiceOK;
+                } catch ( sg_io_exception & e) {
+                    voiceOK  = false;
+                    SG_LOG(SG_ATC, SG_ALERT, "Unable to load default voice : "
+                                            << e.getFormattedMessage().c_str());
+                    voice = false;
+                    delete v1;
+                    v1 = 0;
+                }
+            }
+#endif
             if(voiceOK) {
                 return(v1);
             }
index 84663cc9328060989f7103b520b41c147b663834..21c4a1d44bfd524b0af273b0f22ba67fef0e3bcd 100644 (file)
@@ -142,17 +142,17 @@ void FGReplay::update( double dt ) {
     timingInfo.clear();
     stamp("begin");
     static SGPropertyNode *replay_master
-        = fgGetNode( "/sim/freeze/replay", true );
+        = fgGetNode( "/sim/freeze/replay-state", true );
 
     if( disable_replay->getBoolValue() ) {
-        if( sim_time != 0.0 ) {
+        if ( sim_time != 0.0 ) {
             // we were recording data
             init();
         }
         return;
     }
     //stamp("point_01");
-    if ( replay_master->getBoolValue() ) {
+    if ( replay_master->getIntValue() > 0 ) {
         // don't record the replay session
         return;
     }
@@ -177,9 +177,9 @@ void FGReplay::update( double dt ) {
         r = new FGReplayData;
        stamp("Replay_02");
     } else {
-      r = recycler.front();
-      recycler.pop_front();
-    //stamp("point_04be");
+       r = recycler.front();
+       recycler.pop_front();
+       //stamp("point_04be");
     }
     r->sim_time = sim_time;
     //r->ctrls = c;
index 8984214d994f305d35a7fd8cccbdff80ff496cf3..e64ee5923a6efd8fea6c64ec5eef6af7f49dafef 100644 (file)
@@ -237,7 +237,6 @@ private:
     SGGeod pos(SGGeod::fromDegFt(lon, lat, last_apt_elev));
     FGAirport* apt = new FGAirport(last_apt_id, pos, tower, last_apt_name, false,
         fptypeFromRobinType(atoi(last_apt_type.c_str())));
-        
     apt->setRunwaysAndTaxiways(runways, taxiways, pavements);
   }
   
index 3e658a1473aa5effe73f158c7fe181d1e2c797b0..a323d809c97e4d5abd7b4d63c40db02da914c9fe 100644 (file)
@@ -50,31 +50,34 @@ using std::random_shuffle;
 #include "simple.hxx"
 #include "dynamics.hxx"
 
-FGAirportDynamics::FGAirportDynamics(FGAirport* ap) :
-  _ap(ap), rwyPrefs(ap), SIDs(ap) {
-  lastUpdate = 0;
+FGAirportDynamics::FGAirportDynamics(FGAirport * ap):
+_ap(ap), rwyPrefs(ap), SIDs(ap)
+{
+    lastUpdate = 0;
 
-  // For testing only. This needs to be refined when we move ATIS functionality over.
-  atisInformation = "Sierra";
+    // For testing only. This needs to be refined when we move ATIS functionality over.
+    atisInformation = "Sierra";
 }
 
 // Note that the ground network should also be copied
-FGAirportDynamics::FGAirportDynamics(const FGAirportDynamics& other) :
-  rwyPrefs(other.rwyPrefs),
-  SIDs(other.SIDs)
+FGAirportDynamics::
+FGAirportDynamics(const FGAirportDynamics & other):rwyPrefs(other.
+                                                            rwyPrefs),
+SIDs(other.SIDs)
 {
-  for (FGParkingVecConstIterator ip= other.parkings.begin(); ip != other.parkings.end(); ip++)
-    parkings.push_back(*(ip));
-  // rwyPrefs = other.rwyPrefs;
-  lastUpdate = other.lastUpdate;
-  
-  stringVecConstIterator il;
-  for (il = other.landing.begin(); il != other.landing.end(); il++)
-    landing.push_back(*il);
-  for (il = other.takeoff.begin(); il != other.takeoff.end(); il++)
-    takeoff.push_back(*il);
-  lastUpdate = other.lastUpdate;
-  atisInformation = other.atisInformation; 
+    for (FGParkingVecConstIterator ip = other.parkings.begin();
+         ip != other.parkings.end(); ip++)
+        parkings.push_back(*(ip));
+    // rwyPrefs = other.rwyPrefs;
+    lastUpdate = other.lastUpdate;
+
+    stringVecConstIterator il;
+    for (il = other.landing.begin(); il != other.landing.end(); il++)
+        landing.push_back(*il);
+    for (il = other.takeoff.begin(); il != other.takeoff.end(); il++)
+        takeoff.push_back(*il);
+    lastUpdate = other.lastUpdate;
+    atisInformation = other.atisInformation;
 }
 
 // Destructor
@@ -84,449 +87,404 @@ FGAirportDynamics::~FGAirportDynamics()
 
 
 // Initialization required after XMLRead
-void FGAirportDynamics::init() 
+void FGAirportDynamics::init()
 {
-  // This may seem a bit weird to first randomly shuffle the parkings
-  // and then sort them again. However, parkings are sorted here by ascending 
-  // radius. Since many parkings have similar radii, with each radius class they will
-  // still be allocated relatively systematically. Randomizing prior to sorting will
-  // prevent any initial orderings to be destroyed, leading (hopefully) to a more 
-  // naturalistic gate assignment. 
-  random_shuffle(parkings.begin(), parkings.end());
-  sort(parkings.begin(), parkings.end());
-  // add the gate positions to the ground network. 
-  groundNetwork.addNodes(&parkings);
-  groundNetwork.init();
-  groundNetwork.setTowerController(&towerController);
-  groundNetwork.setParent(_ap);
+    // This may seem a bit weird to first randomly shuffle the parkings
+    // and then sort them again. However, parkings are sorted here by ascending 
+    // radius. Since many parkings have similar radii, with each radius class they will
+    // still be allocated relatively systematically. Randomizing prior to sorting will
+    // prevent any initial orderings to be destroyed, leading (hopefully) to a more 
+    // naturalistic gate assignment. 
+    random_shuffle(parkings.begin(), parkings.end());
+    sort(parkings.begin(), parkings.end());
+    // add the gate positions to the ground network. 
+    groundNetwork.addNodes(&parkings);
+    groundNetwork.init();
+    groundNetwork.setTowerController(&towerController);
+    groundNetwork.setParent(_ap);
 }
 
-bool FGAirportDynamics::getAvailableParking(double *lat, double *lon, double *heading, int *gateId, double rad, const string &flType, const string &acType, const string &airline)
+bool FGAirportDynamics::getAvailableParking(double *lat, double *lon,
+                                            double *heading, int *gateId,
+                                            double rad,
+                                            const string & flType,
+                                            const string & acType,
+                                            const string & airline)
 {
-  bool found = false;
-  bool available = false;
-  //string gateType;
-
-  FGParkingVecIterator i;
-//   if (flType == "cargo")
-//     {
-//       gateType = "RAMP_CARGO";
-//     }
-//   else if (flType == "ga")
-//     {
-//       gateType = "RAMP_GA";
-//     }
-//   else gateType = "GATE";
-  
-  if (parkings.begin() == parkings.end())
-    {
-      //cerr << "Could not find parking spot at " << _ap->getId() << endl;
-      *lat = _ap->getLatitude();
-      *lon = _ap->getLongitude();
-      *heading = 0;
-      found = true;
+    bool found = false;
+    bool available = false;
+
+
+    FGParkingVecIterator i;
+    if (parkings.begin() == parkings.end()) {
+        //cerr << "Could not find parking spot at " << _ap->getId() << endl;
+        *lat = _ap->getLatitude();
+        *lon = _ap->getLongitude();
+        *heading = 0;
+        found = true;
+    } else {
+        // First try finding a parking with a designated airline code
+        for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
+            available = true;
+            // Taken by another aircraft
+            if (!(i->isAvailable())) {
+                available = false;
+                continue;
+            }
+            // No airline codes, so skip
+            if (i->getCodes().empty()) {
+                available = false;
+                continue;
+            } else {             // Airline code doesn't match
+                //cerr << "Code = " << airline << ": Codes " << i->getCodes();
+                if (i->getCodes().find(airline, 0) == string::npos) {
+                    available = false;
+                    //cerr << "Unavailable" << endl;
+                    continue;
+                } else {
+                    //cerr << "Available" << endl;
+                }
+            }
+            // Type doesn't match
+            if (i->getType() != flType) {
+                available = false;
+                continue;
+            }
+            // too small
+            if (i->getRadius() < rad) {
+                available = false;
+                continue;
+            }
+
+            if (available) {
+                *lat = i->getLatitude();
+                *lon = i->getLongitude();
+                *heading = i->getHeading();
+                *gateId = i->getIndex();
+                i->setAvailable(false);
+                found = true;
+            }
+        }
+        // then try again for those without codes. 
+        for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
+            available = true;
+            if (!(i->isAvailable())) {
+                available = false;
+                continue;
+            }
+            if (!(i->getCodes().empty())) {
+                if ((i->getCodes().find(airline, 0) == string::npos)) {
+                    available = false;
+                    continue;
+                }
+            }
+            if (i->getType() != flType) {
+                available = false;
+                continue;
+            }
+
+            if (i->getRadius() < rad) {
+                available = false;
+                continue;
+            }
+
+            if (available) {
+                *lat = i->getLatitude();
+                *lon = i->getLongitude();
+                *heading = i->getHeading();
+                *gateId = i->getIndex();
+                i->setAvailable(false);
+                found = true;
+            }
+        }
+        // And finally once more if that didn't work. Now ignore the airline codes, as a last resort
+        for (i = parkings.begin(); !(i == parkings.end() || found); i++) {
+            available = true;
+            if (!(i->isAvailable())) {
+                available = false;
+                continue;
+            }
+            if (i->getType() != flType) {
+                available = false;
+                continue;
+            }
+
+            if (i->getRadius() < rad) {
+                available = false;
+                continue;
+            }
+
+            if (available) {
+                *lat = i->getLatitude();
+                *lon = i->getLongitude();
+                *heading = i->getHeading();
+                *gateId = i->getIndex();
+                i->setAvailable(false);
+                found = true;
+            }
+        }
     }
-  else
-    {
-      // First try finding a parking with a designated airline code
-      for (i = parkings.begin(); !(i == parkings.end() || found); i++)
-       {
-         //cerr << "Gate Id: " << i->getIndex()
-         //     << " Type  : " << i->getType()
-         //     << " Codes : " << i->getCodes()
-         //     << " Radius: " << i->getRadius()
-         //     << " Name  : " << i->getName()
-          //     << " Available: " << i->isAvailable() << endl;
-         available = true;
-         // Taken by another aircraft
-         if (!(i->isAvailable()))
-           {
-             available = false;
-             continue;
-           }
-         // No airline codes, so skip
-         if (i->getCodes().empty())
-           {
-             available = false;
-             continue;
-           }
-         else // Airline code doesn't match
-           {
-             //cerr << "Code = " << airline << ": Codes " << i->getCodes();
-             if (i->getCodes().find(airline, 0) == string::npos)
-               {
-                 available = false;
-                 //cerr << "Unavailable" << endl;
-                 continue;
-               }
-             else
-               {
-                 //cerr << "Available" << endl;
-               }
-           }
-         // Type doesn't match
-         if (i->getType() != flType)
-           {
-             available = false;
-             continue;
-           }
-         // too small
-         if (i->getRadius() < rad)
-           {
-             available = false;
-             continue;
-           }
-         
-         if (available)
-           {
-             *lat     = i->getLatitude ();
-             *lon     = i->getLongitude();
-             *heading = i->getHeading  ();
-             *gateId  = i->getIndex    ();
-             i->setAvailable(false);
-             found = true;
-           }
-       }
-      // then try again for those without codes. 
-      for (i = parkings.begin(); !(i == parkings.end() || found); i++)
-       {
-         available = true;
-         if (!(i->isAvailable()))
-           {
-             available = false;
-             continue;
-           }
-         if (!(i->getCodes().empty()))
-           {
-             if ((i->getCodes().find(airline,0) == string::npos))
-               {
-                   available = false;
-                   continue;
-               }
-           }
-         if (i->getType() != flType)
-           {
-             available = false;
-             continue;
-           }
-             
-         if (i->getRadius() < rad)
-           {
-             available = false;
-             continue;
-           }
-         
-         if (available)
-           {
-             *lat     = i->getLatitude ();
-             *lon     = i->getLongitude();
-             *heading = i->getHeading  ();
-             *gateId  = i->getIndex    ();
-             i->setAvailable(false);
-             found = true;
-           }
-       }
-      // And finally once more if that didn't work. Now ignore the airline codes, as a last resort
-      for (i = parkings.begin(); !(i == parkings.end() || found); i++)
-       {
-         available = true;
-         if (!(i->isAvailable()))
-           {
-             available = false;
-             continue;
-           }
-         if (i->getType() != flType)
-           {
-             available = false;
-             continue;
-           }
-         
-         if (i->getRadius() < rad)
-           {
-             available = false;
-             continue;
-           }
-         
-         if (available)
-           {
-             *lat     = i->getLatitude ();
-             *lon     = i->getLongitude();
-             *heading = i->getHeading  ();
-             *gateId  = i->getIndex    ();
-             i->setAvailable(false);
-             found = true;
-           }
-       }
+    if (!found) {
+        //cerr << "Traffic overflow at" << _ap->getId() 
+        //           << ". flType = " << flType 
+        //           << ". airline = " << airline 
+        //           << " Radius = " <<rad
+        //           << endl;
+        *lat = _ap->getLatitude();
+        *lon = _ap->getLongitude();
+        *heading = 0;
+        *gateId = -1;
+        //exit(1);
     }
-  if (!found)
-    {
-      //cerr << "Traffic overflow at" << _ap->getId() 
-      //          << ". flType = " << flType 
-      //          << ". airline = " << airline 
-      //          << " Radius = " <<rad
-      //          << endl;
-      *lat = _ap->getLatitude();
-      *lon = _ap->getLongitude();
-      *heading = 0;
-      *gateId  = -1;
-      //exit(1);
-    }
-  return found;
+    return found;
 }
 
-void FGAirportDynamics::getParking (int id, double *lat, double* lon, double *heading)
+void FGAirportDynamics::getParking(int id, double *lat, double *lon,
+                                   double *heading)
 {
-  if (id < 0)
-    {
-      *lat = _ap->getLatitude();
-      *lon = _ap->getLongitude();
-      *heading = 0;
-    }
-  else
-    {
-      FGParkingVecIterator i = parkings.begin();
-      for (i = parkings.begin(); i != parkings.end(); i++)
-       {
-         if (id == i->getIndex())
-           {
-             *lat     = i->getLatitude();
-             *lon     = i->getLongitude();
-             *heading = i->getHeading();
-           }
-       }
+    if (id < 0) {
+        *lat = _ap->getLatitude();
+        *lon = _ap->getLongitude();
+        *heading = 0;
+    } else {
+        FGParkingVecIterator i = parkings.begin();
+        for (i = parkings.begin(); i != parkings.end(); i++) {
+            if (id == i->getIndex()) {
+                *lat = i->getLatitude();
+                *lon = i->getLongitude();
+                *heading = i->getHeading();
+            }
+        }
     }
-} 
+}
 
-FGParking *FGAirportDynamics::getParking(int id) 
-{ 
+FGParking *FGAirportDynamics::getParking(int id)
+{
     FGParkingVecIterator i = parkings.begin();
-    for (i = parkings.begin(); i != parkings.end(); i++)
-       {
-         if (id == i->getIndex()) {
-               return &(*i);
-          }
+    for (i = parkings.begin(); i != parkings.end(); i++) {
+        if (id == i->getIndex()) {
+            return &(*i);
         }
+    }
     return 0;
 }
-string FGAirportDynamics::getParkingName(int id) 
-{ 
+
+string FGAirportDynamics::getParkingName(int id)
+{
     FGParkingVecIterator i = parkings.begin();
-    for (i = parkings.begin(); i != parkings.end(); i++)
-       {
-         if (id == i->getIndex()) {
-               return i->getName();
-          }
+    for (i = parkings.begin(); i != parkings.end(); i++) {
+        if (id == i->getIndex()) {
+            return i->getName();
         }
+    }
 
     return string("overflow");
 }
+
 void FGAirportDynamics::releaseParking(int id)
 {
-  if (id >= 0)
-    {
-      
-      FGParkingVecIterator i = parkings.begin();
-      for (i = parkings.begin(); i != parkings.end(); i++)
-       {
-         if (id == i->getIndex())
-           {
-             i -> setAvailable(true);
-           }
-       }
+    if (id >= 0) {
+
+        FGParkingVecIterator i = parkings.begin();
+        for (i = parkings.begin(); i != parkings.end(); i++) {
+            if (id == i->getIndex()) {
+                i->setAvailable(true);
+            }
+        }
     }
 }
-  
-void FGAirportDynamics::setRwyUse(const FGRunwayPreference& ref)
+
+void FGAirportDynamics::setRwyUse(const FGRunwayPreference & ref)
 {
-  rwyPrefs = ref;
-  //cerr << "Exiting due to not implemented yet" << endl;
-  //exit(1);
+    rwyPrefs = ref;
+    //cerr << "Exiting due to not implemented yet" << endl;
+    //exit(1);
 }
 
-bool FGAirportDynamics::innerGetActiveRunway(const string &trafficType, int action, string &runway, double heading)
+bool FGAirportDynamics::innerGetActiveRunway(const string & trafficType,
+                                             int action, string & runway,
+                                             double heading)
 {
-double windSpeed;
-  double windHeading;
-  double maxTail;
-  double maxCross;
-  string name;
-  string type;
-
-  if (!rwyPrefs.available()) {
-    return false;
-  }
-  
-  RunwayGroup *currRunwayGroup = 0;
-  int nrActiveRunways = 0;
-  time_t dayStart = fgGetLong("/sim/time/utc/day-seconds");
-  if ((abs((long)(dayStart - lastUpdate)) > 600) || trafficType != prevTrafficType)
-       {
-         landing.clear();
-         takeoff.clear();
-         lastUpdate = dayStart;
-         prevTrafficType = trafficType;
-
-         FGEnvironment 
-           stationweather = ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
-           ->getEnvironment(getLatitude(), 
-                            getLongitude(), 
-                            getElevation());
-         
-         windSpeed = stationweather.get_wind_speed_kt();
-         windHeading = stationweather.get_wind_from_heading_deg();
-         string scheduleName;
-         //cerr << "finding active Runway for" << _ap->getId() << endl;
-         //cerr << "Nr of seconds since day start << " << dayStart << endl;
-
-         ScheduleTime *currSched;
-         //cerr << "A"<< endl;
-         currSched = rwyPrefs.getSchedule(trafficType.c_str());
-         if (!(currSched))
-           return false;
-         //cerr << "B"<< endl;
-         scheduleName = currSched->getName(dayStart);
-         maxTail  = currSched->getTailWind  ();
-         maxCross = currSched->getCrossWind ();
-         //cerr << "SChedule anme = " << scheduleName << endl;
-         if (scheduleName.empty())
-           return false;
-         //cerr << "C"<< endl;
-         currRunwayGroup = rwyPrefs.getGroup(scheduleName); 
-         //cerr << "D"<< endl;
-         if (!(currRunwayGroup))
-           return false;
-         nrActiveRunways = currRunwayGroup->getNrActiveRunways();
+    double windSpeed;
+    double windHeading;
+    double maxTail;
+    double maxCross;
+    string name;
+    string type;
+
+    if (!rwyPrefs.available()) {
+        return false;
+    }
+
+    RunwayGroup *currRunwayGroup = 0;
+    int nrActiveRunways = 0;
+    time_t dayStart = fgGetLong("/sim/time/utc/day-seconds");
+    if ((abs((long) (dayStart - lastUpdate)) > 600)
+        || trafficType != prevTrafficType) {
+        landing.clear();
+        takeoff.clear();
+        lastUpdate = dayStart;
+        prevTrafficType = trafficType;
+
+        FGEnvironment
+            stationweather =
+            ((FGEnvironmentMgr *) globals->get_subsystem("environment"))
+            ->getEnvironment(getLatitude(), getLongitude(),
+                             getElevation());
+
+        windSpeed = stationweather.get_wind_speed_kt();
+        windHeading = stationweather.get_wind_from_heading_deg();
+        string scheduleName;
+        //cerr << "finding active Runway for" << _ap->getId() << endl;
+        //cerr << "Nr of seconds since day start << " << dayStart << endl;
+
+        ScheduleTime *currSched;
+        //cerr << "A"<< endl;
+        currSched = rwyPrefs.getSchedule(trafficType.c_str());
+        if (!(currSched))
+            return false;
+        //cerr << "B"<< endl;
+        scheduleName = currSched->getName(dayStart);
+        maxTail = currSched->getTailWind();
+        maxCross = currSched->getCrossWind();
+        //cerr << "SChedule anme = " << scheduleName << endl;
+        if (scheduleName.empty())
+            return false;
+        //cerr << "C"<< endl;
+        currRunwayGroup = rwyPrefs.getGroup(scheduleName);
+        //cerr << "D"<< endl;
+        if (!(currRunwayGroup))
+            return false;
+        nrActiveRunways = currRunwayGroup->getNrActiveRunways();
 
         // Keep a history of the currently active runways, to ensure
         // that an already established selection of runways will not
         // be overridden once a more preferred selection becomes 
         // available as that can lead to random runway swapping.
-       if (trafficType == "com") {
-          currentlyActive = &comActive;
+        if (trafficType == "com") {
+            currentlyActive = &comActive;
         } else if (trafficType == "gen") {
-          currentlyActive = &genActive;
+            currentlyActive = &genActive;
         } else if (trafficType == "mil") {
-          currentlyActive = &milActive;
+            currentlyActive = &milActive;
         } else if (trafficType == "ul") {
-          currentlyActive = &ulActive;
+            currentlyActive = &ulActive;
+        }
+
+        currRunwayGroup->setActive(_ap,
+                                   windSpeed,
+                                   windHeading,
+                                   maxTail, maxCross, currentlyActive);
+
+        // Note that I SHOULD keep multiple lists in memory, one for 
+        // general aviation, one for commercial and one for military
+        // traffic.
+        currentlyActive->clear();
+        nrActiveRunways = currRunwayGroup->getNrActiveRunways();
+        //cerr << "Choosing runway for " << trafficType << endl;
+        for (int i = 0; i < nrActiveRunways; i++) {
+            type = "unknown";   // initialize to something other than landing or takeoff
+            currRunwayGroup->getActive(i, name, type);
+            if (type == "landing") {
+                landing.push_back(name);
+                currentlyActive->push_back(name);
+                //cerr << "Landing " << name << endl; 
+            }
+            if (type == "takeoff") {
+                takeoff.push_back(name);
+                currentlyActive->push_back(name);
+                //cerr << "takeoff " << name << endl;
+            }
         }
-         // 
-         currRunwayGroup->setActive(_ap, 
-                                    windSpeed, 
-                                    windHeading, 
-                                    maxTail, 
-                                    maxCross, 
-                                    currentlyActive); 
-
-         // Note that I SHOULD keep multiple lists in memory, one for 
-         // general aviation, one for commercial and one for military
-         // traffic.
-         currentlyActive->clear();
-         nrActiveRunways = currRunwayGroup->getNrActiveRunways();
-          //cerr << "Choosing runway for " << trafficType << endl;
-         for (int i = 0; i < nrActiveRunways; i++)
-           {
-             type = "unknown"; // initialize to something other than landing or takeoff
-             currRunwayGroup->getActive(i, name, type);
-             if (type == "landing")
-               {
-                 landing.push_back(name);
-                 currentlyActive->push_back(name);
-                 //cerr << "Landing " << name << endl; 
-               }
-             if (type == "takeoff")
-               {
-                 takeoff.push_back(name);
-                 currentlyActive->push_back(name);
-                 //cerr << "takeoff " << name << endl;
-               }
-           }
-          //cerr << endl;
-       }
-  
-  if (action == 1) // takeoff 
-       {
-         int nr = takeoff.size();
-         if (nr)
-           {
-             // Note that the randomization below, is just a placeholder to choose between
-             // multiple active runways for this action. This should be
-             // under ATC control.
-             runway = chooseRwyByHeading (takeoff, heading);
-           }
-         else
-           { // Fallback
-             runway = chooseRunwayFallback();
-           }
-       } 
-  
-  if (action == 2) // landing
-       {
-         int nr = landing.size();
-         if (nr)
-           {
-             runway = chooseRwyByHeading (landing, heading);
-           }
-         else
-           {  //fallback
-              runway = chooseRunwayFallback();
-           }
-       } 
-
-  return true;
+        //cerr << endl;
+    }
+
+    if (action == 1)            // takeoff 
+    {
+        int nr = takeoff.size();
+        if (nr) {
+            // Note that the randomization below, is just a placeholder to choose between
+            // multiple active runways for this action. This should be
+            // under ATC control.
+            runway = chooseRwyByHeading(takeoff, heading);
+        } else {                // Fallback
+            runway = chooseRunwayFallback();
+        }
+    }
+
+    if (action == 2)            // landing
+    {
+        int nr = landing.size();
+        if (nr) {
+            runway = chooseRwyByHeading(landing, heading);
+        } else {                //fallback
+            runway = chooseRunwayFallback();
+        }
+    }
+
+    return true;
 }
 
-string FGAirportDynamics::chooseRwyByHeading(stringVec rwys, double heading) {
-   double bestError = 360.0;
-   double rwyHeading, headingError;
-   string runway;
-   for (stringVecIterator i = rwys.begin(); i != rwys.end(); i++) {
-       FGRunway *rwy = _ap->getRunwayByIdent((*i));
-       rwyHeading = rwy->headingDeg();
-       headingError = fabs(heading - rwyHeading);
+string FGAirportDynamics::chooseRwyByHeading(stringVec rwys,
+                                             double heading)
+{
+    double bestError = 360.0;
+    double rwyHeading, headingError;
+    string runway;
+    for (stringVecIterator i = rwys.begin(); i != rwys.end(); i++) {
+        FGRunway *rwy = _ap->getRunwayByIdent((*i));
+        rwyHeading = rwy->headingDeg();
+        headingError = fabs(heading - rwyHeading);
         if (headingError > 180)
             headingError = fabs(headingError - 360);
         if (headingError < bestError) {
             runway = (*i);
             bestError = headingError;
         }
-   }
-   //cerr << "Using active runway " << runway << " for heading " << heading << endl;
-   return runway;
+    }
+    //cerr << "Using active runway " << runway << " for heading " << heading << endl;
+    return runway;
 }
 
-void FGAirportDynamics::getActiveRunway(const string &trafficType, int action, string &runway, double heading)
+void FGAirportDynamics::getActiveRunway(const string & trafficType,
+                                        int action, string & runway,
+                                        double heading)
 {
-  bool ok = innerGetActiveRunway(trafficType, action, runway, heading);
-  if (!ok) {
-    runway = chooseRunwayFallback();
-  }
+    bool ok = innerGetActiveRunway(trafficType, action, runway, heading);
+    if (!ok) {
+        runway = chooseRunwayFallback();
+    }
 }
 
 string FGAirportDynamics::chooseRunwayFallback()
-{   
-  FGRunway* rwy = _ap->getActiveRunwayForUsage();
-  return rwy->ident();
+{
+    FGRunway *rwy = _ap->getActiveRunwayForUsage();
+    return rwy->ident();
 }
 
-void FGAirportDynamics::addParking(FGParking& park) {
-  parkings.push_back(park);
+void FGAirportDynamics::addParking(FGParking & park)
+{
+    parkings.push_back(park);
 }
 
-double FGAirportDynamics::getLatitude() const {
-  return _ap->getLatitude();
+double FGAirportDynamics::getLatitude() const
+{
+    return _ap->getLatitude();
 }
 
-double FGAirportDynamics::getLongitude() const {
-  return _ap->getLongitude();
+double FGAirportDynamics::getLongitude() const
+{
+    return _ap->getLongitude();
 }
 
-double FGAirportDynamics::getElevation() const {
-  return _ap->getElevation();
+double FGAirportDynamics::getElevation() const
+{
+    return _ap->getElevation();
 }
 
-const string& FGAirportDynamics::getId() const {
-  return _ap->getId();
+const string & FGAirportDynamics::getId() const
+{
+    return _ap->getId();
 }
 
 // Experimental: Return a different ground frequency depending on the leg of the
@@ -536,28 +494,34 @@ const string& FGAirportDynamics::getId() const {
 // so that at least I can start working on assigning different frequencies to different
 // operations.
 
-int FGAirportDynamics::getGroundFrequency(unsigned leg) { 
-     //return freqGround.size() ? freqGround[0] : 0; };
-     int groundFreq = 0;
-     if (leg < 2) {
-         SG_LOG(SG_ATC, SG_ALERT, "Leg value is smaller than two at " << SG_ORIGIN);
-     }
-     if (freqGround.size() == 0) {
-         return 0;
-     }
-     if ((freqGround.size() > leg-1) && (leg > 1)) {
-          groundFreq =  freqGround[leg-1];
-     }
-     if ((freqGround.size() < leg-1) && (leg > 1)) {
-          groundFreq = (freqGround.size() < (leg-1)) ? freqGround[freqGround.size()-1] : freqGround[leg-2];
-     }
-     if ((freqGround.size() >= leg-1) && (leg > 1)) {
-          groundFreq = freqGround[leg-2];
-     }
+int FGAirportDynamics::getGroundFrequency(unsigned leg)
+{
+    //return freqGround.size() ? freqGround[0] : 0; };
+    int groundFreq = 0;
+    if (leg < 2) {
+        SG_LOG(SG_ATC, SG_ALERT,
+               "Leg value is smaller than two at " << SG_ORIGIN);
+    }
+    if (freqGround.size() == 0) {
+        return 0;
+    }
+    if ((freqGround.size() > leg - 1) && (leg > 1)) {
+        groundFreq = freqGround[leg - 1];
+    }
+    if ((freqGround.size() < leg - 1) && (leg > 1)) {
+        groundFreq =
+            (freqGround.size() <
+             (leg - 1)) ? freqGround[freqGround.size() -
+                                     1] : freqGround[leg - 2];
+    }
+    if ((freqGround.size() >= leg - 1) && (leg > 1)) {
+        groundFreq = freqGround[leg - 2];
+    }
     return groundFreq;
 }
 
-FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway, double heading)
+FGAIFlightPlan *FGAirportDynamics::getSID(string activeRunway,
+                                          double heading)
 {
-   return SIDs.getBest(activeRunway, heading);
+    return SIDs.getBest(activeRunway, heading);
 }
index 321a3af68833c7212d8f67d037e6b3e651d872e5..011acb866d513014d9023dd164be137047255eb6 100644 (file)
@@ -32,6 +32,7 @@
 
 #include <Airports/dynamics.hxx>
 
+#include <AIModel/AIAircraft.hxx>
 #include <AIModel/AIFlightPlan.hxx>
 
 #include "groundnetwork.hxx"
  * FGTaxiSegment
  **************************************************************************/
 
-void FGTaxiSegment::setStart(FGTaxiNodeVector *nodes)
+void FGTaxiSegment::setStart(FGTaxiNodeVector * nodes)
 {
-  FGTaxiNodeVectorIterator i = nodes->begin();
-  while (i != nodes->end())
-    {
-      //cerr << "Scanning start node index" << (*i)->getIndex() << endl;
-      if ((*i)->getIndex() == startNode)
-       {
-         start = (*i)->getAddress();
-         (*i)->addSegment(this);
-         return;
-       }
-      i++;
-    }
-  SG_LOG(SG_GENERAL, SG_ALERT,  "Could not find start node " << startNode << endl);
+    FGTaxiNodeVectorIterator i = nodes->begin();
+    while (i != nodes->end()) {
+        //cerr << "Scanning start node index" << (*i)->getIndex() << endl;
+        if ((*i)->getIndex() == startNode) {
+            start = (*i)->getAddress();
+            (*i)->addSegment(this);
+            return;
+        }
+        i++;
+    }
+    SG_LOG(SG_GENERAL, SG_ALERT,
+           "Could not find start node " << startNode << endl);
 }
 
-void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
+void FGTaxiSegment::setEnd(FGTaxiNodeVector * nodes)
 {
-  FGTaxiNodeVectorIterator i = nodes->begin();
-  while (i != nodes->end())
-    {
-      //cerr << "Scanning end node index" << (*i)->getIndex() << endl;
-      if ((*i)->getIndex() == endNode)
-       {
-         end = (*i)->getAddress();
-         return;
-       }
-      i++;
-    }
-  SG_LOG(SG_GENERAL, SG_ALERT,  "Could not find end node " << endNode << endl);
+    FGTaxiNodeVectorIterator i = nodes->begin();
+    while (i != nodes->end()) {
+        //cerr << "Scanning end node index" << (*i)->getIndex() << endl;
+        if ((*i)->getIndex() == endNode) {
+            end = (*i)->getAddress();
+            return;
+        }
+        i++;
+    }
+    SG_LOG(SG_GENERAL, SG_ALERT,
+           "Could not find end node " << endNode << endl);
 }
 
 
@@ -79,90 +78,91 @@ void FGTaxiSegment::setEnd(FGTaxiNodeVector *nodes)
 // doing this.
 void FGTaxiSegment::setTrackDistance()
 {
-  length = SGGeodesy::distanceM(start->getGeod(), end->getGeod());
+    length = SGGeodesy::distanceM(start->getGeod(), end->getGeod());
 }
 
 
 void FGTaxiSegment::setCourseDiff(double crse)
 {
-  headingDiff = fabs(course-crse);
-  
-  if (headingDiff > 180)
-    headingDiff = fabs(headingDiff - 360);
+    headingDiff = fabs(course - crse);
+
+    if (headingDiff > 180)
+        headingDiff = fabs(headingDiff - 360);
 }
 
 
 /***************************************************************************
  * FGTaxiRoute
  **************************************************************************/
-bool FGTaxiRoute::next(int *nde) 
-{ 
-  //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
-  //  cerr << "FGTaxiRoute contains : " << *(i) << endl;
-  //cerr << "Offset from end: " << nodes.end() - currNode << endl;
-  //if (currNode != nodes.end())
-  //  cerr << "true" << endl;
-  //else
-  //  cerr << "false" << endl;
-  //if (nodes.size() != (routes.size()) +1)
-  //  cerr << "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size() << endl;
-      
-  if (currNode == nodes.end())
-    return false;
-  *nde = *(currNode); 
-  if (currNode != nodes.begin()) // make sure route corresponds to the end node
-    currRoute++;
-  currNode++;
-  return true;
+bool FGTaxiRoute::next(int *nde)
+{
+    //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
+    //  cerr << "FGTaxiRoute contains : " << *(i) << endl;
+    //cerr << "Offset from end: " << nodes.end() - currNode << endl;
+    //if (currNode != nodes.end())
+    //  cerr << "true" << endl;
+    //else
+    //  cerr << "false" << endl;
+    //if (nodes.size() != (routes.size()) +1)
+    //  cerr << "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size() << endl;
+
+    if (currNode == nodes.end())
+        return false;
+    *nde = *(currNode);
+    if (currNode != nodes.begin())      // make sure route corresponds to the end node
+        currRoute++;
+    currNode++;
+    return true;
 };
 
-bool FGTaxiRoute::next(int *nde, int *rte) 
-{ 
-  //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
-  //  cerr << "FGTaxiRoute contains : " << *(i) << endl;
-  //cerr << "Offset from end: " << nodes.end() - currNode << endl;
-  //if (currNode != nodes.end())
-  //  cerr << "true" << endl;
-  //else
-  //  cerr << "false" << endl;
-  if (nodes.size() != (routes.size()) +1) {
-    SG_LOG(SG_GENERAL, SG_ALERT, "ALERT: Misconfigured TaxiRoute : " << nodes.size() << " " << routes.size());
-    exit(1);
-  }
-  if (currNode == nodes.end())
-    return false;
-  *nde = *(currNode); 
-  //*rte = *(currRoute);
-  if (currNode != nodes.begin()) // Make sure route corresponds to the end node
-    {
-      *rte = *(currRoute);
-      currRoute++;
+bool FGTaxiRoute::next(int *nde, int *rte)
+{
+    //for (intVecIterator i = nodes.begin(); i != nodes.end(); i++)
+    //  cerr << "FGTaxiRoute contains : " << *(i) << endl;
+    //cerr << "Offset from end: " << nodes.end() - currNode << endl;
+    //if (currNode != nodes.end())
+    //  cerr << "true" << endl;
+    //else
+    //  cerr << "false" << endl;
+    if (nodes.size() != (routes.size()) + 1) {
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "ALERT: Misconfigured TaxiRoute : " << nodes.
+               size() << " " << routes.size());
+        exit(1);
     }
-  else
+    if (currNode == nodes.end())
+        return false;
+    *nde = *(currNode);
+    //*rte = *(currRoute);
+    if (currNode != nodes.begin())      // Make sure route corresponds to the end node
     {
-      // If currNode points to the first node, this means the aircraft is not on the taxi node
-      // yet. Make sure to return a unique identifyer in this situation though, because otherwise
-      // the speed adjust AI code may be unable to resolve whether two aircraft are on the same 
-      // taxi route or not. the negative of the preceding route seems a logical choice, as it is 
-      // unique for any starting location. 
-      // Note that this is probably just a temporary fix until I get Parking / tower control working.
-      *rte = -1 * *(currRoute); 
-    }
-  currNode++;
-  return true;
+        *rte = *(currRoute);
+        currRoute++;
+    } else {
+        // If currNode points to the first node, this means the aircraft is not on the taxi node
+        // yet. Make sure to return a unique identifyer in this situation though, because otherwise
+        // the speed adjust AI code may be unable to resolve whether two aircraft are on the same 
+        // taxi route or not. the negative of the preceding route seems a logical choice, as it is 
+        // unique for any starting location. 
+        // Note that this is probably just a temporary fix until I get Parking / tower control working.
+        *rte = -1 * *(currRoute);
+    }
+    currNode++;
+    return true;
 };
 
 void FGTaxiRoute::rewind(int route)
 {
-  int currPoint;
-  int currRoute;
-  first();
-  do {
-    if (!(next(&currPoint, &currRoute))) { 
-      SG_LOG(SG_GENERAL,SG_ALERT, "Error in rewinding TaxiRoute: current" << currRoute 
-            << " goal " << route);
-    }
-  } while (currRoute != route);
+    int currPoint;
+    int currRoute;
+    first();
+    do {
+        if (!(next(&currPoint, &currRoute))) {
+            SG_LOG(SG_GENERAL, SG_ALERT,
+                   "Error in rewinding TaxiRoute: current" << currRoute <<
+                   " goal " << route);
+        }
+    } while (currRoute != route);
 }
 
 
@@ -171,67 +171,64 @@ void FGTaxiRoute::rewind(int route)
 /***************************************************************************
  * FGGroundNetwork()
  **************************************************************************/
-bool compare_nodes(FGTaxiNode *a, FGTaxiNode *b) {
-return (*a) < (*b);
+bool compare_nodes(FGTaxiNode * a, FGTaxiNode * b)
+{
+    return (*a) < (*b);
 }
 
-bool compare_segments(FGTaxiSegment *a, FGTaxiSegment *b) {
-return (*a) < (*b);
+bool compare_segments(FGTaxiSegment * a, FGTaxiSegment * b)
+{
+    return (*a) < (*b);
 }
 
 FGGroundNetwork::FGGroundNetwork()
 {
-  hasNetwork = false;
-  foundRoute = false;
-  totalDistance = 0;
-  maxDistance = 0;
-  //maxDepth    = 1000;
-  count       = 0;
-  currTraffic = activeTraffic.begin();
+    hasNetwork = false;
+    foundRoute = false;
+    totalDistance = 0;
+    maxDistance = 0;
+    //maxDepth    = 1000;
+    count = 0;
+    currTraffic = activeTraffic.begin();
 
 }
 
 FGGroundNetwork::~FGGroundNetwork()
 {
-  for (FGTaxiNodeVectorIterator node = nodes.begin();
-       node != nodes.end();
-       node++)
-    {
-      delete (*node);
+    for (FGTaxiNodeVectorIterator node = nodes.begin();
+         node != nodes.end(); node++) {
+        delete(*node);
     }
-  nodes.clear();
-  pushBackNodes.clear();
-  for (FGTaxiSegmentVectorIterator seg = segments.begin();
-       seg != segments.end();
-       seg++)
-    {
-      delete (*seg);
+    nodes.clear();
+    pushBackNodes.clear();
+    for (FGTaxiSegmentVectorIterator seg = segments.begin();
+         seg != segments.end(); seg++) {
+        delete(*seg);
     }
-  segments.clear();
+    segments.clear();
 }
 
-void FGGroundNetwork::addSegment(const FGTaxiSegment &seg)
+void FGGroundNetwork::addSegment(const FGTaxiSegment & seg)
 {
-  segments.push_back(new FGTaxiSegment(seg));
+    segments.push_back(new FGTaxiSegment(seg));
 }
 
-void FGGroundNetwork::addNode(const FGTaxiNode &node)
+void FGGroundNetwork::addNode(const FGTaxiNode & node)
 {
-  nodes.push_back(new FGTaxiNode(node));
+    nodes.push_back(new FGTaxiNode(node));
 }
 
-void FGGroundNetwork::addNodes(FGParkingVec *parkings)
+void FGGroundNetwork::addNodes(FGParkingVec * parkings)
 {
-  FGTaxiNode n;
-  FGParkingVecIterator i = parkings->begin();
-  while (i != parkings->end())
-    {
-      n.setIndex(i->getIndex());
-      n.setLatitude(i->getLatitude());
-      n.setLongitude(i->getLongitude());
-      nodes.push_back(new FGTaxiNode(n));
-
-      i++;
+    FGTaxiNode n;
+    FGParkingVecIterator i = parkings->begin();
+    while (i != parkings->end()) {
+        n.setIndex(i->getIndex());
+        n.setLatitude(i->getLatitude());
+        n.setLongitude(i->getLongitude());
+        nodes.push_back(new FGTaxiNode(n));
+
+        i++;
     }
 }
 
@@ -239,120 +236,117 @@ void FGGroundNetwork::addNodes(FGParkingVec *parkings)
 
 void FGGroundNetwork::init()
 {
-  hasNetwork = true;
-  int index = 1;
-  sort(nodes.begin(), nodes.end(), compare_nodes);
-  //sort(segments.begin(), segments.end(), compare_segments());
-  FGTaxiSegmentVectorIterator i = segments.begin();
-  while(i != segments.end()) {
-    (*i)->setStart(&nodes);
-    (*i)->setEnd  (&nodes);
-    (*i)->setTrackDistance();
-    (*i)->setIndex(index);
-    if ((*i)->isPushBack()) {
-          pushBackNodes.push_back((*i)->getEnd());
-    }
-    //SG_LOG(SG_GENERAL, SG_BULK,  "initializing segment " << (*i)->getIndex() << endl);
-    //SG_LOG(SG_GENERAL, SG_BULK, "Track distance = "     << (*i)->getLength() << endl);
-    //SG_LOG(SG_GENERAL, SG_BULK, "Track runs from "      << (*i)->getStart()->getIndex() << " to "
-    //                                                    << (*i)->getEnd()->getIndex() << endl);
-    i++;
-    index++;
-  }
-  i = segments.begin();
-  while(i != segments.end()) {
-    FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute(); 
-    while (j != (*i)->getEnd()->getEndRoute())
-      {
-       if ((*j)->getEnd()->getIndex() == (*i)->getStart()->getIndex())
-         {
-//         int start1 = (*i)->getStart()->getIndex();
-//         int end1   = (*i)->getEnd()  ->getIndex();
-//         int start2 = (*j)->getStart()->getIndex();
-//         int end2   = (*j)->getEnd()->getIndex();
-//         int oppIndex = (*j)->getIndex();
-           //cerr << "Opposite of  " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") "
-           //   << "happens to be " << oppIndex      << " (" << start2 << "," << end2 << ") " << endl;
-           (*i)->setOpposite(*j);
-           break;
-         }
-         j++;
-      }
-    i++;
-  }
-  //FGTaxiNodeVectorIterator j = nodes.begin();
-  //while (j != nodes.end()) {
-  //    if ((*j)->getHoldPointType() == 3) {
-  //        pushBackNodes.push_back((*j));
-  //    }
-  //    j++;
-  //}
-  //cerr << "Done initializing ground network" << endl;
-  //exit(1);
+    hasNetwork = true;
+    int index = 1;
+    sort(nodes.begin(), nodes.end(), compare_nodes);
+    //sort(segments.begin(), segments.end(), compare_segments());
+    FGTaxiSegmentVectorIterator i = segments.begin();
+    while (i != segments.end()) {
+        (*i)->setStart(&nodes);
+        (*i)->setEnd(&nodes);
+        (*i)->setTrackDistance();
+        (*i)->setIndex(index);
+        if ((*i)->isPushBack()) {
+            pushBackNodes.push_back((*i)->getEnd());
+        }
+        //SG_LOG(SG_GENERAL, SG_BULK,  "initializing segment " << (*i)->getIndex() << endl);
+        //SG_LOG(SG_GENERAL, SG_BULK, "Track distance = "     << (*i)->getLength() << endl);
+        //SG_LOG(SG_GENERAL, SG_BULK, "Track runs from "      << (*i)->getStart()->getIndex() << " to "
+        //                                                    << (*i)->getEnd()->getIndex() << endl);
+        i++;
+        index++;
+    }
+
+    i = segments.begin();
+    while (i != segments.end()) {
+        FGTaxiSegmentVectorIterator j = (*i)->getEnd()->getBeginRoute();
+        while (j != (*i)->getEnd()->getEndRoute()) {
+            if ((*j)->getEnd()->getIndex() == (*i)->getStart()->getIndex()) {
+//          int start1 = (*i)->getStart()->getIndex();
+//          int end1   = (*i)->getEnd()  ->getIndex();
+//          int start2 = (*j)->getStart()->getIndex();
+//          int end2   = (*j)->getEnd()->getIndex();
+//          int oppIndex = (*j)->getIndex();
+                //cerr << "Opposite of  " << (*i)->getIndex() << " (" << start1 << "," << end1 << ") "
+                //   << "happens to be " << oppIndex      << " (" << start2 << "," << end2 << ") " << endl;
+                (*i)->setOpposite(*j);
+                break;
+            }
+            j++;
+        }
+        i++;
+    }
+    //FGTaxiNodeVectorIterator j = nodes.begin();
+    //while (j != nodes.end()) {
+    //    if ((*j)->getHoldPointType() == 3) {
+    //        pushBackNodes.push_back((*j));
+    //    }
+    //    j++;
+    //}
+    //cerr << "Done initializing ground network" << endl;
+    //exit(1);
 }
 
-int FGGroundNetwork::findNearestNode(const SGGeod& aGeod)
+int FGGroundNetwork::findNearestNode(const SGGeod & aGeod)
 {
-  double minDist = HUGE_VAL;
-  int index = -1;
-  
-  for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end(); itr++)
-  {
-    double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
-    if (d < minDist)
-    {
-      minDist = d;
-      index = (*itr)->getIndex();
-      //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+    double minDist = HUGE_VAL;
+    int index = -1;
+
+    for (FGTaxiNodeVectorIterator itr = nodes.begin(); itr != nodes.end();
+         itr++) {
+        double d = SGGeodesy::distanceM(aGeod, (*itr)->getGeod());
+        if (d < minDist) {
+            minDist = d;
+            index = (*itr)->getIndex();
+            //cerr << "Minimum distance of " << minDist << " for index " << index << endl;
+        }
     }
-  }
-  
-  return index;
+
+    return index;
 }
 
 int FGGroundNetwork::findNearestNode(double lat, double lon)
 {
-  return findNearestNode(SGGeod::fromDeg(lon, lat));
+    return findNearestNode(SGGeod::fromDeg(lon, lat));
 }
 
 FGTaxiNode *FGGroundNetwork::findNode(unsigned idx)
-{ /*
-    for (FGTaxiNodeVectorIterator 
-    itr = nodes.begin();
-    itr != nodes.end(); itr++)
-    {
-    if (itr->getIndex() == idx)
-    return itr->getAddress();
-    }*/
-  
-  if ((idx >= 0) && (idx < nodes.size())) 
-    return nodes[idx]->getAddress();
-  else
-    return 0;
+{                               /*
+                                   for (FGTaxiNodeVectorIterator 
+                                   itr = nodes.begin();
+                                   itr != nodes.end(); itr++)
+                                   {
+                                   if (itr->getIndex() == idx)
+                                   return itr->getAddress();
+                                   } */
+
+    if ((idx >= 0) && (idx < nodes.size()))
+        return nodes[idx]->getAddress();
+    else
+        return 0;
 }
 
 FGTaxiSegment *FGGroundNetwork::findSegment(unsigned idx)
-{/*
-  for (FGTaxiSegmentVectorIterator 
-        itr = segments.begin();
-       itr != segments.end(); itr++)
-    {
-      if (itr->getIndex() == idx)
-       return itr->getAddress();
-    } 
- */
-  if ((idx > 0) && (idx <= segments.size()))
-    return segments[idx-1]->getAddress();
-  else
-    {
-      //cerr << "Alert: trying to find invalid segment " << idx << endl;
-      return 0;
+{                               /*
+                                   for (FGTaxiSegmentVectorIterator 
+                                   itr = segments.begin();
+                                   itr != segments.end(); itr++)
+                                   {
+                                   if (itr->getIndex() == idx)
+                                   return itr->getAddress();
+                                   } 
+                                 */
+    if ((idx > 0) && (idx <= segments.size()))
+        return segments[idx - 1]->getAddress();
+    else {
+        //cerr << "Alert: trying to find invalid segment " << idx << endl;
+        return 0;
     }
 }
 
 
-FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, bool fullSearch) 
+FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end,
+                                               bool fullSearch)
 {
 //implements Dijkstra's algorithm to find shortest distance route from start to end
 //taken from http://en.wikipedia.org/wiki/Dijkstra's_algorithm
@@ -362,38 +356,37 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, bool fullSear
     int nParkings = parent->getDynamics()->getNrOfParkings();
     FGTaxiNodeVector *currNodesSet;
     if (fullSearch) {
-         currNodesSet = &nodes;
+        currNodesSet = &nodes;
     } else {
-         currNodesSet = &pushBackNodes;
+        currNodesSet = &pushBackNodes;
     }
 
     for (FGTaxiNodeVectorIterator
-         itr = currNodesSet->begin();
-         itr != currNodesSet->end(); itr++) {
-            (*itr)->setPathScore(HUGE_VAL); //infinity by all practical means
-            (*itr)->setPreviousNode(0); //
-            (*itr)->setPreviousSeg (0); //
-         }
+         itr = currNodesSet->begin(); itr != currNodesSet->end(); itr++) {
+        (*itr)->setPathScore(HUGE_VAL); //infinity by all practical means
+        (*itr)->setPreviousNode(0);     //
+        (*itr)->setPreviousSeg(0);      //
+    }
 
     FGTaxiNode *firstNode = findNode(start);
     firstNode->setPathScore(0);
 
-    FGTaxiNode *lastNode  = findNode(end);
+    FGTaxiNode *lastNode = findNode(end);
 
-    FGTaxiNodeVector unvisited(*currNodesSet); // working copy
+    FGTaxiNodeVector unvisited(*currNodesSet);  // working copy
 
     while (!unvisited.empty()) {
-        FGTaxiNodebest = *(unvisited.begin());
+        FGTaxiNode *best = *(unvisited.begin());
         for (FGTaxiNodeVectorIterator
-             itr = unvisited.begin();
-             itr != unvisited.end(); itr++) {
-                 if ((*itr)->getPathScore() < best->getPathScore())
-                     best = (*itr);
+             itr = unvisited.begin(); itr != unvisited.end(); itr++) {
+            if ((*itr)->getPathScore() < best->getPathScore())
+                best = (*itr);
         }
 
-        FGTaxiNodeVectorIterator newend = remove(unvisited.begin(), unvisited.end(), best);
+        FGTaxiNodeVectorIterator newend =
+            remove(unvisited.begin(), unvisited.end(), best);
         unvisited.erase(newend, unvisited.end());
-        
+
         if (best == lastNode) { // found route or best not connected
             break;
         } else {
@@ -401,15 +394,17 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, bool fullSear
                  seg = best->getBeginRoute();
                  seg != best->getEndRoute(); seg++) {
                 if (fullSearch || (*seg)->isPushBack()) {
-                    FGTaxiNode* tgt = (*seg)->getEnd();
-                    double alt = best->getPathScore() + (*seg)->getLength() + (*seg)->getPenalty(nParkings);
-                    if (alt < tgt->getPathScore()) {              // Relax (u,v)
+                    FGTaxiNode *tgt = (*seg)->getEnd();
+                    double alt =
+                        best->getPathScore() + (*seg)->getLength() +
+                        (*seg)->getPenalty(nParkings);
+                    if (alt < tgt->getPathScore()) {    // Relax (u,v)
                         tgt->setPathScore(alt);
                         tgt->setPreviousNode(best);
-                        tgt->setPreviousSeg(*seg); //
-                   }
+                        tgt->setPreviousSeg(*seg);      //
+                    }
                 } else {
-                //   // cerr << "Skipping TaxiSegment " << (*seg)->getIndex() << endl;
+                    //   // cerr << "Skipping TaxiSegment " << (*seg)->getIndex() << endl;
                 }
             }
         }
@@ -417,17 +412,18 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, bool fullSear
 
     if (lastNode->getPathScore() == HUGE_VAL) {
         // no valid route found
-       if (fullSearch) {
-            SG_LOG( SG_GENERAL, SG_ALERT, "Failed to find route from waypoint " << start << " to " << end << " at " <<
-                    parent->getId());
+        if (fullSearch) {
+            SG_LOG(SG_GENERAL, SG_ALERT,
+                   "Failed to find route from waypoint " << start << " to "
+                   << end << " at " << parent->getId());
         }
-       FGTaxiRoute empty;
-       return empty;
+        FGTaxiRoute empty;
+        return empty;
         //exit(1); //TODO exit more gracefully, no need to stall the whole sim with broken GN's
     } else {
         // assemble route from backtrace information
         intVec nodes, routes;
-        FGTaxiNodebt = lastNode;
+        FGTaxiNode *bt = lastNode;
         while (bt->getPreviousNode() != 0) {
             nodes.push_back(bt->getIndex());
             routes.push_back(bt->getPreviousSegment()->getIndex());
@@ -441,116 +437,151 @@ FGTaxiRoute FGGroundNetwork::findShortestRoute(int start, int end, bool fullSear
     }
 }
 
-int FGTaxiSegment::getPenalty(int nGates) {
-     int penalty = 0;
-     if (end->getIndex() < nGates) {
-         penalty += 10000;
-     }
-     if (end->getIsOnRunway()) { // For now. In future versions, need to find out whether runway is active.
-         penalty += 1000;
-     }
-     return penalty;
+int FGTaxiSegment::getPenalty(int nGates)
+{
+    int penalty = 0;
+    if (end->getIndex() < nGates) {
+        penalty += 10000;
+    }
+    if (end->getIsOnRunway()) { // For now. In future versions, need to find out whether runway is active.
+        penalty += 1000;
+    }
+    return penalty;
 }
 
 /* ATC Related Functions */
 
-void FGGroundNetwork::announcePosition(int id, FGAIFlightPlan *intendedRoute, int currentPosition,
-                                      double lat, double lon, double heading, 
-                                      double speed, double alt, double radius, int leg,
-                                      FGAIAircraft *aircraft)
+void FGGroundNetwork::announcePosition(int id,
+                                       FGAIFlightPlan * intendedRoute,
+                                       int currentPosition, double lat,
+                                       double lon, double heading,
+                                       double speed, double alt,
+                                       double radius, int leg,
+                                       FGAIAircraft * aircraft)
 {
-   TrafficVectorIterator i = activeTraffic.begin();
-   // Search search if the current id alread has an entry
-   // This might be faster using a map instead of a vector, but let's start by taking a safe route
-   if (activeTraffic.size()) {
-     //while ((i->getId() != id) && i != activeTraffic.end()) {
-     while (i != activeTraffic.end()) {
-       if (i->getId() == id) {
-        break;
-       }
-       i++;
-     }
-   }
-   // Add a new TrafficRecord if no one exsists for this aircraft.
-   if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-     FGTrafficRecord rec;
-     rec.setId(id);
-     rec.setPositionAndIntentions(currentPosition, intendedRoute);
-     rec.setPositionAndHeading(lat, lon, heading, speed, alt);
-     rec.setRadius(radius); // only need to do this when creating the record.
-     rec.setAircraft(aircraft);
-     activeTraffic.push_back(rec);
-   } else {
-     i->setPositionAndIntentions(currentPosition, intendedRoute); 
-     i->setPositionAndHeading(lat, lon, heading, speed, alt);
-   }
+    TrafficVectorIterator i = activeTraffic.begin();
+    // Search search if the current id alread has an entry
+    // This might be faster using a map instead of a vector, but let's start by taking a safe route
+    if (activeTraffic.size()) {
+        //while ((i->getId() != id) && i != activeTraffic.end()) {
+        while (i != activeTraffic.end()) {
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
+        }
+    }
+    // Add a new TrafficRecord if no one exsists for this aircraft.
+    if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+        FGTrafficRecord rec;
+        rec.setId(id);
+        rec.setLeg(leg);
+        rec.setPositionAndIntentions(currentPosition, intendedRoute);
+        rec.setPositionAndHeading(lat, lon, heading, speed, alt);
+        rec.setRadius(radius);  // only need to do this when creating the record.
+        rec.setAircraft(aircraft);
+        activeTraffic.push_back(rec);
+    } else {
+        i->setPositionAndIntentions(currentPosition, intendedRoute);
+        i->setPositionAndHeading(lat, lon, heading, speed, alt);
+    }
 }
 
-void FGGroundNetwork::signOff(int id) {
-  TrafficVectorIterator i = activeTraffic.begin();
-   // Search search if the current id alread has an entry
-   // This might be faster using a map instead of a vector, but let's start by taking a safe route
-   if (activeTraffic.size()) {
-     //while ((i->getId() != id) && i != activeTraffic.end()) {
-     while (i != activeTraffic.end()) {
-       if (i->getId() == id) {
-        break;
-       }
-       i++;
-     }
-   }
-   if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-     SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Aircraft without traffic record is signing off");
-   } else {
-       i = activeTraffic.erase(i);
-   }
+void FGGroundNetwork::signOff(int id)
+{
+    TrafficVectorIterator i = activeTraffic.begin();
+    // Search search if the current id alread has an entry
+    // This might be faster using a map instead of a vector, but let's start by taking a safe route
+    if (activeTraffic.size()) {
+        //while ((i->getId() != id) && i != activeTraffic.end()) {
+        while (i != activeTraffic.end()) {
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
+        }
+    }
+    if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "AI error: Aircraft without traffic record is signing off");
+    } else {
+        i = activeTraffic.erase(i);
+    }
 }
 
-void FGGroundNetwork::update(int id, double lat, double lon, double heading, double speed, double alt, 
-                            double dt) {
-   // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to 
-   // Transmit air-to-ground "Ready to taxi request:
-   // Transmit ground to air approval / hold
-   // Transmit confirmation ... 
-   // Probably use a status mechanism similar to the Engine start procedure in the startup controller.
-
-
-   TrafficVectorIterator i = activeTraffic.begin();
-   // Search search if the current id has an entry
-   // This might be faster using a map instead of a vector, but let's start by taking a safe route
-   TrafficVectorIterator current, closest;
-   if (activeTraffic.size()) {
-     //while ((i->getId() != id) && i != activeTraffic.end()) {
-     while (i != activeTraffic.end()) {
-       if (i->getId() == id) {
-        break;
-       }
-       i++;
-     }
-   }
-   // update position of the current aircraft
-   if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-     SG_LOG(SG_GENERAL, SG_ALERT, "AI error: updating aircraft without traffic record");
-   } else {
-     i->setPositionAndHeading(lat, lon, heading, speed, alt);
-     current = i;
-   }
-  
-   setDt(getDt() + dt);
-  
-   // Update every three secs, but add some randomness
-   // to prevent all IA objects doing this in synchrony
-   //if (getDt() < (3.0) + (rand() % 10))
-   //  return;
-   //else
-   //  setDt(0);
-   current->clearResolveCircularWait();
-   current->setWaitsForId(0);
-   checkSpeedAdjustment(id, lat, lon, heading, speed, alt);
-   checkHoldPosition   (id, lat, lon, heading, speed, alt);
-   if (checkForCircularWaits(id)) {
-       i->setResolveCircularWait();
-   }
+void FGGroundNetwork::update(int id, double lat, double lon,
+                             double heading, double speed, double alt,
+                             double dt)
+{
+    // Check whether aircraft are on hold due to a preceding pushback. If so, make sure to 
+    // Transmit air-to-ground "Ready to taxi request:
+    // Transmit ground to air approval / hold
+    // Transmit confirmation ... 
+    // Probably use a status mechanism similar to the Engine start procedure in the startup controller.
+
+
+    TrafficVectorIterator i = activeTraffic.begin();
+    // Search search if the current id has an entry
+    // This might be faster using a map instead of a vector, but let's start by taking a safe route
+    TrafficVectorIterator current, closest;
+    if (activeTraffic.size()) {
+        //while ((i->getId() != id) && i != activeTraffic.end()) {
+        while (i != activeTraffic.end()) {
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
+        }
+    }
+    // update position of the current aircraft
+    if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "AI error: updating aircraft without traffic record");
+    } else {
+        i->setPositionAndHeading(lat, lon, heading, speed, alt);
+        current = i;
+    }
+
+    setDt(getDt() + dt);
+
+    // Update every three secs, but add some randomness
+    // to prevent all IA objects doing this in synchrony
+    //if (getDt() < (3.0) + (rand() % 10))
+    //  return;
+    //else
+    //  setDt(0);
+    current->clearResolveCircularWait();
+    current->setWaitsForId(0);
+    checkSpeedAdjustment(id, lat, lon, heading, speed, alt);
+    checkHoldPosition(id, lat, lon, heading, speed, alt);
+    if (checkForCircularWaits(id)) {
+        i->setResolveCircularWait();
+    }
+    bool needsTaxiClearance = current->getAircraft()->getTaxiClearanceRequest();
+    int state = current->getState();
+    time_t now = time(NULL) + fgGetLong("/sim/time/warp");
+    if ((now - lastTransmission) > 15) {
+        available = true;
+    }
+    if (needsTaxiClearance && available) {
+         transmit(&(*current), MSG_REQUEST_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
+         current->getAircraft()->setTaxiClearanceRequest(false);
+         current->setState(3);
+         lastTransmission = now;
+         available = false;
+    }
+    if ((state == 3) && available) {
+         transmit(&(*current), MSG_ISSUE_TAXI_CLEARANCE, ATC_GROUND_TO_AIR);
+         current->setState(4);
+         lastTransmission = now;
+         available = false;
+    }
+    if ((state == 4) && available) {
+         transmit(&(*current), MSG_ACKNOWLEDGE_TAXI_CLEARANCE, ATC_AIR_TO_GROUND);
+         current->setState(0);
+         lastTransmission = now;
+         available = false;
+    }
 }
 
 /**
@@ -567,129 +598,123 @@ void FGGroundNetwork::update(int id, double lat, double lon, double heading, dou
    not addressed yet, but should be.
 */
 
-void FGGroundNetwork::checkSpeedAdjustment(int id, double lat, 
-                                          double lon, double heading, 
-                                          double speed, double alt)
+void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
+                                           double lon, double heading,
+                                           double speed, double alt)
 {
-  
-  TrafficVectorIterator current, closest;
-  TrafficVectorIterator i = activeTraffic.begin();
-  bool otherReasonToSlowDown = false;
-  bool previousInstruction;
-  if (activeTraffic.size()) 
-    {
-      //while ((i->getId() != id) && (i != activeTraffic.end()))
-      while (i != activeTraffic.end()) {
-       if (i->getId() == id) {
-         break;
-       }
-       i++;
-      }
-    }
-  else
-    {
-      return;
-    }
-  if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-    SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment");
-  }
-  current = i;
-  //closest = current;
-  
-  previousInstruction = current->getSpeedAdjustment();
-  double mindist = HUGE_VAL;
-  if (activeTraffic.size()) 
-    {
-      double course, dist, bearing, minbearing, az2;
-      SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
-      //TrafficVector iterator closest;
-      closest = current;
-      for (TrafficVectorIterator i = activeTraffic.begin(); 
-          i != activeTraffic.end(); i++)
-       {
-         if (i == current) {
-        continue;
-      }
-      
-        SGGeod other(SGGeod::fromDegM(i->getLongitude(),
-          i->getLatitude(), i->getAltitude()));
-        SGGeodesy::inverse(curr, other, course, az2, dist);
-        bearing = fabs(heading-course);
-           if (bearing > 180)
-             bearing = 360-bearing;
-           if ((dist < mindist) && (bearing < 60.0))
-             {
-               mindist = dist;
-               closest = i;
-               minbearing = bearing;
-             }
-       }
-      //Check traffic at the tower controller
-      if (towerController->hasActiveTraffic())
-       {
-         for (TrafficVectorIterator i = towerController->getActiveTraffic().begin(); 
-              i != towerController->getActiveTraffic().end(); i++)
-           {
-             //cerr << "Comparing " << current->getId() << " and " << i->getId() << endl;
-             SGGeod other(SGGeod::fromDegM(i->getLongitude(),
-                                            i->getLatitude(), 
-                                            i->getAltitude()));
-        SGGeodesy::inverse(curr, other, course, az2, dist);
-        bearing = fabs(heading-course);
-             if (bearing > 180)
-          bearing = 360-bearing;
-             if ((dist < mindist) && (bearing < 60.0))
-               {
-                 mindist = dist;
-                 closest = i;
-                 minbearing = bearing;
-                 otherReasonToSlowDown = true;
-               }
-           }
-       }
-      // Finally, check UserPosition
-      double userLatitude  = fgGetDouble("/position/latitude-deg");
-      double userLongitude = fgGetDouble("/position/longitude-deg");
-      SGGeod user(SGGeod::fromDeg(userLongitude,userLatitude));
-      SGGeodesy::inverse(curr, user, course, az2, dist);
-
-      bearing = fabs(heading-course);
-      if (bearing > 180)
-      bearing = 360-bearing;
-      if ((dist < mindist) && (bearing < 60.0))
-       {
-         mindist = dist;
-         //closest = i;
-         minbearing = bearing;
-         otherReasonToSlowDown = true;
-       }
-
-      current->clearSpeedAdjustment();
-    
-      if (current->checkPositionAndIntentions(*closest) || otherReasonToSlowDown) 
-       {
-          double maxAllowableDistance = (1.1*current->getRadius()) + (1.1*closest->getRadius());
-          if (mindist < 2*maxAllowableDistance)
-            {
-              if (current->getId() == closest->getWaitsForId())
-                return;
-              else 
-                current->setWaitsForId(closest->getId());
-              if (closest->getId() != current->getId())
-                current->setSpeedAdjustment(closest->getSpeed()* (mindist/100));
-              else
-                current->setSpeedAdjustment(0); // This can only happen when the user aircraft is the one closest
-              if (mindist < maxAllowableDistance)
-                {
-                  //double newSpeed = (maxAllowableDistance-mindist);
-                  //current->setSpeedAdjustment(newSpeed);
-                  //if (mindist < 0.5* maxAllowableDistance)
-                  //  {
-                      current->setSpeedAdjustment(0);
-                      //  }
-                }
-            }
-       }
+
+    TrafficVectorIterator current, closest;
+    TrafficVectorIterator i = activeTraffic.begin();
+    bool otherReasonToSlowDown = false;
+    bool previousInstruction;
+    if (activeTraffic.size()) {
+        //while ((i->getId() != id) && (i != activeTraffic.end()))
+        while (i != activeTraffic.end()) {
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
+        }
+    } else {
+        return;
+    }
+    if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkSpeedAdjustment");
+    }
+    current = i;
+    //closest = current;
+
+    previousInstruction = current->getSpeedAdjustment();
+    double mindist = HUGE_VAL;
+    if (activeTraffic.size()) {
+        double course, dist, bearing, minbearing, az2;
+        SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+        //TrafficVector iterator closest;
+        closest = current;
+        for (TrafficVectorIterator i = activeTraffic.begin();
+             i != activeTraffic.end(); i++) {
+            if (i == current) {
+                continue;
+            }
+
+            SGGeod other(SGGeod::fromDegM(i->getLongitude(),
+                                          i->getLatitude(),
+                                          i->getAltitude()));
+            SGGeodesy::inverse(curr, other, course, az2, dist);
+            bearing = fabs(heading - course);
+            if (bearing > 180)
+                bearing = 360 - bearing;
+            if ((dist < mindist) && (bearing < 60.0)) {
+                mindist = dist;
+                closest = i;
+                minbearing = bearing;
+            }
+        }
+        //Check traffic at the tower controller
+        if (towerController->hasActiveTraffic()) {
+            for (TrafficVectorIterator i =
+                 towerController->getActiveTraffic().begin();
+                 i != towerController->getActiveTraffic().end(); i++) {
+                //cerr << "Comparing " << current->getId() << " and " << i->getId() << endl;
+                SGGeod other(SGGeod::fromDegM(i->getLongitude(),
+                                              i->getLatitude(),
+                                              i->getAltitude()));
+                SGGeodesy::inverse(curr, other, course, az2, dist);
+                bearing = fabs(heading - course);
+                if (bearing > 180)
+                    bearing = 360 - bearing;
+                if ((dist < mindist) && (bearing < 60.0)) {
+                    mindist = dist;
+                    closest = i;
+                    minbearing = bearing;
+                    otherReasonToSlowDown = true;
+                }
+            }
+        }
+        // Finally, check UserPosition
+        double userLatitude = fgGetDouble("/position/latitude-deg");
+        double userLongitude = fgGetDouble("/position/longitude-deg");
+        SGGeod user(SGGeod::fromDeg(userLongitude, userLatitude));
+        SGGeodesy::inverse(curr, user, course, az2, dist);
+
+        bearing = fabs(heading - course);
+        if (bearing > 180)
+            bearing = 360 - bearing;
+        if ((dist < mindist) && (bearing < 60.0)) {
+            mindist = dist;
+            //closest = i;
+            minbearing = bearing;
+            otherReasonToSlowDown = true;
+        }
+
+        current->clearSpeedAdjustment();
+
+        if (current->checkPositionAndIntentions(*closest)
+            || otherReasonToSlowDown) {
+            double maxAllowableDistance =
+                (1.1 * current->getRadius()) +
+                (1.1 * closest->getRadius());
+            if (mindist < 2 * maxAllowableDistance) {
+                if (current->getId() == closest->getWaitsForId())
+                    return;
+                else
+                    current->setWaitsForId(closest->getId());
+                if (closest->getId() != current->getId())
+                    current->setSpeedAdjustment(closest->getSpeed() *
+                                                (mindist / 100));
+                else
+                    current->setSpeedAdjustment(0);     // This can only happen when the user aircraft is the one closest
+                if (mindist < maxAllowableDistance) {
+                    //double newSpeed = (maxAllowableDistance-mindist);
+                    //current->setSpeedAdjustment(newSpeed);
+                    //if (mindist < 0.5* maxAllowableDistance)
+                    //  {
+                    current->setSpeedAdjustment(0);
+                    //  }
+                }
+            }
+        }
     }
 }
 
@@ -701,114 +726,146 @@ void FGGroundNetwork::checkSpeedAdjustment(int id, double lat,
    3) For crossing or merging taxiroutes.
 */
 
-void FGGroundNetwork::checkHoldPosition(int id, double lat, 
-                                       double lon, double heading, 
-                                       double speed, double alt)
+void FGGroundNetwork::checkHoldPosition(int id, double lat,
+                                        double lon, double heading,
+                                        double speed, double alt)
 {
-  
-  TrafficVectorIterator current;
-  TrafficVectorIterator i = activeTraffic.begin();
-  if (activeTraffic.size()) 
-    {
-      //while ((i->getId() != id) && i != activeTraffic.end()) 
-      while (i != activeTraffic.end()) {
-       if (i->getId() == id) {
-         break;
-       }
-       i++;
-      }
-    }
-  else
-    {
-      return ;
-    } 
-  if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-    SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition");
-  }
-  current = i;
-  current->setHoldPosition(false);
-  SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
-  
-  for (i = activeTraffic.begin(); 
-       i != activeTraffic.end(); i++)
-    {
-      if (i->getId() != current->getId()) 
-       {
-         int node = current->crosses(this, *i);
-         if (node != -1)
-           {
-          FGTaxiNode* taxiNode = findNode(node);
-          
-             // Determine whether it's save to continue or not. 
-             // If we have a crossing route, there are two possibilities:
-             // 1) This is an interestion
-             // 2) This is oncoming two-way traffic, using the same taxiway.
-             //cerr << "Hold check 1 : " << id << " has common node " << node << endl;
-            
-        SGGeod other(SGGeod::fromDegM(i->getLongitude(), i->getLatitude(), i->getAltitude()));
-        bool needsToWait;
-             bool opposing;
-             if (current->isOpposing(this, *i, node))
-               {
-                 needsToWait = true;
-                 opposing    = true;
-                 //cerr << "Hold check 2 : " << node << "  has opposing segment " << endl;
-                 // issue a "Hold Position" as soon as we're close to the offending node
-                 // For now, I'm doing this as long as the other aircraft doesn't
-                 // have a hold instruction as soon as we're within a reasonable 
-                 // distance from the offending node.
-                 // This may be a bit of a conservative estimate though, as it may
-                 // be well possible that both aircraft can both continue to taxi 
-                 // without crashing into each other.
-               } 
-             else 
-               {
-                 opposing = false;
-                 if (SGGeodesy::distanceM(other, taxiNode->getGeod()) > 200) // 2.0*i->getRadius())
-                   {
-                     needsToWait = false; 
-                     //cerr << "Hold check 3 : " << id <<"  Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue " 
-                     //           << endl;
-                   }
-                 else 
-                   {
-                     needsToWait = true;
-                     //cerr << "Hold check 4: " << id << "  Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
-                   }
-               }
-      
-      double dist = SGGeodesy::distanceM(curr, taxiNode->getGeod());
-      if (!(i->hasHoldPosition()))
-               {
-                 
-                 if ((dist < 200) && //2.5*current->getRadius()) && 
-                     (needsToWait) &&
-                     (i->onRoute(this, *current)) &&
-                     //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
-                     (!(current->getId() == i->getWaitsForId())))
-                     //(!(i->getSpeedAdjustment()))) // &&
-                     //(!(current->getSpeedAdjustment())))
-                   
-                   {
-                     current->setHoldPosition(true);
-                     current->setWaitsForId(i->getId());
-                     //cerr << "Hold check 5: " << current->getCallSign() <<"  Setting Hold Position: distance to node ("  << node << ") "
-                     //           << dist << " meters. Waiting for " << i->getCallSign();
-                     //if (opposing)
-                     //cerr <<" [opposing] " << endl;
-                     //else
-                     //        cerr << "[non-opposing] " << endl;
-                     //if (i->hasSpeefAdjustment())
-                     //        {
-                     //          cerr << " (which in turn waits for ) " << i->
-                   }
-                 else
-                   {
-                     //cerr << "Hold check 6: " << id << "  No need to hold yet: Distance to node : " << dist << " nm"<< endl;
-                   }
-               }
-           }
-       }
+    TrafficVectorIterator current;
+    TrafficVectorIterator i = activeTraffic.begin();
+    if (activeTraffic.size()) {
+        //while ((i->getId() != id) && i != activeTraffic.end()) 
+        while (i != activeTraffic.end()) {
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
+        }
+    } else {
+        return;
+    }
+    if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkHoldPosition");
+    }
+    current = i;
+    bool origStatus = current->hasHoldPosition();
+    current->setHoldPosition(false);
+    SGGeod curr(SGGeod::fromDegM(lon, lat, alt));
+
+    for (i = activeTraffic.begin(); i != activeTraffic.end(); i++) {
+        if (i->getId() != current->getId()) {
+            int node = current->crosses(this, *i);
+            if (node != -1) {
+                FGTaxiNode *taxiNode = findNode(node);
+
+                // Determine whether it's save to continue or not. 
+                // If we have a crossing route, there are two possibilities:
+                // 1) This is an interestion
+                // 2) This is oncoming two-way traffic, using the same taxiway.
+                //cerr << "Hold check 1 : " << id << " has common node " << node << endl;
+
+                SGGeod other(SGGeod::
+                             fromDegM(i->getLongitude(), i->getLatitude(),
+                                      i->getAltitude()));
+                bool needsToWait;
+                bool opposing;
+                if (current->isOpposing(this, *i, node)) {
+                    needsToWait = true;
+                    opposing = true;
+                    //cerr << "Hold check 2 : " << node << "  has opposing segment " << endl;
+                    // issue a "Hold Position" as soon as we're close to the offending node
+                    // For now, I'm doing this as long as the other aircraft doesn't
+                    // have a hold instruction as soon as we're within a reasonable 
+                    // distance from the offending node.
+                    // This may be a bit of a conservative estimate though, as it may
+                    // be well possible that both aircraft can both continue to taxi 
+                    // without crashing into each other.
+                } else {
+                    opposing = false;
+                    if (SGGeodesy::distanceM(other, taxiNode->getGeod()) > 200) // 2.0*i->getRadius())
+                    {
+                        needsToWait = false;
+                        //cerr << "Hold check 3 : " << id <<"  Other aircraft approaching node is still far away. (" << dist << " nm). Can safely continue " 
+                        //           << endl;
+                    } else {
+                        needsToWait = true;
+                        //cerr << "Hold check 4: " << id << "  Would need to wait for other aircraft : distance = " << dist << " meters" << endl;
+                    }
+                }
+
+                double dist =
+                    SGGeodesy::distanceM(curr, taxiNode->getGeod());
+                if (!(i->hasHoldPosition())) {
+
+                    if ((dist < 200) && //2.5*current->getRadius()) && 
+                        (needsToWait) && (i->onRoute(this, *current)) &&
+                        //((i->onRoute(this, *current)) || ((!(i->getSpeedAdjustment())))) &&
+                        (!(current->getId() == i->getWaitsForId())))
+                        //(!(i->getSpeedAdjustment()))) // &&
+                        //(!(current->getSpeedAdjustment())))
+
+                    {
+                        current->setHoldPosition(true);
+                        current->setWaitsForId(i->getId());
+                        //cerr << "Hold check 5: " << current->getCallSign() <<"  Setting Hold Position: distance to node ("  << node << ") "
+                        //           << dist << " meters. Waiting for " << i->getCallSign();
+                        //if (opposing)
+                        //cerr <<" [opposing] " << endl;
+                        //else
+                        //        cerr << "[non-opposing] " << endl;
+                        //if (i->hasSpeefAdjustment())
+                        //        {
+                        //          cerr << " (which in turn waits for ) " << i->
+                    } else {
+                        //cerr << "Hold check 6: " << id << "  No need to hold yet: Distance to node : " << dist << " nm"<< endl;
+                    }
+                }
+            }
+        }
+    }
+    bool currStatus = current->hasHoldPosition();
+
+    // Either a Hold Position or a resume taxi transmission has been issued
+    time_t now = time(NULL) + fgGetLong("/sim/time/warp");
+    if ((now - lastTransmission) > 2) {
+        available = true;
+    }
+    if ((origStatus != currStatus) && available) {
+        //cerr << "Issueing hold short instrudtion " << currStatus << " " << available << endl;
+        if (currStatus == true) { // No has a hold short instruction
+           transmit(&(*current), MSG_HOLD_POSITION, ATC_GROUND_TO_AIR);
+           //cerr << "Transmittin hold short instrudtion " << currStatus << " " << available << endl;
+           current->setState(1);
+        } else {
+           transmit(&(*current), MSG_RESUME_TAXI, ATC_GROUND_TO_AIR);
+           //cerr << "Transmittig resume instrudtion " << currStatus << " " << available << endl;
+           current->setState(2);
+        }
+        lastTransmission = now;
+        available = false;
+        // Don't act on the changed instruction until the transmission is confirmed
+        // So set back to original status
+        current->setHoldPosition(origStatus);
+        //cerr << "Current state " << current->getState() << endl;
+    } else {
+    }
+    int state = current->getState();
+    if ((state == 1) && (available)) {
+        //cerr << "ACKNOWLEDGE HOLD" << endl;
+        transmit(&(*current), MSG_ACKNOWLEDGE_HOLD_POSITION, ATC_AIR_TO_GROUND);
+        current->setState(0);
+        current->setHoldPosition(true);
+        lastTransmission = now;
+        available = false;
+
+    }
+    if ((state == 2) && (available)) {
+        //cerr << "ACKNOWLEDGE RESUME" << endl;
+        transmit(&(*current), MSG_ACKNOWLEDGE_RESUME_TAXI, ATC_AIR_TO_GROUND);
+        current->setState(0);
+        current->setHoldPosition(false);
+        lastTransmission = now;
+        available = false;
     }
 }
 
@@ -827,142 +884,142 @@ void FGGroundNetwork::checkHoldPosition(int id, double lat,
  */
 
 bool FGGroundNetwork::checkForCircularWaits(int id)
-{  
-   //cerr << "Performing Wait check " << id << endl;
-   int target = 0;
-   TrafficVectorIterator current, other;
-   TrafficVectorIterator i = activeTraffic.begin();
-   int trafficSize = activeTraffic.size();
-   if (trafficSize)  {
+{
+    //cerr << "Performing Wait check " << id << endl;
+    int target = 0;
+    TrafficVectorIterator current, other;
+    TrafficVectorIterator i = activeTraffic.begin();
+    int trafficSize = activeTraffic.size();
+    if (trafficSize) {
         while (i != activeTraffic.end()) {
-        if (i->getId() == id) {
-           break;
-       }
-       i++;
-    }
-  }
-  else {
-      return false;
-  }
-  if (i == activeTraffic.end() || (trafficSize == 0)) {
-    SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
-  }
-   
-   current = i;
-   target = current->getWaitsForId();
-   //bool printed = false; // Note that this variable is for debugging purposes only.
-   int counter = 0;
-
-   if (id == target) {
-       //cerr << "aircraft waits for user" << endl;
-       return false;
-   }
-
-
-   while ((target > 0) && (target != id) && counter++ < trafficSize) {
-    //printed = true;
-     TrafficVectorIterator i = activeTraffic.begin();
-     if (trafficSize)  {
-          //while ((i->getId() != id) && i != activeTraffic.end()) 
-          while (i != activeTraffic.end()) {
-          if (i->getId() == target) {
-             break;
-         }
-         i++;
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
         }
-      }
-      else {
+    } else {
         return false;
-    } 
+    }
     if (i == activeTraffic.end() || (trafficSize == 0)) {
-       //cerr << "[Waiting for traffic at Runway: DONE] " << endl << endl;;
-      // The target id is not found on the current network, which means it's at the tower
-      //SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
-      return false;
-    }
-    other = i;
-    target = other->getWaitsForId();
-
-    // actually this trap isn't as impossible as it first seemed:
-    // the setWaitsForID(id) is set to current when the aircraft
-    // is waiting for the user controlled aircraft. 
-    //if (current->getId() == other->getId()) {
-    //    cerr << "Caught the impossible trap" << endl;
-    //    cerr << "Current = " << current->getId() << endl;
-    //    cerr << "Other   = " << other  ->getId() << endl;
-    //    for (TrafficVectorIterator at = activeTraffic.begin();
-    //          at != activeTraffic.end();
-    //          at++) {
-    //        cerr << "currently active aircraft : " << at->getCallSign() << " with Id " << at->getId() << " waits for " << at->getWaitsForId() << endl;
-    //    }
-    //    exit(1);
-    if (current->getId() == other->getId())
-       return false;
-    //}
-    //cerr << current->getCallSign() << " (" << current->getId()  << ") " << " -> " << other->getCallSign() 
-    //     << " (" << other->getId()  << "); " << endl;;
-    //current = other;
-   }
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
+    }
+
+    current = i;
+    target = current->getWaitsForId();
+    //bool printed = false; // Note that this variable is for debugging purposes only.
+    int counter = 0;
+
+    if (id == target) {
+        //cerr << "aircraft waits for user" << endl;
+        return false;
+    }
+
+
+    while ((target > 0) && (target != id) && counter++ < trafficSize) {
+        //printed = true;
+        TrafficVectorIterator i = activeTraffic.begin();
+        if (trafficSize) {
+            //while ((i->getId() != id) && i != activeTraffic.end()) 
+            while (i != activeTraffic.end()) {
+                if (i->getId() == target) {
+                    break;
+                }
+                i++;
+            }
+        } else {
+            return false;
+        }
+        if (i == activeTraffic.end() || (trafficSize == 0)) {
+            //cerr << "[Waiting for traffic at Runway: DONE] " << endl << endl;;
+            // The target id is not found on the current network, which means it's at the tower
+            //SG_LOG(SG_GENERAL, SG_ALERT, "AI error: Trying to access non-existing aircraft in FGGroundNetwork::checkForCircularWaits");
+            return false;
+        }
+        other = i;
+        target = other->getWaitsForId();
+
+        // actually this trap isn't as impossible as it first seemed:
+        // the setWaitsForID(id) is set to current when the aircraft
+        // is waiting for the user controlled aircraft. 
+        //if (current->getId() == other->getId()) {
+        //    cerr << "Caught the impossible trap" << endl;
+        //    cerr << "Current = " << current->getId() << endl;
+        //    cerr << "Other   = " << other  ->getId() << endl;
+        //    for (TrafficVectorIterator at = activeTraffic.begin();
+        //          at != activeTraffic.end();
+        //          at++) {
+        //        cerr << "currently active aircraft : " << at->getCallSign() << " with Id " << at->getId() << " waits for " << at->getWaitsForId() << endl;
+        //    }
+        //    exit(1);
+        if (current->getId() == other->getId())
+            return false;
+        //}
+        //cerr << current->getCallSign() << " (" << current->getId()  << ") " << " -> " << other->getCallSign() 
+        //     << " (" << other->getId()  << "); " << endl;;
+        //current = other;
+    }
 
 
 
 
 
 
-   //if (printed)
-   //   cerr << "[done] " << endl << endl;;
-   if (id == target) {
-       SG_LOG(SG_GENERAL, SG_WARN, "Detected circular wait condition: Id = " << id << "target = " << target);
-       return true;
-   } else {
-   return false;
-   }
+    //if (printed)
+    //   cerr << "[done] " << endl << endl;;
+    if (id == target) {
+        SG_LOG(SG_GENERAL, SG_WARN,
+               "Detected circular wait condition: Id = " << id <<
+               "target = " << target);
+        return true;
+    } else {
+        return false;
+    }
 }
 
 // Note that this function is probably obsolete...
 bool FGGroundNetwork::hasInstruction(int id)
 {
     TrafficVectorIterator i = activeTraffic.begin();
-   // Search search if the current id has an entry
-   // This might be faster using a map instead of a vector, but let's start by taking a safe route
-   if (activeTraffic.size()) 
-     {
-       //while ((i->getId() != id) && i != activeTraffic.end()) {
-       while (i != activeTraffic.end()) {
-        if (i->getId() == id) {
-          break;
-        }
-        i++;
-       }
-     }
-   if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-     SG_LOG(SG_GENERAL, SG_ALERT, "AI error: checking ATC instruction for aircraft without traffic record");
-   } else {
-     return i->hasInstruction();
-   }
-  return false;
+    // Search search if the current id has an entry
+    // This might be faster using a map instead of a vector, but let's start by taking a safe route
+    if (activeTraffic.size()) {
+        //while ((i->getId() != id) && i != activeTraffic.end()) {
+        while (i != activeTraffic.end()) {
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
+        }
+    }
+    if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "AI error: checking ATC instruction for aircraft without traffic record");
+    } else {
+        return i->hasInstruction();
+    }
+    return false;
 }
 
 FGATCInstruction FGGroundNetwork::getInstruction(int id)
 {
-  TrafficVectorIterator i = activeTraffic.begin();
-  // Search search if the current id has an entry
-   // This might be faster using a map instead of a vector, but let's start by taking a safe route
-   if (activeTraffic.size()) {
-     //while ((i->getId() != id) && i != activeTraffic.end()) {
-     while (i != activeTraffic.end()) {
-       if (i->getId() == id) {
-        break;
-       }
-       i++;
-     }
-   }
-   if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
-     SG_LOG(SG_GENERAL, SG_ALERT, "AI error: requesting ATC instruction for aircraft without traffic record");
-   } else {
-     return i->getInstruction();
-   }
-  return FGATCInstruction();
+    TrafficVectorIterator i = activeTraffic.begin();
+    // Search search if the current id has an entry
+    // This might be faster using a map instead of a vector, but let's start by taking a safe route
+    if (activeTraffic.size()) {
+        //while ((i->getId() != id) && i != activeTraffic.end()) {
+        while (i != activeTraffic.end()) {
+            if (i->getId() == id) {
+                break;
+            }
+            i++;
+        }
+    }
+    if (i == activeTraffic.end() || (activeTraffic.size() == 0)) {
+        SG_LOG(SG_GENERAL, SG_ALERT,
+               "AI error: requesting ATC instruction for aircraft without traffic record");
+    } else {
+        return i->getInstruction();
+    }
+    return FGATCInstruction();
 }
-
-
index 733cede9e4ca116207f25d54fbb970f51a0a22ff..fe83d4df25cd51b4db5e2b4fcac2001b9836628d 100644 (file)
@@ -252,10 +252,10 @@ public:
   void init();
   bool exists() { return hasNetwork; };
   void setTowerController(FGTowerController *twrCtrlr) { towerController = twrCtrlr; };
-  
+
   int findNearestNode(double lat, double lon);
   int findNearestNode(const SGGeod& aGeod);
-  
+
   FGTaxiNode *findNode(unsigned idx);
   FGTaxiSegment *findSegment(unsigned idx);
   FGTaxiRoute findShortestRoute(int start, int end, bool fullSearch=true);
index af715ac3552b98a791d8486f522b98968be44ae7..8337d31f9fad3e60c7c8ea5430536fa4fe8bed47 100644 (file)
@@ -225,7 +225,13 @@ void RunwayGroup::setActive(const FGAirport* airport,
          validSelection = true;
          for (int j = 0; j < activeRwys; j++)
     {
-            rwy = airport->getRunwayByIdent(rwyList[j].getRwyList(i));
+      string ident(rwyList[j].getRwyList(i));
+      if (!airport->hasRunwayWithIdent(ident)) {
+        SG_LOG(SG_GENERAL, SG_WARN, "no such runway:" << ident << " at " << airport->ident());
+        continue;
+      }
+      
+            rwy = airport->getRunwayByIdent(ident);
        
                          //cerr << "Succes" << endl;
                  hdgDiff = fabs(windHeading - rwy->headingDeg());
index 2a3349ad8cad64da9d8c2a603093a7497e70a48d..fe51f37b126023009edb8514ab1685e344e27b15 100644 (file)
@@ -40,6 +40,8 @@
 using std::cout;
 using std::endl;
 
+using simgear::PropertyList;
+
 FGPeriodicalValue::FGPeriodicalValue( SGPropertyNode_ptr root )
 {
   SGPropertyNode_ptr minNode = root->getChild( "min" );
@@ -1003,13 +1005,13 @@ void FGXMLAutopilotGroup::reinit()
 
 void FGXMLAutopilotGroup::init()
 {
-    vector<SGPropertyNode_ptr> autopilotNodes = fgGetNode( "/sim/systems", true )->getChildren("autopilot");
+    PropertyList autopilotNodes = fgGetNode( "/sim/systems", true )->getChildren("autopilot");
     if( autopilotNodes.size() == 0 ) {
         SG_LOG( SG_ALL, SG_WARN, "No autopilot configuration specified for this model!");
         return;
     }
 
-    for( vector<SGPropertyNode_ptr>::size_type i = 0; i < autopilotNodes.size(); i++ ) {
+    for( PropertyList::size_type i = 0; i < autopilotNodes.size(); i++ ) {
         SGPropertyNode_ptr pathNode = autopilotNodes[i]->getNode( "path" );
         if( pathNode == NULL ) {
             SG_LOG( SG_ALL, SG_WARN, "No autopilot configuration file specified for this autopilot!");
index d3b5fa34ea2daf32bd83c181d389c68cb1141bb7..a29d49e236b827f86030bc01e1cb200d694ccced 100644 (file)
@@ -122,7 +122,7 @@ class FGXMLAutoInputList : public std::vector<FGXMLAutoInput_ptr> {
 class FGXMLAutoComponent : public SGReferenced {
 
 private:
-    std::vector <SGPropertyNode_ptr> output_list;
+    simgear::PropertyList output_list;
 
     SGSharedPtr<const SGCondition> _condition;
     SGPropertyNode_ptr enable_prop;
@@ -201,7 +201,8 @@ public:
         // helpful for things like flight directors which position
         // their vbars from the autopilot computations.
         if ( honor_passive && passive_mode->getBoolValue() ) return;
-        for( std::vector <SGPropertyNode_ptr>::iterator it = output_list.begin(); it != output_list.end(); ++it)
+        for( simgear::PropertyList::iterator it = output_list.begin();
+             it != output_list.end(); ++it)
           (*it)->setDoubleValue( clamp( value ) );
     }
 
@@ -212,7 +213,8 @@ public:
         // helpful for things like flight directors which position
         // their vbars from the autopilot computations.
         if ( honor_passive && passive_mode->getBoolValue() ) return;
-        for( std::vector <SGPropertyNode_ptr>::iterator it = output_list.begin(); it != output_list.end(); ++it)
+        for( simgear::PropertyList::iterator it = output_list.begin();
+             it != output_list.end(); ++it)
           (*it)->setBoolValue( value ); // don't use clamp here, bool is clamped anyway
     }
 
index 212e51d856aed4fa286ea947c63ffcd5d6e21eb3..9a5755e3db3d7f8cabeaa89a739547c8b28fb71f 100644 (file)
@@ -140,6 +140,7 @@ void FGEnvironment::_init()
     wind_from_down_fps = 0;
     thermal_lift_fps = 0;
     ridge_lift_fps= 0;
+    local_weather_lift_fps=0;
     altitude_half_to_sun_m = 1000;
     altitude_tropo_top_m = 10000;
 #ifdef USING_TABLES
@@ -182,6 +183,7 @@ FGEnvironment::copy (const FGEnvironment &env)
     wind_from_down_fps = env.wind_from_down_fps;
     thermal_lift_fps = env.thermal_lift_fps;
     ridge_lift_fps= env.ridge_lift_fps;
+    local_weather_lift_fps = env.local_weather_lift_fps;
     turbulence_magnitude_norm = env.turbulence_magnitude_norm;
     turbulence_rate_hz = env.turbulence_rate_hz;
 }
@@ -238,6 +240,7 @@ FGEnvironment::read (const SGPropertyNode * node)
 
     maybe_copy_value(this, node, "turbulence/rate-hz",
                      &FGEnvironment::set_turbulence_rate_hz);
+
     // calculate derived properties here to avoid duplicate expensive computations
     _recalc_ne();
     _recalc_alt_pt();
@@ -369,6 +372,12 @@ FGEnvironment::get_ridge_lift_fps () const
   return ridge_lift_fps;
 }
 
+double
+FGEnvironment::get_local_weather_lift_fps () const
+{
+  return local_weather_lift_fps;
+}
+
 double
 FGEnvironment::get_turbulence_magnitude_norm () const
 {
@@ -524,7 +533,16 @@ FGEnvironment::set_ridge_lift_fps (double ri)
   ridge_lift_fps = ri;
   if( live_update ) {
     _recalc_updraft();
+  }
 }
+
+void
+FGEnvironment::set_local_weather_lift_fps (double lwl)
+{
+  local_weather_lift_fps = lwl;
+  if( live_update ) {
+    _recalc_updraft();
+  }
 }
 
 void
@@ -618,7 +636,7 @@ FGEnvironment::_recalc_ne ()
 void
 FGEnvironment::_recalc_updraft ()
 {
-  wind_from_down_fps = thermal_lift_fps + ridge_lift_fps ;
+  wind_from_down_fps = thermal_lift_fps + ridge_lift_fps + local_weather_lift_fps ;
 }
 
 // Intended to help with the interpretation of METAR data,
index d9543d5ab68704813d814df6fea66544d72ee59e..c270132262f7883c2fd9a20a4c4f458653918084 100644 (file)
@@ -72,6 +72,7 @@ public:
   virtual double get_wind_from_down_fps () const;
   virtual double get_thermal_lift_fps () const;
   virtual double get_ridge_lift_fps () const;  
+  virtual double get_local_weather_lift_fps () const;
 
   virtual double get_turbulence_magnitude_norm () const;
   virtual double get_turbulence_rate_hz () const;
@@ -92,6 +93,7 @@ public:
   virtual void set_wind_from_down_fps (double d);
   virtual void set_thermal_lift_fps (double th);
   virtual void set_ridge_lift_fps (double ri);
+  virtual void set_local_weather_lift_fps (double lwl);
 
   virtual void set_turbulence_magnitude_norm (double t);
   virtual void set_turbulence_rate_hz (double t);
@@ -147,6 +149,7 @@ private:
   double wind_from_down_fps;
   double thermal_lift_fps;
   double ridge_lift_fps;
+  double local_weather_lift_fps;
 
   bool     live_update;
 
index e15ecae20370967dd2ecd978152957e805fa76d3..acf20b861ed86f18059c2991cf8401dc874b84a6 100644 (file)
@@ -166,9 +166,12 @@ FGEnvironmentMgr::bind ()
   fgSetArchivable("/environment/thermal-lift-fps");
   fgTie("/environment/ridge-lift-fps", _environment,
        &FGEnvironment::get_ridge_lift_fps,
-       &FGEnvironment::set_ridge_lift_fps);
+       &FGEnvironment::set_ridge_lift_fps);    
   fgSetArchivable("/environment/ridge-lift-fps");
-
+  
+    fgTie("/environment/local-weather-lift", _environment,
+       &FGEnvironment::get_local_weather_lift_fps); //read-only
+     
   fgTie("/environment/turbulence/magnitude-norm", _environment,
         &FGEnvironment::get_turbulence_magnitude_norm,
         &FGEnvironment::set_turbulence_magnitude_norm);
@@ -255,6 +258,7 @@ FGEnvironmentMgr::unbind ()
 
   fgUntie("/environment/thermal-lift-fps");
   fgUntie("/environment/ridge-lift-fps");
+  fgUntie("/environment/local-weather-lift");
 
   fgUntie("/environment/atmosphere/altitude-half-to-sun");
   fgUntie("/environment/atmosphere/altitude-troposphere-top");
@@ -293,6 +297,7 @@ FGEnvironmentMgr::update (double dt)
                                   _environment->get_wind_from_east_fps(),
                                   _environment->get_wind_from_down_fps());
   _environment->set_elevation_ft(fgGetDouble("/position/altitude-ft"));
+  _environment->set_local_weather_lift_fps(fgGetDouble("/local-weather/current/thermal-lift"));
   osg::Vec3 windVec(-_environment->get_wind_from_north_fps(),
                     -_environment->get_wind_from_east_fps(),
                     _environment->get_wind_from_down_fps());
index a94537d478a753efa164a3a15589fd0d25d1ba60..3e9d92aa981188d20c631b780c7ce951ed72c0e0 100644 (file)
 
 #include <simgear/math/SGMath.hxx>
 
+using simgear::PropertyList;
+
 void FGCommonInput::read_bindings (const SGPropertyNode * node, binding_list_t * binding_list, int modifiers, const string & module )
 {
   SG_LOG(SG_INPUT, SG_DEBUG, "Reading all bindings");
-  vector<SGPropertyNode_ptr> bindings = node->getChildren("binding");
+  PropertyList bindings = node->getChildren("binding");
   static string nasal = "nasal";
   for (unsigned int i = 0; i < bindings.size(); i++) {
     const char *cmd = bindings[i]->getStringValue("command");
index 431a6fa5ecc47bb73e647ca160adec86b399d00c..5ad2a0bd7435f3786c0049777386bcce6ed52e91 100644 (file)
@@ -35,6 +35,8 @@
 #include <simgear/props/props_io.hxx>
 #include <Main/globals.hxx>
 
+using simgear::PropertyList;
+
 FGDeviceConfigurationMap::FGDeviceConfigurationMap( const char * relative_path, SGPropertyNode_ptr aBase, const char * aChildname ) :
   base(aBase),
   childname(aChildname)
@@ -45,10 +47,10 @@ FGDeviceConfigurationMap::FGDeviceConfigurationMap( const char * relative_path,
   int index = 1000;
   scan_dir( path, &index);
 
-  vector<SGPropertyNode_ptr> childNodes = base->getChildren(childname);
+  PropertyList childNodes = base->getChildren(childname);
   for (int k = (int)childNodes.size() - 1; k >= 0; k--) {
     SGPropertyNode *n = childNodes[k];
-    vector<SGPropertyNode_ptr> names = n->getChildren("name");
+    PropertyList names = n->getChildren("name");
     if (names.size() ) // && (n->getChildren("axis").size() || n->getChildren("button").size()))
       for (unsigned int j = 0; j < names.size(); j++)
         (*this)[names[j]->getStringValue()] = n;
index 928c20c242a58ddee1ea5e97eafef1f0f89580ff..31e6fc9788361ad78d313e1e13c067dd798194b9 100644 (file)
@@ -29,6 +29,8 @@
 #include <simgear/io/sg_file.hxx>
 #include <Scripting/NasalSys.hxx>
 
+using simgear::PropertyList;
+
 FGEventSetting::FGEventSetting( SGPropertyNode_ptr base ) :
   value(0.0)
 {
@@ -93,8 +95,8 @@ FGInputEvent::FGInputEvent( FGInputDevice * aDevice, SGPropertyNode_ptr node ) :
   
   read_bindings( node, bindings, KEYMOD_NONE, device->GetNasalModule() );
 
-  vector<SGPropertyNode_ptr> settingNodes = node->getChildren("setting");
-  for( vector<SGPropertyNode_ptr>::iterator it = settingNodes.begin(); it != settingNodes.end(); it++ )
+  PropertyList settingNodes = node->getChildren("setting");
+  for( PropertyList::iterator it = settingNodes.begin(); it != settingNodes.end(); it++ )
     settings.push_back( new FGEventSetting( *it ) );
 }
 
@@ -235,8 +237,8 @@ void FGInputDevice::Configure( SGPropertyNode_ptr aDeviceNode )
 
   nasalModule = string("__event:") + GetName();
 
-  vector<SGPropertyNode_ptr> eventNodes = deviceNode->getChildren( "event" );
-  for( vector<SGPropertyNode_ptr>::iterator it = eventNodes.begin(); it != eventNodes.end(); it++ )
+  PropertyList eventNodes = deviceNode->getChildren( "event" );
+  for( PropertyList::iterator it = eventNodes.begin(); it != eventNodes.end(); it++ )
     AddHandledEvent( FGInputEvent::NewObject( this, *it ) );
 
   debugEvents = deviceNode->getBoolValue("debug-events", debugEvents );
index 5c3b82b2e13a01d6acb1d0f81fbe842ea47861bf..349782d5b5e3c890abfb46e89a7c45c3e79cd59a 100644 (file)
@@ -27,6 +27,8 @@
 #include <Main/fg_props.hxx>
 #include <Scripting/NasalSys.hxx>
 
+using simgear::PropertyList;
+
 FGJoystickInput::axis::axis ()
   : last_value(9999999),
     tolerance(0.002),
@@ -166,7 +168,7 @@ void FGJoystickInput::postinit()
     string module = str.str();
     nasalsys->createModule(module.c_str(), module.c_str(), "", 0);
 
-    vector<SGPropertyNode_ptr> nasal = js_node->getChildren("nasal");
+    PropertyList nasal = js_node->getChildren("nasal");
     unsigned int j;
     for (j = 0; j < nasal.size(); j++) {
       nasal[j]->setStringValue("module", module.c_str());
@@ -176,7 +178,7 @@ void FGJoystickInput::postinit()
     //
     // Initialize the axes.
     //
-    vector<SGPropertyNode_ptr> axes = js_node->getChildren("axis");
+    PropertyList axes = js_node->getChildren("axis");
     size_t nb_axes = axes.size();
     for (j = 0; j < nb_axes; j++ ) {
       const SGPropertyNode * axis_node = axes[j];
@@ -219,7 +221,7 @@ void FGJoystickInput::postinit()
     //
     // Initialize the buttons.
     //
-    vector<SGPropertyNode_ptr> buttons = js_node->getChildren("button");
+    PropertyList buttons = js_node->getChildren("button");
     char buf[32];
     for (j = 0; j < buttons.size() && j < nbuttons; j++) {
       const SGPropertyNode * button_node = buttons[j];
index f4d20d66cf530acd35eeda9d0c35c21a8f8f4923..94c485c6a184d0402eef6313f9e9834339947173 100644 (file)
@@ -27,6 +27,8 @@
 #include <Scripting/NasalSys.hxx>
 #include <plib/pu.h>
 
+using simgear::PropertyList;
+
 static int getModifiers ()
 {
   return fgGetKeyModifiers() >> 1;
@@ -94,13 +96,13 @@ void FGKeyboardInput::postinit()
   }
 
   FGNasalSys *nasalsys = (FGNasalSys *)globals->get_subsystem("nasal");
-  vector<SGPropertyNode_ptr> nasal = key_nodes->getChildren("nasal");
+  PropertyList nasal = key_nodes->getChildren("nasal");
   for (unsigned int j = 0; j < nasal.size(); j++) {
     nasal[j]->setStringValue("module", module.c_str());
     nasalsys->handleCommand(nasal[j]);
   }
 
-  vector<SGPropertyNode_ptr> keys = key_nodes->getChildren("key");
+  PropertyList keys = key_nodes->getChildren("key");
   for (unsigned int i = 0; i < keys.size(); i++) {
     int index = keys[i]->getIndex();
     SG_LOG(SG_INPUT, SG_DEBUG, "Binding key " << index);
index 9391c022afd879447c73db2e4790c698f4664a86..f1930b0e389ca552e72c1b06e4d75b305be405ad 100644 (file)
@@ -58,6 +58,7 @@ using std::string;
 
 #include "jsinput.h"
 
+using simgear::PropertyList;
 
 bool confirmAnswer() {
     char answer;
@@ -136,8 +137,8 @@ int main( int argc, char *argv[] ) {
         cout << e.getFormattedMessage ();
     }
 
-    vector<SGPropertyNode_ptr> axes = templatetree->getChildren("axis");
-    for(vector<SGPropertyNode_ptr>::iterator iter = axes.begin(); iter != axes.end(); iter++) {
+    PropertyList axes = templatetree->getChildren("axis");
+    for(PropertyList::iterator iter = axes.begin(); iter != axes.end(); iter++) {
         cout << "Move the control you wish to use for " << (*iter)->getStringValue("desc")
              << " " << (*iter)->getStringValue("direction") << endl;
         cout << "Pressing a button skips this axis" << endl;
@@ -164,8 +165,8 @@ int main( int argc, char *argv[] ) {
         cout << endl;
     }
 
-    vector<SGPropertyNode_ptr> buttons = templatetree->getChildren("button");
-    for(vector<SGPropertyNode_ptr>::iterator iter = buttons.begin(); iter != buttons.end(); iter++) {
+    PropertyList buttons = templatetree->getChildren("button");
+    for(PropertyList::iterator iter = buttons.begin(); iter != buttons.end(); iter++) {
         cout << "Press the button you wish to use for " << (*iter)->getStringValue("desc") << endl;
         cout << "Moving a joystick axis skips this button" << endl;
         fflush( stdout );
index 0196ddbaef9bd20b3d420f1c0f78ae0f868b9af0..0622f2103adfc2ac9d4c49880ccd597f80da1c28 100644 (file)
@@ -10,6 +10,8 @@
 #include "airspeed_indicator.hxx"
 #include <Main/fg_props.hxx>
 #include <Main/util.hxx>
+#include <Environment/environment_mgr.hxx>
+#include <Environment/environment.hxx>
 
 
 // A higher number means more responsive.
@@ -20,8 +22,14 @@ AirspeedIndicator::AirspeedIndicator ( SGPropertyNode *node )
     _name(node->getStringValue("name", "airspeed-indicator")),
     _num(node->getIntValue("number", 0)),
     _total_pressure(node->getStringValue("total-pressure", "/systems/pitot/total-pressure-inhg")),
-    _static_pressure(node->getStringValue("static-pressure", "/systems/static/pressure-inhg"))
+    _static_pressure(node->getStringValue("static-pressure", "/systems/static/pressure-inhg")),
+    _has_overspeed(node->getBoolValue("has-overspeed-indicator",false)),
+    _pressure_alt_source(node->getStringValue("pressure-alt-source", "/instrumentation/altimeter/pressure-alt-ft")),
+    _ias_limit(node->getDoubleValue("ias-limit", 248.0)),
+    _mach_limit(node->getDoubleValue("mach-limit", 0.48)),
+    _alt_threshold(node->getDoubleValue("alt-threshold", 13200))
 {
+  _environmentManager = NULL;
 }
 
 AirspeedIndicator::~AirspeedIndicator ()
@@ -40,6 +48,32 @@ AirspeedIndicator::init ()
     _static_pressure_node = fgGetNode(_static_pressure.c_str(), true);
     _density_node = fgGetNode("/environment/density-slugft3", true);
     _speed_node = node->getChild("indicated-speed-kt", 0, true);
+    _tas_node = node->getChild("true-speed-kt", 0, true);
+    _mach_node = node->getChild("indicated-mach", 0, true);
+    
+  // overspeed-indicator properties
+    if (_has_overspeed) {
+        _ias_limit_node = node->getNode("ias-limit",0, true);
+        _mach_limit_node = node->getNode("mach-limit",0, true);
+        _alt_threshold_node = node->getNode("alt-threshold",0, true);
+        
+        if (!_ias_limit_node->hasValue()) {
+          _ias_limit_node->setDoubleValue(_ias_limit);
+        }
+
+        if (!_mach_limit_node->hasValue()) {
+          _mach_limit_node->setDoubleValue(_mach_limit);
+        }
+
+        if (!_alt_threshold_node->hasValue()) {
+          _alt_threshold_node->setDoubleValue(_alt_threshold);
+        }
+
+        _airspeed_limit = node->getChild("airspeed-limit-kt", 0, true);
+        _pressure_alt = fgGetNode(_pressure_alt_source.c_str(), true);
+    }
+    
+    _environmentManager = (FGEnvironmentMgr*) globals->get_subsystem("environment");
 }
 
 #ifndef FPSTOKTS
@@ -53,24 +87,66 @@ AirspeedIndicator::init ()
 void
 AirspeedIndicator::update (double dt)
 {
-    if (_serviceable_node->getBoolValue()) {
-        double pt = _total_pressure_node->getDoubleValue() * INHGTOPSF;
-        double p = _static_pressure_node->getDoubleValue() * INHGTOPSF;
-        double r = _density_node->getDoubleValue();
-        double q = ( pt - p );  // dynamic pressure
-
-        // Now, reverse the equation (normalize dynamic pressure to
-        // avoid "nan" results from sqrt)
-        if ( q < 0 ) { q = 0.0; }
-        double v_fps = sqrt((2 * q) / r);
-
-                                // Publish the indicated airspeed
-        double last_speed_kt = _speed_node->getDoubleValue();
-        double current_speed_kt = v_fps * FPSTOKTS;
-        _speed_node->setDoubleValue(fgGetLowPass(last_speed_kt,
-                                                 current_speed_kt,
-                                                 dt * RESPONSIVENESS));
+    if (!_serviceable_node->getBoolValue()) {
+        return;
+    }
+    
+    double pt = _total_pressure_node->getDoubleValue() * INHGTOPSF;
+    double p = _static_pressure_node->getDoubleValue() * INHGTOPSF;
+    double r = _density_node->getDoubleValue();
+    double q = ( pt - p );  // dynamic pressure
+
+    // Now, reverse the equation (normalize dynamic pressure to
+    // avoid "nan" results from sqrt)
+    if ( q < 0 ) { q = 0.0; }
+    double v_fps = sqrt((2 * q) / r);
+
+                            // Publish the indicated airspeed
+    double last_speed_kt = _speed_node->getDoubleValue();
+    double current_speed_kt = v_fps * FPSTOKTS;
+    double filtered_speed = fgGetLowPass(last_speed_kt,
+                                             current_speed_kt,
+                                             dt * RESPONSIVENESS);
+    _speed_node->setDoubleValue(filtered_speed);
+    computeMach(filtered_speed);
+
+    if (!_has_overspeed) {
+        return;
+    }
+    
+    double lmt = _ias_limit_node->getDoubleValue();
+    if (_pressure_alt->getDoubleValue() > _alt_threshold_node->getDoubleValue()) {
+        double mmo = _mach_limit_node->getDoubleValue();
+        lmt = (filtered_speed/_mach_node->getDoubleValue())* mmo;
     }
+    
+    _airspeed_limit->setDoubleValue(lmt);
+}
+
+void
+AirspeedIndicator::computeMach(double ias)
+{
+  if (!_environmentManager) {
+    return;
+  }
+  
+  FGEnvironment env(_environmentManager->getEnvironment());
+  
+  // derived from http://williams.best.vwh.net/avform.htm#Mach
+  // names here are picked to be consistent with those formulae!
+
+  double oatK = env.get_temperature_degc() + 273.15; // OAT in Kelvin
+  double CS = 38.967854 * sqrt(oatK); // speed-of-sound in knots at altitude
+  double CS_0 = 661.4786; // speed-of-sound in knots at sea-level
+  double P_0 = env.get_pressure_sea_level_inhg();
+  double P = _static_pressure_node->getDoubleValue();
+  
+  double DP = P_0 * (pow(1 + 0.2*pow(ias/CS_0, 2), 3.5) - 1);
+  double mach = pow(5 * ( pow(DP/P + 1, 2.0/7.0) -1) , 0.5);
+  
+  // publish Mach and TAS
+  _mach_node->setDoubleValue(mach);
+  _tas_node->setDoubleValue(CS * mach);
 }
 
 // end of airspeed_indicator.cxx
index e4827081d1706aace56016c2ac097463039fb7ff..41e544c66704228c89c5da84fef7fb4bdbf08eae 100644 (file)
@@ -14,6 +14,8 @@
 #include <simgear/props/props.hxx>
 #include <simgear/structure/subsystem_mgr.hxx>
 
+// forward decls
+class FGEnvironmentMgr;
 
 /**
  * Model an airspeed indicator tied to the pitot and static ports.
@@ -41,17 +43,32 @@ public:
     virtual void update (double dt);
 
 private:
+    void computeMach(double ias);
 
     string _name;
     unsigned int _num;
     string _total_pressure;
     string _static_pressure;
+    bool _has_overspeed;
+    string _pressure_alt_source;
+    double _ias_limit;
+    double _mach_limit;
+    double _alt_threshold;
+    
+    SGPropertyNode_ptr _ias_limit_node;
+    SGPropertyNode_ptr _mach_limit_node;
+    SGPropertyNode_ptr _alt_threshold_node;
     SGPropertyNode_ptr _serviceable_node;
     SGPropertyNode_ptr _total_pressure_node;
     SGPropertyNode_ptr _static_pressure_node;
     SGPropertyNode_ptr _density_node;
     SGPropertyNode_ptr _speed_node;
+    SGPropertyNode_ptr _airspeed_limit;
+    SGPropertyNode_ptr _pressure_alt;
+    SGPropertyNode_ptr _mach_node;
+    SGPropertyNode_ptr _tas_node;
     
+    FGEnvironmentMgr* _environmentManager;
 };
 
 #endif // __INSTRUMENTS_AIRSPEED_INDICATOR_HXX
index 754008bd47efdb77c177923ec04541dffc92e272..925681e0acbe08bd444cf25f5573a8bdd657a487 100644 (file)
@@ -97,6 +97,7 @@ DME::update (double delta_time_sec)
         _time_before_search_sec = 0;
         _last_frequency_mhz = frequency_mhz;
     }
+    _frequency_node->setDoubleValue(frequency_mhz);
 
                                 // Get the aircraft position
     double longitude_rad =
index 70ceb23b5fd3d2326c18c6fe4c9258461fdf57b7..6131e4795fc2f6796d56702ecd9677075f9ed93b 100644 (file)
@@ -576,10 +576,8 @@ do_tile_cache_reload (const SGPropertyNode * arg)
  * boundary and aloft environment layers.
  */
 static bool
-do_set_sea_level_degc (const SGPropertyNode * arg)
+do_set_sea_level_degc ( double temp_sea_level_degc)
 {
-    double temp_sea_level_degc = arg->getDoubleValue("temp-degc", 15.0);
-
     SGPropertyNode *node, *child;
 
     // boundary layers
@@ -607,6 +605,12 @@ do_set_sea_level_degc (const SGPropertyNode * arg)
     return true;
 }
 
+static bool
+do_set_sea_level_degc (const SGPropertyNode * arg)
+{
+    return do_set_sea_level_degc( arg->getDoubleValue("temp-degc", 15.0) );
+}
+
 
 /**
  * Set the outside air temperature at the "current" altitude by first
@@ -616,8 +620,7 @@ do_set_sea_level_degc (const SGPropertyNode * arg)
 static bool
 do_set_oat_degc (const SGPropertyNode * arg)
 {
-    const string &temp_str = arg->getStringValue("temp-degc", "15.0");
-
+    double oat_degc = arg->getDoubleValue("temp-degc", 15.0);
     // check for an altitude specified in the arguments, otherwise use
     // current aircraft altitude.
     const SGPropertyNode *altitude_ft = arg->getChild("altitude-ft");
@@ -627,38 +630,8 @@ do_set_oat_degc (const SGPropertyNode * arg)
 
     FGEnvironment dummy;       // instantiate a dummy so we can leech a method
     dummy.set_elevation_ft( altitude_ft->getDoubleValue() );
-    dummy.set_temperature_degc( atof( temp_str.c_str() ) );
-    double temp_sea_level_degc = dummy.get_temperature_sea_level_degc();
-
-    //cout << "Altitude = " << altitude_ft->getDoubleValue() << endl;
-    //cout << "Temp at alt (C) = " << atof( temp_str.c_str() ) << endl;
-    //cout << "Temp sea level (C) = " << temp_sea_level_degc << endl;
-    SGPropertyNode *node, *child;
-
-    // boundary layers
-    node = fgGetNode( "/environment/config/boundary" );
-    if ( node != NULL ) {
-      int i = 0;
-      while ( ( child = node->getNode( "entry", i ) ) != NULL ) {
-       child->setDoubleValue( "temperature-sea-level-degc",
-                              temp_sea_level_degc );
-       ++i;
-      }
-    }
-
-    // aloft layers
-    node = fgGetNode( "/environment/config/aloft" );
-    if ( node != NULL ) {
-      int i = 0;
-      while ( ( child = node->getNode( "entry", i ) ) != NULL ) {
-       child->setDoubleValue( "temperature-sea-level-degc",
-                              temp_sea_level_degc );
-       ++i;
-      }
-    }
-
-    return true;
+    dummy.set_temperature_degc( oat_degc );
+    return do_set_sea_level_degc( dummy.get_temperature_sea_level_degc());
 }
 
 /**
@@ -666,9 +639,8 @@ do_set_oat_degc (const SGPropertyNode * arg)
  * boundary and aloft environment layers.
  */
 static bool
-do_set_dewpoint_sea_level_degc (const SGPropertyNode * arg)
+do_set_dewpoint_sea_level_degc (double dewpoint_sea_level_degc)
 {
-    double dewpoint_sea_level_degc = arg->getDoubleValue("dewpoint-degc", 5.0);
 
     SGPropertyNode *node, *child;
 
@@ -697,6 +669,11 @@ do_set_dewpoint_sea_level_degc (const SGPropertyNode * arg)
     return true;
 }
 
+static bool
+do_set_dewpoint_sea_level_degc (const SGPropertyNode * arg)
+{
+    return do_set_dewpoint_sea_level_degc(arg->getDoubleValue("dewpoint-degc", 5.0));
+}
 
 /**
  * Set the outside air dewpoint at the "current" altitude by first
@@ -706,7 +683,7 @@ do_set_dewpoint_sea_level_degc (const SGPropertyNode * arg)
 static bool
 do_set_dewpoint_degc (const SGPropertyNode * arg)
 {
-    const string &dewpoint_str = arg->getStringValue("dewpoint-degc", "5.0");
+    double dewpoint_degc = arg->getDoubleValue("dewpoint-degc", 5.0);
 
     // check for an altitude specified in the arguments, otherwise use
     // current aircraft altitude.
@@ -717,38 +694,8 @@ do_set_dewpoint_degc (const SGPropertyNode * arg)
 
     FGEnvironment dummy;       // instantiate a dummy so we can leech a method
     dummy.set_elevation_ft( altitude_ft->getDoubleValue() );
-    dummy.set_dewpoint_degc( atof( dewpoint_str.c_str() ) );
-    double dewpoint_sea_level_degc = dummy.get_dewpoint_sea_level_degc();
-
-    //cout << "Altitude = " << altitude_ft->getDoubleValue() << endl;
-    //cout << "Dewpoint at alt (C) = " << atof( dewpoint_str.c_str() ) << endl;
-    //cout << "Dewpoint at sea level (C) = " << dewpoint_sea_level_degc << endl;
-    SGPropertyNode *node, *child;
-
-    // boundary layers
-    node = fgGetNode( "/environment/config/boundary" );
-    if ( node != NULL ) {
-      int i = 0;
-      while ( ( child = node->getNode( "entry", i ) ) != NULL ) {
-       child->setDoubleValue( "dewpoint-sea-level-degc",
-                              dewpoint_sea_level_degc );
-       ++i;
-      }
-    }
-
-    // aloft layers
-    node = fgGetNode( "/environment/config/aloft" );
-    if ( node != NULL ) {
-      int i = 0;
-      while ( ( child = node->getNode( "entry", i ) ) != NULL ) {
-       child->setDoubleValue( "dewpoint-sea-level-degc",
-                              dewpoint_sea_level_degc );
-       ++i;
-      }
-    }
-
-    return true;
+    dummy.set_dewpoint_degc( dewpoint_degc );
+    return do_set_dewpoint_sea_level_degc(dummy.get_dewpoint_sea_level_degc());
 }
 
 /**
index 8ac54aa5695984ea8d671a3e80b50954dad03b14..e1a50d6c3798cdfffe813a1afaad1fe46b1ad478 100644 (file)
@@ -485,8 +485,8 @@ static void fgMainLoop( void ) {
     // is processing the scenery (doubled the frame-rate for me) -EMH-
 #ifdef ENABLE_AUDIO_SUPPORT
     static bool smgr_init = true;
+    static SGPropertyNode *sound_working = fgGetNode("/sim/sound/working");
     if (smgr_init == true) {
-        static SGPropertyNode *sound_working = fgGetNode("/sim/sound/working");
         if (sound_working->getBoolValue() == true) {
             fgInitSoundManager();
             smgr_init = false;
@@ -496,6 +496,12 @@ static void fgMainLoop( void ) {
         static SGSoundMgr *smgr = globals->get_soundmgr();
         static bool smgr_enabled = true;
 
+        if (sound_working->getBoolValue() == false) {  // request to reinit
+           smgr->reinit();
+           smgr->resume();
+           sound_working->setBoolValue(true);
+        }
+
         if (smgr_enabled != sound_enabled->getBoolValue()) {
             if (smgr_enabled == true) { // request to suspend
                 smgr->suspend();
index 8dcfb982dbf5f4913eb0c573e2d9e55019293c7d..ffa05fc3f3499b4160771df8af9b43eb1759ee81 100644 (file)
@@ -64,10 +64,6 @@ FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index,
     _roll_deg(0),
     _pitch_deg(0),
     _heading_deg(0),
-    _damp_sync(0),
-    _damp_roll(0),
-    _damp_pitch(0),
-    _damp_heading(0),
     _scaling_type(FG_SCALING_MAX),
     _aspect_ratio(0),
     _cameraGroup(CameraGroup::getDefault())
@@ -81,12 +77,16 @@ FGViewer::FGViewer( fgViewType Type, bool from_model, int from_model_index,
 
     _internal = internal;
 
+    _dampFactor = SGVec3d::zeros();
+    _dampOutput = SGVec3d::zeros();
+    _dampTarget = SGVec3d::zeros();
+    
     if (damp_roll > 0.0)
-      _damp_roll = 1.0 / pow(10.0, fabs(damp_roll));
+      _dampFactor[0] = 1.0 / pow(10.0, fabs(damp_roll));
     if (damp_pitch > 0.0)
-      _damp_pitch = 1.0 / pow(10.0, fabs(damp_pitch));
+      _dampFactor[1] = 1.0 / pow(10.0, fabs(damp_pitch));
     if (damp_heading > 0.0)
-      _damp_heading = 1.0 / pow(10.0, fabs(damp_heading));
+      _dampFactor[2] = 1.0 / pow(10.0, fabs(damp_heading));
 
     _offset_m.x() = x_offset_m;
     _offset_m.y() = y_offset_m;
@@ -369,7 +369,8 @@ FGViewer::recalcLookFrom ()
   double roll = _roll_deg;
   if ( !_from_model ) {
     // update from our own data...
-    dampEyeData(roll, pitch, head);
+    setDampTarget(roll, pitch, head);
+    getDampOutput(roll, pitch, head);
   }
 
   // The rotation rotating from the earth centerd frame to
@@ -411,13 +412,13 @@ FGViewer::recalcLookAt ()
     _target_roll_deg = placement->getRollDeg();
   } else {
     // if not model then calculate our own target position...
-    dampEyeData(_target_roll_deg, _target_pitch_deg, _target_heading_deg);
-
+    setDampTarget(_target_roll_deg, _target_pitch_deg, _target_heading_deg);
+    getDampOutput(_target_roll_deg, _target_pitch_deg, _target_heading_deg);
   }
 
   SGQuatd geodTargetOr = SGQuatd::fromYawPitchRollDeg(_target_heading_deg,
-                                                      _target_pitch_deg,
-                                                      _target_roll_deg);
+                                                   _target_pitch_deg,
+                                                   _target_roll_deg);
   SGQuatd geodTargetHlOr = SGQuatd::fromLonLat(_target);
 
 
@@ -429,11 +430,10 @@ FGViewer::recalcLookAt ()
     _roll_deg = placement->getRollDeg();
   } else {
     // update from our own data, just the rotation here...
-    dampEyeData(_roll_deg, _pitch_deg, _heading_deg);
+    setDampTarget(_roll_deg, _pitch_deg, _heading_deg);
+    getDampOutput(_roll_deg, _pitch_deg, _heading_deg);
   }
-  SGQuatd geodEyeOr = SGQuatd::fromYawPitchRollDeg(_heading_deg,
-                                                   _pitch_deg,
-                                                   _roll_deg);
+  SGQuatd geodEyeOr = SGQuatd::fromYawPitchRollDeg(_heading_deg, _pitch_deg, _roll_deg);
   SGQuatd geodEyeHlOr = SGQuatd::fromLonLat(_position);
 
   // the rotation offset, don't know why heading is negative here ...
@@ -472,61 +472,53 @@ FGViewer::recalcLookAt ()
 }
 
 void
-FGViewer::dampEyeData(double &roll_deg, double &pitch_deg, double &heading_deg)
+FGViewer::setDampTarget(double roll, double pitch, double heading)
 {
-  const double interval = 0.01;
+  _dampTarget = SGVec3d(roll, pitch, heading);
+}
+
+void
+FGViewer::getDampOutput(double& roll, double& pitch, double& heading)
+{
+  roll = _dampOutput[0];
+  pitch = _dampOutput[1];
+  heading = _dampOutput[2];
+}
 
+
+void
+FGViewer::updateDampOutput(double dt)
+{
   static FGViewer *last_view = 0;
-  if (last_view != this) {
-    _damp_sync = 0.0;
-    _damped_roll_deg = roll_deg;
-    _damped_pitch_deg = pitch_deg;
-    _damped_heading_deg = heading_deg;
+  if ((last_view != this) || (dt > 1.0)) {
+    _dampOutput = _dampTarget;
     last_view = this;
     return;
   }
-
-  if (_damp_sync < interval) {
-    if (_damp_roll > 0.0)
-      roll_deg = _damped_roll_deg;
-    if (_damp_pitch > 0.0)
-      pitch_deg = _damped_pitch_deg;
-    if (_damp_heading > 0.0)
-      heading_deg = _damped_heading_deg;
-    return;
-  }
-
-  while (_damp_sync >= interval) {
-    _damp_sync -= interval;
-
-    double d;
-    if (_damp_roll > 0.0) {
-      d = _damped_roll_deg - roll_deg;
-      if (d >= 180.0)
-        _damped_roll_deg -= 360.0;
-      else if (d < -180.0)
-        _damped_roll_deg += 360.0;
-      roll_deg = _damped_roll_deg = roll_deg * _damp_roll + _damped_roll_deg * (1 - _damp_roll);
-    }
-
-    if (_damp_pitch > 0.0) {
-      d = _damped_pitch_deg - pitch_deg;
-      if (d >= 180.0)
-        _damped_pitch_deg -= 360.0;
-      else if (d < -180.0)
-        _damped_pitch_deg += 360.0;
-      pitch_deg = _damped_pitch_deg = pitch_deg * _damp_pitch + _damped_pitch_deg * (1 - _damp_pitch);
-    }
-
-    if (_damp_heading > 0.0) {
-      d = _damped_heading_deg - heading_deg;
-      if (d >= 180.0)
-        _damped_heading_deg -= 360.0;
-      else if (d < -180.0)
-        _damped_heading_deg += 360.0;
-      heading_deg = _damped_heading_deg = heading_deg * _damp_heading + _damped_heading_deg * (1 - _damp_heading);
-    }
-  }
+  
+  const double interval = 0.01;
+  while (dt > interval) {
+    
+    for (unsigned int i=0; i<3; ++i) {
+      if (_dampFactor[i] <= 0.0) {
+        // axis is un-damped, set output to target directly
+        _dampOutput[i] = _dampTarget[i];
+        continue;
+      }
+      
+      double d = _dampOutput[i] - _dampTarget[i];
+      if (d > 180.0) {
+        _dampOutput[i] -= 360.0;
+      } else if (d < -180.0) {
+        _dampOutput[i] += 360.0;
+      }
+      
+      _dampOutput[i] = (_dampTarget[i] * _dampFactor[i]) + 
+        (_dampOutput[i] * (1.0 - _dampFactor[i]));
+    } // of axis iteration
+    
+    dt -= interval;
+  } // of dt subdivision by interval
 }
 
 double
@@ -583,8 +575,8 @@ FGViewer::get_v_fov()
 void
 FGViewer::update (double dt)
 {
-  _damp_sync += dt;
-
+  updateDampOutput(dt);
+  
   int i;
   int dt_ms = int(dt * 1000);
   for ( i = 0; i < dt_ms; i++ ) {
index 7005e661ff6b029f44e08a70b48855a058d4b872..7cd58adae583058a48911b57a9d553581ebba261 100644 (file)
@@ -262,15 +262,10 @@ private:
     double _target_pitch_deg;
     double _target_heading_deg;
 
-    double _damp_sync;
-    double _damp_roll;
-    double _damp_pitch;
-    double _damp_heading;
-
-    double _damped_roll_deg;
-    double _damped_pitch_deg;
-    double _damped_heading_deg;
-
+    SGVec3d _dampTarget; ///< current target value we are damping towards
+    SGVec3d _dampOutput; ///< current output of damping filter
+    SGVec3d _dampFactor; ///< weighting of the damping filter
+    
     // Position offsets from FDM origin.  The X axis is positive
     // out the tail, Y is out the right wing, and Z is positive up.
     // distance in meters
@@ -328,8 +323,12 @@ private:
     void recalc ();
     void recalcLookFrom();
     void recalcLookAt();
-    void dampEyeData(double &roll_deg, double &pitch_deg, double &heading_deg);
 
+    void setDampTarget(double h, double p, double r);
+    void getDampOutput(double& roll, double& pitch, double& heading);
+    
+    void updateDampOutput(double dt);
+    
     // add to _heading_offset_deg
     inline void incHeadingOffset_deg( double amt ) {
        set_dirty();
index 1fff200ad012e0cfb694ded55ad4aed4bda905ae..33c80d24bfecd4d2845cd97f0103ba3da88d046c 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <simgear/debug/logstream.hxx>
 #include <simgear/io/iochannel.hxx>
+#include <simgear/misc/stdint.hxx>
 
 #include <Aircraft/aircraft.hxx>
 #include <Main/fg_props.hxx>
@@ -91,8 +92,7 @@ bool FGJsClient::process() {
        if ( io->get_type() == sgFileType ) {
            if ( io->read( (char *)(& buf), length ) == length ) {
                SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
-               long int *msg;
-               msg = (long int *)buf;
+               int32_t *msg = (int32_t *)buf;
                for( int i = 0; i < 4; ++i )
                {
                        axis[i] = ((double)msg[i] / 2147483647.0);
@@ -105,8 +105,7 @@ bool FGJsClient::process() {
        } else {
            while ( io->read( (char *)(& buf), length ) == length ) {
                SG_LOG( SG_IO, SG_DEBUG, "Success reading data." );
-               long int *msg;
-               msg = (long int *)buf;
+               int32_t *msg = (int32_t *)buf;
                SG_LOG( SG_IO, SG_DEBUG, "ax0 = " << msg[0] << " ax1 = "
                        << msg[1] << "ax2 = " << msg[2] << "ax3 = " << msg[3]);
                for( int i = 0; i < 4; ++i )
index 517bb3c2117b5e6e1b0000ec91bcc833672b85e7..3b990e377d3364213c27d6269af5ee5e3a2f28a9 100644 (file)
@@ -201,15 +201,17 @@ bool FGAISchedule::update(time_t now, const SGVec3d& userCart)
   
   if (firstRun) {
      if (fgGetBool("/sim/traffic-manager/instantaneous-action") == true) {
-         deptime = now + rand() % 300; // Wait up to 5 minutes until traffic starts moving to prevent too many aircraft 
+         deptime = now; // + rand() % 300; // Wait up to 5 minutes until traffic starts moving to prevent too many aircraft 
                                    // from cluttering the gate areas.
      }
      firstRun = false;
   }
   
   FGScheduledFlight* flight = flights.front();
-  if (!deptime)
+  if (!deptime) {
     deptime = flight->getDepartureTime();
+    //cerr << "Settiing departure time " << deptime << endl;
+  }
     
   if (AIManagerRef) {
     // Check if this aircraft has been released. 
index 78daec4ba003a6815e44bd16343edf11a6c28b90..d6763de5388bee69e3adb4d319350105ac8d2760 100644 (file)
@@ -35,11 +35,6 @@ int parse_option(char **args, int n) {
    }
 
    sz = strlen(opt);
-   if (!strncmp(opt, "-help", sz)) {
-      printf("usage:\n  normalmap [-c=contrast] [-b=brightness]");
-      printf(" --t=file [--o=file]\n");
-      exit(0);
-   }
    if (!strncmp(opt, "-contrast", sz)) {
       contrast = atof(arg);
       return ret;
@@ -58,6 +53,11 @@ int parse_option(char **args, int n) {
       normalmap_file = strdup(arg);
       return ret;
    }
+   if (!strncmp(opt, "-help", sz)) {
+      printf("usage:\n  normalmap [-c=contrast] [-b=brightness]");
+      printf(" --i=file [--o=file]\n\n");
+      exit(0);
+   }
 
    return 1;
 }
@@ -71,7 +71,9 @@ int main (int argc, char **argv)
 
    if ( !texture_file )
    {
-      printf("Error: texture file not specified\n");
+      printf("Error: texture file not specified.\n");
+      printf("usage:\n  normalmap [-c=contrast] [-b=brightness]");
+      printf(" --i=file [--o=file]\n\n");
       return -1;
    }
 
@@ -79,7 +81,7 @@ int main (int argc, char **argv)
    if ( !texture.texture() )
    {
       printf("Error: unable to process input file: %s\n", texture_file);
-      printf("       (%s)\n", texture.err_str());
+      printf("       (%s)\n\n", texture.err_str());
       return -2;
    }
 
index 6f744c35dda23fece90a776141333658d6849c97..3c747e60c5a693b866f1cb4dff934c576b9bd0da 100644 (file)
@@ -901,6 +901,7 @@ SGTexture::make_normalmap(float brightness, float contrast) {
          int yp1 = (y < (texture_height-1)) ? y+1 : 0;
          int posxp1 = (xp1 + ytw)*num_colors;
          int posyp1 = (x + yp1*texture_width)*num_colors;
+         float fx,fy;
 
          GLubyte c = texture_data[dpos];
          GLubyte cx1 = texture_data[posxp1];
@@ -918,8 +919,11 @@ SGTexture::make_normalmap(float brightness, float contrast) {
             map[mpos+3] = a;
          }
 
-         map[mpos+0] = (128+(cx1-c)/2);
-         map[mpos+1] = (128+(cy1-c)/2);
+         fx = asin((c/256.0-cx1/256.0))/1.57079633;
+         fy = asin((cy1/256.0-c/256.0))/1.57079633;
+
+         map[mpos+0] = (GLuint)(fx*256.0)-128;
+         map[mpos+1] = (GLuint)(fy*256.0)-128;
          map[mpos+2] = 127+int(brightness*128); // 255-c/2;
 
          mpos += colors;
index e586632dda8cd371d52a30e4c95d5ac3f8581bbe..f6c33c9b64c3e393ae6f2749c127dc22d88a43e8 100644 (file)
 #ifdef __MINGW32__
 #include <time.h>
 #include <unistd.h>
+#elif defined(_MSC_VER)
+#include <io.h>
 #endif
 
 #include <stdlib.h>             // atoi() atof() abs() system()
+#include <signal.h>             // signal()
 
 #include <simgear/compiler.h>
 
@@ -109,9 +112,10 @@ static void usage( const string& prog ) {
 
 }
 
-std::deque<std::string> waitingTiles;
-typedef std::map<std::string,time_t> CompletedTiles;
+deque<string> waitingTiles;
+typedef map<string,time_t> CompletedTiles;
 CompletedTiles completedTiles;
+netSocket theSocket;
 
 #ifdef HAVE_SVN_CLIENT_H
 
@@ -269,9 +273,37 @@ void sync_tree(const char* dir) {
     }
 }
 
+#ifdef _MSC_VER
+typedef void (__cdecl * sighandler_t)(int);
+#elif defined( __APPLE__ )
+typedef sig_t sighandler_t;
+#endif
+
+bool terminating = false;
+sighandler_t prior_signal_handlers[32];
+int termination_triggering_signals[] = {
+#ifndef _MSC_VER
+    SIGHUP, SIGINT, SIGQUIT, SIGKILL,
+#else
+    SIGINT, SIGILL, SIGFPE, SIGSEGV, SIGTERM, SIGBREAK, SIGABRT,
+#endif
+    0};  // zero terminated
+
+void terminate_request_handler(int param) {
+    char msg[] = "\nReceived signal XX, intend to exit soon.\n"
+         "repeat the signal to force immediate termination.\n";
+    msg[17] = '0' + param / 10;
+    msg[18] = '0' + param % 10;
+    write(1, msg, sizeof(msg) - 1);
+    terminating = true;
+    signal(param, prior_signal_handlers[param]);
+    theSocket.close();
+}
+
 
 const int nowhere = -9999;
 
+
 // parse message
 static void parse_message( const string &msg, int *lat, int *lon ) {
     double dlat, dlon;
@@ -281,8 +313,8 @@ static void parse_message( const string &msg, int *lat, int *lon ) {
     string::size_type pos = text.find( "$GPGGA" );
     if ( pos == string::npos )
     {
-       *lat = -9999.0;
-       *lon = -9999.0;
+       *lat = nowhere;
+       *lon = nowhere;
        return;
     }
     string tmp = text.substr( pos + 7 );
@@ -408,7 +440,8 @@ static void sync_areas( int lat, int lon, int lat_dir, int lon_dir ) {
 
 void getWaitingTile() {
     while ( !waitingTiles.empty() ) {
-       CompletedTiles::iterator ii = completedTiles.find( waitingTiles.front() );
+       CompletedTiles::iterator ii =
+            completedTiles.find( waitingTiles.front() );
        time_t now = time(0);
        if ( ii == completedTiles.end() || ii->second + 600 < now ) {
            sync_tree(waitingTiles.front().c_str());
@@ -422,7 +455,7 @@ void getWaitingTile() {
 
 int main( int argc, char **argv ) {
     int port = 5501;
-    char host[256] = "";        // accept messages from anyone
+    char host[256] = "localhost";
     bool testing = false;
     bool do_checkout(true);
     int verbose(0);
@@ -486,14 +519,12 @@ int main( int argc, char **argv ) {
     // Must call this before any other net stuff
     netInit( &argc,argv );
 
-    netSocket s;
-
-    if ( ! s.open( false ) ) {  // open a UDP socket
+    if ( ! theSocket.open( false ) ) {  // open a UDP socket
         printf("error opening socket\n");
         return -1;
     }
 
-    if ( s.bind( host, port ) == -1 ) {
+    if ( theSocket.bind( host, port ) == -1 ) {
         printf("error binding to port %d\n", port);
         return -1;
     }
@@ -524,7 +555,14 @@ int main( int argc, char **argv ) {
     }
 
 
-    while ( true ) {                    // main loop
+    for (int* sigp=termination_triggering_signals; *sigp; sigp++) {
+        prior_signal_handlers[*sigp] =
+            signal(*sigp, *terminate_request_handler);
+        if (verbose) cout << "Intercepted signal " << *sigp << endl;
+    }
+
+    while ( !terminating ) {
+        // main loop
         recv_msg = false;
         if ( testing ) {
             // No FGFS communications
@@ -532,8 +570,11 @@ int main( int argc, char **argv ) {
             lon = -123;
             recv_msg = (lat != last_lat) || (lon != last_lon);
         } else {
-            s.setBlocking(waitingTiles.empty());
-            len = s.recv(msg, maxlen, 0);
+            if (verbose && waitingTiles.empty()) {
+                cout << "Idle; waiting for FlightGear position\n";
+            }
+            theSocket.setBlocking(waitingTiles.empty());
+            len = theSocket.recv(msg, maxlen, 0);
             if (len >= 0) {
                 msg[len] = '\0';
                 recv_msg = true;
@@ -546,7 +587,7 @@ int main( int argc, char **argv ) {
              // Ignore messages where the location does not change
              if ( lat != last_lat || lon != last_lon ) {
                cout << "pos in msg = " << lat << "," << lon << endl;
-               std::deque<std::string> oldRequests;
+               deque<string> oldRequests;
                oldRequests.swap( waitingTiles );
                 int lat_dir, lon_dir, dist;
                 if ( last_lat == nowhere || last_lon == nowhere ) {
@@ -584,11 +625,11 @@ int main( int argc, char **argv ) {
         }
 
        else if ( testing ) {
-           exit( 0 );
+           terminating = true;
        } else
 
         ulSleep( 1 );
-    } // while true
+    } // while !terminating
         
     return 0;
 }
index 620b4b57e5ea9c6922cce7c3fb0c2ff29d4cca2b..4da358ce71c90e30bbb42e472159ec0abfb9c2d7 100644 (file)
@@ -67,7 +67,7 @@ int main ( int argc, char ** argv )
   ax = new float [ numaxes ] ;
   activeaxes = numaxes;
   
-  if( numaxes < 4 )
+  if( numaxes > 4 )
   {
     printf("max 4 axes joysticks supported at the moment, however %i axes were detected\nWill only use the first 4 axes!\n", numaxes);
     activeaxes = 4;
@@ -101,25 +101,25 @@ int main ( int argc, char ** argv )
         js->read( &b, ax );
        for ( axis = 0 ; axis < activeaxes ; axis++ )
        {
-         long axisvalue = (long int)(ax[axis]*2147483647.0);
-         printf("axisval=%li\n", axisvalue);
-         memcpy(packet+len, &axisvalue, 4);
-         len+=4;
+         int32_t axisvalue = (int32_t)(ax[axis]*2147483647.0);
+         printf("axisval=%li\n", (long)axisvalue);
+         memcpy(packet+len, &axisvalue, sizeof(axisvalue));
+         len+=sizeof(axisvalue);
        }
        // fill emtpy values into packes when less than 4 axes
        for( ; axis < 4; axis++ )
        {
-         long axisvalue = 0;
-         memcpy(packet+len, &axisvalue, 4);
-         len+=4;
+         int32_t axisvalue = 0;
+         memcpy(packet+len, &axisvalue, sizeof(axisvalue));
+         len+=sizeof(axisvalue);
        }
 
-       long int b_l = b;
-        memcpy(packet+len, &b_l, 4);
-        len+=4;
+       int32_t b_l = b;
+        memcpy(packet+len, &b_l, sizeof(b_l));
+        len+=sizeof(b_l);
 
-       char termstr[5] = "\0\0\r\n";
-        memcpy(packet+len, &termstr, 4);
+       const char * termstr = "\0\0\r\n";
+        memcpy(packet+len, termstr, 4);
        len += 4;
 
         c.send( packet, len, 0 );