diff --git a/Nasal/aircraft.nas b/Nasal/aircraft.nas index c033e28fc..ca9fed1dc 100644 --- a/Nasal/aircraft.nas +++ b/Nasal/aircraft.nas @@ -643,6 +643,76 @@ var steering = { +# autotrim +# ============================================================================= +# Singleton class that supports quick trimming and compensates for the lack +# of resistance/force feedback in most joysticks. Normally the pilot trims such +# that no real or artificially generated (by means of servo motors and spring +# preloading) forces act on the stick/yoke and it is in a comfortable position. +# This doesn't work well on computer joysticks. +# +# SYNOPSIS: +# autotrim.start(); # on key/button press +# autotrim.stop(); # on key/button release (mod-up) +# +# USAGE: +# (1) move the stick such that the aircraft is in an orientation that +# you want to trim for (forward flight, hover, ...) +# (2) press autotrim button and keep it pressed +# (3) move stick/yoke to neutral position (center) +# (4) release autotrim button +# +var autotrim = { + init : func { + me.elevator = me.Trim.new("elevator"); + me.aileron = me.Trim.new("aileron"); + me.rudder = me.Trim.new("rudder"); + me.loopid = 0; + me.active = 0; + }, + start : func { + me.active and return; + me.active = 1; + me.elevator.start(); + me.aileron.start(); + me.rudder.start(); + me._loop_(me.loopid += 1); + }, + stop : func { + me.active or return; + me.active = 0; + me.loopid += 1; + me.update(); + }, + _loop_ : func(id) { + id == me.loopid or return; + me.update(); + settimer(func { me._loop_(id) }, 0); + }, + update : func { + me.elevator.update(); + me.aileron.update(); + me.rudder.update(); + }, + Trim : { + new : func(name) { + var m = { parents : [ autotrim.Trim ] }; + m.trimN = props.globals.getNode("/controls/flight/" ~ name ~ "-trim", 1); + m.ctrlN = props.globals.getNode("/controls/flight/" ~ name, 1); + return m; + }, + start : func { + me.last = me.ctrlN.getValue(); + }, + update : func { + var v = me.ctrlN.getValue(); + me.trimN.setDoubleValue(me.trimN.getValue() + me.last - v); + me.last = v; + }, + }, +}; + + # HUD control class to handle both HUD implementations # ============================================================================== # @@ -709,6 +779,7 @@ _setlistener("/sim/signals/nasal-dir-initialized", func { props.globals.getNode("/sim/time/delta-realtime-sec", 1).setDoubleValue(0.00000001); HUD.init(); data.init(); + autotrim.init(); if (getprop("/sim/startup/save-on-exit")) { data.load();