BulletSim: remove friction calcuation from BSMotor and move linear and

angular friction computation into linear and angular movement code.
The friction wasn't being applied properly. This will make it so vehicles
don't drift as much and the drift is tunable by changing the friction
timescales.
user_profiles
Robert Adams 2013-05-06 13:29:19 -07:00
parent bf31896983
commit 045aaa838a
7 changed files with 47 additions and 67 deletions

View File

@ -118,7 +118,6 @@ public class BSActorAvatarMove : BSActor
m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
0.2f, // time scale
BSMotor.Infinite, // decay time scale
BSMotor.InfiniteVector, // friction timescale
1f // efficiency
);
// _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages.

View File

@ -102,7 +102,6 @@ public class BSActorHover : BSActor
m_hoverMotor = new BSFMotor("BSActorHover",
m_controllingPrim.HoverTau, // timeScale
BSMotor.Infinite, // decay time scale
BSMotor.Infinite, // friction timescale
1f // efficiency
);
m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());

View File

@ -105,7 +105,6 @@ public class BSActorMoveToTarget : BSActor
m_targetMotor = new BSVMotor("BSActorMoveToTargget.Activate",
m_controllingPrim.MoveToTargetTau, // timeScale
BSMotor.Infinite, // decay time scale
BSMotor.InfiniteVector, // friction timescale
1f // efficiency
);
m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages.

View File

@ -101,7 +101,7 @@ public class BSActorSetForce : BSActor
if (m_forceMotor == null)
{
// A fake motor that might be used someday
m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f, 1f);
m_forceMotor = new BSFMotor("setForce", 1f, 1f, 1f);
m_physicsScene.BeforeStep += Mover;
}

View File

@ -101,7 +101,7 @@ public class BSActorSetTorque : BSActor
if (m_torqueMotor == null)
{
// A fake motor that might be used someday
m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f, 1f);
m_torqueMotor = new BSFMotor("setTorque", 1f, 1f, 1f);
m_physicsScene.BeforeStep += Mover;
}

View File

@ -235,7 +235,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// set all of the components to the same value
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
@ -244,7 +243,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
@ -265,7 +263,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
case Vehicle.ANGULAR_FRICTION_TIMESCALE:
m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
break;
case Vehicle.ANGULAR_MOTOR_DIRECTION:
// Limit requested angular speed to 2 rps= 4 pi rads/sec
@ -278,7 +275,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
break;
case Vehicle.LINEAR_FRICTION_TIMESCALE:
m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
break;
case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
@ -559,14 +555,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
break;
}
m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale,
m_linearMotorDecayTimescale, m_linearFrictionTimescale,
1f);
m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale,
m_angularMotorDecayTimescale, m_angularFrictionTimescale,
1f);
m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
/* Not implemented
@ -574,7 +566,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
BSMotor.Infinite, BSMotor.InfiniteVector,
m_verticalAttractionEfficiency);
// Z goes away and we keep X and Y
m_verticalAttractionMotor.FrictionTimescale = new Vector3(BSMotor.Infinite, BSMotor.Infinite, 0.1f);
m_verticalAttractionMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
*/
@ -1050,8 +1041,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Add this correction to the velocity to make it faster/slower.
VehicleVelocity += linearMotorVelocityW;
VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}",
ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity);
// Friction reduces vehicle motion
Vector3 frictionFactor = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep);
VehicleVelocity -= (VehicleVelocity * frictionFactor);
VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}",
ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV,
linearMotorVelocityW, VehicleVelocity, frictionFactor);
}
public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@ -1342,6 +1338,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// }
VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation;
// Reduce any velocity by friction.
Vector3 frictionFactor = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep);
VehicleRotationalVelocity -= (VehicleRotationalVelocity * frictionFactor);
VDetailLog("{0}, MoveAngular,angularTurning,angularMotorContrib={1}", ControllingPrim.LocalID, angularMotorContributionV);
}
@ -1629,6 +1630,23 @@ namespace OpenSim.Region.Physics.BulletSPlugin
}
// Given a friction vector (reduction in seconds) and a timestep, return the factor to reduce
// some value by to apply this friction.
private Vector3 ComputeFrictionFactor(Vector3 friction, float pTimestep)
{
Vector3 frictionFactor = Vector3.Zero;
if (friction != BSMotor.InfiniteVector)
{
// frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
// Individual friction components can be 'infinite' so compute each separately.
frictionFactor.X = (friction.X == BSMotor.Infinite) ? 0f : (1f / friction.X);
frictionFactor.Y = (friction.Y == BSMotor.Infinite) ? 0f : (1f / friction.Y);
frictionFactor.Z = (friction.Z == BSMotor.Infinite) ? 0f : (1f / friction.Z);
frictionFactor *= pTimestep;
}
return frictionFactor;
}
private float ClampInRange(float low, float val, float high)
{
return Math.Max(low, Math.Min(val, high));

View File

@ -65,13 +65,11 @@ public abstract class BSMotor
}
// Motor which moves CurrentValue to TargetValue over TimeScale seconds.
// The TargetValue decays in TargetValueDecayTimeScale and
// the CurrentValue will be held back by FrictionTimeScale.
// The TargetValue decays in TargetValueDecayTimeScale.
// This motor will "zero itself" over time in that the targetValue will
// decay to zero and the currentValue will follow it to that zero.
// The overall effect is for the returned correction value to go from large
// values (the total difference between current and target minus friction)
// to small and eventually zero values.
// values to small and eventually zero values.
// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay.
// For instance, if something is moving at speed X and the desired speed is Y,
@ -88,7 +86,6 @@ public class BSVMotor : BSMotor
public virtual float TimeScale { get; set; }
public virtual float TargetValueDecayTimeScale { get; set; }
public virtual Vector3 FrictionTimescale { get; set; }
public virtual float Efficiency { get; set; }
public virtual float ErrorZeroThreshold { get; set; }
@ -111,16 +108,14 @@ public class BSVMotor : BSMotor
{
TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
Efficiency = 1f;
FrictionTimescale = BSMotor.InfiniteVector;
CurrentValue = TargetValue = Vector3.Zero;
ErrorZeroThreshold = 0.001f;
}
public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
public BSVMotor(string useName, float timeScale, float decayTimeScale, float efficiency)
: this(useName)
{
TimeScale = timeScale;
TargetValueDecayTimeScale = decayTimeScale;
FrictionTimescale = frictionTimeScale;
Efficiency = efficiency;
CurrentValue = TargetValue = Vector3.Zero;
}
@ -165,26 +160,11 @@ public class BSVMotor : BSMotor
TargetValue *= (1f - decayFactor);
}
// The amount we can correct the error is reduced by the friction
Vector3 frictionFactor = Vector3.Zero;
if (FrictionTimescale != BSMotor.InfiniteVector)
{
// frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
// Individual friction components can be 'infinite' so compute each separately.
frictionFactor.X = (FrictionTimescale.X == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.X);
frictionFactor.Y = (FrictionTimescale.Y == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Y);
frictionFactor.Z = (FrictionTimescale.Z == BSMotor.Infinite) ? 0f : (1f / FrictionTimescale.Z);
frictionFactor *= timeStep;
CurrentValue *= (Vector3.One - frictionFactor);
}
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
timeStep, error, correction);
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}",
BSScene.DetailLogZero, UseName,
TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
TargetValue, CurrentValue);
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
}
else
{
@ -235,9 +215,9 @@ public class BSVMotor : BSMotor
// maximum number of outputs to generate.
int maxOutput = 50;
MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName);
MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},frictTS={4},eff={5},curr={6},tgt={7}",
MDetailLog("{0},BSVMotor.Test,{1},timeScale={2},targDlyTS={3},eff={4},curr={5},tgt={6}",
BSScene.DetailLogZero, UseName,
TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency,
TimeScale, TargetValueDecayTimeScale, Efficiency,
CurrentValue, TargetValue);
LastError = BSMotor.InfiniteVector;
@ -254,8 +234,8 @@ public class BSVMotor : BSMotor
public override string ToString()
{
return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>",
UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale);
return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
}
}
@ -265,7 +245,6 @@ public class BSFMotor : BSMotor
{
public virtual float TimeScale { get; set; }
public virtual float TargetValueDecayTimeScale { get; set; }
public virtual float FrictionTimescale { get; set; }
public virtual float Efficiency { get; set; }
public virtual float ErrorZeroThreshold { get; set; }
@ -283,12 +262,11 @@ public class BSFMotor : BSMotor
return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold);
}
public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency)
public BSFMotor(string useName, float timeScale, float decayTimescale, float efficiency)
: base(useName)
{
TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
Efficiency = 1f;
FrictionTimescale = BSMotor.Infinite;
CurrentValue = TargetValue = 0f;
ErrorZeroThreshold = 0.01f;
}
@ -331,24 +309,11 @@ public class BSFMotor : BSMotor
TargetValue *= (1f - decayFactor);
}
// The amount we can correct the error is reduced by the friction
float frictionFactor = 0f;
if (FrictionTimescale != BSMotor.Infinite)
{
// frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
// Individual friction components can be 'infinite' so compute each separately.
frictionFactor = 1f / FrictionTimescale;
frictionFactor *= timeStep;
CurrentValue *= (1f - frictionFactor);
}
MDetailLog("{0}, BSFMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
timeStep, error, correction);
MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}",
BSScene.DetailLogZero, UseName,
TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
TargetValue, CurrentValue);
MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
}
else
{
@ -390,8 +355,8 @@ public class BSFMotor : BSMotor
public override string ToString()
{
return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>",
UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale);
return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
}
}