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", m_velocityMotor = new BSVMotor("BSCharacter.Velocity",
0.2f, // time scale 0.2f, // time scale
BSMotor.Infinite, // decay time scale BSMotor.Infinite, // decay time scale
BSMotor.InfiniteVector, // friction timescale
1f // efficiency 1f // efficiency
); );
// _velocityMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG so motor will output detail log messages. // _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_hoverMotor = new BSFMotor("BSActorHover",
m_controllingPrim.HoverTau, // timeScale m_controllingPrim.HoverTau, // timeScale
BSMotor.Infinite, // decay time scale BSMotor.Infinite, // decay time scale
BSMotor.Infinite, // friction timescale
1f // efficiency 1f // efficiency
); );
m_hoverMotor.SetTarget(ComputeCurrentHoverHeight()); m_hoverMotor.SetTarget(ComputeCurrentHoverHeight());

View File

@ -105,7 +105,6 @@ public class BSActorMoveToTarget : BSActor
m_targetMotor = new BSVMotor("BSActorMoveToTargget.Activate", m_targetMotor = new BSVMotor("BSActorMoveToTargget.Activate",
m_controllingPrim.MoveToTargetTau, // timeScale m_controllingPrim.MoveToTargetTau, // timeScale
BSMotor.Infinite, // decay time scale BSMotor.Infinite, // decay time scale
BSMotor.InfiniteVector, // friction timescale
1f // efficiency 1f // efficiency
); );
m_targetMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG so motor will output detail log messages. 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) if (m_forceMotor == null)
{ {
// A fake motor that might be used someday // 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; m_physicsScene.BeforeStep += Mover;
} }

View File

@ -101,7 +101,7 @@ public class BSActorSetTorque : BSActor
if (m_torqueMotor == null) if (m_torqueMotor == null)
{ {
// A fake motor that might be used someday // 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; m_physicsScene.BeforeStep += Mover;
} }

View File

@ -235,7 +235,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// set all of the components to the same value // set all of the components to the same value
case Vehicle.ANGULAR_FRICTION_TIMESCALE: case Vehicle.ANGULAR_FRICTION_TIMESCALE:
m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue); m_angularFrictionTimescale = new Vector3(pValue, pValue, pValue);
m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
break; break;
case Vehicle.ANGULAR_MOTOR_DIRECTION: case Vehicle.ANGULAR_MOTOR_DIRECTION:
m_angularMotorDirection = new Vector3(pValue, pValue, pValue); m_angularMotorDirection = new Vector3(pValue, pValue, pValue);
@ -244,7 +243,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
break; break;
case Vehicle.LINEAR_FRICTION_TIMESCALE: case Vehicle.LINEAR_FRICTION_TIMESCALE:
m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue);
m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
break; break;
case Vehicle.LINEAR_MOTOR_DIRECTION: case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue, pValue, pValue); m_linearMotorDirection = new Vector3(pValue, pValue, pValue);
@ -265,7 +263,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{ {
case Vehicle.ANGULAR_FRICTION_TIMESCALE: case Vehicle.ANGULAR_FRICTION_TIMESCALE:
m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
m_angularMotor.FrictionTimescale = m_angularFrictionTimescale;
break; break;
case Vehicle.ANGULAR_MOTOR_DIRECTION: case Vehicle.ANGULAR_MOTOR_DIRECTION:
// Limit requested angular speed to 2 rps= 4 pi rads/sec // Limit requested angular speed to 2 rps= 4 pi rads/sec
@ -278,7 +275,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
break; break;
case Vehicle.LINEAR_FRICTION_TIMESCALE: case Vehicle.LINEAR_FRICTION_TIMESCALE:
m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z);
m_linearMotor.FrictionTimescale = m_linearFrictionTimescale;
break; break;
case Vehicle.LINEAR_MOTOR_DIRECTION: case Vehicle.LINEAR_MOTOR_DIRECTION:
m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); m_linearMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z);
@ -559,14 +555,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin
break; break;
} }
m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, 1f);
m_linearMotorDecayTimescale, m_linearFrictionTimescale,
1f);
m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) m_linearMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotor = new BSVMotor("AngularMotor", m_angularMotorTimescale, m_angularMotorDecayTimescale, 1f);
m_angularMotorDecayTimescale, m_angularFrictionTimescale,
1f);
m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging) m_angularMotor.PhysicsScene = m_physicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
/* Not implemented /* Not implemented
@ -574,7 +566,6 @@ namespace OpenSim.Region.Physics.BulletSPlugin
BSMotor.Infinite, BSMotor.InfiniteVector, BSMotor.Infinite, BSMotor.InfiniteVector,
m_verticalAttractionEfficiency); m_verticalAttractionEfficiency);
// Z goes away and we keep X and Y // 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) 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. // Add this correction to the velocity to make it faster/slower.
VehicleVelocity += linearMotorVelocityW; VehicleVelocity += linearMotorVelocityW;
VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5}", // Friction reduces vehicle motion
ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, linearMotorVelocityW, VehicleVelocity); 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) public void ComputeLinearTerrainHeightCorrection(float pTimestep)
@ -1342,6 +1338,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// } // }
VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; 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); 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) private float ClampInRange(float low, float val, float high)
{ {
return Math.Max(low, Math.Min(val, 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. // Motor which moves CurrentValue to TargetValue over TimeScale seconds.
// The TargetValue decays in TargetValueDecayTimeScale and // The TargetValue decays in TargetValueDecayTimeScale.
// the CurrentValue will be held back by FrictionTimeScale.
// This motor will "zero itself" over time in that the targetValue will // This motor will "zero itself" over time in that the targetValue will
// decay to zero and the currentValue will follow it to that zero. // 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 // The overall effect is for the returned correction value to go from large
// values (the total difference between current and target minus friction) // values to small and eventually zero values.
// to small and eventually zero values.
// TimeScale and TargetDelayTimeScale may be 'infinite' which means no decay. // 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, // 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 TimeScale { get; set; }
public virtual float TargetValueDecayTimeScale { get; set; } public virtual float TargetValueDecayTimeScale { get; set; }
public virtual Vector3 FrictionTimescale { get; set; }
public virtual float Efficiency { get; set; } public virtual float Efficiency { get; set; }
public virtual float ErrorZeroThreshold { get; set; } public virtual float ErrorZeroThreshold { get; set; }
@ -111,16 +108,14 @@ public class BSVMotor : BSMotor
{ {
TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
Efficiency = 1f; Efficiency = 1f;
FrictionTimescale = BSMotor.InfiniteVector;
CurrentValue = TargetValue = Vector3.Zero; CurrentValue = TargetValue = Vector3.Zero;
ErrorZeroThreshold = 0.001f; 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) : this(useName)
{ {
TimeScale = timeScale; TimeScale = timeScale;
TargetValueDecayTimeScale = decayTimeScale; TargetValueDecayTimeScale = decayTimeScale;
FrictionTimescale = frictionTimeScale;
Efficiency = efficiency; Efficiency = efficiency;
CurrentValue = TargetValue = Vector3.Zero; CurrentValue = TargetValue = Vector3.Zero;
} }
@ -165,26 +160,11 @@ public class BSVMotor : BSMotor
TargetValue *= (1f - decayFactor); 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}", MDetailLog("{0}, BSVMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
BSScene.DetailLogZero, UseName, origCurrVal, origTarget, BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
timeStep, error, correction); timeStep, error, correction);
MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", MDetailLog("{0}, BSVMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
BSScene.DetailLogZero, UseName, BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
TargetValue, CurrentValue);
} }
else else
{ {
@ -235,9 +215,9 @@ public class BSVMotor : BSMotor
// maximum number of outputs to generate. // maximum number of outputs to generate.
int maxOutput = 50; int maxOutput = 50;
MDetailLog("{0},BSVMotor.Test,{1},===================================== BEGIN Test Output", BSScene.DetailLogZero, UseName); 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, BSScene.DetailLogZero, UseName,
TimeScale, TargetValueDecayTimeScale, FrictionTimescale, Efficiency, TimeScale, TargetValueDecayTimeScale, Efficiency,
CurrentValue, TargetValue); CurrentValue, TargetValue);
LastError = BSMotor.InfiniteVector; LastError = BSMotor.InfiniteVector;
@ -254,8 +234,8 @@ public class BSVMotor : BSMotor
public override string ToString() public override string ToString()
{ {
return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
} }
} }
@ -265,7 +245,6 @@ public class BSFMotor : BSMotor
{ {
public virtual float TimeScale { get; set; } public virtual float TimeScale { get; set; }
public virtual float TargetValueDecayTimeScale { get; set; } public virtual float TargetValueDecayTimeScale { get; set; }
public virtual float FrictionTimescale { get; set; }
public virtual float Efficiency { get; set; } public virtual float Efficiency { get; set; }
public virtual float ErrorZeroThreshold { get; set; } public virtual float ErrorZeroThreshold { get; set; }
@ -283,12 +262,11 @@ public class BSFMotor : BSMotor
return (err >= -ErrorZeroThreshold && err <= ErrorZeroThreshold); 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) : base(useName)
{ {
TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite; TimeScale = TargetValueDecayTimeScale = BSMotor.Infinite;
Efficiency = 1f; Efficiency = 1f;
FrictionTimescale = BSMotor.Infinite;
CurrentValue = TargetValue = 0f; CurrentValue = TargetValue = 0f;
ErrorZeroThreshold = 0.01f; ErrorZeroThreshold = 0.01f;
} }
@ -331,24 +309,11 @@ public class BSFMotor : BSMotor
TargetValue *= (1f - decayFactor); 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}", MDetailLog("{0}, BSFMotor.Step,nonZero,{1},origCurr={2},origTarget={3},timeStep={4},err={5},corr={6}",
BSScene.DetailLogZero, UseName, origCurrVal, origTarget, BSScene.DetailLogZero, UseName, origCurrVal, origTarget,
timeStep, error, correction); timeStep, error, correction);
MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},frictTS={4},frictFact={5},tgt={6},curr={7}", MDetailLog("{0}, BSFMotor.Step,nonZero,{1},tgtDecayTS={2},decayFact={3},tgt={4},curr={5}",
BSScene.DetailLogZero, UseName, BSScene.DetailLogZero, UseName, TargetValueDecayTimeScale, decayFactor, TargetValue, CurrentValue);
TargetValueDecayTimeScale, decayFactor, FrictionTimescale, frictionFactor,
TargetValue, CurrentValue);
} }
else else
{ {
@ -390,8 +355,8 @@ public class BSFMotor : BSMotor
public override string ToString() public override string ToString()
{ {
return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4},frictTS={5}>", return String.Format("<{0},curr={1},targ={2},lastErr={3},decayTS={4}>",
UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale, FrictionTimescale); UseName, CurrentValue, TargetValue, LastError, TargetValueDecayTimeScale);
} }
} }