diff --git a/Nasal/towing/hitch.nas b/Nasal/towing/hitch.nas
index 45a738c9c..aec20ea6e 100644
--- a/Nasal/towing/hitch.nas
+++ b/Nasal/towing/hitch.nas
@@ -1,23 +1,23 @@
#
-# Version: 10. March 2014
+# Version: 30. December 2014
#
# Purpose of this routine:
# ------------------------
#
# - Create visible winch- and towropes for gliders and towplanes
-# - Support of aerotowing and winch for JSBSim-aircrafts (glider and towplanes)
+# - Support of aerotowing and winch for JSBSim-aircraft (glider and towplanes)
#
# This routine is very similar to /FDM/YASim/Hitch.cpp
-# Aerotowing is fully compatible to the YASim functionality.
-# This means that YASim-gliders could be towed by JSBSim-aircrafts and vice versa.
+# Aerotowing is fully compatible to the YASim functionality.
+# This means that YASim-gliders could be towed by JSBSim-aircraft and vice versa.
# Setup-instructions with copy and paste examples are given below:
#
#
-# Setup of visible winch/towropes for Yasim-aircrafts:
-# ----------------------------------------------------
+# Setup of visible winch/towropes for Yasim-aircraft:
+# ----------------------------------------------------
#
-# YASim-aircrafts with winch/aerotowing functionality should work out of the box.
-# Optional you can customize the rope-diameter by adding the following to "your_aircraft-set.xml":
+# YASim-aircraft with winch/aerotowing functionality should work out of the box.
+# Optional you can customize the rope-diameter by adding the following to "your_aircraft-set.xml":
#
#
#
@@ -37,19 +37,17 @@
#
#
#
-# Support of aerotowing and winch for JSBSim-aircrafts (glider and towplanes):
-# ----------------------------------------------------------------------------
+# Support of aerotowing and winch for JSBSim-aircraft (glider and towplanes):
+# ----------------------------------------------------------------------------
#
# 1. Define a hitch in the JSBSim-File. Coordinates according to JSBSims structural frame of reference
-# (x points to the tail, y points to the right wing, z points upwards). Be careful! This
-# coordinates don't appear in the property tree. You can only check them with test flights!
-# The visible towrope is NOT an indicator of correct settings!
-# Unit must be "LBS", frame must be "BODY". The force name is arbitrary.
+# (x points to the tail, y points to the right wing, z points upwards).
+# Unit must be "LBS", frame must be "BODY". The force name is arbitrary.
#
#
#
#
-# 3.65
+# 3.65
# 0.0
# -0.12
#
@@ -61,10 +59,11 @@
#
#
+
# 2. Define controls for aerotowing and winch.
# Add the following key bindings in "yourAircraft-set.xml":
-#
-#
+#
+#
#
#
# Ctrl-o
@@ -74,7 +73,7 @@
#
#
#
-#
+#
#
# o
# Lock aerotow-hook
@@ -83,7 +82,7 @@
#
#
#
-#
+#
#
# O
# Open aerotow-hook
@@ -101,7 +100,7 @@
#
#
#
-#
+#
#
# w
# Start winch
@@ -110,7 +109,7 @@
#
#
#
-#
+#
#
# W
# Open winch-hook
@@ -120,42 +119,53 @@
#
#
#
-#
-#
+#
+#
#
# For towplanes only "key n=79" (Open aerotow-hook) is required!
-#
-#
+
+
# 3. Set mandatory properties:
#
#
#
# hitch
-# 1.5
-# 0.00
-# -0.3
# false
# 0.0
+#
#
#
# hitch
-# 0.0
-# 0.0
-# 0.0
+#
#
#
#
#
# "force_name_jsbsim" must be the external force name in JSBSim.
+# "force-is-calculated-by-other" should be "false" for gliders and "true" for tow planes.
+# "mp-auto-connect-period" is only needed for tow planes and should be "1".
#
# IMPORTANT:
-# JSBSim doesn't provide the hitch coordinates in the property tree. Hence you must set them again to get a
-# visible towrope (local-pos-x/y/z). Unfortunately the coordinate systems are different. Here the coordinates
-# for the "YASim-System" are needed (x points to the nose, y points to the left wing, z points upwards).
-# If you see the rope at the expected position "local-pos-x/y/z" are correct.
-#
-# "force-is-calculated-by-other" should be "false" for gliders and "true" for towplanes.
-# "mp-auto-connect-period" is only needed for towplanes and should be "1".
+# The hitch location is stored twice in the property tree (for tow force and for rope animation).
+# This is necessary to keep the towrope animation compatible to YASim-aircraft.
+# The hitch location for the tow force is stored in "fdm/jsbsim/external_reactions/hitch/location-x(yz)-in" and for the
+# animated towrope in "sim/hitches/aerotow(winch)/local-pos-x(yz)".
+# By default only values for the tow force location have to be defined. The values for the towrope location are set
+# automatically (decoupled-force-and-rope-locations is "false" by default).
+# It is feasible to use different locations for the force and rope. In order to do this, you have to set
+# "decoupled-force-and-rope-locations" to "true" and provide values for "sim/hitches/aerotow(winch)/local-pos-x(yz)".
+# Note that the frame of reference is different. Here the coordinates for the "YASim-System" are needed
+# (x points to the nose, y points to the left wing, z points upwards).
# 4. Set optional properties:
@@ -174,7 +184,7 @@
# 70.
#
# 1000.
-# 1500.
+# 1500.
# 800.
# 100.
# 15.
@@ -193,7 +203,8 @@
#
#
#
-#
+
+
# That's it!
@@ -203,25 +214,25 @@
# AI-planes are identified by the node "ai/models/aircraft/".
# MP-planes (interactice/non-interactive) are identified by the existence of node "ai/models/multiplayer".
# Interactive MP-plane: variables in node "ai/models/multiplayer/sim/hitches/" are updated.
-# Non-interactive MP-plane: variables are not updated (values are either not defined or have "wrong" values
+# Non-interactive MP-plane: variables are not updated (values are either not defined or have "wrong" values
# from a former owner of this node.
-#
+#
# The following properties are transmitted in multiplayer:
# "sim/hitches/aerotow/tow/elastic-constant"
# "sim/hitches/aerotow/tow/weight-per-m-kg-m"
# "sim/hitches/aerotow/tow/dist"
# "sim/hitches/aerotow/tow/connected-to-property-node"
-# "sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign"
+# "sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign"
# "sim/hitches/aerotow/tow/brake-force"
# "sim/hitches/aerotow/tow/end-force-x"
# "sim/hitches/aerotow/tow/end-force-y"
# "sim/hitches/aerotow/tow/end-force-z"
# "sim/hitches/aerotow/is-slave"
# "sim/hitches/aerotow/speed-in-tow-direction"
-# "sim/hitches/aerotow/open", open);
+# "sim/hitches/aerotow/open", open);
# "sim/hitches/aerotow/local-pos-x"
# "sim/hitches/aerotow/local-pos-y"
-# "sim/hitches/aerotow/local-pos-z"
+# "sim/hitches/aerotow/local-pos-z"
#
##############################################################################################################
@@ -229,76 +240,76 @@
# ######################################################################################################################
-# check, if towing support makes sense
+# check, if towing support makes sense
# ######################################################################################################################
# Check if node "sim/hitches" is defined. If not, return!
if (props.globals.getNode("sim/hitches") == nil ) return;
- print("towing is active!");
+ print("towing is active!");
# ######################################################################################################################
-# set defaults / initialize at startup
+# set defaults / initialize at startup
# ######################################################################################################################
-# set defaults for properties that are NOT already defined
+# set defaults for properties that are NOT already defined
- # yasim properties for aerotow (should be already defined for yasim aircrafts but not for JSBSim aircrafts
+ # yasim properties for aerotow (should be already defined for yasim aircraft but not for JSBSim aircraft
if (props.globals.getNode("sim/hitches/aerotow/broken") == nil )
props.globals.getNode("sim/hitches/aerotow/broken", 1).setBoolValue(0);
if (props.globals.getNode("sim/hitches/aerotow/force") == nil )
props.globals.getNode("sim/hitches/aerotow/force", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/force-is-calculated-by-other") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/force-is-calculated-by-other") == nil )
props.globals.getNode("sim/hitches/aerotow/force-is-calculated-by-other", 1).setBoolValue(0);
if (props.globals.getNode("sim/hitches/aerotow/is-slave") == nil )
props.globals.getNode("sim/hitches/aerotow/is-slave", 1).setBoolValue(0);
if (props.globals.getNode("sim/hitches/aerotow/local-pos-x") == nil )
- props.globals.getNode("sim/hitches/aerotow/local-pos-x", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/local-pos-y") == nil )
+ props.globals.getNode("sim/hitches/aerotow/local-pos-x", 1).setValue(0.);
+ if (props.globals.getNode("sim/hitches/aerotow/local-pos-y") == nil )
props.globals.getNode("sim/hitches/aerotow/local-pos-y", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/local-pos-z") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/local-pos-z") == nil )
props.globals.getNode("sim/hitches/aerotow/local-pos-z", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/mp-auto-connect-period") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/mp-auto-connect-period") == nil )
props.globals.getNode("sim/hitches/aerotow/mp-auto-connect-period", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/mp-time-lag") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/mp-time-lag") == nil )
props.globals.getNode("sim/hitches/aerotow/mp-time-lag", 1).setValue(0.);
- #if (props.globals.getNode("sim/hitches/aerotow/open") == nil )
+ #if (props.globals.getNode("sim/hitches/aerotow/open") == nil )
props.globals.getNode("sim/hitches/aerotow/open", 1).setBoolValue(1);
- if (props.globals.getNode("sim/hitches/aerotow/speed-in-tow-direction") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/speed-in-tow-direction") == nil )
props.globals.getNode("sim/hitches/aerotow/speed-in-tow-direction", 1).setValue(0.);
if (props.globals.getNode("sim/hitches/aerotow/tow/brake-force") == nil )
- props.globals.getNode("sim/hitches/aerotow/tow/brake-force", 1).setValue(12345.);
- if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-node") == nil )
+ props.globals.getNode("sim/hitches/aerotow/tow/brake-force", 1).setValue(12345.);
+ if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-node") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-node", 1).setBoolValue(0);
- if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign", 1).setValue("");
- if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id") == nil )
- props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id", 1).setIntValue(0);
- if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-mp-node") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id") == nil )
+ props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id", 1).setIntValue(0);
+ if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-mp-node") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-mp-node", 1).setBoolValue(0);
- if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-property-node") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/connected-to-property-node") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-property-node", 1).setBoolValue(0);
- if (props.globals.getNode("sim/hitches/aerotow/tow/dist") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/dist") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/dist", 1).setValue(0.);
if (props.globals.getNode("sim/hitches/aerotow/tow/elastic-constant") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/elastic-constant", 1).setValue(9111.);
- if (props.globals.getNode("sim/hitches/aerotow/tow/end-force-x") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/end-force-x") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/end-force-x", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/tow/end-force-y") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/end-force-y") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/end-force-y", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/tow/end-force-z") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/end-force-z") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/end-force-z", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/aerotow/tow/length") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/length") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/length", 1).setValue(60.);
- if (props.globals.getNode("sim/hitches/aerotow/tow/node") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/node") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/node", 1).setValue("");
if (props.globals.getNode("sim/hitches/aerotow/tow/weight-per-m-kg-m") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/weight-per-m-kg-m", 1).setValue(0.35);
- # additional properties
- if (props.globals.getNode("sim/hitches/aerotow/oldOpen") == nil )
+ # additional properties
+ if (props.globals.getNode("sim/hitches/aerotow/oldOpen") == nil )
props.globals.getNode("sim/hitches/aerotow/oldOpen", 1).setBoolValue(1);
-
+
# new properties for towrope
if (props.globals.getNode("sim/hitches/aerotow/rope/exist") == nil )
props.globals.getNode("sim/hitches/aerotow/rope/exist", 1).setBoolValue(0);
@@ -312,47 +323,47 @@
# new properties for JSBSim aerotow
if ( getprop("sim/flight-model") == "jsb" ) {
if (props.globals.getNode("sim/hitches/aerotow/force_name_jsbsim") == nil )
- props.globals.getNode("sim/hitches/aerotow/force_name_jsbsim", 1).setValue("hitch");
- if (props.globals.getNode("sim/hitches/aerotow/mp_oldOpen") == nil )
+ props.globals.getNode("sim/hitches/aerotow/force_name_jsbsim", 1).setValue("hitch");
+ if (props.globals.getNode("sim/hitches/aerotow/mp_oldOpen") == nil )
props.globals.getNode("sim/hitches/aerotow/mp_oldOpen", 1).setBoolValue(1);
- if (props.globals.getNode("sim/hitches/aerotow/tow/mp_last_reporded_dist") == nil )
+ if (props.globals.getNode("sim/hitches/aerotow/tow/mp_last_reporded_dist") == nil )
props.globals.getNode("sim/hitches/aerotow/tow/mp_last_reported_dist", 1).setValue(0.);
}
- # yasim properties for winch (should be already defined for yasim aircrafts but not for JSBSim aircrafts
- #if (props.globals.getNode("sim/hitches/winch/open") == nil )
+ # yasim properties for winch (should already be defined for yasim aircraft but not for JSBSim aircraft
+ #if (props.globals.getNode("sim/hitches/winch/open") == nil )
props.globals.getNode("sim/hitches/winch/open", 1).setBoolValue(1);
if (props.globals.getNode("sim/hitches/winch/broken") == nil )
props.globals.getNode("sim/hitches/winch/broken", 1).setBoolValue(0);
if (props.globals.getNode("sim/hitches/winch/winch/global-pos-x") == nil )
props.globals.getNode("sim/hitches/winch/winch/global-pos-x", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/winch/winch/global-pos-y") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/global-pos-y") == nil )
props.globals.getNode("sim/hitches/winch/winch/global-pos-y", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/winch/winch/global-pos-z") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/global-pos-z") == nil )
props.globals.getNode("sim/hitches/winch/winch/global-pos-z", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/winch/winch/initial-tow-length-m") == nil )
- props.globals.getNode("sim/hitches/winch/winch/initial-tow-length-m", 1).setValue(1000.);
- if (props.globals.getNode("sim/hitches/winch/winch/max-tow-length-m") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/initial-tow-length-m") == nil )
+ props.globals.getNode("sim/hitches/winch/winch/initial-tow-length-m", 1).setValue(1000.);
+ if (props.globals.getNode("sim/hitches/winch/winch/max-tow-length-m") == nil )
props.globals.getNode("sim/hitches/winch/winch/max-tow-length-m", 1).setValue(1500.);
- if (props.globals.getNode("sim/hitches/winch/winch/min-tow-length-m") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/min-tow-length-m") == nil )
props.globals.getNode("sim/hitches/winch/winch/min-tow-length-m", 1).setValue(1.);
- if (props.globals.getNode("sim/hitches/winch/tow/length") == nil )
+ if (props.globals.getNode("sim/hitches/winch/tow/length") == nil )
props.globals.getNode("sim/hitches/winch/tow/length", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/winch/tow/dist") == nil )
+ if (props.globals.getNode("sim/hitches/winch/tow/dist") == nil )
props.globals.getNode("sim/hitches/winch/tow/dist", 1).setValue(0.);
if (props.globals.getNode("sim/hitches/winch/tow/elastic-constant") == nil )
props.globals.getNode("sim/hitches/winch/tow/elastic-constant", 1).setValue(40001.);
if (props.globals.getNode("sim/hitches/winch/tow/weight-per-m-kg-m") == nil )
props.globals.getNode("sim/hitches/winch/tow/weight-per-m-kg-m", 1).setValue(0.1);
- # additional properties
- if (props.globals.getNode("sim/hitches/winch/oldOpen") == nil )
+ # additional properties
+ if (props.globals.getNode("sim/hitches/winch/oldOpen") == nil )
props.globals.getNode("sim/hitches/winch/oldOpen", 1).setBoolValue(1);
- if (props.globals.getNode("sim/hitches/winch/winch/max-spool-speed-m-s") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/max-spool-speed-m-s") == nil )
props.globals.getNode("sim/hitches/winch/winch/max-spool-speed-m-s", 1).setValue(40.);
- # new properties for winch-rope
+ # new properties for winch-rope
if (props.globals.getNode("sim/hitches/winch/rope/exist") == nil )
props.globals.getNode("sim/hitches/winch/rope/exist", 1).setBoolValue(0);
if (props.globals.getNode("sim/hitches/winch/rope/model_id") == nil )
@@ -366,38 +377,51 @@
if ( getprop("sim/flight-model") == "jsb" ) {
if (props.globals.getNode("sim/hitches/winch/force_name_jsbsim") == nil )
props.globals.getNode("sim/hitches/winch/force_name_jsbsim", 1).setValue("hitch");
- if (props.globals.getNode("sim/hitches/winch/automatic-release-angle-deg") == nil )
+ if (props.globals.getNode("sim/hitches/winch/automatic-release-angle-deg") == nil )
props.globals.getNode("sim/hitches/winch/automatic-release-angle-deg", 1).setValue(361.);
if (props.globals.getNode("sim/hitches/winch/winch/clutched") == nil )
props.globals.getNode("sim/hitches/winch/winch/clutched", 1).setBoolValue(0);
- if (props.globals.getNode("sim/hitches/winch/winch/actual-spool-speed-m-s") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/actual-spool-speed-m-s") == nil )
props.globals.getNode("sim/hitches/winch/winch/actual-spool-speed-m-s", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/winch/winch/spool-acceleration-m-s-s") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/spool-acceleration-m-s-s") == nil )
props.globals.getNode("sim/hitches/winch/winch/spool-acceleration-m-s-s", 1).setValue(8.);
- if (props.globals.getNode("sim/hitches/winch/winch/max-unspool-speed-m-s") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/max-unspool-speed-m-s") == nil )
props.globals.getNode("sim/hitches/winch/winch/max-unspool-speed-m-s", 1).setValue(40.);
- if (props.globals.getNode("sim/hitches/winch/winch/actual-force-N") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/actual-force-N") == nil )
props.globals.getNode("sim/hitches/winch/winch/actual-force-N", 1).setValue(0.);
- if (props.globals.getNode("sim/hitches/winch/winch/max-force-N") == nil )
+ if (props.globals.getNode("sim/hitches/winch/winch/max-force-N") == nil )
props.globals.getNode("sim/hitches/winch/winch/max-force-N", 1).setValue(1000.);
- if (props.globals.getNode("sim/hitches/winch/winch/max-power-kW") == nil )
- props.globals.getNode("sim/hitches/winch/winch/max-power-kW", 1).setValue(123.);
+ if (props.globals.getNode("sim/hitches/winch/winch/max-power-kW") == nil )
+ props.globals.getNode("sim/hitches/winch/winch/max-power-kW", 1).setValue(123.);
if (props.globals.getNode("sim/hitches/winch/tow/break-force-N") == nil )
- props.globals.getNode("sim/hitches/winch/tow/break-force-N", 1).setValue(12345.);
+ props.globals.getNode("sim/hitches/winch/tow/break-force-N", 1).setValue(12345.);
if (props.globals.getNode("sim/hitches/winch/winch/magic-constant") == nil )
- props.globals.getNode("sim/hitches/winch/winch/magic-constant", 1).setValue(500.);
+ props.globals.getNode("sim/hitches/winch/winch/magic-constant", 1).setValue(500.);
}
-
+ # new properties for JSBSim aerotow and winch
+ if ( getprop("sim/flight-model") == "jsb" ) {
+ if (props.globals.getNode("sim/hitches/aerotow/decoupled-force-and-rope-locations") == nil )
+ props.globals.getNode("sim/hitches/aerotow/decoupled-force-and-rope-locations", 1).setBoolValue(0);
+ if (props.globals.getNode("sim/hitches/winch/decoupled-force-and-rope-locations") == nil )
+ props.globals.getNode("sim/hitches/winch/decoupled-force-and-rope-locations", 1).setBoolValue(0);
+ # consider older JSBSim-versions which do NOT provide the locations of external_reactions in the property tree
+ var hitchname_aerotow = getprop("sim/hitches/aerotow/force_name_jsbsim");
+ var hitchname_winch = getprop("sim/hitches/winch/force_name_jsbsim");
+ if (props.globals.getNode("fdm/jsbsim/external_reactions/" ~ hitchname_aerotow ~ "/location-x-in") == nil )
+ props.globals.getNode("sim/hitches/aerotow/decoupled-force-and-rope-locations").setBoolValue(1);
+ if (props.globals.getNode("fdm/jsbsim/external_reactions/" ~ hitchname_winch ~ "/location-x-in") == nil )
+ props.globals.getNode("sim/hitches/winch/decoupled-force-and-rope-locations").setBoolValue(1);
+ }
# ######################################################################################################################
-# main function
+# main function
# ######################################################################################################################
var towing = func {
-
+
#print("function towing is running");
-
+
var FT2M = 0.30480;
var M2FT = 1 / FT2M;
var dt = 0;
@@ -406,18 +430,18 @@ var towing = func {
var open = getprop("sim/hitches/aerotow/open");
var oldOpen = getprop("sim/hitches/aerotow/oldOpen");
-
+
if ( open != oldOpen ) { # check if my hitch state has changed, if yes: message
#print("state has changed: open=",open," oldOpen=",oldOpen);
if ( !open ) { # my hitch was open and is closed now
if ( getprop("sim/flight-model") == "jsb" ) {
- var distance = getprop("sim/hitches/aerotow/tow/dist");
+ var distance = getprop("sim/hitches/aerotow/tow/dist");
var towlength_m = getprop("sim/hitches/aerotow/tow/length");
if ( distance > towlength_m * 1.0001 ) {
setprop("sim/messages/pilot", sprintf("Could not lock hitch (tow length is insufficient) on hitch %i!",
getprop("sim/hitches/aerotow/tow/connected-to-mp-node")));
- props.globals.getNode("sim/hitches/aerotow/open").setBoolValue(1); # open my hitch again
+ props.globals.getNode("sim/hitches/aerotow/open").setBoolValue(1); # open my hitch again
} # mp aircraft to far away
else { # my hitch is closed
setprop("sim/messages/pilot", sprintf("Locked hitch aerotow %i!",
@@ -427,28 +451,28 @@ var towing = func {
} # end: JSBSim
if ( !getprop("sim/hitches/aerotow/open") ) {
# setup ai-towrope
- createTowrope("aerotow");
+ createTowrope("aerotow");
- # set default hitch coordinates (needed for Ai- and non-interactive MP aircrafts)
- setAIObjectDefaults() ;
- }
+ # set default hitch coordinates (needed for Ai- and non-interactive MP aircraft)
+ setAIObjectDefaults() ;
+ }
} # end hitch is closed
-
+
if ( open ) { # my hitch is now open
if ( getprop("sim/flight-model") == "jsb" ) {
if ( getprop("sim/hitches/aerotow/broken") ) {
setprop("sim/messages/pilot", sprintf("Oh no, the tow is broken"));
- }
+ }
else {
setprop("sim/messages/pilot", sprintf("Opened hitch aerotow %i!",
getprop("sim/hitches/aerotow/tow/connected-to-mp-node")));
}
releaseHitch("aerotow"); # open=1 / forces=0
} # end: JSBSim
- removeTowrope("aerotow"); # remove towrope model
- } # end hitch is open
-
- setprop("sim/hitches/aerotow/oldOpen",open);
+ removeTowrope("aerotow"); # remove towrope model
+ } # end hitch is open
+
+ setprop("sim/hitches/aerotow/oldOpen",open);
} # end hitch state has changed
if (!open ) {
@@ -473,17 +497,17 @@ var towing = func {
var winchopen = getprop("sim/hitches/winch/open");
var wincholdOpen = getprop("sim/hitches/winch/oldOpen");
-
+
if ( winchopen != wincholdOpen ) { # check if my hitch state has changed, if yes: message
#print("winch state has changed: open=",winchopen," oldOpen=",wincholdOpen);
if ( !winchopen ) { # my hitch was open and is closed now
if ( getprop("sim/flight-model") == "jsb" ) {
- var distance = getprop("sim/hitches/winch/tow/dist");
+ var distance = getprop("sim/hitches/winch/tow/dist");
var towlength_m = getprop("sim/hitches/winch/tow/length");
if ( distance > towlength_m ) {
setprop("sim/messages/pilot", sprintf("Could not lock hitch (tow length is insufficient) on hitch %i!",
getprop("sim/hitches/aerotow/tow/connected-to-mp-node")));
- props.globals.getNode("sim/hitches/aerotow/open").setBoolValue(1); # open my hitch again
+ props.globals.getNode("sim/hitches/aerotow/open").setBoolValue(1); # open my hitch again
} # mp aircraft to far away
else { # my hitch is closed
setprop("sim/messages/pilot", sprintf("Locked hitch winch %i!",
@@ -495,24 +519,24 @@ var towing = func {
} # end: JSBSim
if ( !getprop("sim/hitches/winch/open") ) {
# setup ai-towrope
- createTowrope("winch");
+ createTowrope("winch");
- # set default hitch coordinates (needed for Ai- and non-interactive MP aircrafts)
- setAIObjectDefaults() ;
- }
+ # set default hitch coordinates (needed for Ai- and non-interactive MP aircraft)
+ setAIObjectDefaults() ;
+ }
} # end hitch is closed
-
+
if ( winchopen ) { # my hitch is now open
if ( getprop("sim/flight-model") == "jsb" ) {
if ( getprop("sim/hitches/winch/broken") ) {
setprop("sim/messages/pilot", sprintf("Oh no, the tow is broken"));
- }
- releaseHitch("winch");
+ }
+ releaseHitch("winch");
} # end: JSBSim
pull_in_rope();
} # end hitch is open
-
- setprop("sim/hitches/winch/oldOpen",winchopen);
+
+ setprop("sim/hitches/winch/oldOpen",winchopen);
} # end hitch state has changed
if (!winchopen ) {
@@ -520,7 +544,7 @@ var towing = func {
}
settimer( towing, dt );
-
+
} # end towing
@@ -531,104 +555,103 @@ var towing = func {
var findBestAIObject = func (){
# the nearest found plane, that is close enough will be used
- # set some default variables, needed later to identify if the found object is
+ # set some default variables, needed later to identify if the found object is
# an AI-Object, a "non-interactiv MP-Object or an interactive MP-Object
-
+
# local variables
var aiobjects = []; # keeps the ai-planes from the property tree
- var AI_id = 0; # id of towplane
- var callsign = 0; # callsign of towplane
var aiPosition = geo.Coord.new(); # current processed ai-plane
- var lat_deg = 0; # latitude of current processed aiobject
- var lon_deg = 0; # longitude of current processed aiobject
- var alt_m = 0; # altitude of current processed aiobject
var myPosition = geo.Coord.new(); # coordinates of glider
var distance_m = 0; # distance to ai-plane
var FT2M = 0.30480;
-
+
var nodeIsAiAircraft = 0;
var nodeIsMpAircraft = 0;
var running_as_autoconnect = 0;
var mp_open_last_state = 0;
var isSlave = 0;
-
- if ( getprop("sim/flight-model") == "yasim" ) return; # bypass this routine for Yasim-aircrafts
-
+
+ if ( getprop("sim/flight-model") == "yasim" ) return; # bypass this routine for Yasim-aircraft
+
#print("findBestAIObject");
-
+
if (props.globals.getNode("sim/hitches/aerotow/mp-auto-connect-period").getValue() != 0 ) {
var running_as_autoconnect = 1;
#print("findBestAIObject: running as auto connect");
}
-
- var towlength_m = props.globals.getNode("sim/hitches/aerotow/tow/length").getValue();
+
+ var towlength_m = props.globals.getNode("sim/hitches/aerotow/tow/length").getValue();
var bestdist_m = towlength_m; # initial value
-
+
myPosition = geo.aircraft_position();
# todo: calculate exact hitch position
if( running_as_autoconnect ) {
var mycallsign = props.globals.getNode("sim/multiplay/callsign").getValue();
- #print('mycallsign=',mycallsign);
+ #print('mycallsign=',mycallsign);
}
var found = 0;
- aiobjects = props.globals.getNode("ai/models").getChildren();
- foreach (var aimember; aiobjects) {
+ aiobjects = props.globals.getNode("ai/models").getChildren();
+ foreach (var aimember; aiobjects) {
if ( (var node = aimember.getName() ) != nil ) {
nodeIsAiAircraft = 0;
nodeIsMpAircraft = 0;
if ( sprintf("%8s",node) == "aircraft" ) nodeIsAiAircraft = 1;
if ( sprintf("%11s",node) == "multiplayer" ) nodeIsMpAircraft = 1;
#print("found NodeName=",node," nodeIsAiAircraft=",nodeIsAiAircraft," nodeIsMpAircraft=",nodeIsMpAircraft );
-
- if( !nodeIsAiAircraft and !nodeIsMpAircraft ) continue;
-
+ if ( !nodeIsAiAircraft and !nodeIsMpAircraft ) continue;
+ if ( !aimember.getNode("valid").getValue() ) continue; # node is invalid
+
if( running_as_autoconnect ) {
if ( !nodeIsMpAircraft ) continue;
- if ( aimember.getValue("sim/hitches/aerotow/open") == 1 ) continue; # if mp hook open, auto-connect isn't possible
- if (mycallsign != aimember.getValue("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign") ) continue ; # I'm the wrong one
+ #if ( aimember.getValue("sim/hitches/aerotow/open") == nil ) continue; # this node MUST exist for mp-aircraft which want to be towed
+ #if ( aimember.getValue("sim/hitches/aerotow/open") == 1 ) continue; # if mp hook open, auto-connect is NOT possible
+ if ( aimember.getValue("sim/hitches/aerotow/open") != 0 ) continue;
+ if (mycallsign != aimember.getValue("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign") ) continue ; # I am the wrong one
+ if ( !getprop("sim/hitches/aerotow/mp_oldOpen") ) continue; # this prevents an unwanted immediate auto-connect after the dragger
+ # released its hitch. Firstly wait for a reported "open" hitch from glider
}
- var lat_deg = aimember.getNode("position/latitude-deg").getValue();
- var lon_deg = aimember.getNode("position/longitude-deg").getValue();
- var alt_m = aimember.getNode("position/altitude-ft").getValue() * FT2M;
-
- var aiPosition = geo.Coord.set_latlon( lat_deg, lon_deg, alt_m );
- distance_m = (myPosition.distance_to(aiPosition));
- #print('distance_m=',distance_m,' bestdist_m=',bestdist_m);
- if ( distance_m < bestdist_m ) {
+ var lat_deg = aimember.getNode("position/latitude-deg").getValue();
+ var lon_deg = aimember.getNode("position/longitude-deg").getValue();
+ var alt_m = aimember.getNode("position/altitude-ft").getValue() * FT2M;
+
+ var aiPosition = geo.Coord.set_latlon( lat_deg, lon_deg, alt_m );
+ distance_m = (myPosition.distance_to(aiPosition));
+ #print('distance_m=',distance_m,' bestdist_m=',bestdist_m);
+ if ( distance_m < bestdist_m ) {
bestdist_m = distance_m;
- var towEndNode = node;
+ var towEndNode = node;
var nodeID = aimember.getNode("id").getValue();
var aicallsign = aimember.getNode("callsign").getValue();
#print('nodeId=',nodeID,' AiCallsign=',aicallsign);
- #set properties
+ #set properties
props.globals.getNode("sim/hitches/aerotow/open").setBoolValue(0);
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-node").setBoolValue(nodeIsAiAircraft);
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-mp-node").setBoolValue(nodeIsMpAircraft);
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign").setValue(aicallsign);
- props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id").setIntValue(nodeID);
+ props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id").setIntValue(nodeID);
props.globals.getNode("sim/hitches/aerotow/tow/connected-to-property-node").setBoolValue(1);
props.globals.getNode("sim/hitches/aerotow/tow/node").setValue(towEndNode);
props.globals.getNode("sim/hitches/aerotow/tow/dist").setValue(bestdist_m);
props.globals.getNode("sim/hitches/aerotow/tow/mp_last_reported_dist", 1).setValue(0.);
- # Set some dummy values. In case of an "interactive"-MP plane
+ # Set some dummy values. In case of an "interactive"-MP plane
# the correct values will be transmitted in the following loop
aimember.getNode("sim/hitches/aerotow/local-pos-x",1).setValue(-5.);
aimember.getNode("sim/hitches/aerotow/local-pos-y",1).setValue(0.);
aimember.getNode("sim/hitches/aerotow/local-pos-z",1).setValue(0.);
aimember.getNode("sim/hitches/aerotow/tow/dist",1).setValue(-1.);
-
+
found = 1;
- }
- }
- }
+ } # end distance_m < bestdist_m
+ } # end node != nil
+ } # end loop aiobjects
if (found) {
if ( !running_as_autoconnect) {
setprop("sim/messages/pilot", sprintf("%s, I am on your hook, distance %4.3f meter.",aicallsign,bestdist_m));
@@ -640,17 +663,20 @@ var findBestAIObject = func (){
isSlave = 1;
props.globals.getNode("sim/hitches/aerotow/is-slave").setBoolValue(isSlave);
}
- # set the dist value to some value below the tow length (if not, the hitch would open the next calc force run
- distance_m = towlength_m * 0.5;
+
props.globals.getNode("sim/hitches/aerotow/mp_oldOpen").setBoolValue(1);
-
- } # end: if found
+
+ } # end: if found
else {
if (!running_as_autoconnect) {
setprop("sim/messages/atc", sprintf("Sorry, no aircraft for aerotow!"));
}
- }
-
+ else{
+ #print("auto-connect: found=0");
+ props.globals.getNode("sim/hitches/aerotow/mp_oldOpen").setBoolValue(1);
+ }
+ }
+
} # End function findBestAIObject
@@ -663,7 +689,7 @@ towing();
# ######################################################################################################################
-# aerotow function
+# aerotow function
# ######################################################################################################################
var aerotow = func (open){
@@ -671,105 +697,122 @@ var aerotow = func (open){
#print("function aerotow is running");
# if (!open ) {
-
+
########################################### my hitch position ############################################
-
+
myPosition = geo.aircraft_position();
var my_head_deg = getprop("orientation/heading-deg");
var my_roll_deg = getprop("orientation/roll-deg");
var my_pitch_deg = getprop("orientation/pitch-deg");
-
+
# hook coordinates in Yasim-system (x-> nose / y -> left wing / z -> up)
+ assignHitchLocations("aerotow");
var x = getprop("sim/hitches/aerotow/local-pos-x");
var y = getprop("sim/hitches/aerotow/local-pos-y");
var z = getprop("sim/hitches/aerotow/local-pos-z");
var alpha_deg = my_roll_deg * (1.); # roll clockwise (looking in x-direction) := +
var beta_deg = my_pitch_deg * (-1.); # pitch clockwise (looking in y-direction) := -
-
+
# transform hook coordinates
var Xn = PointRotate3D(x:x,y:y,z:z,xr:0.,yr:0.,zr:0.,alpha_deg:alpha_deg,beta_deg:beta_deg,gamma_deg:0.);
var install_distance_m = Xn[0]; # in front of ref-point of glider
var install_side_m = Xn[1];
- var install_alt_m = Xn[2];
-
- var myHitch_pos = myPosition.apply_course_distance( my_head_deg , install_distance_m );
- var myHitch_pos = myPosition.apply_course_distance( my_head_deg - 90. , install_side_m );
- myHitch_pos.set_alt(myPosition.alt() + install_alt_m);
-
+ var install_alt_m = Xn[2];
+
+ var myHitch_pos = myPosition.apply_course_distance( my_head_deg , install_distance_m );
+ var myHitch_pos = myPosition.apply_course_distance( my_head_deg - 90. , install_side_m );
+ myHitch_pos.set_alt(myPosition.alt() + install_alt_m);
+
########################################### ai hitch position ############################################
-
- var aiNodeID = getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id"); # id of former found ai/mp aircraft
+
+ #var aiNodeID = getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id"); # id of former found ai/mp aircraft
#print("aiNodeID=",aiNodeID);
-
- aiobjects = props.globals.getNode("ai/models").getChildren();
- foreach (var aimember; aiobjects) {
- if ( (var c = aimember.getNode("id") ) != nil ) {
- var testprop = c.getValue();
- if ( testprop == aiNodeID) {
+ var aiCallsign = getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign"); # callsign of former found ai/mp aircraft
+
+ var found = 0;
+
+ aiobjects = props.globals.getNode("ai/models").getChildren();
+ foreach (var aimember; aiobjects) {
+ if ( (var c = aimember.getNode("id") ) != nil ) {
+ if ( !aimember.getNode("valid").getValue() ) continue; # node is invalid
+
+ # Identifying the MP-aircraft by its node-id works fine with JSBSim-aircraft but NOT with YASim.
+ # In YASim the node-id is not updated which could lead to complications (e.g. node-id changes after "Pause" or "Exit").
+ #var testprop = c.getValue();
+ #if ( testprop == aiNodeID) {
+
+ # Identifying the MP-aircraft by its callsign works fine with JSBSim AND YASim-aircraft
+ var testprop = aimember.getNode("callsign").getValue();
+ if ( testprop == aiCallsign ) {
+
+ found = found + 1;
+
+ ###################### check status of ai hitch ######################
+ if ( getprop("sim/flight-model") == "jsb" ) {
+ # check if the multiplayer hitch state has changed
+ # this trick avoids immediate opening after locking because MP-aircraft has not yet reported a locked hitch
+ if ( (var d = aimember.getNode("sim/hitches/aerotow/open") ) != nil ) {
+ var mpOpen = aimember.getNode("sim/hitches/aerotow/open").getValue();
+ var mp_oldOpen = getprop("sim/hitches/aerotow/mp_oldOpen");
+ #print('mpOpen=',mpOpen,' mp_oldOpen=',mp_oldOpen);
+ if ( mpOpen != mp_oldOpen ) { # state has changed: was open and is now locked OR was locked and is now open
+ if ( mpOpen ) {
+ setprop("sim/messages/ai-plane", sprintf("%s: I have released the tow!",getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign")) );
+ releaseHitch("aerotow"); # my open=1 / forces=0 / remove towrope
+ } # end: open
+ props.globals.getNode("sim/hitches/aerotow/mp_oldOpen").setBoolValue(mpOpen);
+ } # end: state has changed
+ } # end: node is available
+ } #end : JSBSim
+ ########################################################################
+
# get coordinates
- var ai_lat = aimember.getNode("position/latitude-deg").getValue();
- var ai_lon = aimember.getNode("position/longitude-deg").getValue();
- var ai_alt = (aimember.getNode("position/altitude-ft").getValue()) * FT2M;
+ var ai_lat = aimember.getNode("position/latitude-deg").getValue();
+ var ai_lon = aimember.getNode("position/longitude-deg").getValue();
+ var ai_alt = (aimember.getNode("position/altitude-ft").getValue()) * FT2M;
#print("ai_lat,lon,alt",ai_lat,ai_lon,ai_alt);
-
+
var ai_pitch_deg = aimember.getNode("orientation/pitch-deg").getValue();
var ai_roll_deg = aimember.getNode("orientation/roll-deg").getValue();
var ai_head_deg = aimember.getNode("orientation/true-heading-deg").getValue();
var aiHitchX = aimember.getNode("sim/hitches/aerotow/local-pos-x").getValue();
var aiHitchY = aimember.getNode("sim/hitches/aerotow/local-pos-y").getValue();
- var aiHitchZ = aimember.getNode("sim/hitches/aerotow/local-pos-z").getValue();
+ var aiHitchZ = aimember.getNode("sim/hitches/aerotow/local-pos-z").getValue();
- if ( getprop("sim/flight-model") == "jsb" ) {
- # check if the multiplayer hitch state has changed
- # this trick avoids immediate opening after locking because MP-aircraft has not yet reported a locked hitch
- if ( (var d = aimember.getNode("sim/hitches/aerotow/open") ) != nil ) {
- var mpOpen = aimember.getNode("sim/hitches/aerotow/open").getValue();
- var mp_oldOpen = getprop("sim/hitches/aerotow/mp_oldOpen");
- #print('mpOpen=',mpOpen,' mp_oldOpen=',mp_oldOpen);
- if ( mpOpen != mp_oldOpen ) { # state has changed: was open and is now locked OR was locked and is now open
- if ( mpOpen ) {
- setprop("sim/messages/ai-plane", sprintf("%s: I have released the tow!",getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign")) );
- releaseHitch("aerotow"); # my open=1 / forces=0 / remove towrope
- } # end: open
- props.globals.getNode("sim/hitches/aerotow/mp_oldOpen").setBoolValue(mpOpen);
- } # end: state has changed
- } # end: node is available
- } #end : JSBSim
-
var aiPosition = geo.Coord.set_latlon( ai_lat, ai_lon, ai_alt );
-
+
var alpha_deg = ai_roll_deg * (1.);
- var beta_deg = ai_pitch_deg * (-1.);
+ var beta_deg = ai_pitch_deg * (-1.);
# transform hook coordinates
var Xn = PointRotate3D(x:aiHitchX,y:aiHitchY,z:aiHitchZ,xr:0.,yr:0.,zr:0.,alpha_deg:alpha_deg,beta_deg:beta_deg,gamma_deg:0.);
- var install_distance_m = Xn[0]; # in front of ref-point of glider
+ var install_distance_m = Xn[0]; # in front of ref-point of glider
var install_side_m = Xn[1];
- var install_alt_m = Xn[2];
+ var install_alt_m = Xn[2];
- var aiHitch_pos = aiPosition.apply_course_distance( ai_head_deg , install_distance_m );
- var aiHitch_pos = aiPosition.apply_course_distance( ai_head_deg - 90. , install_side_m );
- aiHitch_pos.set_alt(aiPosition.alt() + install_alt_m);
+ var aiHitch_pos = aiPosition.apply_course_distance( ai_head_deg , install_distance_m );
+ var aiHitch_pos = aiPosition.apply_course_distance( ai_head_deg - 90. , install_side_m );
+ aiHitch_pos.set_alt(aiPosition.alt() + install_alt_m);
########################################### distance between hitches #####################################
-
+
var distance = (myHitch_pos.direct_distance_to(aiHitch_pos)); # distance to plane in meter
var aiHitchheadto = (myHitch_pos.course_to(aiHitch_pos));
var height = myHitch_pos.alt() - aiHitch_pos.alt();
var aiHitchpitchto = -math.asin((myHitch_pos.alt()-aiHitch_pos.alt())/distance) / 0.01745;
#print(" pitch: ", aiHitchpitchto);
-
+
# update position of rope
setprop("ai/models/aerotowrope/position/latitude-deg", myHitch_pos.lat());
setprop("ai/models/aerotowrope/position/longitude-deg", myHitch_pos.lon());
setprop("ai/models/aerotowrope/position/altitude-ft", myHitch_pos.alt() * M2FT);
#print("ai_lat,lon,alt",myHitch_pos.lat()," ",myHitch_pos.lon()," ",myHitch_pos.alt() );
-
+
# update pitch and heading of rope
setprop("ai/models/aerotowrope/orientation/true-heading-deg", aiHitchheadto);
setprop("ai/models/aerotowrope/orientation/pitch-deg", aiHitchpitchto);
@@ -778,31 +821,31 @@ var aerotow = func (open){
setprop("sim/hitches/aerotow/tow/dist", distance);
#print("distance=",distance);
-
+
############################################# calc forces ##################################################
- # calc forces only for JSBSim-aircrafts
-
- # tow-end-forces must be reported in N to be consiststent to Yasim-aircrafts
- # hitch-forces must be LBS to be consistent to the JSBSim "external_forces/.../magnitude" definition
+ # calc forces only for JSBSim-aircraft
- if ( getprop("sim/flight-model") == "jsb" ) {
+ # tow-end-forces must be reported in N to be consiststent to Yasim-aircraft
+ # hitch-forces must be LBS to be consistent to the JSBSim "external_forces/.../magnitude" definition
+
+ if ( getprop("sim/flight-model") == "jsb" ) {
#print("Force-Routine");
# check if the MP-aircraft properties have been updated. If not (maybe due to time-lag) bypass force calculation (use previous forces instead)
var mp_reported_dist = aimember.getNode("sim/hitches/aerotow/tow/dist").getValue();
var mp_last_reported_dist = getprop("sim/hitches/aerotow/tow/mp_last_reported_dist");
- var mp_delta_reported_dist = mp_reported_dist - mp_last_reported_dist ;
+ var mp_delta_reported_dist = mp_reported_dist - mp_last_reported_dist ;
setprop("sim/hitches/aerotow/tow/mp_last_reported_dist",mp_reported_dist);
var mp_delta_reported_dist2 = mp_delta_reported_dist * mp_delta_reported_dist ; # we need the absolute value
- if ( (mp_delta_reported_dist2 > 0.0000001) or (mp_reported_dist < 0. )){ # we have the updated MP coordinates (no time lag)
+ if ( (mp_delta_reported_dist2 > 0.0000001) or (mp_reported_dist < 0. )){ # we have the updated MP coordinates (no time lag)
# or the MP-aircraft is a non-interactive mp plane (mp_reported_dist = -1)
- # => update forces else use the old forces!
-
- var breakforce_N = getprop("sim/hitches/aerotow/tow/brake-force"); # could be different in both aircrafts
+ # => update forces else use the old forces!
+
+ var breakforce_N = getprop("sim/hitches/aerotow/tow/brake-force"); # could be different in both aircraft
var isSlave = getprop("sim/hitches/aerotow/is-slave");
- if ( !isSlave ){ # if we are master, we have to calculate the forces
+ if ( !isSlave ){ # if we are master, we have to calculate the forces
#print("master: calc forces");
var elastic_constant = getprop("sim/hitches/aerotow/tow/elastic-constant");
var towlength_m = getprop("sim/hitches/aerotow/tow/length");
@@ -823,26 +866,26 @@ var aerotow = func (open){
var forcetowX_N = aimember.getNode("sim/hitches/aerotow/tow/end-force-x").getValue() * 1;
var forcetowY_N = aimember.getNode("sim/hitches/aerotow/tow/end-force-y").getValue() * 1;
var forcetowZ_N = aimember.getNode("sim/hitches/aerotow/tow/end-force-z").getValue() * 1;
- var forcetow_N = math.sqrt( forcetowX_N * forcetowX_N + forcetowY_N * forcetowY_N + forcetowZ_N * forcetowZ_N );
+ var forcetow_N = math.sqrt( forcetowX_N * forcetowX_N + forcetowY_N * forcetowY_N + forcetowZ_N * forcetowZ_N );
} # end isSlave
-
- var forcetow_LBS = forcetow_N * 0.224809; # N -> LBF
+
+ var forcetow_LBS = forcetow_N * 0.224809; # N -> LBF
#print(" forcetow_N ", forcetow_N , " distance ", distance," ", breakforce_N);
if ( forcetow_N < breakforce_N ) {
-
- var distancepr = (myHitch_pos.distance_to(aiHitch_pos));
-
+
+ var distancepr = (myHitch_pos.distance_to(aiHitch_pos));
+
# correct a failure, if the projected length is larger than direct length
- if (distancepr > distance) { distancepr = distance;}
-
+ if (distancepr > distance) { distancepr = distance;}
+
var alpha = math.acos( (distancepr / distance) );
if ( aiHitch_pos.alt() > myHitch_pos.alt()) alpha = - alpha;
- var beta = ( aiHitchheadto - my_head_deg ) * 0.01745;
+ var beta = ( aiHitchheadto - my_head_deg ) * 0.01745;
var gamma = my_pitch_deg * 0.01745;
var delta = my_roll_deg * 0.01745;
-
+
var sina = math.sin(alpha);
var cosa = math.cos(alpha);
var sinb = math.sin(beta);
@@ -851,37 +894,37 @@ var aerotow = func (open){
var cosg = math.cos(gamma);
var sind = math.sin(delta);
var cosd = math.cos(delta);
-
+
#var forcetow = forcetow_N; # we deliver N to JSBSim
var forcetow = forcetow_LBS; # we deliver LBS to JSBSim
-
- # calculate unit vector of force direction in JSBSim-system
+
+ # calculate unit vector of force direction in JSBSim-system
var force = 1;
-
+
# global forces: alpha beta
var fglobalx = force * cosa * cosb;
var fglobaly = force * cosa * sinb;
var fglobalz = force * sina;
-
+
# local forces by pitch: gamma
var flpitchx = fglobalx * cosg - fglobalz * sing;
var flpitchy = fglobaly;
var flpitchz = fglobalx * sing + fglobalz * cosg;
-
+
# local forces by roll: delta
var flrollx = flpitchx;
var flrolly = flpitchy * cosd + flpitchz * sind;
var flrollz = - flpitchy * sind + flpitchz * cosd;
-
+
# asigning to LOCAL coord of plane
var forcex = flrollx;
var forcey = flrolly;
var forcez = flrollz;
#print("fx=",forcex," fy=",forcey," fz=",forcez);
-
+
# JSBSim-body-frame: x-> nose / y -> right wing / z -> down
# apply forces to hook (forces are in LBS or N see above)
- var hitchname = getprop("sim/hitches/aerotow/force_name_jsbsim");
+ var hitchname = getprop("sim/hitches/aerotow/force_name_jsbsim");
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/magnitude", forcetow);
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/x", forcex);
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/y", forcey);
@@ -891,23 +934,23 @@ var aerotow = func (open){
else { # rope is broken
props.globals.getNode("sim/hitches/aerotow/broken").setBoolValue(1);
#setprop("sim/messages/atc", sprintf("Oh no, the tow is broken"));
- releaseHitch("aerotow"); # open=1 / forces=0 / remove towrope
+ releaseHitch("aerotow"); # open=1 / forces=0 / remove towrope
}
-
+
############################################# report forces ##############################################
- # if we are connected to an MP aircraft and master
+ # if we are connected to a MP-aircraft and master
var nodeIsMpAircraft = getprop("sim/hitches/aerotow/tow/connected-to-mp-node");
if ( nodeIsMpAircraft and !isSlave ){
#print("report Forces");
- # transform my hitch coordinates to cartesian earth coordinates
+ # transform my hitch coordinates to cartesian earth coordinates
var myHitchCartEarth = geodtocart(myHitch_pos.lat(),myHitch_pos.lon(),myHitch_pos.alt() );
var myHitchXearth_m = myHitchCartEarth[0];
var myHitchYearth_m = myHitchCartEarth[1];
var myHitchZearth_m = myHitchCartEarth[2];
- # transform MP hitch coordinates to cartesian earth coordinates
+ # transform MP hitch coordinates to cartesian earth coordinates
var aiHitchCartEarth = geodtocart(aiHitch_pos.lat(),aiHitch_pos.lon(),aiHitch_pos.alt() );
var aiHitchXearth_m = aiHitchCartEarth[0];
var aiHitchYearth_m = aiHitchCartEarth[1];
@@ -918,18 +961,18 @@ var aerotow = func (open){
var dy = aiHitchYearth_m - myHitchYearth_m;
var dz = aiHitchZearth_m - myHitchZearth_m;
var dl = math.sqrt( dx * dx + dy * dy + dz * dz );
-
+
var forcetowX_N = forcetow_N * dx / dl;
var forcetowY_N = forcetow_N * dy / dl;
var forcetowZ_N = forcetow_N * dz / dl;
-
+
setprop("sim/hitches/aerotow/tow/dist", distance);
- setprop("sim/hitches/aerotow/tow/end-force-x", -forcetowX_N); # force acts in
- setprop("sim/hitches/aerotow/tow/end-force-y", -forcetowY_N); # opposite direction
+ setprop("sim/hitches/aerotow/tow/end-force-x", -forcetowX_N); # force acts in
+ setprop("sim/hitches/aerotow/tow/end-force-y", -forcetowY_N); # opposite direction
setprop("sim/hitches/aerotow/tow/end-force-z", -forcetowZ_N); # at tow end
-
+
} # end report forces
-
+
} # end: timelag
else{
#print("forces NOT updated!");
@@ -938,93 +981,99 @@ var aerotow = func (open){
} # end: aiNodeID
- else{
- if ( !aimember.getNode("valid").getValue() ) { # MP-aircraft is accessable (node is valid)
- #print("MP-aircraft isn't valid!");
- props.globals.getNode("sim/hitches/aerotow/open").setBoolValue(1); # open my hitch
- setprop("sim/messages/atc", sprintf("MP-aircraft disappeared!" ));
- }
- }
} # end: check id != nil
} # end: loop over aiobjects
+ if ( found == 0 ) {
+ if ( getprop("sim/flight-model") == "jsb" ) {
+ setprop("sim/messages/atc", sprintf("MP-aircraft disappeared!" ));
+ props.globals.getNode("sim/hitches/aerotow/open").setBoolValue(1); # open my hitch
+ props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id").setIntValue(0);
+ props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign").setValue("");
+ props.globals.getNode("sim/hitches/aerotow/tow/connected-to-ai-node").setBoolValue(0);
+ props.globals.getNode("sim/hitches/aerotow/tow/connected-to-mp-node").setBoolValue(0);
+ props.globals.getNode("sim/hitches/aerotow/tow/connected-to-property-node").setBoolValue(0);
+ }
+ #if ( getprop("sim/flight-model") == "yasim" ) removeTowrope("aerotow"); # remove towrope model
+ } # end found=0
} # end function aerotow
-
+
# ######################################################################################################################
-# winch function
+# winch function
# ######################################################################################################################
var winch = func (open){
-
+
var FT2M = 0.30480;
var M2FT = 1. / FT2M;
var RAD2DEG = 57.29578;
var DEG2RAD = 1. / RAD2DEG;
-
+
if (!open ) {
-
+
########################################### my hitch position ############################################
-
+
myPosition = geo.aircraft_position();
var my_head_deg = getprop("orientation/heading-deg");
var my_roll_deg = getprop("orientation/roll-deg");
var my_pitch_deg = getprop("orientation/pitch-deg");
-
+
# hitch coordinates in YASim-system (x-> nose / y -> left wing / z -> up)
+ assignHitchLocations("winch");
var x = getprop("sim/hitches/winch/local-pos-x");
var y = getprop("sim/hitches/winch/local-pos-y");
var z = getprop("sim/hitches/winch/local-pos-z");
var alpha_deg = my_roll_deg * (1.); # roll clockwise (looking in x-direction) := +
var beta_deg = my_pitch_deg * (-1.); # pitch clockwise (looking in y-direction) := -
-
+
# transform hook coordinates
var Xn = PointRotate3D(x:x,y:y,z:z,xr:0.,yr:0.,zr:0.,alpha_deg:alpha_deg,beta_deg:beta_deg,gamma_deg:0.);
var install_distance_m = Xn[0]; # in front of ref-point of glider
var install_side_m = Xn[1];
- var install_alt_m = Xn[2];
-
- var myHitch_pos = myPosition.apply_course_distance( my_head_deg , install_distance_m );
- var myHitch_pos = myPosition.apply_course_distance( my_head_deg - 90. , install_side_m );
- myHitch_pos.set_alt(myPosition.alt() + install_alt_m);
-
+ var install_alt_m = Xn[2];
+
+ var myHitch_pos = myPosition.apply_course_distance( my_head_deg , install_distance_m );
+ var myHitch_pos = myPosition.apply_course_distance( my_head_deg - 90. , install_side_m );
+ myHitch_pos.set_alt(myPosition.alt() + install_alt_m);
+
########################################### winch hitch position ############################################
- # get coordinates
- var winch_global_pos_x = getprop("sim/hitches/winch/winch/global-pos-x");
+ # get coordinates
+ var winch_global_pos_x = getprop("sim/hitches/winch/winch/global-pos-x");
var winch_global_pos_y = getprop("sim/hitches/winch/winch/global-pos-y");
var winch_global_pos_z = getprop("sim/hitches/winch/winch/global-pos-z");
var winch_geod = carttogeod(winch_global_pos_x,winch_global_pos_y,winch_global_pos_z);
var ai_lat = winch_geod[0];
- var ai_lon = winch_geod[1];
- #var ai_alt = winch_geod[2] * FT2M;
+ var ai_lon = winch_geod[1];
+ #var ai_alt = winch_geod[2] * FT2M;
var ai_alt = winch_geod[2];
#print("ai_lat,lon,alt",ai_lat,ai_lon,ai_alt);
var aiHitch_pos = geo.Coord.set_latlon( ai_lat, ai_lon, ai_alt );
-
+
########################################### distance between hitches #####################################
-
+
var distance = (myHitch_pos.direct_distance_to(aiHitch_pos)); # distance to winch in meter
var aiHitchheadto = (myHitch_pos.course_to(aiHitch_pos));
var height = myHitch_pos.alt() - aiHitch_pos.alt();
var aiHitchpitchto = -math.asin((myHitch_pos.alt()-aiHitch_pos.alt())/distance) / 0.01745;
#print(" pitch: ", aiHitchpitchto);
-
+
# update position of rope
setprop("ai/models/winchrope/position/latitude-deg", myHitch_pos.lat());
setprop("ai/models/winchrope/position/longitude-deg", myHitch_pos.lon());
setprop("ai/models/winchrope/position/altitude-ft", myHitch_pos.alt() * M2FT);
#print("ai_lat,lon,alt",myHitch_pos.lat()," ",myHitch_pos.lon()," ",myHitch_pos.alt() );
-
+
# update pitch and heading of rope
setprop("ai/models/winchrope/orientation/true-heading-deg", aiHitchheadto);
setprop("ai/models/winchrope/orientation/pitch-deg", aiHitchpitchto);
@@ -1033,54 +1082,54 @@ var winch = func (open){
setprop("sim/hitches/winch/tow/dist", distance);
#print("distance=",distance);
-
+
############################################# calc forces ##################################################
- # calc forces only for JSBSim-aircrafts
-
- # tow-end-forces must be reported in N to be consiststent to Yasim-aircrafts
- # hitch-forces must be LBS to be consistent to the JSBSim "external_forces/.../magnitude" definition
+ # calc forces only for JSBSim-aircraft
+
+ # tow-end-forces must be reported in N to be consiststent to Yasim-aircraft
+ # hitch-forces must be LBS to be consistent to the JSBSim "external_forces/.../magnitude" definition
if ( getprop("sim/flight-model") == "jsb" ) {
-
+
var spool_max = getprop("sim/hitches/winch/winch/max-spool-speed-m-s");
- var unspool_max = getprop("sim/hitches/winch/winch/max-unspool-speed-m-s");
+ var unspool_max = getprop("sim/hitches/winch/winch/max-unspool-speed-m-s");
var max_force_N = getprop("sim/hitches/winch/winch/max-force-N");
- var max_power_W = getprop("sim/hitches/winch/winch/max-power-kW") * 1000.;
- var breakforce_N = getprop("sim/hitches/winch/tow/break-force-N");
+ var max_power_W = getprop("sim/hitches/winch/winch/max-power-kW") * 1000.;
+ var breakforce_N = getprop("sim/hitches/winch/tow/break-force-N");
var elastic_constant = getprop("sim/hitches/winch/tow/elastic-constant");
var towlength_m = getprop("sim/hitches/winch/tow/length");
var max_tow_length_m = getprop("sim/hitches/winch/winch/max-tow-length-m");
var spoolspeed = getprop("sim/hitches/winch/winch/actual-spool-speed-m-s");
var spool_acceleration = getprop("sim/hitches/winch/winch/spool-acceleration-m-s-s");
- var delta_t = getprop("sim/time/delta-sec");
+ var delta_t = getprop("sim/time/delta-sec");
var towlength_new_m = towlength_m - spoolspeed * delta_t;
var delta_towlength_m = distance - towlength_new_m;
#print("towlength_m= ", towlength_m , " elastic_constant= ", elastic_constant," delta_towlength_m= ", delta_towlength_m);
if ( getprop("sim/hitches/winch/winch/clutched") ) {
- var delta_spoolspeed = spool_acceleration * delta_t;
+ var delta_spoolspeed = spool_acceleration * delta_t;
spoolspeed = spoolspeed + delta_spoolspeed ;
if ( spoolspeed > spool_max ) spoolspeed = spool_max;
}
- else { # un-clutched
+ else { # un-clutched
# --- experimental --- #
# we assume that the the winch-operator avoids tow sagging ( => rigid rope; negativ forces allowed)
var forcetow_N = elastic_constant * delta_towlength_m / towlength_new_m;
-
+
# drag of tow-rope ( magic! )
var magic_constant = getprop("sim/hitches/winch/winch/magic-constant");
tow_drag_N = spoolspeed * spoolspeed * math.sqrt( math.sqrt( height * height ) * max_tow_length_m ) / magic_constant ;
-
+
# mass = tow-mass only (drum-mass ignored)
var mass_kg = max_tow_length_m * getprop("sim/hitches/winch/tow/weight-per-m-kg-m");
var acceleration = ( forcetow_N - tow_drag_N ) / mass_kg;
- var delta_spoolspeed = acceleration * delta_t;
+ var delta_spoolspeed = acceleration * delta_t;
spoolspeed = spoolspeed - delta_spoolspeed;
- if ( spoolspeed < - unspool_max ) spoolspeed = - unspool_max;
+ if ( spoolspeed < - unspool_max ) spoolspeed = - unspool_max;
#print("spoolspeed= ",spoolspeed," delta_spoolspeed= ",delta_spoolspeed," delta_towlength= ", delta_towlength_m);
#print("forcetow_N= ",forcetow_N," tow_drag_N= ",tow_drag_N," acceleration= ", acceleration);
}
@@ -1091,13 +1140,13 @@ var winch = func (open){
else{
var forcetow_N = elastic_constant * delta_towlength_m / towlength_new_m;
}
-
+
if ( forcetow_N > max_force_N ) {
forcetow_N = max_force_N;
var towlength_new_m = distance / ( forcetow_N / elastic_constant + 1. );
spoolspeed = (towlength_m - towlength_new_m ) / delta_t;
- }
-
+ }
+
var power = forcetow_N * spoolspeed;
if ( power > max_power_W) {
power = max_power_W;
@@ -1105,33 +1154,33 @@ var winch = func (open){
towlength_new_m = towlength_m - spoolspeed * delta_t;
}
#print("power=",power," spoolspeed=",spoolspeed," force=",forcetow_N);
-
+
setprop("sim/hitches/winch/tow/length",towlength_new_m);
setprop("sim/hitches/winch/winch/actual-spool-speed-m-s",spoolspeed);
setprop("sim/hitches/winch/winch/actual-force-N",forcetow_N);
-
+
# force due to tow-weight (acts in tow direction at the heigher hitch)
var force_due_to_weight_N = getprop("sim/hitches/winch/tow/weight-per-m-kg-m") * 9.81 * height;
- if (height < 0. ) force_due_to_weight_N = 0.;
-
+ if (height < 0. ) force_due_to_weight_N = 0.;
+
forcetow_N = forcetow_N + force_due_to_weight_N;
- var forcetow_LBS = forcetow_N * 0.224809; # N -> LBF
+ var forcetow_LBS = forcetow_N * 0.224809; # N -> LBF
#print(" forcetow_N ", forcetow_N , " distance ", distance," ", breakforce_N);
#print(" forcetow_N=", forcetow_N , " force_due_to_weight_N=", force_due_to_weight_N," height=",height);
if ( forcetow_N < breakforce_N ) {
-
- var distancepr = (myHitch_pos.distance_to(aiHitch_pos));
-
+
+ var distancepr = (myHitch_pos.distance_to(aiHitch_pos));
+
# correct a failure, if the projected length is larger than direct length
- if (distancepr > distance) { distancepr = distance;}
-
+ if (distancepr > distance) { distancepr = distance;}
+
var alpha = math.acos( (distancepr / distance) );
if ( aiHitch_pos.alt() > myHitch_pos.alt()) alpha = - alpha;
- var beta = ( aiHitchheadto - my_head_deg ) * DEG2RAD;
+ var beta = ( aiHitchheadto - my_head_deg ) * DEG2RAD;
var gamma = my_pitch_deg * DEG2RAD;
var delta = my_roll_deg * DEG2RAD;
-
+
var sina = math.sin(alpha);
var cosa = math.cos(alpha);
var sinb = math.sin(beta);
@@ -1140,11 +1189,11 @@ var winch = func (open){
var cosg = math.cos(gamma);
var sind = math.sin(delta);
var cosd = math.cos(delta);
-
+
#var forcetow = forcetow_N; # we deliver N to JSBSim
var forcetow = forcetow_LBS; # we deliver LBS to JSBSim
- # calculate unit vector of force direction in JSBSim-system
+ # calculate unit vector of force direction in JSBSim-system
var force = 1;
# global forces: alpha beta
@@ -1156,7 +1205,7 @@ var winch = func (open){
var flpitchx = fglobalx * cosg - fglobalz * sing;
var flpitchy = fglobaly;
var flpitchz = fglobalx * sing + fglobalz * cosg;
-
+
# local forces by roll: delta
var flrollx = flpitchx;
var flrolly = flpitchy * cosd + flpitchz * sind;
@@ -1167,10 +1216,10 @@ var winch = func (open){
var forcey = flrolly;
var forcez = flrollz;
#print("fx=",forcex," fy=",forcey," fz=",forcez);
-
+
# JSBSim-body-frame: x-> nose / y -> right wing / z -> down
# apply forces to hook (forces are in LBS or N see above)
- var hitchname = getprop("sim/hitches/winch/force_name_jsbsim");
+ var hitchname = getprop("sim/hitches/winch/force_name_jsbsim");
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/magnitude", forcetow);
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/x", forcex );
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/y", forcey );
@@ -1184,12 +1233,12 @@ var winch = func (open){
} # end force < break force
else { # rope is broken
props.globals.getNode("sim/hitches/winch/broken").setBoolValue(1);
- releaseWinch();
+ releaseWinch();
}
if ( towlength_new_m > max_tow_length_m ) {
setprop("sim/messages/atc", sprintf("tow length exceeded!"));
- releaseWinch();
+ releaseWinch();
}
} # end forces/JSBSim
@@ -1215,10 +1264,10 @@ var createTowrope = func (device){
props.globals.getNode("sim/hitches/" ~ device ~ "/rope/model_id").setIntValue(freeModelid);
props.globals.getNode("sim/hitches/" ~ device ~ "/rope/exist").setBoolValue(1);
-
+
var towrope_ai = props.globals.getNode("ai/models/" ~ device ~ "rope", 1);
var towrope_mod = props.globals.getNode("models", 1);
-
+
towrope_ai.getNode("id", 1).setIntValue(4711);
towrope_ai.getNode("callsign", 1).setValue("towrope");
towrope_ai.getNode("valid", 1).setBoolValue(1);
@@ -1243,49 +1292,148 @@ var createTowrope = func (device){
# ######################################################################################################################
-# get the next free id of "models/model" members
+# get the next free id of "models/model" members
# ######################################################################################################################
var getFreeModelID = func {
#print("getFreeModelID");
- var modelid = 0; # next unused id
- modelobjects = props.globals.getNode("models", 1).getChildren();
- foreach ( var member; modelobjects ) {
- if ( (var c = member.getIndex()) != nil) {
+ var modelid = 0; # next unused id
+ modelobjects = props.globals.getNode("models", 1).getChildren();
+ foreach ( var member; modelobjects ) {
+ if ( (var c = member.getIndex()) != nil) {
modelid = c + 1;
}
}
- #print("modelid=",modelid);
+ #print("modelid=",modelid);
return(modelid);
}
# ######################################################################################################################
-# close hitch
+# close aerotow hitch
# ######################################################################################################################
var closeHitch = func {
-
+
#print("closeHitch");
+ # close only, if
+ # - not yet closed
+ # - connected to property-node
+ # - distance < towrope length
+
+ var open = getprop("sim/hitches/aerotow/open");
+ if ( !open ) return;
+
+ var aiNodeID = getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id"); # id of former found ai/mp aircraft
+ if ( aiNodeID < 1 ) {
+ setprop("sim/messages/atc", sprintf("No aircraft selected!"));
+ return;
+ }
+
+ ##################################### calc distance between hitches ######################
+
+ ###################### my hitch position #######################
+
+ myPosition = geo.aircraft_position();
+ var my_head_deg = getprop("orientation/heading-deg");
+ var my_roll_deg = getprop("orientation/roll-deg");
+ var my_pitch_deg = getprop("orientation/pitch-deg");
+
+ # hook coordinates in Yasim-system (x-> nose / y -> left wing / z -> up)
+ assignHitchLocations("aerotow");
+ var x = getprop("sim/hitches/aerotow/local-pos-x");
+ var y = getprop("sim/hitches/aerotow/local-pos-y");
+ var z = getprop("sim/hitches/aerotow/local-pos-z");
+
+ var alpha_deg = my_roll_deg * (1.); # roll clockwise (looking in x-direction) := +
+ var beta_deg = my_pitch_deg * (-1.); # pitch clockwise (looking in y-direction) := -
+
+ # transform hook coordinates
+ var Xn = PointRotate3D(x:x,y:y,z:z,xr:0.,yr:0.,zr:0.,alpha_deg:alpha_deg,beta_deg:beta_deg,gamma_deg:0.);
+
+ var install_distance_m = Xn[0]; # in front of ref-point of glider
+ var install_side_m = Xn[1];
+ var install_alt_m = Xn[2];
+
+ var myHitch_pos = myPosition.apply_course_distance( my_head_deg , install_distance_m );
+ var myHitch_pos = myPosition.apply_course_distance( my_head_deg - 90. , install_side_m );
+ myHitch_pos.set_alt(myPosition.alt() + install_alt_m);
+
+ ###################### ai hitch position #######################
+
+ var found = 0;
+
+ aiobjects = props.globals.getNode("ai/models").getChildren();
+ foreach (var aimember; aiobjects) {
+ if ( (var c = aimember.getNode("id") ) != nil ) {
+ var testprop = c.getValue();
+ if ( testprop == aiNodeID) {
+ found = found + 1;
+
+ # get coordinates
+ var ai_lat = aimember.getNode("position/latitude-deg").getValue();
+ var ai_lon = aimember.getNode("position/longitude-deg").getValue();
+ var ai_alt = (aimember.getNode("position/altitude-ft").getValue()) * FT2M;
+
+ var ai_pitch_deg = aimember.getNode("orientation/pitch-deg").getValue();
+ var ai_roll_deg = aimember.getNode("orientation/roll-deg").getValue();
+ var ai_head_deg = aimember.getNode("orientation/true-heading-deg").getValue();
+
+ var aiHitchX = aimember.getNode("sim/hitches/aerotow/local-pos-x").getValue();
+ var aiHitchY = aimember.getNode("sim/hitches/aerotow/local-pos-y").getValue();
+ var aiHitchZ = aimember.getNode("sim/hitches/aerotow/local-pos-z").getValue();
+
+ var aiPosition = geo.Coord.set_latlon( ai_lat, ai_lon, ai_alt );
+
+ var alpha_deg = ai_roll_deg * (1.);
+ var beta_deg = ai_pitch_deg * (-1.);
+
+ # transform hook coordinates
+ var Xn = PointRotate3D(x:aiHitchX,y:aiHitchY,z:aiHitchZ,xr:0.,yr:0.,zr:0.,alpha_deg:alpha_deg,beta_deg:beta_deg,gamma_deg:0.);
+
+ var install_distance_m = Xn[0]; # in front of ref-point of glider
+ var install_side_m = Xn[1];
+ var install_alt_m = Xn[2];
+
+ var aiHitch_pos = aiPosition.apply_course_distance( ai_head_deg , install_distance_m );
+ var aiHitch_pos = aiPosition.apply_course_distance( ai_head_deg - 90. , install_side_m );
+ aiHitch_pos.set_alt(aiPosition.alt() + install_alt_m);
+
+ var distance = (myHitch_pos.direct_distance_to(aiHitch_pos));
+
+ var towlength_m = props.globals.getNode("sim/hitches/aerotow/tow/length").getValue();
+ if ( distance > towlength_m ) {
+ var aicallsign = getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-callsign");
+ #setprop("sim/messages/atc", sprintf("Aircraft with callsign %s is too far away (distance is %4.0f meter).",aicallsign, distance));
+ setprop("sim/messages/atc", sprintf("Selected aircraft is too far away (distance to %s is %4.0f meter).",aicallsign, distance));
+ return;
+ }
+
+ setprop("sim/hitches/aerotow/tow/dist", distance);
+
+ }
+ }
+ }
+
setprop("sim/hitches/aerotow/open", "false");
setprop("sim/hitches/aerotow/mp_oldOpen", "true");
-
+
} # End function closeHitch
# ######################################################################################################################
-# release hitch
+# release hitch
# ######################################################################################################################
var releaseHitch = func (device){
-
+
#print("releaseHitch");
-
- if ( getprop("sim/flight-model") == "yasim" ) return; # bypass this routine for Yasim-aircrafts
+
+ if ( getprop("sim/flight-model") == "yasim" ) return; # bypass this routine for Yasim-aircraft
setprop("sim/hitches/" ~ device ~ "/open", "true");
-
+
var hitchname = getprop("sim/hitches/" ~ device ~ "/force_name_jsbsim");
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/magnitude", 0.);
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/x", 0.);
@@ -1293,23 +1441,23 @@ var releaseHitch = func (device){
setprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/z", 0.);
if ( device == "aerotow" ) {
- setprop("sim/hitches/aerotow/tow/end-force-x", 0.); # MP tow-end forces
- setprop("sim/hitches/aerotow/tow/end-force-y", 0.); #
- setprop("sim/hitches/aerotow/tow/end-force-z", 0.); #
+ setprop("sim/hitches/aerotow/tow/end-force-x", 0.); # MP tow-end forces
+ setprop("sim/hitches/aerotow/tow/end-force-y", 0.); #
+ setprop("sim/hitches/aerotow/tow/end-force-z", 0.); #
}
-
+
} # End function releaseHitch
# ######################################################################################################################
-# remove/delete towrope
+# remove/delete towrope
# ######################################################################################################################
var removeTowrope = func (device){
-
+
# remove the towrope from the property tree ai/models
# remove the towrope from the property tree models/
-
+
if ( getprop("sim/hitches/" ~ device ~ "/rope/exist") == 1 ) { # does the towrope exist?
# remove 3d model from scenery
@@ -1321,17 +1469,17 @@ var removeTowrope = func (device){
#print("towrope removed");
setprop("sim/hitches/" ~ device ~ "/rope/exist", 0);
}
-
+
}
# ######################################################################################################################
-# pull in towrope after hitch has been opened
+# pull in towrope after hitch has been opened
# ######################################################################################################################
var pull_in_rope = func {
- var deg2rad = math.pi / 180.;
+ var deg2rad = math.pi / 180.;
var FT2M = 0.30480;
if ( getprop("sim/hitches/winch/open") ) {
@@ -1340,13 +1488,13 @@ var pull_in_rope = func {
#var distance = getprop("sim/hitches/winch/tow/dist");
var towlength_m = getprop("sim/hitches/winch/tow/length");
- var spoolspeed = getprop("sim/hitches/winch/winch/max-spool-speed-m-s");
- var delta_t = getprop("sim/time/delta-sec");
+ var spoolspeed = getprop("sim/hitches/winch/winch/max-spool-speed-m-s");
+ var delta_t = getprop("sim/time/delta-sec");
var delta_length_m = spoolspeed * delta_t;
var towlength_new_m = towlength_m - delta_length_m;
var towlength_min_m = getprop("sim/hitches/winch/winch/min-tow-length-m");
-
+
if ( towlength_new_m > towlength_min_m ) {
#print("actual towlength= ",towlength_new_m);
@@ -1358,23 +1506,23 @@ var pull_in_rope = func {
var tow_heading_deg = getprop("ai/models/winchrope/orientation/true-heading-deg");
var tow_pitch_rad = getprop("ai/models/winchrope/orientation/pitch-deg") * deg2rad;
- var aiTow_pos = geo.Coord.set_latlon( tow_lat, tow_lon, tow_alt_m );
-
- var delta_distance_m = delta_length_m * math.cos(tow_pitch_rad);
+ var aiTow_pos = geo.Coord.set_latlon( tow_lat, tow_lon, tow_alt_m );
+
+ var delta_distance_m = delta_length_m * math.cos(tow_pitch_rad);
var delta_alt_m = delta_length_m * math.sin(tow_pitch_rad);
- # vertical sink rate not yet taken into account!
- aiTow_pos = aiTow_pos.apply_course_distance( tow_heading_deg , delta_distance_m );
- aiTow_pos.set_alt(tow_alt_m + delta_alt_m);
+ # vertical sink rate not yet taken into account!
+ aiTow_pos = aiTow_pos.apply_course_distance( tow_heading_deg , delta_distance_m );
+ aiTow_pos.set_alt(tow_alt_m + delta_alt_m);
#print("aiTow_pos.alt()= ",aiTow_pos.alt()," ",tow_alt_m + delta_alt_m);
-
+
# update position of rope
setprop("ai/models/winchrope/position/latitude-deg", aiTow_pos.lat());
setprop("ai/models/winchrope/position/longitude-deg", aiTow_pos.lon());
setprop("ai/models/winchrope/position/altitude-ft", aiTow_pos.alt() * M2FT);
- # update length of rope
+ # update length of rope
setprop("sim/hitches/winch/tow/length",towlength_new_m);
-
+
settimer( pull_in_rope , 0 );
} # end towlength > min
else {
@@ -1382,9 +1530,9 @@ var pull_in_rope = func {
setprop("sim/hitches/winch/winch/actual-spool-speed-m-s", 0. );
removeTowrope("winch"); # remove towrope model
}
-
+
} # end if open
-
+
}
@@ -1399,22 +1547,22 @@ var setAIObjectDefaults = func (){
var aiNodeID = getprop("sim/hitches/aerotow/tow/connected-to-ai-or-mp-id"); # id of former found ai/mp aircraft
- aiobjects = props.globals.getNode("ai/models").getChildren();
- foreach (var aimember; aiobjects) {
- if ( (var c = aimember.getNode("id") ) != nil ) {
+ aiobjects = props.globals.getNode("ai/models").getChildren();
+ foreach (var aimember; aiobjects) {
+ if ( (var c = aimember.getNode("id") ) != nil ) {
var testprop = c.getValue();
if ( testprop == aiNodeID) {
- # Set some dummy values. In case of an "interactive"-MP plane
+ # Set some dummy values. In case of an "interactive"-MP plane
# the correct values will be transmitted in the following loop.
- # Create this variables if not present.
+ # Create this variables if not present.
aimember.getNode("sim/hitches/aerotow/local-pos-x",1).setValue(-5.);
aimember.getNode("sim/hitches/aerotow/local-pos-y",1).setValue(0.);
aimember.getNode("sim/hitches/aerotow/local-pos-z",1).setValue(0.);
- aimember.getNode("sim/hitches/aerotow/tow/dist",1).setValue(-1.);
+ aimember.getNode("sim/hitches/aerotow/tow/dist",1).setValue(-1.);
}
- }
+ }
}
-
+
}
@@ -1423,53 +1571,53 @@ var setAIObjectDefaults = func (){
# ######################################################################################################################
var setWinchPositionAuto = func {
-
+
# remove already existing winch model
if ( getprop("/sim/hitches/winch/winch/winch-model-index") != nil ) {
var id_model = getprop("/sim/hitches/winch/winch/winch-model-index");
var modelsNode = "models/model[" ~ id_model ~ "]";
props.globals.getNode(modelsNode).remove();
#print("winch model removed");
- }
+ }
var initial_length_m = getprop("sim/hitches/winch/winch/initial-tow-length-m");
var ac_pos = geo.aircraft_position(); # get position of aircraft
var ac_hd = getprop("orientation/heading-deg"); # get heading of aircraft
-
+
# setup winch
# get initial runway position
var ipos_lat_deg = getprop("sim/presets/latitude-deg");
var ipos_lon_deg = getprop("sim/presets/longitude-deg");
var ipos_hd_deg = getprop("sim/presets/heading-deg");
var ipos_alt_m = geo.elevation(ipos_lat_deg,ipos_lon_deg);
- var ipos_geo = geo.Coord.new().set_latlon(ipos_lat_deg, ipos_lon_deg, ipos_alt_m);
+ var ipos_geo = geo.Coord.new().set_latlon(ipos_lat_deg, ipos_lon_deg, ipos_alt_m);
# offset to initial position
- var deviation = (ac_pos.distance_to(ipos_geo));
+ var deviation = (ac_pos.distance_to(ipos_geo));
# if deviation is too much, locate winch in front of glider, otherwise locate winch to end of runway
- if ( deviation > 200) {
- var w = ac_pos.apply_course_distance( ac_hd , initial_length_m -1. );
+ if ( deviation > 200) {
+ var w = ac_pos.apply_course_distance( ac_hd , initial_length_m -1. );
}
else {
- var w = ipos_geo.apply_course_distance( ipos_hd_deg , initial_length_m - 1. );
+ var w = ipos_geo.apply_course_distance( ipos_hd_deg , initial_length_m - 1. );
}
- var wpalt = geo.elevation(w.lat(), w.lon());
+ var wpalt = geo.elevation(w.lat(), w.lon());
w.set_alt(wpalt);
var winchModel = geo.put_model("Models/Airport/supacat_winch.xml", w.lat(), w.lon(), (w.alt()+0.81), (w.course_to(ac_pos) ));
-
+
setprop("/sim/hitches/winch/winch/global-pos-x", w.x());
setprop("/sim/hitches/winch/winch/global-pos-y", w.y());
setprop("/sim/hitches/winch/winch/global-pos-z", w.z());
setprop("sim/hitches/winch/tow/dist",initial_length_m - 1.);
setprop("sim/hitches/winch/tow/length",initial_length_m);
-
+
#print("name=",winchModel.getName()," Index=",winchModel.getIndex()," Type=",winchModel.getType() );
- #print("val=",winchModel.getValue()," children=",winchModel.getChildren()," size=",size(winchModel) );
+ #print("val=",winchModel.getValue()," children=",winchModel.getChildren()," size=",size(winchModel) );
setprop("/sim/hitches/winch/winch/winch-model-index",winchModel.getIndex() );
setprop("sim/messages/pilot", sprintf("Connected to winch!"));
-
- props.globals.getNode("sim/hitches/winch/open").setBoolValue(0);
+
+ props.globals.getNode("sim/hitches/winch/open").setBoolValue(0);
} # End function setWinchPositionAuto
@@ -1480,15 +1628,15 @@ var setWinchPositionAuto = func {
var runWinch = func {
- if ( !getprop("sim/hitches/winch/winch/clutched") ) {
+ if ( !getprop("sim/hitches/winch/winch/clutched") ) {
setprop("sim/hitches/winch/winch/clutched","true");
setprop("sim/messages/pilot", sprintf("Winch clutched!"));
- }
- else {
+ }
+ else {
setprop("sim/hitches/winch/winch/clutched","false");
setprop("sim/messages/pilot", sprintf("Winch un-clutched!"));
}
-
+
} # End function runWinch
@@ -1497,14 +1645,43 @@ var runWinch = func {
# ######################################################################################################################
var releaseWinch = func {
-
+
setprop("sim/hitches/winch/open","true");
-
+
} # End function releaseWinch
# ######################################################################################################################
-# point transformation
+# assignHitchLocations
+# ######################################################################################################################
+
+var assignHitchLocations = func (device){
+
+ if ( getprop("sim/flight-model") == "yasim" ) return; # bypass this routine for Yasim-aircraft
+
+ if ( getprop("sim/hitches/" ~ device ~ "/decoupled-force-and-rope-locations") ) return; # bypass this routine
+
+ #print("assignHitchLocations");
+
+ var in2m = 0.0254;
+
+ var hitchname = getprop("sim/hitches/" ~ device ~ "/force_name_jsbsim");
+
+ # location-x(yz)-in: JSBSim Structural Frame: x points to tail, y points to right wing, z points upward
+ # local-pos-x(yz): YaSim frame: x points to nose, y points to left wing, z points upward
+
+ setprop("sim/hitches/" ~ device ~ "/local-pos-x",
+ - getprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/location-x-in") * in2m );
+ setprop("sim/hitches/" ~ device ~ "/local-pos-y",
+ - getprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/location-y-in") * in2m );
+ setprop("sim/hitches/" ~ device ~ "/local-pos-z",
+ getprop("fdm/jsbsim/external_reactions/" ~ hitchname ~ "/location-z-in") * in2m );
+
+} # End function assignHitchLocations
+
+
+# ######################################################################################################################
+# point transformation
# ######################################################################################################################
var PointRotate3D = func (x,y,z,xr,yr,zr,alpha_deg,beta_deg,gamma_deg){
@@ -1520,27 +1697,27 @@ var PointRotate3D = func (x,y,z,xr,yr,zr,alpha_deg,beta_deg,gamma_deg){
#
#
# Definitions:
- # ----------------
+ # ----------------
#
- # x y z
- # alpha beta gamma
- #
- #
- # z
- # | y
- # | /
- # |/
- # ----->x
- #
- #----------------------------------------------------------------------------------
+ # x y z
+ # alpha beta gamma
+ #
+ #
+ # z
+ # | y
+ # | /
+ # |/
+ # ----->x
+ #
+ #----------------------------------------------------------------------------------
# Transformation in rotation-system X_rel = X-Xr = (x-xr, y-yr, z-zr)
var x_rel = x-xr;
- var y_rel = y-yr;
- var z_rel = z-zr;
+ var y_rel = y-yr;
+ var z_rel = z-zr;
# Trigonometry
- var deg2rad = math.pi / 180.;
+ var deg2rad = math.pi / 180.;
var alpha_rad = deg2rad * alpha_deg;
var beta_rad = deg2rad * beta_deg;
@@ -1555,9 +1732,9 @@ var PointRotate3D = func (x,y,z,xr,yr,zr,alpha_deg,beta_deg,gamma_deg){
var sin_gamma = math.sin(gamma_rad);
var cos_gamma = math.cos(gamma_rad);
- # Matrices
+ # Matrices
#
- # Rotate about x-axis Rx(alpha)
+ # Rotate about x-axis Rx(alpha)
#
# Rx11 Rx12 Rx13 1 0 0
# Rx(alpha)= Rx21 Rx22 Rx23 = 0 cos(alpha) -sin(alpha)
@@ -1573,10 +1750,10 @@ var PointRotate3D = func (x,y,z,xr,yr,zr,alpha_deg,beta_deg,gamma_deg){
var Rx32 = sin_alpha;
var Rx33 = cos_alpha;
#
- # Rotate about y-axis Ry(beta)
+ # Rotate about y-axis Ry(beta)
#
- # Ry11 Ry12 Ry13 cos(beta) 0 sin(beta)
- # Ry(beta)= Ry21 Ry22 Ry23 = 0 1 0
+ # Ry11 Ry12 Ry13 cos(beta) 0 sin(beta)
+ # Ry(beta)= Ry21 Ry22 Ry23 = 0 1 0
# Ry31 Ry32 Ry33 -sin(beta) 0 cos(beta)
#
var Ry11 = cos_beta;
@@ -1589,10 +1766,10 @@ var PointRotate3D = func (x,y,z,xr,yr,zr,alpha_deg,beta_deg,gamma_deg){
var Ry32 = 0.;
var Ry33 = cos_beta;
#
- # Rotate about z-axis Rz(gamma)
+ # Rotate about z-axis Rz(gamma)
#
- # Rz11 Rz12 Rz13 cos(gamma) -sin(gamma) 0
- # Rz(gamma)= Rz21 Rz22 Rz23 = sin(gamma) cos(gamma) 0
+ # Rz11 Rz12 Rz13 cos(gamma) -sin(gamma) 0
+ # Rz(gamma)= Rz21 Rz22 Rz23 = sin(gamma) cos(gamma) 0
# Rz31 Rz32 Rz33 0 0 1
#
var Rz11 = cos_gamma;
@@ -1603,37 +1780,37 @@ var PointRotate3D = func (x,y,z,xr,yr,zr,alpha_deg,beta_deg,gamma_deg){
var Rz23 = 0.;
var Rz31 = 0.;
var Rz32 = 0.;
- var Rz33 = 1.;
+ var Rz33 = 1.;
#
# First rotation about x-axis
# X_x = Rx*X_rel
var x_x = Rx11 * x_rel + Rx12 * y_rel + Rx13 * z_rel;
var y_x = Rx21 * x_rel + Rx22 * y_rel + Rx23 * z_rel;
- var z_x = Rx31 * x_rel + Rx32 * y_rel + Rx33 * z_rel;
+ var z_x = Rx31 * x_rel + Rx32 * y_rel + Rx33 * z_rel;
#
# subsequent rotation about y-axis
# X_xy = Ry*X_x
var x_xy = Ry11 * x_x + Ry12 * y_x + Ry13 * z_x;
var y_xy = Ry21 * x_x + Ry22 * y_x + Ry23 * z_x;
- var z_xy = Ry31 * x_x + Ry32 * y_x + Ry33 * z_x;
+ var z_xy = Ry31 * x_x + Ry32 * y_x + Ry33 * z_x;
#
# subsequent rotation about z-axis:
# X_xyz = Rz*X_xy
var x_xyz = Rz11 * x_xy + Rz12 * y_xy + Rz13 * z_xy;
var y_xyz = Rz21 * x_xy + Rz22 * y_xy + Rz23 * z_xy;
var z_xyz = Rz31 * x_xy + Rz32 * y_xy + Rz33 * z_xy;
-
+
# Back transformation X_rel = X-Xr = (x-xr, y-yr, z-zr)
var xn = xr + x_xyz;
var yn = yr + y_xyz;
var zn = zr + z_xyz;
-
+
var Xn = [xn,yn,zn];
-
+
return Xn;
-
-}
-
+
+}
+
##################################################################################################################################
@@ -1644,5 +1821,5 @@ var PointRotate3D = func (x,y,z,xr,yr,zr,alpha_deg,beta_deg,gamma_deg){
# - pull in towrope: take sink rate of rope into account
# - dynamic ID for ai-rope-model
#
-# Please contact D-NXKT at yahoo.de for bug-reports, suggestions, ...
-#
+# Please contact D_NXKT at yahoo.de for bug-reports, suggestions, ...
+#
\ No newline at end of file