BulletSim: add BSVMotor as BSDynamics linear motor.

Properly limit *_MOTOR_DECAY_TIMESCALE to 120 as per specs.
Invode BSDynamics.Refresh() when vehicle type is changed. Previously
   the vehicle properties weren't getting set because the physical
   properties were set before the vehicle type was set.
Add a "use name" to BSMotors for identification while debugging.
Correct current and target confusion in BSVMotor design.
Rename CurrentValueReductionTimescale to FrictionTimescale.
Event more detailed logging.
connector_plugin^2
Robert Adams 2012-11-25 17:41:15 -08:00
parent bd635e264a
commit 319ec3235c
2 changed files with 71 additions and 24 deletions

View File

@ -80,6 +80,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private Quaternion m_referenceFrame = Quaternion.Identity;
// Linear properties
private BSVMotor m_linearMotor = new BSVMotor("LinearMotor");
private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time
private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center
private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL
@ -152,7 +153,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_angularDeflectionTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE:
m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f);
m_angularMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
break;
case Vehicle.ANGULAR_MOTOR_TIMESCALE:
m_angularMotorTimescale = Math.Max(pValue, 0.01f);
@ -185,10 +186,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_linearDeflectionTimescale = Math.Max(pValue, 0.01f);
break;
case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE:
m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f);
m_linearMotorDecayTimescale = Math.Max(0.01f, Math.Min(pValue,120));
m_linearMotor.TargetValueDecayTimeScale = m_linearMotorDecayTimescale;
break;
case Vehicle.LINEAR_MOTOR_TIMESCALE:
m_linearMotorTimescale = Math.Max(pValue, 0.01f);
m_linearMotor.TimeScale = m_linearMotorTimescale;
break;
case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY:
m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f));
@ -208,10 +211,12 @@ 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);
m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue);
m_linearMotor.SetTarget(m_linearMotorDirection);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
m_linearMotorOffset = new Vector3(pValue, pValue, pValue);
@ -238,10 +243,12 @@ 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);
m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z);
m_linearMotor.SetTarget(m_linearMotorDirection);
break;
case Vehicle.LINEAR_MOTOR_OFFSET:
m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z);
@ -319,6 +326,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_referenceFrame = Quaternion.Identity;
m_flags = (VehicleFlag)0;
break;
case Vehicle.TYPE_SLED:
@ -510,6 +518,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
| VehicleFlag.HOVER_GLOBAL_HEIGHT);
break;
}
// Update any physical parameters based on this type.
Refresh();
m_linearMotor = new BSVMotor("LinearMotor", m_linearMotorTimescale, m_linearMotorDecayTimescale, m_linearFrictionTimescale, 1f);
m_linearMotor.PhysicsScene = PhysicsScene; // DEBUG DEBUG DEBUG (enables detail logging)
}
// Some of the properties of this prim may have changed.
@ -518,18 +532,25 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
if (IsActive)
{
VDetailLog("{0},BSDynamics.Refresh", Prim.LocalID);
m_vehicleMass = Prim.Linkset.LinksetMass;
// Friction effects are handled by this vehicle code
BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f);
BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f);
float friction = 0f;
BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, friction);
BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, PhysicsScene.Params.vehicleAngularDamping);
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, new Vector3(1f, 1f, 1f));
// Moderate angular movement introduced by Bullet.
// TODO: possibly set AngularFactor and LinearFactor for the type of vehicle.
// Maybe compute linear and angular factor and damping from params.
float angularDamping = PhysicsScene.Params.vehicleAngularDamping;
BulletSimAPI.SetAngularDamping2(Prim.PhysBody.ptr, angularDamping);
// DEBUG DEBUG DEBUG: use uniform inertia to smooth movement added by Bullet
// Vector3 localInertia = new Vector3(1f, 1f, 1f);
Vector3 localInertia = new Vector3(m_vehicleMass, m_vehicleMass, m_vehicleMass);
BulletSimAPI.SetMassProps2(Prim.PhysBody.ptr, m_vehicleMass, localInertia);
VDetailLog("{0},BSDynamics.Refresh,frict={1},inert={2},aDamp={3}",
Prim.LocalID, friction, localInertia, angularDamping);
}
}
@ -591,6 +612,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
// Also does hover and float.
private void MoveLinear(float pTimestep)
{
/*
// m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates
// m_lastLinearVelocityVector is the current speed we are moving in that direction
if (m_linearMotorDirection.LengthSquared() > 0.001f)
@ -627,6 +649,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin
VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID);
}
*/
m_newVelocity = m_linearMotor.Step(pTimestep);
// Rotate new object velocity from vehicle relative to world coordinates
m_newVelocity *= Prim.ForceOrientation;
// m_newVelocity is velocity computed from linear motor in world coordinates
@ -785,12 +813,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
m_newVelocity.Z = 0;
// Clamp REALLY high or low velocities
if (m_newVelocity.LengthSquared() > 1e6f)
float newVelocityLengthSq = m_newVelocity.LengthSquared();
if (newVelocityLengthSq > 1e6f)
{
m_newVelocity /= m_newVelocity.Length();
m_newVelocity *= 1000f;
}
else if (m_newVelocity.LengthSquared() < 1e-6f)
else if (newVelocityLengthSq < 1e-6f)
m_newVelocity = Vector3.Zero;
// Stuff new linear velocity into the vehicle

View File

@ -7,13 +7,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
public abstract class BSMotor
{
public BSMotor()
public BSMotor(string useName)
{
UseName = useName;
PhysicsScene = null;
}
public virtual void Reset() { }
public virtual void Zero() { }
public string UseName { get; private set; }
// Used only for outputting debug information. Might not be set so check for null.
public BSScene PhysicsScene { get; set; }
protected void MDetailLog(string msg, params Object[] parms)
@ -35,17 +37,25 @@ public class BSVMotor : BSMotor
public float TimeScale { get; set; }
public float TargetValueDecayTimeScale { get; set; }
public Vector3 CurrentValueReductionTimescale { get; set; }
public Vector3 FrictionTimescale { get; set; }
public float Efficiency { get; set; }
public Vector3 TargetValue { get; private set; }
public Vector3 CurrentValue { get; private set; }
BSVMotor(float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency) : base()
public BSVMotor(string useName)
: base(useName)
{
TimeScale = TargetValueDecayTimeScale = Efficiency = 1f;
FrictionTimescale = Vector3.Zero;
CurrentValue = TargetValue = Vector3.Zero;
}
public BSVMotor(string useName, float timeScale, float decayTimeScale, Vector3 frictionTimeScale, float efficiency)
: this(useName)
{
TimeScale = timeScale;
TargetValueDecayTimeScale = decayTimeScale;
CurrentValueReductionTimescale = frictionTimeScale;
FrictionTimescale = frictionTimeScale;
Efficiency = efficiency;
CurrentValue = TargetValue = Vector3.Zero;
}
@ -60,10 +70,10 @@ public class BSVMotor : BSMotor
public Vector3 Step(float timeStep)
{
Vector3 returnCurrent = Vector3.Zero;
if (CurrentValue.LengthSquared() > 0.001f)
if (!CurrentValue.ApproxEquals(TargetValue, 0.01f))
{
// Vector3 origDir = Target; // DEBUG
// Vector3 origVel = CurrentValue; // DEBUG
Vector3 origTarget = TargetValue; // DEBUG
Vector3 origCurrVal = CurrentValue; // DEBUG
// Add (desiredVector - currentAppliedVector) / howLongItShouldTakeToComplete
Vector3 addAmount = (TargetValue - CurrentValue)/TimeScale * timeStep;
@ -74,11 +84,17 @@ public class BSVMotor : BSMotor
float decayFactor = (1.0f / TargetValueDecayTimeScale) * timeStep;
TargetValue *= (1f - decayFactor);
Vector3 frictionFactor = (Vector3.One / CurrentValueReductionTimescale) * timeStep;
Vector3 frictionFactor = Vector3.Zero;
frictionFactor = (Vector3.One / FrictionTimescale) * timeStep;
CurrentValue *= (Vector3.One - frictionFactor);
MDetailLog("{0},BSVMotor.Step,nonZero,curr={1},target={2},add={3},decay={4},frict={5},ret={6}",
BSScene.DetailLogZero, TargetValue, CurrentValue,
MDetailLog("{0},BSVMotor.Step,nonZero,{1},origTarget={2},origCurr={3},timeStep={4},timeScale={5},addAmnt={6},targetDecay={7},decayFact={8},fricTS={9},frictFact={10}",
BSScene.DetailLogZero, UseName, origTarget, origCurrVal,
timeStep, TimeScale, addAmount,
TargetValueDecayTimeScale, decayFactor,
FrictionTimescale, frictionFactor);
MDetailLog("{0},BSVMotor.Step,nonZero,{1},curr={2},target={3},add={4},decay={5},frict={6},ret={7}",
BSScene.DetailLogZero, UseName, TargetValue, CurrentValue,
addAmount, decayFactor, frictionFactor, returnCurrent);
}
else
@ -87,8 +103,8 @@ public class BSVMotor : BSMotor
CurrentValue = Vector3.Zero;
TargetValue = Vector3.Zero;
MDetailLog("{0},BSVMotor.Step,zero,curr={1},target={2},ret={3}",
BSScene.DetailLogZero, TargetValue, CurrentValue, returnCurrent);
MDetailLog("{0},BSVMotor.Step,zero,{1},curr={2},target={3},ret={4}",
BSScene.DetailLogZero, UseName, TargetValue, CurrentValue, returnCurrent);
}
return returnCurrent;
@ -105,7 +121,8 @@ public class BSFMotor : BSMotor
public float Target { get; private set; }
public float CurrentValue { get; private set; }
BSFMotor(float timeScale, float decayTimescale, float friction, float efficiency) : base()
public BSFMotor(string useName, float timeScale, float decayTimescale, float friction, float efficiency)
: base(useName)
{
}
public void SetCurrent(float target)
@ -122,7 +139,8 @@ public class BSFMotor : BSMotor
public class BSPIDMotor : BSMotor
{
// TODO: write and use this one
BSPIDMotor() : base()
public BSPIDMotor(string useName)
: base(useName)
{
}
}