best way to fly

I am scripting a player controlled eagle and I’d like to give it a nice aerodynamic feel. I am using addrelative torque but it’s making it spin out of control - very hard to player-control so I am trying to implement auto zero of the eagle’s roll - not too successfully at the moment.
What is the best way to zero out rigidbody roll?

using UnityEngine;
using System.Collections;

public class EagleControl : MonoBehaviour
{
    public float speedGlide = 1f;
    public float speedNormal = 2f;
    public float speedStrong = 4f;
    public Transform eagleTransform;
    void Start()
    {
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Right"].clip, "HeadRight");
        eagleTransform.animation["HeadRight"].AddMixingTransform(deepFind(eagleTransform,"neck"),true);
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Left"].clip, "HeadLeft");
        eagleTransform.animation["HeadLeft"].AddMixingTransform(deepFind(eagleTransform,"neck"), true);
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Down"].clip, "HeadDown");
        eagleTransform.animation["HeadDown"].AddMixingTransform(deepFind(eagleTransform,"neck"), true);
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Up"].clip, "HeadUp");
        eagleTransform.animation["HeadUp"].AddMixingTransform(deepFind(eagleTransform,"neck"), true);

        eagleTransform.animation["Gliding"].layer = eagleTransform.animation["Flight Strong"].layer = eagleTransform.animation["Flight Regular"].layer = 1;
        eagleTransform.animation.SyncLayer(1); // brovides nice smooth blending between the various flight powers

        // Set all eagleTransform.animations to loop
        eagleTransform.animation.wrapMode = WrapMode.Loop;

        // Except our action eagleTransform.animations, Dont loop those
        eagleTransform.animation["Bank Left"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["Bank Right"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadLeft"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadRight"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadUp"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadDown"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["Diving"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["Grab"].wrapMode = WrapMode.Clamp;

        // this doesn't work
        eagleTransform.animation["Flight Regular"].layer = -1;

//        eagleTransform.animation.Stop();
    }

    static Transform deepFind (Transform t, string s)
    {
	    Transform dt = t.Find (s);
	    if (dt != null)	
		    return dt;
	    else
	    {
		    foreach (Transform child in t) 
            {
			    dt = deepFind (child, s);
			    if (dt != null)	return dt;
		    }
	    }	
	    return null;
    }

    void FixedUpdate()
    {
        Vector3 rotation = transform.eulerAngles;
        if (Input.GetAxis("Horizontal") > 0.1f)
        {
            rigidbody.AddRelativeTorque(0, 0, 10f);
        }
        else
           if (Input.GetAxis("Horizontal") < -0.1f)
           {
               rigidbody.AddRelativeTorque(0, 0, -10f);
           }
           else
           { 
               if (transform.localRotation.eulerAngles.z < 0 + rigidbody.angularVelocity.z*Time.deltaTime) rigidbody.AddRelativeTorque(0,0,-5f);
               if (transform.localRotation.eulerAngles.z > 0 - rigidbody.angularVelocity.z * Time.deltaTime) rigidbody.AddRelativeTorque(0, 0, 5f);
           }

        rigidbody.AddRelativeForce(0, 10, speedNormal); // adding lift force to counter gravity and forward force to counter drag

        if (Input.GetAxis("Vertical") > 0.1f)
        {
            rigidbody.AddRelativeForce(0, 5f, speedStrong-speedNormal);
            eagleTransform.animation.CrossFade("Flight Strong");
        }
        else
            if (Input.GetAxis("Vertical") < -0.1f)
            {
                rigidbody.AddRelativeForce(0, -3f, speedGlide-speedNormal);
                eagleTransform.animation.CrossFade("Gliding");
            }
            else eagleTransform.animation.CrossFade("Flight Regular");

        if (Input.GetButtonDown("Jump"))
        {
            eagleTransform.animation.CrossFade("Diving", 0.3f);
        }

        if (Input.GetButtonDown("Fire1"))
        {
            // We are running so play it only on the upper body
            if (eagleTransform.animation["Flight Regular"].weight > 0.5f)
                eagleTransform.animation.CrossFadeQueued("Grab", 0.3f, QueueMode.PlayNow);
            // We are in idle so play it on the fully body
            else
                eagleTransform.animation.CrossFadeQueued("Grab", 0.3f, QueueMode.PlayNow);
        }
    }

}

Quite honestly, controlling rotation through physics in a way that feels right is hard. Even when you made it feel right, when a collision happens you usually don’t want the flying direction to spin around even though it may be physically correct.

Have you thought about just explicitly controlling the rotation and using physics for position control only. rigidbody.freezeRotation is your friend.

I just tried that to cancel the wobble I get here.
If I were to take full control over the eagle banking, I would do it with Lerps ?
By the way, are there Lerps with ease in and ease out ie: non linear?

using UnityEngine;
using System.Collections;

public class EagleControl : MonoBehaviour
{
    public float speedGlide = 1f;
    public float speedNormal = 2f;
    public float speedStrong = 4f;
    public float torque = 5f;
    public Transform eagleTransform;
    void Start()
    {
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Right"].clip, "HeadRight");
        eagleTransform.animation["HeadRight"].AddMixingTransform(deepFind(eagleTransform,"neck"),true);
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Left"].clip, "HeadLeft");
        eagleTransform.animation["HeadLeft"].AddMixingTransform(deepFind(eagleTransform,"neck"), true);
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Down"].clip, "HeadDown");
        eagleTransform.animation["HeadDown"].AddMixingTransform(deepFind(eagleTransform,"neck"), true);
        eagleTransform.animation.AddClip(eagleTransform.animation["Head Up"].clip, "HeadUp");
        eagleTransform.animation["HeadUp"].AddMixingTransform(deepFind(eagleTransform,"neck"), true);

        eagleTransform.animation["Gliding"].layer = eagleTransform.animation["Flight Strong"].layer = eagleTransform.animation["Flight Regular"].layer = 1;
        eagleTransform.animation.SyncLayer(1); // brovides nice smooth blending between the various flight powers

        // Set all eagleTransform.animations to loop
        eagleTransform.animation.wrapMode = WrapMode.Loop;

        // Except our action eagleTransform.animations, Dont loop those
        eagleTransform.animation["Bank Left"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["Bank Right"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadLeft"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadRight"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadUp"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["HeadDown"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["Diving"].wrapMode = WrapMode.Clamp;
        eagleTransform.animation["Grab"].wrapMode = WrapMode.Clamp;

        // this doesn't work
        eagleTransform.animation["Flight Regular"].layer = -1;

//        eagleTransform.animation.Stop();
    }

    static Transform deepFind (Transform t, string s)
    {
	    Transform dt = t.Find (s);
	    if (dt != null)	
		    return dt;
	    else
	    {
		    foreach (Transform child in t) 
            {
			    dt = deepFind (child, s);
			    if (dt != null)	return dt;
		    }
	    }	
	    return null;
    }

    void FixedUpdate()
    {
        Vector3 rotation = transform.eulerAngles;
        if (Input.GetAxis("Horizontal") > 0.1f  ((transform.localEulerAngles.z >270 || transform.localEulerAngles.z >0)))
        {
            rigidbody.AddRelativeTorque(0, 0, -torque, ForceMode.Acceleration);
        }
        else
           if (Input.GetAxis("Horizontal") < -0.1f  (transform.localEulerAngles.z >270 || transform.localEulerAngles.z >0))
           {
               rigidbody.AddRelativeTorque(0, 0, torque, ForceMode.Acceleration);
           }
           else
           {
               if (transform.localEulerAngles.z > 180) rigidbody.AddRelativeTorque(0, 0, torque * rigidbody.angularVelocity.z * Time.deltaTime, ForceMode.Acceleration);
              if (transform.localEulerAngles.z < 180) rigidbody.AddRelativeTorque(0, 0, -torque * rigidbody.angularVelocity.z * Time.deltaTime, ForceMode.Acceleration);
           }

        rigidbody.AddRelativeForce(0, 10, speedNormal, ForceMode.Acceleration); // adding lift force to counter gravity and forward force to counter drag

        if (Input.GetAxis("Vertical") > 0.1f)
        {
            rigidbody.AddRelativeForce(0, 5f, speedStrong-speedNormal, ForceMode.Acceleration);
            eagleTransform.animation.CrossFade("Flight Strong");
        }
        else
            if (Input.GetAxis("Vertical") < -0.1f)
            {
                rigidbody.AddRelativeForce(0, -3f, speedGlide - speedNormal, ForceMode.Acceleration);
                eagleTransform.animation.CrossFade("Gliding");
            }
            else eagleTransform.animation.CrossFade("Flight Regular");

        if (Input.GetButtonDown("Jump"))
        {
            eagleTransform.animation.CrossFade("Diving", 0.3f);
        }

        if (Input.GetButtonDown("Fire1"))
        {
            // We are running so play it only on the upper body
            if (eagleTransform.animation["Flight Regular"].weight > 0.5f)
                eagleTransform.animation.CrossFadeQueued("Grab", 0.3f, QueueMode.PlayNow);
            // We are in idle so play it on the fully body
            else
                eagleTransform.animation.CrossFadeQueued("Grab", 0.3f, QueueMode.PlayNow);
        }
    }

}

Thanks - and after some help with Unity input, here is what I ended up using which is nice because i have two controls: joystick sensitivity AND banksmooth variable.

    private float velocity;
 
    void FixedUpdate()
    {
        Vector3 rotation = transform.localEulerAngles;
        rotation.z = Mathf.SmoothDampAngle(rotation.z,-Input.GetAxis("Horizontal") * bankSpeed, ref velocity, bankSmooth );
        transform.localEulerAngles = rotation;
etc...

Although it never seems to reach the max angle (which makes sense since the reference rotaion.z is alway refreshed)… any idea ?