public void Update(double dt)
        {
            CollectiveCommand = CollectiveInput;
            LongCommand       = LongInput;
            LatCommand        = LatInput;
            PedalCommand      = PedalInput;

            if (enabled)
            {
                // Apply nullzones
                if (trimControl && collectiveNullZone > 1e-5)
                {
                    CollectiveCommand = Math.Abs(CollectiveCommand) > collectiveNullZone
                        ? (CollectiveCommand - Math.Sign(CollectiveCommand) * collectiveNullZone) / (1.0 - collectiveNullZone)
                        : 0.0;
                }
                if (longNullZone > 1e-5)
                {
                    LongCommand = Math.Abs(LongCommand) > longNullZone
                        ? (LongCommand - Math.Sign(LongCommand) * longNullZone) / (1.0 - longNullZone)
                        : 0.0;
                }
                if (latNullZone > 1e-5)
                {
                    LatCommand = Math.Abs(LatCommand) > latNullZone
                        ? (LatCommand - Math.Sign(LatCommand) * latNullZone) / (1.0 - latNullZone)
                        : 0.0;
                }
                if (pedalNullZone > 1e-5)
                {
                    PedalCommand = Math.Abs(PedalCommand) > pedalNullZone
                        ? (PedalCommand - Math.Sign(PedalCommand) * pedalNullZone) / (1.0 - pedalNullZone)
                        : 0.0;
                }

                // Apply exponential controls
                if (trimControl && collectiveExpo > 1e-5)
                {
                    CollectiveCommand = Math.Sign(CollectiveCommand) * Math.Pow(Math.Abs(CollectiveCommand), collectiveExpo);
                }
                if (longExpo > 1e-5)
                {
                    LongCyclic = Math.Sign(LongCommand) * Math.Pow(Math.Abs(LongCommand), longExpo);
                }
                if (latExpo > 1e-5)
                {
                    LatCyclic = Math.Sign(LatCommand) * Math.Pow(Math.Abs(LatCommand), latExpo);
                }
                if (pedalExpo > 1e-5)
                {
                    PedalCommand = Math.Sign(PedalCommand) * Math.Pow(Math.Abs(PedalCommand), pedalExpo);
                }
            }

            // Start with 1:1 control
            Collective = CollectiveCommand * collectiveDirect;
            LongCyclic = LongCommand * longDirect;
            LatCyclic  = LatCommand * latDirect;
            Pedal      = PedalCommand * pedalDirect;

            if (!enabled)
            {
                return;
            }

            // Apply PID controllers
            if (pitchRatePID != null)
            {
                LongCyclic -= pitchRatePID.Calculate(dt, -LongCommand, AngularVelocity.y());
            }
            if (rollRatePID != null)
            {
                LatCyclic += rollRatePID.Calculate(dt, LatCommand, AngularVelocity.x());
            }
            if (verticalRateControl && verticalRatePID != null)
            {
                if (IsOnGround)
                {
                    verticalRatePID.Reset();
                    if (trimControl)
                    {
                        CollectiveCommand -= 0.1;
                    }
                }
                Collective += verticalRatePID.Calculate(dt, CollectiveCommand, -HorizonVelocity.z());
            }

            var desiredPitchAngle = TrimAttitude.y();
            var desiredRollAngle  = TrimAttitude.x();

            if (attitudeControl)
            {
                desiredPitchAngle -= LongCommand * maxPitchAngle * Math.PI / 180.0;
                desiredRollAngle  += LatCommand * maxRollAngle * Math.PI / 180.0;
            }
            if (lateralControl)
            {
                if (longitudinalPID != null)
                {
                    if (IsOnGround || LongCommand > 1e-5 || Math.Abs(HorizonVelocity.x()) > lateralResetVelocity)
                    {
                        longitudinalPID.Reset();
                    }
                    LongPositionOutput = longitudinalPID.Calculate(dt, LongCommand, HorizonVelocity.x() - DesiredSpeed);
                    // Longitudinal pitch bypass used for tiltrotor control
                    desiredPitchAngle -= (1.0 - LongitudinalPositionBypass) * LongPositionOutput * maxPitchAngle * Math.PI / 180.0;
                }
                if (lateralPID != null)
                {
                    if (IsOnGround || LatCommand > 1e-5 || Math.Abs(HorizonVelocity.y()) > lateralResetVelocity)
                    {
                        lateralPID.Reset();
                    }
                    desiredRollAngle += lateralPID.Calculate(dt, LatCommand, HorizonVelocity.y()) * maxRollAngle * Math.PI / 180.0;
                }
            }
            if (attitudeControl || lateralControl)
            {
                if (pitchPID != null)
                {
                    LongCyclic -= pitchPID.Calculate(dt, desiredPitchAngle, Attitude.y());
                }
                if (rollPID != null)
                {
                    LatCyclic += rollPID.Calculate(dt, desiredRollAngle, Attitude.x());
                }
            }

            if (Attitude != null && Math.Abs(Attitude.x()) < MAX_ROLL_FOR_YAW_CONTROL)
            {
                double yawscale = 1.0;
                if (yawRatePID != null)
                {
                    // Gradually decrease yaw damper output with airspeed
                    if (yawDamperVelocity1 > 1e-5 && yawDamperVelocity2 > 1e-5)
                    {
                        double v = Velocity.x();
                        if (v > yawDamperVelocity2)
                        {
                            yawscale = 0.0;
                        }
                        else if (v > yawDamperVelocity1)
                        {
                            yawscale = 1.0 - (v - yawDamperVelocity1) / (yawDamperVelocity2 - yawDamperVelocity1);
                        }
                    }
                    Pedal += yawscale * yawRatePID.Calculate(dt, PedalCommand, AngularVelocity.z());
                }
            }

            if (trimControl)
            {
                Collective = TrimCollective + Collective * (1 - Math.Sign(Collective) * Math.Sign(TrimCollective) * Math.Abs(TrimCollective));
                LongCyclic = TrimLongCyclic + LongCyclic * (1 - Math.Sign(LongCyclic) * Math.Sign(TrimLongCyclic) * Math.Abs(TrimLongCyclic));
                LatCyclic  = TrimLatCyclic + LatCyclic * (1 - Math.Sign(LatCyclic) * Math.Sign(TrimLatCyclic) * Math.Abs(TrimLatCyclic));
                Pedal      = TrimPedal + Pedal * (1 - Math.Sign(Pedal) * Math.Sign(TrimPedal) * Math.Abs(TrimPedal));
            }

            Collective = limit(Collective, 1);
            LongCyclic = limit(LongCyclic, 1);
            LatCyclic  = limit(LatCyclic, 1);
            Pedal      = limit(Pedal, 1);
        }