public void ComputeAngularDeflection()
{
// Since angularMotorUp and angularDeflection are computed independently, they will calculate
// approximately the same X or Y correction. When added together (when contributions are combined)
// this creates an over-correction and then wabbling as the target is overshot.
// TODO: rethink how the different correction computations inter-relate.
if (BSParam.VehicleEnableAngularDeflection && m_angularDeflectionEfficiency != 0 && VehicleForwardSpeed > 0.2)
{
Vector3 deflectContributionV = Vector3.Zero;
// The direction the vehicle is moving
Vector3 movingDirection = VehicleVelocity;
movingDirection.Normalize();
// If the vehicle is going backward, it is still pointing forward
movingDirection *= Math.Sign(VehicleForwardSpeed);
// The direction the vehicle is pointing
/* Vector3 pointingDirection = Vector3.UnitX * VehicleOrientation;
pointingDirection.Normalize();
// The difference between what is and what should be.
Vector3 deflectionError = movingDirection - pointingDirection;
*/
Vector3 pointingDirection = Vector3.UnitX * VehicleFrameOrientation;
//Predict where the Vehicle will be pointing after AngularVelocity change is applied. This will keep
// from overshooting and allow this correction to merge with the Vertical Attraction peacefully.
Vector3 predictedPointingDirection = pointingDirection * Quaternion.CreateFromAxisAngle(VehicleRotationalVelocity, 0f);
predictedPointingDirection.Normalize();
// The difference between what is and what should be.
// Vector3 deflectionError = movingDirection - predictedPointingDirection;
Vector3 deflectionError = Vector3.Cross(movingDirection, predictedPointingDirection);
// Don't try to correct very large errors (not our job)
// if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = PIOverTwo * Math.Sign(deflectionError.X);
// if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = PIOverTwo * Math.Sign(deflectionError.Y);
// if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = PIOverTwo * Math.Sign(deflectionError.Z);
if (Math.Abs(deflectionError.X) > PIOverFour) deflectionError.X = 0f;
if (Math.Abs(deflectionError.Y) > PIOverFour) deflectionError.Y = 0f;
if (Math.Abs(deflectionError.Z) > PIOverFour) deflectionError.Z = 0f;
// ret = m_angularDeflectionCorrectionMotor(1f, deflectionError);
// Scale the correction by recovery timescale and efficiency
deflectContributionV = (-deflectionError) * ClampInRange(0,m_angularDeflectionEfficiency/m_angularDeflectionTimescale,1);
deflectContributionV /= m_angularDeflectionTimescale;
VehicleRotationalVelocity += deflectContributionV; // * VehicleOrientation;
VDetailLog("{0}, MoveAngular,Deflection,movingDir={1},pointingDir={2},deflectError={3},ret={4}",
ControllingPrim.LocalID, movingDirection, pointingDirection, deflectionError, deflectContributionV);
VDetailLog("{0}, MoveAngular,Deflection,fwdSpd={1},defEff={2},defTS={3},PredictedPointingDir={4}",
ControllingPrim.LocalID, VehicleForwardSpeed, m_angularDeflectionEfficiency, m_angularDeflectionTimescale, predictedPointingDirection);
}
}