Add hydraulic system, tidy pneumatic system
[fg:toms-fgdata.git] / Aircraft / Hurricane / Systems / pneumatic.nas
1 ###############################################################################
2 ##
3 ##  Pneumatic system module for FlightGear.
4 ##
5 ##  Copyright (C) 2012  Vivian Meazza  (vivian.meazza(at)lineone.net)
6 ##  This file is licensed under the GPL license v2 or later.
7 ##
8 ###############################################################################
9 # Properties under /systems/pneumatic:
10 # + servicable      - Current status  Must be set by user code.
11
12 # + pressure        - OUTPUT ONLY property, do not try to set
13
14 # ==================================== Definiions ===========================================
15 # set constants 
16 MAX_PRESSURE = 300.0;
17 MIN_PRESSURE = 100.0;
18 INHG2PSI = 0.491154077497;
19 MAXTANKS = 2;
20
21 # set the update period
22 UPDATE_PERIOD = 0.3;
23
24 # set the timer for the selected function
25
26 registerTimer = func {
27
28     settimer(arg[0], UPDATE_PERIOD);
29
30 } # end function 
31
32 #does what it says on the tin
33 var clamp = func(v, min, max) { v < min ? min : v > max ? max : v }
34
35 # ================================ Initalize ====================================== 
36 # Make sure all needed properties are present and accounted 
37 # for, and that they have sane default values.
38
39 # =============== Variables ================
40 var pressure = 0;
41 var max_pressure = 0;
42 var min_pressure = 0;
43 var pump = nil;
44
45 var valve = nil;
46 var valve_1 = nil;
47 var valve_2 = nil;
48
49 var actuator = nil;
50 var actuator_1 = nil;
51 var actuator_2 = nil;
52 var actuator_3 = nil;
53 var actuator_4 = nil;
54 var actuator_5 = nil;
55 var actuator_6 = nil;
56 var actuator_7 = nil;
57 var actuator_8 = nil;
58 var actuator_9 = nil;
59 var actuator_10 = nil;
60 var actuator_11 = nil;
61 var actuator_12 = nil;
62 var actuator_13 = nil;
63
64 var relief = nil;
65 var relief_1 = nil;
66
67 var non_return = nil;
68
69 var proportionator  = nil;
70
71 var tank = nil;
72
73 var initialize = func {
74
75 print( "Initializing Pneumatic System ..." );
76
77 props.globals.initNode("/controls/pneumatic/system/engine-pump", 1, "BOOL");
78 props.globals.initNode("/systems/pneumatic/serviceable", 1, "BOOL");
79 props.globals.initNode("/systems/pneumatic/pressure-psi", 0, "DOUBLE");
80 props.globals.initNode("/controls/pneumatic/lever", 1, "DOUBLE");
81 props.globals.initNode("/controls/pneumatic/lever[1]", 0, "DOUBLE");
82 props.globals.initNode("/controls/pneumatic/lever[2]", 0, "DOUBLE");
83 props.globals.initNode("/systems/pneumatic/outputs/brake", 1, "DOUBLE");
84 props.globals.initNode("/systems/pneumatic/outputs/brake[1]", 1, "DOUBLE");
85 props.globals.initNode("/systems/pneumatic/outputs/trigger-gun", 1, "BOOL");
86 props.globals.initNode("/systems/pneumatic/outputs/trigger-gun[1]", 1, "BOOL");
87 props.globals.initNode("/systems/pneumatic/outputs/trigger-gun[2]", 1, "BOOL");
88 props.globals.initNode("/systems/pneumatic/outputs/trigger-gun[3]", 1, "BOOL");
89 props.globals.initNode("/systems/pneumatic/outputs/gear[1]", 0, "DOUBLE");
90 props.globals.initNode("/systems/pneumatic/outputs/gear[2]", 0, "DOUBLE");
91 props.globals.initNode("/environment/pressure-inhg", 0, "DOUBLE");
92
93 for (var i = 0; i < MAXTANKS; i += 1){
94         props.globals.initNode("/consumables/air/tank["~ i ~ "]/capacity-cu-ft", 0.001, "DOUBLE");
95         props.globals.initNode("/consumables/air/tank["~ i ~ "]/level-cu-ft", 0, "DOUBLE");
96         props.globals.initNode("/consumables/air/tank["~ i ~ "]/selected", 0, "BOOL");
97         props.globals.initNode("/consumables/air/tank["~ i ~ "]/pressure-in-psi", 0, "DOUBLE");
98         props.globals.initNode("/consumables/air/tank["~ i ~ "]/pressure-psi", 0, "DOUBLE");
99         }
100
101 ###
102 # overwrite this variable in controls.nas
103 #
104 controls.fullBrakeTime = 0.001;
105
106 #var trigger = func(b) setprop("/controls/armament/trigger", b);
107
108
109 ###
110 # suppliers ("name", "rpm source", "control property", status, factor)
111 #
112         pump = Pump.new("pump-engine",
113                                         "engines/engine[0]/rpm",
114                                         "controls/pneumatic/system/engine-pump",
115                                         1,
116                                         0.5);
117
118 ###
119 # non-return valves ("name", "input property", status)
120 #
121         non_return_valve = NonReturn.new("pump",
122                                         "systems/pneumatic/suppliers/pump-engine/pressure-out-psi",
123                                         1);
124
125 ###
126 # pressure control valves ("name", "source", status, max pressure)
127 #
128         relief = Relief.new("pressure-regulator",
129                                         "systems/pneumatic/non-return-valves/pump/pressure-out-psi",
130                                         1,
131                                         MAX_PRESSURE);
132
133         relief_1 = Relief.new("pressure-reducing",
134                                         "/consumables/air/tank/pressure-psi",
135                                         1,
136                                         200);
137
138 ###
139 # tanks ("name", "source property", capacity, level, selected)
140 #
141         tank = Tank.new("tank",
142                                         "systems/pneumatic/relief-valves/pressure-regulator/pressure-out-psi",
143                                         0.8,
144                                         16.326,
145                                         1);
146
147 ###
148 # valves ("name", "input property", "control property", status, initial state)
149 #
150         valve = Valve.new("brakes",
151                                         "systems/pneumatic/pressure-psi",
152                                         "controls/gear/brake-left",
153                                         1,
154                                         1);
155                                         
156         valve_1 = Valve.new("trigger",
157                                         "systems/pneumatic/pressure-psi",
158                                         "controls/armament/trigger",
159                                         1,
160                                         0);
161
162         valve_3 = Valve.new("gear-assist",
163                                         "systems/pneumatic/pressure-psi",
164                                         "controls/pneumatic/lever[2]",
165                                         1,
166                                         0);
167
168 ###
169 # proportionator valves ("name", "input property", "control property", status, threshold)
170
171         proportionator_valve = Proportionator.new("brakes",
172                                         "systems/pneumatic/valves/brakes/pressure-out-psi",
173                                         "controls/flight/rudder",
174                                         1,
175                                         0.3);
176
177 ###
178 # actuators ("name", "input property", "output property", "position property",
179 # status, min, max, initial state)
180 #
181         actuator = Actuator.new("brake",
182                                         "systems/pneumatic/proportionators/brakes/pressure-out-psi",
183                                         "systems/pneumatic/outputs/brake",
184                                         "gear/gear/position-norm",
185                                         1,
186                                         0.01,
187                                         0,
188                                         1,
189                                         1);
190
191         actuator_1 = Actuator.new("brake-1",
192                                         "systems/pneumatic/proportionators/brakes/pressure-out-psi[1]",
193                                         "systems/pneumatic/outputs/brake[1]",
194                                         "gear/gear/position-norm",
195                                         1,
196                                         0.01,
197                                         0,
198                                         1,
199                                         1);
200
201         actuator_2 = Actuator.new("trigger",
202                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
203                                         "systems/pneumatic/outputs/trigger-gun",
204                                         "systems/pneumatic/actuators/trigger/position-norm",
205                                         1,
206                                         0.005,
207                                         0,
208                                         1,
209                                         0);
210
211         actuator_3 = Actuator.new("trigger-1",
212                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
213                                         "systems/pneumatic/outputs/trigger-gun[1]",
214                                         "systems/pneumatic/actuators/trigger-1/position-norm",
215                                         1,
216                                         0.005,
217                                         0,
218                                         1,
219                                         0);
220
221         actuator_4 = Actuator.new("trigger-2",
222                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
223                                         "systems/pneumatic/outputs/trigger-gun[2]",
224                                         "systems/pneumatic/actuators/trigger-2/position-norm",
225                                         1,
226                                         0.005,
227                                         0,
228                                         1,
229                                         0);
230
231         actuator_5 = Actuator.new("trigger-3",
232                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
233                                         "systems/pneumatic/outputs/trigger-gun[3]",
234                                         "systems/pneumatic/actuators/trigger-3/position-norm",
235                                         1,
236                                         0.005,
237                                         0,
238                                         1,
239                                         0);
240
241         actuator_6 = Actuator.new("trigger-4",
242                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
243                                         "systems/pneumatic/outputs/trigger-gun[4]",
244                                         "systems/pneumatic/actuators/trigger-4/position-norm",
245                                         1,
246                                         0.005,
247                                         0,
248                                         1,
249                                         0);
250
251         actuator_7 = Actuator.new("trigger-5",
252                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
253                                         "systems/pneumatic/outputs/trigger-gun[5]",
254                                         "systems/pneumatic/actuators/trigger-5/position-norm",
255                                         1,
256                                         0.005,
257                                         0,
258                                         1,
259                                         0);
260
261         actuator_8 = Actuator.new("trigger-6",
262                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
263                                         "systems/pneumatic/outputs/trigger-gun[6]",
264                                         "systems/pneumatic/actuators/trigger-6/position-norm",
265                                         1,
266                                         0.005,
267                                         0,
268                                         1,
269                                         0);
270
271         actuator_9 = Actuator.new("trigger-7",
272                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
273                                         "systems/pneumatic/outputs/trigger-gun[7]",
274                                         "systems/pneumatic/actuators/trigger-7/position-norm",
275                                         1,
276                                         0.005,
277                                         0,
278                                         1,
279                                         0);
280
281         actuator_10 = Actuator.new("trigger-8",
282                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
283                                         "systems/pneumatic/outputs/trigger-gun[8]",
284                                         "systems/pneumatic/actuators/trigger-8/position-norm",
285                                         1,
286                                         0.005,
287                                         0,
288                                         1,
289                                         0);
290
291         actuator_11 = Actuator.new("trigger-9",
292                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
293                                         "systems/pneumatic/outputs/trigger-gun[9]",
294                                         "systems/pneumatic/actuators/trigger-9/position-norm",
295                                         1,
296                                         0.005,
297                                         0,
298                                         1,
299                                         0);
300
301         actuator_12 = Actuator.new("trigger-10",
302                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
303                                         "systems/pneumatic/outputs/trigger-gun[10]",
304                                         "systems/pneumatic/actuators/trigger-10/position-norm",
305                                         1,
306                                         0.005,
307                                         0,
308                                         1,
309                                         0);
310
311         actuator_13 = Actuator.new("trigger-11",
312                                         "systems/pneumatic/valves/trigger/pressure-out-psi",
313                                         "systems/pneumatic/outputs/trigger-gun[11]",
314                                         "systems/pneumatic/actuators/trigger-11/position-norm",
315                                         1,
316                                         0.005,
317                                         0,
318                                         1,
319                                         0);
320
321
322 # =============================== listeners ===============================
323 #
324
325 # =============================== start it up ===============================
326 #
327 print( "... done" );
328 update_pneumatic();
329
330 } #end init
331
332 ###
333 # =================== pneumatic system =========================
334 #
335 ###
336 # This is the main loop which keeps eveything updated
337 #
338 update_pneumatic = func {
339 #       time = props.globals.getNode("/sim/time/elapsed-sec", 1).getValue();
340 #       dt = time - last_time;
341 #       last_time = time;
342
343 # set the ambient pressure
344 min_pressure = sprintf("%0.3f", getprop("environment/pressure-inhg") * INHG2PSI);
345
346         foreach (var p; Pump.list)
347                 {
348                 p.update();
349                 }
350
351         foreach (var nrv; NonReturn.list)
352                 {
353                 nrv.update();
354                 }
355
356         foreach (var r; Relief.list)
357                 {
358                 r.update();
359                 }
360
361 setprop("systems/pneumatic/pressure-psi", relief_1.output);
362 #       getprop("systems/pneumatic/relief-valves/pressure-regulator/pressure-out-psi"));
363
364         foreach (var t; Tank.list)
365                 {
366                 t.update();
367                 }
368
369         foreach (var v; Valve.list)
370                 {
371                 v.update();
372                 }
373
374         foreach (var prp; Proportionator.list)
375                 {
376                 prp.update();
377                 }
378
379 #       foreach (var a; Actuator.list)
380 #               {
381 #               a.update();
382 #               }
383
384 # Request that the update fuction be called again 
385         registerTimer(update_pneumatic);
386 }
387
388 ##
389 # Pump class. Defines a pneumatic pump
390
391 Pump = {
392          new : func(name, source, control, serviceable, factor) {
393                 var obj = { parents : [ Pump ] };
394                 obj.name = name;
395                 #print ("name ", name);
396                 #print ("output ", output);
397                 obj.rpm_source_N = props.globals.getNode( source, 1 );
398                 obj.rpm_source_N.setDoubleValue(0);
399                 obj.control_N = props.globals.getNode( control, 1 );
400                 obj.control_N.setBoolValue( 1 );
401                 obj.factor = factor;
402
403                 obj.props_N = props.globals.getNode( "systems/pneumatic/suppliers", 1 ).getChild(name, 0, 1);
404                 obj.props_serviceable_N = obj.props_N.getChild("serviceable", 0, 1);
405                 obj.props_serviceable_N.setBoolValue( serviceable );
406                 obj.props_out_pressure_N = obj.props_N.getChild("pressure-out-psi", 0, 1);
407                 obj.props_out_pressure_N.setDoubleValue( min_pressure );
408                 append(Pump.list, obj); 
409                 return obj;
410         },
411         update : func {
412                 var rpm = me.rpm_source_N.getValue();
413                 var serviceable = me.props_serviceable_N.getValue();
414                 var control = me.control_N.getValue();
415                 var factor = me.factor;
416
417                 if (serviceable)
418                         {
419                         pressure = math.max(factor * rpm * control, min_pressure);
420                         }
421                 else
422                         {
423                         pressure = min_pressure;
424                         }
425
426         me.props_out_pressure_N.setDoubleValue(pressure);
427 #   print ("punp pressure-psi ", pressure);
428                 
429         },
430         setMaxPressure : func (pressure) {
431                 me.max_pressure = pressure;
432         },
433         setServiceable : func (serviceable) {
434                 me.props_serviceable_N.setBoolValue( serviceable ); 
435         },
436         list : [],
437 };
438
439 # Valve class. Defines a valve in the pneumatic system. Input is a pneumatic pressure source, output is used 
440 # to drive an actuator
441
442 Valve = {
443          new : func(name, source, control, serviceable, state) {
444                 var obj = { parents : [ Valve ] };
445                 obj.name = name;
446 #               print ("name ", name);
447 #        print ("source ", source);
448 #               print ("output ", output);
449                 obj.source_N = props.globals.getNode( source, 1 );
450                 obj.source_N.setDoubleValue(0);
451                 obj.control_N = props.globals.getNode( control, 1 );
452                 obj.control_N.setDoubleValue(state);
453
454                 obj.props_N = props.globals.getNode( "systems/pneumatic/valves", 1 ).getChild(name, 0, 1);
455                 obj.props_serviceable_N = obj.props_N.getChild("serviceable", 0, 1);
456                 obj.props_serviceable_N.setBoolValue( serviceable );
457                 obj.props_in_pressure_N = obj.props_N.getChild("pressure-in-psi", 0, 1);
458                 obj.props_in_pressure_N.setDoubleValue( 0 );
459                 obj.props_out_pressure_N = obj.props_N.getChild("pressure-out-psi", 0, 1);
460                 obj.props_out_pressure_N.setDoubleValue( 0 );
461
462                 append(Valve.list, obj); 
463                 return obj;
464         },
465         update : func {
466                 var source = me.source_N.getValue();
467                 var control = clamp(me.control_N.getValue(), -1, 1); 
468                 var serviceable = me.props_serviceable_N.getValue();
469                 var output_pressure = 0;
470                 #print (me.name," source ", source, " control " , control);
471
472                 if (serviceable)
473                         {
474                         output_pressure= math.max( source * control, min_pressure );
475                         }
476                 else
477                         {
478                         output_pressure = min_pressure;
479                         }
480
481                 me.props_in_pressure_N.setDoubleValue(source);
482                 me.props_out_pressure_N.setDoubleValue(output_pressure);
483
484             #print (me.name, " valve output ", output_pressure);
485                 
486         },
487         setServiceable : func (serviceable) {
488                 me.props_serviceable_N.setBoolValue( serviceable ); 
489         },
490         list : [],
491 };
492
493 # Actuator class. Defines an actuator in the pneumatic system.  The output can be used to drive 
494 # control surfaces etc 
495
496 Actuator = {
497          new : func(name, source, output, pos_norm, serviceable, capacity, min, max, state) {
498                 var obj = { parents : [ Actuator ] };
499                 obj.name = name;
500 #               print ("name ", name);
501 #       print ("source ", source);
502                 #print ("output ", output);
503                 obj.source_N = props.globals.getNode( source, 1 );
504                 obj.source_N.setDoubleValue( 0 );
505                 obj.output_N = props.globals.getNode( output, 1 );
506                 obj.output_N.setDoubleValue( state );
507                 obj.position_norm_N = props.globals.getNode( pos_norm, 1 );
508                 obj.position_norm_N.setDoubleValue( state );
509                 obj.capacity = capacity;
510                 obj.min = min;
511                 obj.max = max;
512
513                 obj.props_N = props.globals.getNode( "systems/pneumatic/actuators", 1 ).getChild(name, 0, 1);
514                 obj.props_serviceable_N = obj.props_N.getChild("serviceable", 0, 1);
515                 obj.props_serviceable_N.setBoolValue( serviceable );
516                 obj.props_in_pressure_N = obj.props_N.getChild("pressure-in-psi", 0, 1);
517                 obj.props_in_pressure_N.setDoubleValue( obj.source_N.getValue() );
518                 obj.props_position_norm_N = obj.props_N.getChild("position-norm", 0, 1);
519                 obj.props_position_norm_N.setDoubleValue( state );
520
521                 setlistener(obj.output_N, func (n){
522                         var actuator_pos_norm = obj.props_position_norm_N.getValue();
523                         var name = obj.name;
524                         var pressure = obj.source_N.getValue();
525                         var in_pressure = obj.props_in_pressure_N.getValue();
526                         var level = calcLevel(in_pressure - min_pressure, obj.capacity);
527                         tank.setLevel(level);
528
529 #                       print("listener ",name, " ", actuator_pos_norm, " " , pressure, " " , in_pressure, " level ", level,
530 #                       " capacity ", capacity);
531
532                         },
533                         0,
534                         0);
535
536                 setlistener(obj.source_N, func (n){
537                         obj.update();
538
539 #                       print("listener 2 ", obj.name, " source ",  n.getValue() );
540
541                         },
542                         0,
543                         0);
544
545                 append(Actuator.list, obj); 
546                 return obj;
547         },
548         update : func {
549                 var source = me.source_N.getValue();
550                 var serviceable = me.props_serviceable_N.getValue();
551                 var state = me.position_norm_N.getValue();
552                 var output = 0;
553                 me.props_in_pressure_N.setDoubleValue( source );
554
555 #               print (me.name, " source ", source, " state " , state);
556
557                 if (source >= MIN_PRESSURE and serviceable)
558                         {
559                         output = source / MAX_PRESSURE;
560 #                       print(me.name," max output ", output, " state ", state);
561                         output = math.max(output, state);
562 #                       print(me.name," output max ", output);
563                         }
564                 else
565                         {
566                         output = 0;
567                         }
568
569                 output = clamp(output, me.min, me.max); 
570                 me.output_N.setDoubleValue( output );
571                 me.props_position_norm_N.setDoubleValue( output );
572
573 #           print (me.name, " output ", me.output_N.getValue());
574                 
575         },
576         setServiceable : func (serviceable) {
577                 me.props_serviceable_N.setBoolValue( serviceable ); 
578         },
579         getPressure : func () {
580         me.update();
581         return me.props_in_pressure_N.getValue(); 
582         },
583         list : [],
584 };
585
586 # Relief Valve class. Defines a relief valve in the pneumatic system.  The output controls
587 # the pressure in the pneumatic system.
588 # "name", "input property", "control property", "output property", status,
589 # max, initial state
590
591 Relief = {
592          new : func(name, source, serviceable, max) {
593                 var obj = { parents : [ Relief ] };
594                 obj.name = name;
595 #               print ("name ", name);
596 #       print ("source ", source);
597 #               print ("output ", output);
598                 obj.source_N = props.globals.getNode( source, 1 );
599                 obj.source_N.setDoubleValue( min_pressure );
600                 obj.max = max;
601                 obj.output = 0;
602
603                 obj.props_N = props.globals.getNode( "systems/pneumatic/relief-valves", 1 ).getChild(name, 0, 1);
604                 obj.props_serviceable_N = obj.props_N.getChild("serviceable", 0, 1);
605                 obj.props_serviceable_N.setBoolValue( serviceable );
606                 obj.props_in_pressure_N = obj.props_N.getChild("pressure-in-psi", 0, 1);
607                 obj.props_in_pressure_N.setDoubleValue( obj.source_N.getValue() );
608                 obj.props_out_pressure_N = obj.props_N.getChild("pressure-out-psi", 0, 1);
609                 obj.props_out_pressure_N.setDoubleValue( obj.source_N.getValue() );
610
611                 append(Relief.list, obj); 
612                 return obj;
613         },
614         update : func {
615                 var source = me.source_N.getValue();
616                 var serviceable = me.props_serviceable_N.getValue();
617                 me.output = source;
618         #       print (me.name, " source ", source, " control " , control);
619
620                 if (serviceable)
621                         {
622                         me.output = clamp(source, min_pressure, me.max);
623                         }
624                 else
625                         {
626                         me.output = source;
627                         }
628
629                 me.props_in_pressure_N.setDoubleValue( source );
630                 me.props_out_pressure_N.setDoubleValue( me.output );
631
632         #    print (me.name, " output ", me.output_N.getValue());
633                 
634         },
635         setServiceable : func (serviceable) {
636                 me.props_serviceable_N.setBoolValue( serviceable ); 
637         },
638         list : [],
639 };
640
641 NonReturn = {
642          new : func(name, source, serviceable) {
643                 var obj = { parents : [ NonReturn ] };
644                 obj.name = name;
645 #               print ("name ", name);
646 #        print ("input ", input);
647 #               print ("output ", output);
648                 obj.source_N = props.globals.getNode( source, 1 );
649                 obj.source_N.setDoubleValue( min_pressure );
650
651                 obj.props_N = props.globals.getNode( "systems/pneumatic/non-return-valves", 1 ).getChild(name, 0, 1);
652                 obj.props_serviceable_N = obj.props_N.getChild("serviceable", 0, 1);
653                 obj.props_serviceable_N.setBoolValue( serviceable );
654                 obj.props_in_pressure_N = obj.props_N.getChild("pressure-in-psi", 0, 1);
655                 obj.props_in_pressure_N.setDoubleValue( obj.source_N.getValue() );
656                 obj.props_out_pressure_N = obj.props_N.getChild("pressure-out-psi", 0, 1);
657                 obj.props_out_pressure_N.setDoubleValue( obj.source_N.getValue() );
658
659                 append(NonReturn.list, obj); 
660                 return obj;
661         },
662         update : func {
663                 var input = me.source_N.getValue();
664                 var output = min_pressure;
665                 var serviceable = me.props_serviceable_N.getValue();
666
667 #               print (me.name, " source ", source, " control " , control);
668
669                 if (serviceable)
670                         {
671                         output = math.max(input, output);
672                         }
673
674 #               me.output_N.setDoubleValue( output );
675                 me.props_in_pressure_N.setDoubleValue( input );
676                 me.props_out_pressure_N.setDoubleValue( output );
677
678 #           print (me.name, " output ", me.output_N.getValue());
679                 
680         },
681         setServiceable : func (serviceable) {
682                 me.props_serviceable_N.setBoolValue( serviceable ); 
683         },
684         list : [],
685 };
686
687 Proportionator = {
688          new : func(name, source, control, serviceable, threshold) {
689                 var obj = { parents : [Proportionator ] };
690                 obj.name = name;
691 #               print ("name ", name);
692 #        print ("input ", source);
693 #               print ("control ", control);
694                 obj.source_N = props.globals.getNode( source, 1 );
695                 obj.source_N.setDoubleValue( min_pressure );
696                 obj.control_N = props.globals.getNode( control, 1 );
697                 obj.control_N.setDoubleValue( 0 );
698                 obj.threshold = threshold;
699
700                 obj.props_N = props.globals.getNode( "systems/pneumatic/proportionators", 1 ).getChild(name, 0, 1);
701                 obj.props_serviceable_N = obj.props_N.getChild("serviceable", 0, 1);
702                 obj.props_serviceable_N.setBoolValue( serviceable );
703                 obj.props_in_pressure_N = obj.props_N.getChild("pressure-in-psi", 0, 1);
704                 obj.props_in_pressure_N.setDoubleValue( obj.source_N.getValue() );
705                 obj.props_out_pressure1_N = obj.props_N.getChild("pressure-out-psi", 0, 1);
706                 obj.props_out_pressure1_N.setDoubleValue( obj.source_N.getValue() );
707                 obj.props_out_pressure2_N = obj.props_N.getChild("pressure-out-psi", 1, 1);
708                 obj.props_out_pressure2_N.setDoubleValue( obj.source_N.getValue() );
709                 obj.props_control_N = obj.props_N.getChild("control", 0, 1);
710                 obj.props_control_N.setDoubleValue( 0 );
711                 
712                 append(Proportionator.list, obj); 
713                 return obj;
714         },
715         update : func {
716                 var input = me.source_N.getValue();
717                 var control = me.control_N.getValue();
718                 var threshold = me.threshold;
719                 var serviceable = me.props_serviceable_N.getValue();
720
721 #               print (me.name, " source ", source, " control " , control);
722
723                 if (serviceable)
724                         {
725                         if (control > threshold)
726                                 me.setOutput( min_pressure, input );
727                         elsif (control < -threshold)
728                                 me.setOutput( input, min_pressure );
729                         else
730                                 me.setOutput( input, input );
731                         }
732
733                 me.props_in_pressure_N.setDoubleValue( input );
734                 me.props_control_N.setDoubleValue( control );
735
736 #           print (me.name, " output ", me.output_N.getValue());
737                 
738         },
739         setServiceable : func (serviceable) {
740                 me.props_serviceable_N.setBoolValue( serviceable ); 
741         },
742         setOutput: func (output1, output2) {
743                 me.props_out_pressure1_N.setDoubleValue( output1 );
744                 me.props_out_pressure2_N.setDoubleValue( output2 );
745         },
746         list : [],
747 };
748
749 Tank = {
750          new : func(name, source, capacity, level, selected) {
751                 var obj = { parents : [Tank] };
752                 obj.name = name;
753 #               print ("name ", name);
754 #        print ("input ", source);
755 #               print ("control ", control);
756 #               print ("output1 ", output1);
757 #               print ("output2 ", output2);
758                 obj.source_N = props.globals.getNode( source, 1 );
759                 obj.source_N.setDoubleValue( min_pressure );
760 #               obj.output_N = props.globals.getNode( output, 1 );
761 #               obj.output_N.setDoubleValue( min_pressure );
762                 obj.capacity = capacity;
763                 obj.level = level;
764
765                 obj.props_N = props.globals.getNode( "/consumables/air/tank", 1 );
766                 obj.props_selected_N = obj.props_N.getChild("selected", 0, 1);
767                 obj.props_selected_N.setBoolValue( selected );
768                 obj.props_in_pressure_N = obj.props_N.getChild("pressure-in-psi", 0, 1);
769                 obj.props_in_pressure_N.setDoubleValue( obj.source_N.getValue() );
770                 obj.props_capacity_N = obj.props_N.getChild("capacity-cu-ft", 0, 1);
771                 obj.props_capacity_N.setDoubleValue( capacity );
772                 obj.props_out_pressure_N = obj.props_N.getChild("pressure-psi", 0, 1);
773                 obj.props_out_pressure_N.setDoubleValue( obj.source_N.getValue() );
774                 obj.props_level_N = obj.props_N.getChild("level-cu-ft", 0, 1);
775                 obj.props_level_N.setDoubleValue( level );
776                 obj.props_name_N = obj.props_N.getChild("name", 0, 1);
777                 obj.props_name_N.setValue( name );
778
779                 append(Tank.list, obj); 
780                 return obj;
781         },
782         update : func {
783         var source = me.source_N.getValue();
784         var level = me.props_level_N.getValue();
785         var capacity = me.capacity;
786         var pressure = calcPressure( level, capacity );
787         
788 #       print(me.name, " source ", source, " pressure ", pressure, " level ", level, " capacity ", capacity);
789
790         if (source > pressure)
791                 {
792                 level = calcLevel(source, capacity);
793 #               print(me.name, " source ", source, " level ", level);
794                 }
795
796         pressure = calcPressure( level, capacity );
797         me.props_in_pressure_N.setDoubleValue(source);
798         me.props_out_pressure_N.setDoubleValue(pressure);
799         me.props_level_N.setDoubleValue(level);
800 #       me.output_N.setDoubleValue(pressure);
801
802         #print(me.name, " level ", level , " pressure ", pressure);     
803         },
804         setSelected : func (selected) {
805                 me.props_selected_N.setBoolValue( selected ); 
806         },
807         setOutput: func (output1, output2) {
808         },
809         setLevel: func(n) {
810         #print(me.name, " n ", n, " level ", me.props_level_N.getValue());
811         var level = me.props_level_N.getValue() - n;
812         #print(me.name, "new level ", level);
813         level = math.max(level, me.capacity);
814         me.props_level_N.setDoubleValue( level );
815         },
816         list : [],
817 };
818
819 ###
820 #=============================== functions ===============================
821
822 # We apply Boyle's Law to derive the pressure in the tank fom the capacity of a
823 # tank and the contents. We ignore the effects of temperature.
824
825 var calcPressure = func (cu_ft, cap){
826     var Vc = cap;
827     var Va = cu_ft;
828     var Pa = 14.7;
829
830 #    print (Vc, " ", Va, " ", Pa);
831
832     Pc = (Pa * Va)/Vc;
833     return Pc;
834 }# end func calcPressure
835  
836 var calcLevel = func (pressure, cap){
837     var Vc = cap;
838     var Va = 0;
839     var Pa = 14.7;
840         var Pc = pressure;
841
842     Va = (Pc * Vc)/Pa;
843
844 #       print (" calclevel capacity ", Vc, " level calc", Va, " Pa ", Pa, " Pressure  ", Pc);
845     return Va;
846 }# end func calcLevel
847
848 # ==================== Fire it up =====================
849
850 setlistener("sim/signals/fdm-initialized", initialize);
851
852 # end 
853
854