Fixes Mantis #3260. Thank you kindly, MCortez for a patch that:
llSetHoverHeight() should not clamp the x/y position of an object the way MoveTo does, and it should recalculate the absolute height to hover at as an object moves to reflect the current ground/water height under it. Correctly implementing required adjusting the Physics interfaces and implementing at the physics plug-in level. The attached is a patch that correctly implements llSetHoverHeight() including updates to the ODE physics plug-in.0.6.4-rc1
parent
05ebd44791
commit
b637a11b58
|
@ -1616,6 +1616,37 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="height">Height to hover. Height of zero disables hover.</param>
|
||||||
|
/// <param name="hoverType">Determines what the height is relative to </param>
|
||||||
|
/// <param name="tau">Number of seconds over which to reach target</param>
|
||||||
|
public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
|
||||||
|
{
|
||||||
|
SceneObjectPart rootpart = m_rootPart;
|
||||||
|
if (rootpart != null)
|
||||||
|
{
|
||||||
|
if (rootpart.PhysActor != null)
|
||||||
|
{
|
||||||
|
if (height != 0f)
|
||||||
|
{
|
||||||
|
rootpart.PhysActor.PIDHoverHeight = height;
|
||||||
|
rootpart.PhysActor.PIDHoverType = hoverType;
|
||||||
|
rootpart.PhysActor.PIDTau = tau;
|
||||||
|
rootpart.PhysActor.PIDHoverActive = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rootpart.PhysActor.PIDHoverActive = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the owner of the root part.
|
/// Set the owner of the root part.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -1748,6 +1748,23 @@ if (m_shape != null) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="height">Height to hover. Height of zero disables hover.</param>
|
||||||
|
/// <param name="hoverType">Determines what the height is relative to </param>
|
||||||
|
/// <param name="tau">Number of seconds over which to reach target</param>
|
||||||
|
public void SetHoverHeight(float height, PIDHoverType hoverType, float tau)
|
||||||
|
{
|
||||||
|
m_parentGroup.SetHoverHeight(height, hoverType, tau);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void StopHover()
|
||||||
|
{
|
||||||
|
m_parentGroup.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public virtual void OnGrab(Vector3 offsetPos, IClientAPI remoteClient)
|
public virtual void OnGrab(Vector3 offsetPos, IClientAPI remoteClient)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -447,9 +447,17 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin
|
||||||
public override void CrossingFailure()
|
public override void CrossingFailure()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override PhysicsVector PIDTarget { set { return; } }
|
public override PhysicsVector PIDTarget { set { return; } }
|
||||||
public override bool PIDActive { set { return; } }
|
public override bool PIDActive { set { return; } }
|
||||||
public override float PIDTau { set { return; } }
|
public override float PIDTau { set { return; } }
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
|
|
||||||
public override void SubscribeEvents(int ms)
|
public override void SubscribeEvents(int ms)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -1225,6 +1225,13 @@ namespace OpenSim.Region.Physics.BulletXPlugin
|
||||||
public override PhysicsVector PIDTarget { set { return; } }
|
public override PhysicsVector PIDTarget { set { return; } }
|
||||||
public override bool PIDActive { set { return; } }
|
public override bool PIDActive { set { return; } }
|
||||||
public override float PIDTau { set { return; } }
|
public override float PIDTau { set { return; } }
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
|
|
||||||
public override void SubscribeEvents(int ms)
|
public override void SubscribeEvents(int ms)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,14 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
Ground = 3
|
Ground = 3
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public enum PIDHoverType
|
||||||
|
{
|
||||||
|
Ground
|
||||||
|
, GroundAndWater
|
||||||
|
, Water
|
||||||
|
, Absolute
|
||||||
|
}
|
||||||
|
|
||||||
public class CollisionEventUpdate : EventArgs
|
public class CollisionEventUpdate : EventArgs
|
||||||
{
|
{
|
||||||
// Raising the event on the object, so don't need to provide location.. further up the tree knows that info.
|
// Raising the event on the object, so don't need to provide location.. further up the tree knows that info.
|
||||||
|
@ -204,9 +212,20 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public abstract PhysicsVector RotationalVelocity { get; set; }
|
public abstract PhysicsVector RotationalVelocity { get; set; }
|
||||||
public abstract bool Kinematic { get; set; }
|
public abstract bool Kinematic { get; set; }
|
||||||
public abstract float Buoyancy { get; set; }
|
public abstract float Buoyancy { get; set; }
|
||||||
|
|
||||||
|
// Used for MoveTo
|
||||||
public abstract PhysicsVector PIDTarget { set;}
|
public abstract PhysicsVector PIDTarget { set;}
|
||||||
public abstract bool PIDActive { set;}
|
public abstract bool PIDActive { set;}
|
||||||
public abstract float PIDTau { set; }
|
public abstract float PIDTau { set; }
|
||||||
|
|
||||||
|
// Used for llSetHoverHeight and maybe vehicle height
|
||||||
|
// Hover Height will override MoveTo target's Z
|
||||||
|
public abstract bool PIDHoverActive { set;}
|
||||||
|
public abstract float PIDHoverHeight { set;}
|
||||||
|
public abstract PIDHoverType PIDHoverType { set;}
|
||||||
|
public abstract float PIDHoverTau { set;}
|
||||||
|
|
||||||
|
|
||||||
public abstract void AddForce(PhysicsVector force, bool pushforce);
|
public abstract void AddForce(PhysicsVector force, bool pushforce);
|
||||||
public abstract void AddAngularForce(PhysicsVector force, bool pushforce);
|
public abstract void AddAngularForce(PhysicsVector force, bool pushforce);
|
||||||
public abstract void SetMomentum(PhysicsVector momentum);
|
public abstract void SetMomentum(PhysicsVector momentum);
|
||||||
|
@ -430,6 +449,11 @@ namespace OpenSim.Region.Physics.Manager
|
||||||
public override bool PIDActive { set { return; } }
|
public override bool PIDActive { set { return; } }
|
||||||
public override float PIDTau { set { return; } }
|
public override float PIDTau { set { return; } }
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
public override void SetMomentum(PhysicsVector momentum)
|
public override void SetMomentum(PhysicsVector momentum)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -922,9 +922,16 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public override void CrossingFailure()
|
public override void CrossingFailure()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override PhysicsVector PIDTarget { set { return; } }
|
public override PhysicsVector PIDTarget { set { return; } }
|
||||||
public override bool PIDActive { set { return; } }
|
public override bool PIDActive { set { return; } }
|
||||||
public override float PIDTau { set { return; } }
|
public override float PIDTau { set { return; } }
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
public override void SubscribeEvents(int ms)
|
public override void SubscribeEvents(int ms)
|
||||||
{
|
{
|
||||||
m_eventsubscription = ms;
|
m_eventsubscription = ms;
|
||||||
|
|
|
@ -69,11 +69,20 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
private float m_PIDTau = 0f;
|
private float m_PIDTau = 0f;
|
||||||
private float PID_D = 35f;
|
private float PID_D = 35f;
|
||||||
private float PID_G = 25f;
|
private float PID_G = 25f;
|
||||||
|
private bool m_usePID = false;
|
||||||
|
|
||||||
|
private float m_PIDHoverHeight = 0f;
|
||||||
|
private float m_PIDHoverTau = 0f;
|
||||||
|
private bool m_useHoverPID = false;
|
||||||
|
private PIDHoverType m_PIDHoverType = PIDHoverType.Ground;
|
||||||
|
private float m_targetHoverHeight = 0f;
|
||||||
|
private float m_groundHeight = 0f;
|
||||||
|
private float m_waterHeight = 0f;
|
||||||
|
|
||||||
private float m_tensor = 5f;
|
private float m_tensor = 5f;
|
||||||
private int body_autodisable_frames = 20;
|
private int body_autodisable_frames = 20;
|
||||||
private IMesh primMesh = null;
|
private IMesh primMesh = null;
|
||||||
|
|
||||||
private bool m_usePID = false;
|
|
||||||
|
|
||||||
private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
|
private const CollisionCategories m_default_collisionFlags = (CollisionCategories.Geom
|
||||||
| CollisionCategories.Space
|
| CollisionCategories.Space
|
||||||
|
@ -1554,6 +1563,91 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Hover PID Controller needs to be mutually exlusive to MoveTo PID controller
|
||||||
|
if (m_useHoverPID && !m_usePID)
|
||||||
|
{
|
||||||
|
// If we're using the PID controller, then we have no gravity
|
||||||
|
fz = (-1 * _parent_scene.gravityz) * m_mass;
|
||||||
|
|
||||||
|
// no lock; for now it's only called from within Simulate()
|
||||||
|
|
||||||
|
// If the PID Controller isn't active then we set our force
|
||||||
|
// calculating base velocity to the current position
|
||||||
|
|
||||||
|
if ((m_PIDTau < 1))
|
||||||
|
{
|
||||||
|
PID_G = PID_G / m_PIDTau;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((PID_G - m_PIDTau) <= 0)
|
||||||
|
{
|
||||||
|
PID_G = m_PIDTau + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Where are we, and where are we headed?
|
||||||
|
d.Vector3 pos = d.BodyGetPosition(Body);
|
||||||
|
d.Vector3 vel = d.BodyGetLinearVel(Body);
|
||||||
|
|
||||||
|
// determine what our target height really is based on HoverType
|
||||||
|
switch (m_PIDHoverType)
|
||||||
|
{
|
||||||
|
case PIDHoverType.Absolute:
|
||||||
|
m_targetHoverHeight = m_PIDHoverHeight;
|
||||||
|
break;
|
||||||
|
case PIDHoverType.Ground:
|
||||||
|
m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
|
||||||
|
m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
|
||||||
|
break;
|
||||||
|
case PIDHoverType.GroundAndWater:
|
||||||
|
m_groundHeight = _parent_scene.GetTerrainHeightAtXY(pos.X, pos.Y);
|
||||||
|
m_waterHeight = _parent_scene.GetWaterLevel();
|
||||||
|
if (m_groundHeight > m_waterHeight)
|
||||||
|
{
|
||||||
|
m_targetHoverHeight = m_groundHeight + m_PIDHoverHeight;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case PIDHoverType.Water:
|
||||||
|
m_waterHeight = _parent_scene.GetWaterLevel();
|
||||||
|
m_targetHoverHeight = m_waterHeight + m_PIDHoverHeight;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
_target_velocity =
|
||||||
|
new PhysicsVector(0.0f, 0.0f,
|
||||||
|
(m_targetHoverHeight - pos.Z) * ((PID_G - m_PIDHoverTau) * timestep)
|
||||||
|
);
|
||||||
|
|
||||||
|
// if velocity is zero, use position control; otherwise, velocity control
|
||||||
|
|
||||||
|
if (_target_velocity.IsIdentical(PhysicsVector.Zero, 0.1f))
|
||||||
|
{
|
||||||
|
// keep track of where we stopped. No more slippin' & slidin'
|
||||||
|
|
||||||
|
// We only want to deactivate the PID Controller if we think we want to have our surrogate
|
||||||
|
// react to the physics scene by moving it's position.
|
||||||
|
// Avatar to Avatar collisions
|
||||||
|
// Prim to avatar collisions
|
||||||
|
|
||||||
|
d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight);
|
||||||
|
d.BodySetLinearVel(Body, vel.X, vel.Y, 0);
|
||||||
|
d.BodyAddForce(Body, 0, 0, fz);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_zeroFlag = false;
|
||||||
|
|
||||||
|
// We're flying and colliding with something
|
||||||
|
fz = fz + ((_target_velocity.Z - vel.Z) * (PID_D) * m_mass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fx *= m_mass;
|
fx *= m_mass;
|
||||||
fy *= m_mass;
|
fy *= m_mass;
|
||||||
//fz *= m_mass;
|
//fz *= m_mass;
|
||||||
|
@ -2622,6 +2716,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
public override bool PIDActive { set { m_usePID = value; } }
|
public override bool PIDActive { set { m_usePID = value; } }
|
||||||
public override float PIDTau { set { m_PIDTau = value; } }
|
public override float PIDTau { set { m_PIDTau = value; } }
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { m_PIDHoverHeight = value; ; } }
|
||||||
|
public override bool PIDHoverActive { set { m_useHoverPID = value; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { m_PIDHoverType = value; } }
|
||||||
|
public override float PIDHoverTau { set { m_PIDHoverTau = value; } }
|
||||||
|
|
||||||
private void createAMotor(PhysicsVector axis)
|
private void createAMotor(PhysicsVector axis)
|
||||||
{
|
{
|
||||||
if (Body == IntPtr.Zero)
|
if (Body == IntPtr.Zero)
|
||||||
|
|
|
@ -3031,6 +3031,11 @@ namespace OpenSim.Region.Physics.OdePlugin
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public float GetWaterLevel()
|
||||||
|
{
|
||||||
|
return waterlevel;
|
||||||
|
}
|
||||||
|
|
||||||
public override void SetWaterLevel(float baseheight)
|
public override void SetWaterLevel(float baseheight)
|
||||||
{
|
{
|
||||||
waterlevel = baseheight;
|
waterlevel = baseheight;
|
||||||
|
|
|
@ -288,6 +288,12 @@ namespace OpenSim.Region.Physics.POSPlugin
|
||||||
set { return; }
|
set { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
|
|
||||||
public override void SubscribeEvents(int ms)
|
public override void SubscribeEvents(int ms)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,6 +283,12 @@ namespace OpenSim.Region.Physics.POSPlugin
|
||||||
set { return; }
|
set { return; }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
|
|
||||||
public override void SubscribeEvents(int ms)
|
public override void SubscribeEvents(int ms)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -490,9 +490,16 @@ namespace OpenSim.Region.Physics.PhysXPlugin
|
||||||
{
|
{
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public override PhysicsVector PIDTarget { set { return; } }
|
public override PhysicsVector PIDTarget { set { return; } }
|
||||||
public override bool PIDActive { set { return; } }
|
public override bool PIDActive { set { return; } }
|
||||||
public override float PIDTau { set { return; } }
|
public override float PIDTau { set { return; } }
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
public override void SubscribeEvents(int ms)
|
public override void SubscribeEvents(int ms)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
@ -765,10 +772,16 @@ namespace OpenSim.Region.Physics.PhysXPlugin
|
||||||
public override void CrossingFailure()
|
public override void CrossingFailure()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public override PhysicsVector PIDTarget { set { return; } }
|
public override PhysicsVector PIDTarget { set { return; } }
|
||||||
public override bool PIDActive { set { return; } }
|
public override bool PIDActive { set { return; } }
|
||||||
public override float PIDTau { set { return; } }
|
public override float PIDTau { set { return; } }
|
||||||
|
|
||||||
|
public override float PIDHoverHeight { set { return; } }
|
||||||
|
public override bool PIDHoverActive { set { return; } }
|
||||||
|
public override PIDHoverType PIDHoverType { set { return; } }
|
||||||
|
public override float PIDHoverTau { set { return; } }
|
||||||
|
|
||||||
public override void SubscribeEvents(int ms)
|
public override void SubscribeEvents(int ms)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -2793,26 +2793,24 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attempt to clamp the object on the Z axis at the given height over tau seconds.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="height">Height to hover. Height of zero disables hover.</param>
|
||||||
|
/// <param name="water">False if height is calculated just from ground, otherwise uses ground or water depending on whichever is higher</param>
|
||||||
|
/// <param name="tau">Number of seconds over which to reach target</param>
|
||||||
public void llSetHoverHeight(double height, int water, double tau)
|
public void llSetHoverHeight(double height, int water, double tau)
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
Vector3 pos = m_host.GetWorldPosition();
|
|
||||||
int x = (int)(pos.X);
|
|
||||||
int y = (int)(pos.Y);
|
|
||||||
float landHeight = (float)World.Heightmap[x, y];
|
|
||||||
float targetHeight = landHeight + (float)height;
|
|
||||||
if (water == 1)
|
|
||||||
{
|
|
||||||
float waterHeight = (float)World.RegionInfo.RegionSettings.WaterHeight;
|
|
||||||
if (waterHeight > targetHeight)
|
|
||||||
{
|
|
||||||
targetHeight = waterHeight + (float)height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (m_host.PhysActor != null)
|
if (m_host.PhysActor != null)
|
||||||
{
|
{
|
||||||
m_host.MoveToTarget(new Vector3(pos.X, pos.Y, targetHeight), (float)tau);
|
PIDHoverType hoverType = PIDHoverType.Ground;
|
||||||
m_host.PhysActor.Flying = true;
|
if (water == 1)
|
||||||
|
{
|
||||||
|
hoverType = PIDHoverType.GroundAndWater;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_host.SetHoverHeight((float)height, hoverType, (float)tau);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2821,8 +2819,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
if (m_host.PhysActor != null)
|
if (m_host.PhysActor != null)
|
||||||
{
|
{
|
||||||
m_host.PhysActor.Flying = false;
|
m_host.SetHoverHeight(0f, PIDHoverType.Ground, 0f);
|
||||||
m_host.PhysActor.PIDActive = false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue