Tu-154B2 version 3.1:
[fg:toms-fgdata.git] / Aircraft / tu154b / Nasal / friction.nas
1 ######################################################################
2 #
3 # Terrain reactions for JSBSim (friction, bumpiness, water sinking).
4 #
5 # Configuration:
6 #
7 # Add the following to ...-set.xml:
8 #
9 #   <nasal>
10 #     ...
11 #     <friction>
12 #       <file>path/to/friction.nas</file>
13 #     </friction>
14 #   </nasal>
15 #
16 #   <gear>
17 #     <gear n="N">
18 #       ...
19 #       <zsink-in type="double">INCHES</zsink-in>
20 #     </gear>
21 #   </gear>
22 #
23 # where N is the index of the point of contact (<zsink-in> should be
24 # specified for every point of contact, not just the gears) and INCHES
25 # is how deep that point should sink in the water.
26 #
27 # Information about surface properties will appear in
28 #
29 #   /fdm/jsbsim/gear/unit[*]/friction/
30 #   /fdm/jsbsim/contact/unit[*]/friction/
31 #
32
33
34 setprop("sim/fdm/surface/override-level", 1);
35
36 var rain_factor = 0.3;
37 var snow_factor = 0.45;
38 var meters_in_degree = 1852 * 60;
39 var degrees_in_inch = 0.0254 / meters_in_degree;
40 var radians_in_degree = math.pi / 180;
41
42 var points_of_contact = getprop("fdm/jsbsim/gear/num-units");
43 var point_info = [];
44 for (var i = 0; i < points_of_contact; i += 1) {
45     var x = getprop("gear/gear["~i~"]/xoffset-in") * degrees_in_inch;
46     var y = getprop("gear/gear["~i~"]/yoffset-in") * degrees_in_inch;
47     var z = getprop("gear/gear["~i~"]/zoffset-in");
48     var zs = getprop("gear/gear["~i~"]/zsink-in");
49     if (zs == nil)
50         zs = z;
51
52     var g = 0;
53     var r = 0;
54     var prop = "";
55     if (props.globals.getNode("fdm/jsbsim/gear/unit["~i~"]") != nil) {
56         prop = "fdm/jsbsim/gear/unit["~i~"]";
57         g = 1;
58         r = getprop(prop~"/rolling_friction_coeff");
59     } else {
60         prop = "fdm/jsbsim/contact/unit["~i~"]";
61     }
62     var s = getprop(prop~"/static_friction_coeff");
63     var d = getprop(prop~"/dynamic_friction_coeff");
64
65     append(point_info, { g: g, x: x, y: y, z: z, zs: zs, s: s, d: d, r: r });
66 }
67
68
69 var update_reactions = func {
70     settimer(update_reactions, 0.1);
71
72     if (getprop("fdm/jsbsim/position/h-agl-ft") > 100)
73         return;
74
75     var lat = getprop("fdm/jsbsim/position/lat-geod-deg");
76     var lon = getprop("fdm/jsbsim/position/long-gc-deg");
77     var rot = -getprop("fdm/jsbsim/attitude/heading-true-rad");
78     var h_cos = math.cos(rot);
79     var h_sin = math.sin(rot);
80     var cg = -getprop("fdm/jsbsim/inertia/cg-x-in") * degrees_in_inch;
81
82     var rain_coeff = (getprop("environment/rain-norm")
83                       or getprop("environment/metar/rain-norm")
84                       or 0) * rain_factor;
85     var snow_coeff = (getprop("environment/snow-norm")
86                       or getprop("environment/metar/snow-norm")
87                       or 0) * snow_factor;
88     var wave_amp = ((getprop("environment/wave/amp") or 1) - 1) * 40;
89     var wave_freq = (getprop("environment/wave/freq") or 0) * 60;
90
91     for (var i = 0; i < points_of_contact; i += 1) {
92         if (!getprop("gear/gear["~i~"]/wow"))
93             continue;
94
95         var north = (point_info[i].x - cg) * h_cos + point_info[i].y * h_sin;
96         var east = (point_info[i].x - cg) * -h_sin + point_info[i].y * h_cos;
97         var lat_corr = math.cos(lat * radians_in_degree) or 0.0000000001;
98         east /= lat_corr;
99         var p_lat = lat + north;
100         var p_lon = lon + east;
101
102         var info = geodinfo(p_lat, p_lon);
103         var rolling_friction = point_info[i].r;
104         var dynamic_friction = point_info[i].d;
105         var friction_factor = 1;
106         var bumpiness = 0;
107         var solid = 1;
108         if (info != nil and info[1] != nil) {
109             friction_factor = info[1].friction_factor;
110             rolling_friction = info[1].rolling_friction;
111             bumpiness = info[1].bumpiness;
112             solid = info[1].solid;
113         }
114
115         var z = 0;
116         if (solid) {
117             z = -point_info[i].z;
118             # Bumpiness has a period of about 16m and an amplitude
119             # of about 1m (40 inches) for bumpiness == 1.
120             if (bumpiness) {
121                 var l = p_lon / lat_corr;
122                 var dist_m = math.sqrt(p_lat*p_lat + l*l) * meters_in_degree;
123                 z += 20 * bumpiness * math.sin(math.pi * dist_m * 0.125);
124             }
125
126             var static_friction = point_info[i].s - rain_coeff - snow_coeff;
127             static_friction *= friction_factor;
128             if (static_friction < rolling_friction)
129                 static_friction = rolling_friction;
130             if (static_friction < 0.1)
131                 static_friction = 0.1;
132         } else {
133             if (point_info[i].g)
134                 rolling_friction = 1;
135
136             z = point_info[i].zs;
137             z += wave_amp * math.sin(wave_freq * systime() + i);
138             static_friction = rolling_friction; # Make brakes ineffective.
139         }
140
141         if (dynamic_friction > static_friction)
142             dynamic_friction = static_friction;
143
144         var prop = (point_info[i].g
145                     ? "fdm/jsbsim/gear/unit["~i~"]"
146                     : "fdm/jsbsim/contact/unit["~i~"]");
147
148         setprop(prop~"/static_friction_coeff", static_friction);
149         setprop(prop~"/dynamic_friction_coeff", dynamic_friction);
150         if (point_info[i].g)
151             setprop(prop~"/rolling_friction_coeff", rolling_friction);
152         setprop(prop~"/z-position", z);
153
154         setprop(prop~"/friction/friction_factor", friction_factor);
155         setprop(prop~"/friction/rolling_friction", rolling_friction);
156         setprop(prop~"/friction/bumpiness", bumpiness);
157         setprop(prop~"/friction/solid", solid);
158         setprop(prop~"/friction/lat", p_lat);
159         setprop(prop~"/friction/lon", p_lon);
160     }
161 }
162
163 update_reactions();