BulletSim: first unit test: vehicle angular attraction

user_profiles
Robert Adams 2013-01-28 17:08:34 -08:00
parent e9aff0a91d
commit 531d0429d1
6 changed files with 152 additions and 79 deletions

View File

@ -125,9 +125,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
static readonly float PIOverTwo = ((float)Math.PI) / 2f; static readonly float PIOverTwo = ((float)Math.PI) / 2f;
// For debugging, flags to turn on and off individual corrections. // For debugging, flags to turn on and off individual corrections.
private bool enableAngularVerticalAttraction; public bool enableAngularVerticalAttraction;
private bool enableAngularDeflection; public bool enableAngularDeflection;
private bool enableAngularBanking; public bool enableAngularBanking;
public BSDynamics(BSScene myScene, BSPrim myPrim) public BSDynamics(BSScene myScene, BSPrim myPrim)
{ {
@ -165,7 +165,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin
} }
#region Vehicle parameter setting #region Vehicle parameter setting
internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) public void ProcessFloatVehicleParam(Vehicle pParam, float pValue)
{ {
VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue);
switch (pParam) switch (pParam)
@ -677,13 +677,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin
private const int m_knownChangedWaterLevel = 1 << 9; private const int m_knownChangedWaterLevel = 1 << 9;
private const int m_knownChangedForwardVelocity = 1 <<10; private const int m_knownChangedForwardVelocity = 1 <<10;
private void ForgetKnownVehicleProperties() public void ForgetKnownVehicleProperties()
{ {
m_knownHas = 0; m_knownHas = 0;
m_knownChanged = 0; m_knownChanged = 0;
} }
// Push all the changed values back into the physics engine // Push all the changed values back into the physics engine
private void PushKnownChanged() public void PushKnownChanged()
{ {
if (m_knownChanged != 0) if (m_knownChanged != 0)
{ {

View File

@ -73,7 +73,7 @@ public sealed class BSPrim : BSPhysObject
private bool _kinematic; private bool _kinematic;
private float _buoyancy; private float _buoyancy;
private BSDynamics _vehicle; public BSDynamics VehicleController { get; private set; }
private BSVMotor _targetMotor; private BSVMotor _targetMotor;
private OMV.Vector3 _PIDTarget; private OMV.Vector3 _PIDTarget;
@ -107,7 +107,7 @@ public sealed class BSPrim : BSPhysObject
_friction = PhysicsScene.Params.defaultFriction; _friction = PhysicsScene.Params.defaultFriction;
_restitution = PhysicsScene.Params.defaultRestitution; _restitution = PhysicsScene.Params.defaultRestitution;
_vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness VehicleController = new BSDynamics(PhysicsScene, this); // add vehicleness
_mass = CalculateMass(); _mass = CalculateMass();
@ -512,7 +512,7 @@ public sealed class BSPrim : BSPhysObject
public override int VehicleType { public override int VehicleType {
get { get {
return (int)_vehicle.Type; // if we are a vehicle, return that type return (int)VehicleController.Type; // if we are a vehicle, return that type
} }
set { set {
Vehicle type = (Vehicle)value; Vehicle type = (Vehicle)value;
@ -521,19 +521,19 @@ public sealed class BSPrim : BSPhysObject
{ {
// Done at taint time so we're sure the physics engine is not using the variables // Done at taint time so we're sure the physics engine is not using the variables
// Vehicle code changes the parameters for this vehicle type. // Vehicle code changes the parameters for this vehicle type.
_vehicle.ProcessTypeChange(type); VehicleController.ProcessTypeChange(type);
ActivateIfPhysical(false); ActivateIfPhysical(false);
// If an active vehicle, register the vehicle code to be called before each step // If an active vehicle, register the vehicle code to be called before each step
if (_vehicle.Type == Vehicle.TYPE_NONE) if (VehicleController.Type == Vehicle.TYPE_NONE)
{ {
UnRegisterPreStepAction("BSPrim.Vehicle", LocalID); UnRegisterPreStepAction("BSPrim.Vehicle", LocalID);
PhysicsScene.AfterStep -= _vehicle.PostStep; PhysicsScene.AfterStep -= VehicleController.PostStep;
} }
else else
{ {
RegisterPreStepAction("BSPrim.Vehicle", LocalID, _vehicle.Step); RegisterPreStepAction("BSPrim.Vehicle", LocalID, VehicleController.Step);
PhysicsScene.AfterStep += _vehicle.PostStep; PhysicsScene.AfterStep += VehicleController.PostStep;
} }
}); });
} }
@ -542,7 +542,7 @@ public sealed class BSPrim : BSPhysObject
{ {
PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate()
{ {
_vehicle.ProcessFloatVehicleParam((Vehicle)param, value); VehicleController.ProcessFloatVehicleParam((Vehicle)param, value);
ActivateIfPhysical(false); ActivateIfPhysical(false);
}); });
} }
@ -550,7 +550,7 @@ public sealed class BSPrim : BSPhysObject
{ {
PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate()
{ {
_vehicle.ProcessVectorVehicleParam((Vehicle)param, value); VehicleController.ProcessVectorVehicleParam((Vehicle)param, value);
ActivateIfPhysical(false); ActivateIfPhysical(false);
}); });
} }
@ -558,7 +558,7 @@ public sealed class BSPrim : BSPhysObject
{ {
PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate()
{ {
_vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); VehicleController.ProcessRotationVehicleParam((Vehicle)param, rotation);
ActivateIfPhysical(false); ActivateIfPhysical(false);
}); });
} }
@ -566,7 +566,7 @@ public sealed class BSPrim : BSPhysObject
{ {
PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate()
{ {
_vehicle.ProcessVehicleFlags(param, remove); VehicleController.ProcessVehicleFlags(param, remove);
}); });
} }
@ -747,7 +747,7 @@ public sealed class BSPrim : BSPhysObject
// isSolid: other objects bounce off of this object // isSolid: other objects bounce off of this object
// isVolumeDetect: other objects pass through but can generate collisions // isVolumeDetect: other objects pass through but can generate collisions
// collisionEvents: whether this object returns collision events // collisionEvents: whether this object returns collision events
private void UpdatePhysicalParameters() public void UpdatePhysicalParameters()
{ {
// DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape);
@ -759,7 +759,7 @@ public sealed class BSPrim : BSPhysObject
MakeDynamic(IsStatic); MakeDynamic(IsStatic);
// Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters)
_vehicle.Refresh(); VehicleController.Refresh();
// Arrange for collision events if the simulator wants them // Arrange for collision events if the simulator wants them
EnableCollisions(SubscribedEvents()); EnableCollisions(SubscribedEvents());
@ -1601,7 +1601,7 @@ public sealed class BSPrim : BSPhysObject
// Remove all the physical dependencies on the old body. // Remove all the physical dependencies on the old body.
// (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...) // (Maybe someday make the changing of BSShape an event to be subscribed to by BSLinkset, ...)
Linkset.RemoveBodyDependencies(this); Linkset.RemoveBodyDependencies(this);
_vehicle.RemoveBodyDependencies(this); VehicleController.RemoveBodyDependencies(this);
}); });
// Make sure the properties are set on the new object // Make sure the properties are set on the new object
@ -1618,7 +1618,7 @@ public sealed class BSPrim : BSPhysObject
{ {
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet // A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
// TODO: handle physics introduced by Bullet with computed vehicle physics. // TODO: handle physics introduced by Bullet with computed vehicle physics.
if (_vehicle.IsActive) if (VehicleController.IsActive)
{ {
entprop.RotationalVelocity = OMV.Vector3.Zero; entprop.RotationalVelocity = OMV.Vector3.Zero;
} }

View File

@ -855,7 +855,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters
{ {
DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom);
m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom);
Util.PrintCallStack(DetailLog); // Util.PrintCallStack(DetailLog);
} }
return InTaintTime; return InTaintTime;
} }

View File

@ -1,56 +1,127 @@
/* /*
* Copyright (c) Contributors, http://opensimulator.org/ * Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders. * See CONTRIBUTORS.TXT for a full list of copyright holders.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer. * notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright * * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the * notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution. * documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the * * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using NUnit.Framework; using NUnit.Framework;
using log4net; using log4net;
using OpenSim.Tests.Common; using OpenSim.Framework;
using OpenSim.Region.Physics.BulletSPlugin;
namespace OpenSim.Region.Physics.BulletSPlugin.Tests using OpenSim.Region.Physics.Manager;
{ using OpenSim.Tests.Common;
[TestFixture]
public class BasicVehicles : OpenSimTestCase using OpenMetaverse;
{
// Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1 namespace OpenSim.Region.Physics.BulletSPlugin.Tests
// Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1 {
[TestFixture]
[TestFixtureSetUp] public class BasicVehicles : OpenSimTestCase
public void Init() {
{ // Documentation on attributes: http://www.nunit.org/index.php?p=attributes&r=2.6.1
} // Documentation on assertions: http://www.nunit.org/index.php?p=assertions&r=2.6.1
[TestFixtureTearDown] BSScene PhysicsScene { get; set; }
public void TearDown() BSPrim TestVehicle { get; set; }
{ Vector3 TestVehicleInitPosition { get; set; }
} float timeStep = 0.089f;
}
[TestFixtureSetUp]
public void Init()
{
Dictionary<string, string> engineParams = new Dictionary<string, string>();
PhysicsScene = BulletSimTestsUtil.CreateBasicPhysicsEngine(engineParams);
PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateSphere();
Vector3 pos = new Vector3(100.0f, 100.0f, 0f);
pos.Z = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos) + 2f;
TestVehicleInitPosition = pos;
Vector3 size = new Vector3(1f, 1f, 1f);
pbs.Scale = size;
Quaternion rot = Quaternion.Identity;
bool isPhys = false;
uint localID = 123;
PhysicsScene.AddPrimShape("testPrim", pbs, pos, size, rot, isPhys, localID);
TestVehicle = (BSPrim)PhysicsScene.PhysObjects[localID];
// The actual prim shape creation happens at taint time
PhysicsScene.ProcessTaints();
}
[TestFixtureTearDown]
public void TearDown()
{
if (PhysicsScene != null)
{
// The Dispose() will also free any physical objects in the scene
PhysicsScene.Dispose();
PhysicsScene = null;
}
}
[TestCase(25, 0.25f, 0.25f, 0.25f)]
[TestCase(25, -0.25f, 0.25f, 0.25f)]
[TestCase(25, 0.25f, -0.25f, 0.25f)]
[TestCase(25, -0.25f, -0.25f, 0.25f)]
public void VerticalAttraction(int simSteps, float initRoll, float initPitch, float initYaw)
{
Quaternion initOrientation = Quaternion.CreateFromEulers(initRoll, initPitch, initYaw);
TestVehicle.Orientation = initOrientation;
TestVehicle.Position = TestVehicleInitPosition;
// The vehicle controller is not enabled directly (set a vehicle type).
// Instead the appropriate values are set and calls are made just the parts of the
// controller we want to exercise. Stepping the physics engine then applies
// the actions of that one feature.
TestVehicle.VehicleController.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_EFFICIENCY, 0.2f);
TestVehicle.VehicleController.ProcessFloatVehicleParam(Vehicle.VERTICAL_ATTRACTION_TIMESCALE, 2f);
TestVehicle.VehicleController.enableAngularVerticalAttraction = true;
TestVehicle.IsPhysical = true;
PhysicsScene.ProcessTaints();
// Step the simulator a bunch of times and and vertical attraction should orient the vehicle up
for (int ii = 0; ii < simSteps; ii++)
{
TestVehicle.VehicleController.ForgetKnownVehicleProperties();
TestVehicle.VehicleController.ComputeAngularVerticalAttraction();
TestVehicle.VehicleController.PushKnownChanged();
PhysicsScene.Simulate(timeStep);
}
// After these steps, the vehicle should be upright
Vector3 upPointer = Vector3.UnitZ * TestVehicle.Orientation;
Assert.That(upPointer.Z, Is.GreaterThan(0.99f));
}
}
} }

View File

@ -47,7 +47,7 @@ public static class BulletSimTestsUtil
public static BSScene CreateBasicPhysicsEngine(Dictionary<string,string> paramOverrides) public static BSScene CreateBasicPhysicsEngine(Dictionary<string,string> paramOverrides)
{ {
IConfigSource openSimINI = new IniConfigSource(); IConfigSource openSimINI = new IniConfigSource();
IConfig startupConfig = openSimINI.AddConfig("StartUp"); IConfig startupConfig = openSimINI.AddConfig("Startup");
startupConfig.Set("physics", "BulletSim"); startupConfig.Set("physics", "BulletSim");
startupConfig.Set("meshing", "Meshmerizer"); startupConfig.Set("meshing", "Meshmerizer");
startupConfig.Set("cacheSculptMaps", "false"); // meshmerizer shouldn't save maps startupConfig.Set("cacheSculptMaps", "false"); // meshmerizer shouldn't save maps

View File

@ -3378,6 +3378,8 @@
<Reference name="Nini" path="../../../../../bin/"/> <Reference name="Nini" path="../../../../../bin/"/>
<Reference name="log4net" path="../../../../../bin/"/> <Reference name="log4net" path="../../../../../bin/"/>
<Reference name="nunit.framework" path="../../../../../bin/"/> <Reference name="nunit.framework" path="../../../../../bin/"/>
<Reference name="OpenMetaverse" path="../../../../../bin/"/>
<Reference name="OpenMetaverseTypes" path="../../../../../bin/"/>
<Reference name="OpenSim.Framework"/> <Reference name="OpenSim.Framework"/>
<Reference name="OpenSim.Tests.Common"/> <Reference name="OpenSim.Tests.Common"/>
<Reference name="OpenSim.Region.CoreModules"/> <Reference name="OpenSim.Region.CoreModules"/>