Skip to content

Commit

Permalink
Merge pull request #19 from PisterLab/better-configs
Browse files Browse the repository at this point in the history
Better sim configs, performance optimizations, and time throttling for guaranteed physics update rate
  • Loading branch information
daniellovell authored Oct 29, 2024
2 parents 9ff97aa + 9251fd3 commit 498ffff
Show file tree
Hide file tree
Showing 11 changed files with 73 additions and 46 deletions.
4 changes: 2 additions & 2 deletions Assets/Scripts/SimManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ void Start() {

public void SetTimeScale(float timeScale) {
Time.timeScale = timeScale;
Time.maximumDeltaTime = Time.timeScale * 0.05f;
Time.maximumDeltaTime = Time.fixedDeltaTime * 3;

// Time.fixedDeltaTime is set in the simulator.json
}
Expand All @@ -171,8 +171,8 @@ public void PauseSimulation() {
}

public void ResumeSimulation() {
SetTimeScale(simulationConfig.timeScale);
Time.fixedDeltaTime = (float)(1.0f / simulatorConfig.physicsUpdateRate);
SetTimeScale(simulationConfig.timeScale);
_isSimulationPaused = false;
}

Expand Down
28 changes: 19 additions & 9 deletions Assets/Scripts/Threats/FixedWingThreat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,12 @@ public class FixedWingThreat : Threat {

private Vector3 _accelerationInput;
private double _elapsedTime = 0;
private Rigidbody _rigidbody;

// Start is called before the first frame update
protected override void Start() {
base.Start();
_rigidbody = GetComponent<Rigidbody>();
}

// Update is called once per frame
Expand All @@ -37,7 +39,7 @@ protected override void UpdateMidCourse(double deltaTime) {
if (_elapsedTime >= sensorUpdatePeriod) {
// TODO: Implement guidance filter to estimate state from sensor output
// For now, we'll use the threat's actual state
_sensorOutput = GetComponent<Sensor>().SenseWaypoint(_currentWaypoint);
_sensorOutput = _sensor.SenseWaypoint(_currentWaypoint);
_elapsedTime = 0;
}

Expand All @@ -53,7 +55,7 @@ protected override void UpdateMidCourse(double deltaTime) {

// Calculate and set the total acceleration
Vector3 acceleration = CalculateAcceleration(accelerationInput);
GetComponent<Rigidbody>().AddForce(acceleration, ForceMode.Acceleration);
_rigidbody.AddForce(acceleration, ForceMode.Acceleration);
}

private void UpdateWaypointAndPower() {
Expand All @@ -70,7 +72,15 @@ private Vector3 CalculateAccelerationInput(SensorOutput sensorOutput) {

// Implement (Augmented) Proportional Navigation guidance law
Vector3 accelerationInput = Vector3.zero;

// Cache the transform and velocity to avoid repeated calls to GetTransform
// which can be costly at these large scales
Transform currentTransform = transform;
Vector3 transformRight = currentTransform.right;
Vector3 transformUp = currentTransform.up;
Vector3 transformForward = currentTransform.forward;
Vector3 transformPosition = currentTransform.position;
Vector3 transformVelocity = GetVelocity();
float transformSpeed = transformVelocity.magnitude;
// Extract relevant information from sensor output
float losRateAz = sensorOutput.velocity.azimuth;
float losRateEl = sensorOutput.velocity.elevation;
Expand Down Expand Up @@ -99,21 +109,21 @@ private Vector3 CalculateAccelerationInput(SensorOutput sensorOutput) {
float accAz = N * turnFactor * losRateAz;
float accEl = N * turnFactor * losRateEl;
// Convert acceleration inputs to craft body frame
accelerationInput = transform.right * accAz + transform.up * accEl;
accelerationInput = transformRight * accAz + transformUp * accEl;

// Clamp the normal acceleration input to the maximum normal acceleration
float maxNormalAcceleration = CalculateMaxNormalAcceleration();
accelerationInput = Vector3.ClampMagnitude(accelerationInput, maxNormalAcceleration);

// Avoid the ground when close to the surface and too low on the glideslope
float altitude = GetPosition().y;
float sinkRate = -GetVelocity().y; // Sink rate is opposite to climb rate
float altitude = transformPosition.y;
float sinkRate = -transformVelocity.y; // Sink rate is opposite to climb rate
float distanceToTarget = sensorOutput.position.range;
float groundProximityThreshold =
Mathf.Abs(GetVelocity().y) * 5f; // Adjust threshold as necessary
if (sinkRate > 0 && altitude / sinkRate < distanceToTarget / GetSpeed()) {
Mathf.Abs(transformVelocity.y) * 5f; // Adjust threshold as necessary
if (sinkRate > 0 && altitude / sinkRate < distanceToTarget / transformSpeed) {
// Evade upward normal to the velocity
Vector3 upwardsDirection = Vector3.Cross(transform.forward, transform.right);
Vector3 upwardsDirection = Vector3.Cross(transformForward, transformRight);

// Blend between the calculated acceleration input and the upward acceleration
float blendFactor = 1 - (altitude / groundProximityThreshold);
Expand Down
32 changes: 21 additions & 11 deletions Assets/Scripts/Threats/Threat.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ public abstract class Threat : Agent {

protected SensorOutput _sensorOutput;

protected Sensor _sensor;

public void SetAttackBehavior(AttackBehavior attackBehavior) {
_attackBehavior = attackBehavior;
_target = SimManager.Instance.CreateDummyAgent(attackBehavior.targetPosition,
Expand Down Expand Up @@ -41,18 +43,21 @@ public override bool IsAssignable() {

protected override void Start() {
base.Start();
_sensor = GetComponent<Sensor>();
}

protected override void FixedUpdate() {
base.FixedUpdate();
}

protected Vector3 CalculateForwardAcceleration() {
Vector3 transformVelocity = GetVelocity();

// Get the target speed for the current power setting
float targetSpeed = PowerTableLookup(_currentPowerSetting);

// Calculate the current speed
float currentSpeed = GetVelocity().magnitude;
float currentSpeed = transformVelocity.magnitude;

// Speed error
float speedError = targetSpeed - currentSpeed;
Expand All @@ -69,7 +74,7 @@ protected Vector3 CalculateForwardAcceleration() {
Mathf.Clamp(desiredAccelerationMagnitude, -maxForwardAcceleration, maxForwardAcceleration);

// Acceleration direction (along current velocity direction)
Vector3 accelerationDirection = GetVelocity().normalized;
Vector3 accelerationDirection = transformVelocity.normalized;

// Handle zero velocity case
if (accelerationDirection.magnitude < 0.1f) {
Expand All @@ -90,7 +95,7 @@ protected Agent GetClosestInterceptor() {
float minDistance = float.MaxValue;
foreach (var interceptor in _interceptors) {
if (!interceptor.HasTerminated()) {
SensorOutput sensorOutput = GetComponent<Sensor>().Sense(interceptor);
SensorOutput sensorOutput = _sensor.Sense(interceptor);
if (sensorOutput.position.range < minDistance) {
closestInterceptor = interceptor;
minDistance = sensorOutput.position.range;
Expand All @@ -112,32 +117,37 @@ protected bool ShouldEvade() {

float evasionRangeThreshold =
dynamicAgentConfig.dynamic_config.flight_config.evasionRangeThreshold;
SensorOutput sensorOutput = GetComponent<Sensor>().Sense(closestInterceptor);
SensorOutput sensorOutput = _sensor.Sense(closestInterceptor);
return sensorOutput.position.range <= evasionRangeThreshold && sensorOutput.velocity.range < 0;
}

protected Vector3 EvadeInterceptor(Agent interceptor) {
Vector3 transformVelocity = GetVelocity();
Vector3 interceptorVelocity = interceptor.GetVelocity();
Vector3 transformPosition = GetPosition();
Vector3 interceptorPosition = interceptor.GetPosition();

// Set power setting to maximum
_currentPowerSetting = PowerSetting.MAX;

// Evade the interceptor by changing the velocity to be normal to the interceptor's velocity
Vector3 normalVelocity = Vector3.ProjectOnPlane(GetVelocity(), interceptor.GetVelocity());
Vector3 normalVelocity = Vector3.ProjectOnPlane(transformVelocity, interceptorVelocity);
Vector3 normalAccelerationDirection =
Vector3.ProjectOnPlane(normalVelocity, GetVelocity()).normalized;
Vector3.ProjectOnPlane(normalVelocity, transformVelocity).normalized;

// Turn away from the interceptor
Vector3 relativePosition = interceptor.GetPosition() - GetPosition();
Vector3 relativePosition = interceptorPosition - transformPosition;
if (Vector3.Dot(relativePosition, normalAccelerationDirection) > 0) {
normalAccelerationDirection *= -1;
}

// Avoid evading straight down when near the ground
float altitude = GetPosition().y;
float altitude = transformPosition.y;
float groundProximityThreshold =
Mathf.Abs(GetVelocity().y) * 5f; // Adjust threshold as necessary
if (GetVelocity().y < 0 && altitude < groundProximityThreshold) {
Mathf.Abs(transformVelocity.y) * 5f; // Adjust threshold as necessary
if (transformVelocity.y < 0 && altitude < groundProximityThreshold) {
// Determine evasion direction based on angle to interceptor
Vector3 toInterceptor = interceptor.GetPosition() - GetPosition();
Vector3 toInterceptor = interceptorPosition - transformPosition;
Vector3 rightDirection = Vector3.Cross(Vector3.up, transform.forward);
float angle = Vector3.SignedAngle(transform.forward, toInterceptor, Vector3.up);

Expand Down
7 changes: 7 additions & 0 deletions Assets/Scripts/UI/UIManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,13 @@ private void UpdateSwarmPanel() {
private void UpdateSimTimeText() {
simTimeText.text =
"Elapsed Sim Time: " + SimManager.Instance.GetElapsedSimulationTime().ToString("F2");
float expectedSimTimeAdvance = Time.unscaledDeltaTime * Time.timeScale;
float actualSimTimeAdvance = Time.deltaTime;

// Allow a small epsilon to account for floating-point precision errors
if (actualSimTimeAdvance < expectedSimTimeAdvance - 0.001f) {
simTimeText.text += "\nThrottling time to meet physics rate";
}
}

private void UpdateTotalCostText() {
Expand Down
6 changes: 3 additions & 3 deletions Assets/StreamingAssets/Configs/1_salvo_3_sfrj_30_ascm.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"submunitions_config": {
"num_submunitions": 12,
"dispense_time": 94,
"dispense_time": 101,
"dynamic_agent_config": {
"agent_model": "micromissile.json",
"initial_state": {
Expand All @@ -38,7 +38,7 @@
"velocity": { "x": 0, "y": 0, "z": 0 }
},
"dynamic_config": {
"launch_config": { "launch_time": 95 },
"launch_config": { "launch_time": 101 },
"sensor_config": {
"type": "IDEAL",
"frequency": 100
Expand All @@ -59,7 +59,7 @@
"agent_model": "ascm.json",
"attack_behavior": "default_direct_attack.json",
"initial_state": {
"position": { "x": 0, "y": 9000, "z": 120000 },
"position": { "x": 0, "y": 9000, "z": 110000 },
"velocity": { "x": 0, "y": 0, "z": -300 }
},
"standard_deviation": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
},
"submunitions_config": {
"num_submunitions": 7,
"dispense_time": 20,
"dispense_time": 30,
"dynamic_agent_config": {
"agent_model": "micromissile.json",
"initial_state": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"timeScale": 1,
"interceptor_swarm_configs": [
{
"num_agents": 1,
"num_agents": 2,
"dynamic_agent_config": {
"agent_model": "hydra70.json",
"initial_state": {
Expand Down Expand Up @@ -53,7 +53,7 @@
}
},
{
"num_agents": 1,
"num_agents": 2,
"dynamic_agent_config": {
"agent_model": "hydra70.json",
"initial_state": {
Expand All @@ -65,7 +65,7 @@
"velocity": { "x": 5, "y": 0, "z": 1 }
},
"dynamic_config": {
"launch_config": { "launch_time": 2 },
"launch_config": { "launch_time": 4 },
"sensor_config": {
"type": "IDEAL",
"frequency": 100
Expand All @@ -76,7 +76,7 @@
},
"submunitions_config": {
"num_submunitions": 7,
"dispense_time": 4,
"dispense_time": 6,
"dynamic_agent_config": {
"agent_model": "micromissile.json",
"initial_state": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
"agent_model": "sfrj.json",
"initial_state": {
"position": { "x": 0, "y": 20, "z": 0 },
"velocity": { "x": 0, "y": 300, "z": 200 }
"velocity": { "x": 0, "y": 450, "z": 180 }
},
"standard_deviation": {
"position": { "x": 5, "y": 0, "z": 5 },
Expand All @@ -25,8 +25,8 @@
}
},
"submunitions_config": {
"num_submunitions": 7,
"dispense_time": 14,
"num_submunitions": 12,
"dispense_time": 34,
"dynamic_agent_config": {
"agent_model": "micromissile.json",
"initial_state": {
Expand Down Expand Up @@ -57,14 +57,14 @@
"agent_model": "sfrj.json",
"initial_state": {
"position": { "x": 0, "y": 20, "z": 0 },
"velocity": { "x": 0, "y": 300, "z": 200 }
"velocity": { "x": 0, "y": 400, "z": 200 }
},
"standard_deviation": {
"position": { "x": 5, "y": 0, "z": 5 },
"velocity": { "x": 5, "y": 20, "z": 20 }
},
"dynamic_config": {
"launch_config": { "launch_time": 1 },
"launch_config": { "launch_time": 8 },
"sensor_config": {
"type": "IDEAL",
"frequency": 100
Expand All @@ -74,8 +74,8 @@
}
},
"submunitions_config": {
"num_submunitions": 7,
"dispense_time": 15,
"num_submunitions": 12,
"dispense_time": 36,
"dynamic_agent_config": {
"agent_model": "micromissile.json",
"initial_state": {
Expand Down Expand Up @@ -106,14 +106,14 @@
"agent_model": "sfrj.json",
"initial_state": {
"position": { "x": 0, "y": 20, "z": 0 },
"velocity": { "x": 0, "y": 300, "z": 200 }
"velocity": { "x": 0, "y": 440, "z": 280 }
},
"standard_deviation": {
"position": { "x": 5, "y": 0, "z": 5 },
"velocity": { "x": 5, "y": 20, "z": 20 }
},
"dynamic_config": {
"launch_config": { "launch_time": 4 },
"launch_config": { "launch_time": 22 },
"sensor_config": {
"type": "IDEAL",
"frequency": 100
Expand All @@ -123,8 +123,8 @@
}
},
"submunitions_config": {
"num_submunitions": 7,
"dispense_time": 16,
"num_submunitions": 12,
"dispense_time": 40,
"dynamic_agent_config": {
"agent_model": "micromissile.json",
"initial_state": {
Expand Down Expand Up @@ -152,16 +152,16 @@
],
"threat_swarm_configs": [
{
"num_agents": 5,
"num_agents": 50,
"dynamic_agent_config": {
"agent_model": "fateh110b.json",
"attack_behavior": "fateh110b_direct_attack.json",
"initial_state": {
"position": { "x": 0, "y": 80000, "z": 80000 },
"position": { "x": 0, "y": 100000, "z": 100000 },
"velocity": { "x": 0, "y": -2317, "z": -2317 }
},
"standard_deviation": {
"position": { "x": 3000, "y": 10, "z": 100 },
"position": { "x": 3000, "y": 1000, "z": 1000 },
"velocity": { "x": 0, "y": 0, "z": 25 }
},
"dynamic_config": {
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Assets/StreamingAssets/simulator.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"enableEventLogging": true,
"enableMissileTrailEffect": false,
"enableExplosionEffect": false,
"physicsUpdateRate": 100,
"physicsUpdateRate": 500,
"persistentFlightTrails": true
}

0 comments on commit 498ffff

Please sign in to comment.