From ee7d3647fade77eaa98d203a04e7da33b807ed46 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Tue, 28 Apr 2026 17:13:31 -0700 Subject: [PATCH 1/4] [Communication] Added Communication config and proto example under 5_swarms_7_ucav.pbtxt --- .../Configs/Simulations/5_swarms_7_ucav.pbtxt | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt b/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt index a9f0db88b..0b3a70449 100644 --- a/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt +++ b/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt @@ -283,3 +283,50 @@ threat_swarm_configs { } } } +communication_config { + link_config { + latency_seconds: 0.10 + latency_std_seconds: 0.01 + packet_delivery_ratio: 1.0 + } + + link_overrides { + from: VESSEL + to: CARRIER_INTERCEPTOR + link_config { + latency_seconds: 0.20 + latency_std_seconds: 0.02 + packet_delivery_ratio: 0.99 + } + } + + link_overrides { + from: CARRIER_INTERCEPTOR + to: VESSEL + link_config { + latency_seconds: 0.20 + latency_std_seconds: 0.02 + packet_delivery_ratio: 0.99 + } + } + + link_overrides { + from: CARRIER_INTERCEPTOR + to: MISSILE_INTERCEPTOR + link_config { + latency_seconds: 0.03 + latency_std_seconds: 0.005 + packet_delivery_ratio: 0.995 + } + } + + link_overrides { + from: MISSILE_INTERCEPTOR + to: CARRIER_INTERCEPTOR + link_config { + latency_seconds: 0.03 + latency_std_seconds: 0.005 + packet_delivery_ratio: 0.995 + } + } +} From 34d3f7e0e27dd39effef4189a043d49fc8169100 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Mon, 8 Jun 2026 22:00:34 -0700 Subject: [PATCH 2/4] [Communication] Add end-to-end mailbox test and two communication config examples --- .../Configs/Simulations/5_swarms_7_ucav.pbtxt | 8 +-- .../Configs/Simulations/7_quadcopters.pbtxt | 4 +- .../Tests/EditMode/CarrierBaseMailboxTests.cs | 70 +++++++++++++++++++ 3 files changed, 76 insertions(+), 6 deletions(-) diff --git a/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt b/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt index 0b3a70449..9ddfa849d 100644 --- a/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt +++ b/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt @@ -296,7 +296,7 @@ communication_config { link_config { latency_seconds: 0.20 latency_std_seconds: 0.02 - packet_delivery_ratio: 0.99 + packet_delivery_ratio: 1.0 } } @@ -306,7 +306,7 @@ communication_config { link_config { latency_seconds: 0.20 latency_std_seconds: 0.02 - packet_delivery_ratio: 0.99 + packet_delivery_ratio: 1.0 } } @@ -316,7 +316,7 @@ communication_config { link_config { latency_seconds: 0.03 latency_std_seconds: 0.005 - packet_delivery_ratio: 0.995 + packet_delivery_ratio: 1.0 } } @@ -326,7 +326,7 @@ communication_config { link_config { latency_seconds: 0.03 latency_std_seconds: 0.005 - packet_delivery_ratio: 0.995 + packet_delivery_ratio: 1.0 } } } diff --git a/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt b/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt index cfdbb642b..d7db79c41 100644 --- a/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt +++ b/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt @@ -124,7 +124,7 @@ communication_config { link_config { latency_seconds: 0.25 latency_std_seconds: 0.02 - packet_delivery_ratio: 0.98 + packet_delivery_ratio: 1.0 } } @@ -134,7 +134,7 @@ communication_config { link_config { latency_seconds: 0.05 latency_std_seconds: 0.01 - packet_delivery_ratio: 0.99 + packet_delivery_ratio: 1.0 } } } diff --git a/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs b/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs index 0285ad13d..184ec58e8 100644 --- a/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs +++ b/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs @@ -9,6 +9,8 @@ public class CarrierBaseMailboxTests : TestBase { private Mailbox _mailbox; private SimManager _simManager; + private IADS _iads; + private IadsCommsAgent _commsAgent; private TestCarrier _carrier; private readonly List _spawnedObjects = new List(); @@ -16,14 +18,25 @@ public class CarrierBaseMailboxTests : TestBase { public void SetUp() { SetMailboxInstance(null); SetSimManagerInstance(null); + SetIadsInstance(null); _simManager = CreateSimManagerStub(); SetPrivateField(_simManager, "_dummyAgents", new List()); + SetPrivateField(_simManager, "_interceptors", new List()); + SetPrivateField(_simManager, "_threats", new List()); SetSimManagerInstance(_simManager); SetElapsedTime(0f); _mailbox = new GameObject("Mailbox").AddComponent(); _spawnedObjects.Add(_mailbox.gameObject); + SetMailboxInstance(_mailbox); + + GameObject iadsObject = new GameObject("IADS"); + _spawnedObjects.Add(iadsObject); + _iads = iadsObject.AddComponent(); + InvokePrivateMethod(_iads, "Awake"); + _commsAgent = _iads.GetComponent(); + InvokePrivateMethod(_iads, "Start"); _carrier = CreateCarrier("Carrier", Configs.AgentType.CarrierInterceptor); SetPrivateField(_carrier, "_capacityPerSubInterceptor", 1); @@ -39,6 +52,7 @@ public void TearDown() { _spawnedObjects.Clear(); SetMailboxInstance(null); SetSimManagerInstance(null); + SetIadsInstance(null); } // Verifies that release bookkeeping only counts released interceptor children, surfaces an @@ -108,6 +122,53 @@ public void ReleasedInterceptor_RequestViaMailbox_ProducesCarrierAssignTargetRes Assert.AreSame(expectedLeafTarget, assignedTargets[0]); } + // Verifies that a released interceptor can propagate a mailbox target request through its + // carrier to IADS, and that the requesting interceptor receives the launcher-selected target. + [Test] + public void ReleasedInterceptor_RequestViaMailbox_PropagatesThroughCarrierAndIads() { + SetPrivateField(_carrier, "_numSubInterceptorsRemaining", 1); + + TestReleasedInterceptor releasedInterceptor = + CreateReleasedInterceptor("ReleasedInterceptor", Configs.AgentType.MissileInterceptor); + _carrier.ReleaseStrategy = + new FixedReleaseStrategy(_carrier, new List { releasedInterceptor }); + RunReleaseManagerStep(_carrier, period: 0.2f); + _iads.RegisterNewAsset(_carrier); + + var launcher = + new StubInterceptor(Configs.AgentType.Vessel, capacity: 1) { Position = Vector3.zero }; + launcher.HierarchicalAgent = new HierarchicalAgent(launcher); + FixedHierarchical expectedLeafTarget = + new FixedHierarchical(position: new Vector3(35f, 0f, 0f)); + launcher.HierarchicalAgent.Target = CreateCluster(expectedLeafTarget); + _iads.RegisterNewLauncher(launcher); + + TestReleasedInterceptor requestingInterceptor = + CreateReleasedInterceptor("RequestingInterceptor", Configs.AgentType.MissileInterceptor); + SetPrivateField(requestingInterceptor, "_capacityPerSubInterceptor", 1); + SetPrivateField(requestingInterceptor, "_numSubInterceptorsRemaining", 1); + + _mailbox.Configure(null); + releasedInterceptor.AssignSubInterceptor(requestingInterceptor); + + InvokePrivateMethod(_mailbox, "Update"); + Assert.IsNull(requestingInterceptor.HierarchicalAgent.Target); + + InvokePrivateMethod(_mailbox, "Update"); + Assert.IsNull(requestingInterceptor.HierarchicalAgent.Target); + + InvokePrivateMethod(_mailbox, "Update"); + Assert.NotNull(requestingInterceptor.HierarchicalAgent.Target); + + List assignedTargets = + requestingInterceptor.HierarchicalAgent.Target.LeafHierarchicals(activeOnly: true, + withTargetOnly: false); + Assert.AreEqual(1, assignedTargets.Count); + Assert.AreSame(expectedLeafTarget, assignedTargets[0]); + Assert.AreSame(_carrier, releasedInterceptor.CommsParent); + Assert.AreSame(_commsAgent, _carrier.CommsParent); + } + // Verifies that duplicate interceptor entries in a release batch do not double-count remaining // sub-interceptors. [Test] @@ -198,6 +259,15 @@ private static void SetSimManagerInstance(SimManager simManager) { instanceField.SetValue(null, simManager); } + private static void SetIadsInstance(IADS iads) { + FieldInfo instanceField = typeof(IADS).GetField("k__BackingField", + BindingFlags.NonPublic | BindingFlags.Static); + Assert.NotNull(instanceField, + $"{nameof(IADS)} instance backing field was not found. " + + $"The {nameof(IADS.Instance)} property shape may have changed."); + instanceField.SetValue(null, iads); + } + private void SetElapsedTime(float elapsedTime) { FieldInfo elapsedTimeField = typeof(SimManager) .GetField("k__BackingField", From 03188381ad6d07cd15f0f2f8fef471df516f96ac Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Mon, 8 Jun 2026 22:04:54 -0700 Subject: [PATCH 3/4] [Communication] Fixed Titan's Comments --- .../StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt | 4 ---- .../StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt | 2 -- 2 files changed, 6 deletions(-) diff --git a/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt b/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt index 9ddfa849d..05bc178af 100644 --- a/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt +++ b/Assets/StreamingAssets/Configs/Simulations/5_swarms_7_ucav.pbtxt @@ -289,7 +289,6 @@ communication_config { latency_std_seconds: 0.01 packet_delivery_ratio: 1.0 } - link_overrides { from: VESSEL to: CARRIER_INTERCEPTOR @@ -299,7 +298,6 @@ communication_config { packet_delivery_ratio: 1.0 } } - link_overrides { from: CARRIER_INTERCEPTOR to: VESSEL @@ -309,7 +307,6 @@ communication_config { packet_delivery_ratio: 1.0 } } - link_overrides { from: CARRIER_INTERCEPTOR to: MISSILE_INTERCEPTOR @@ -319,7 +316,6 @@ communication_config { packet_delivery_ratio: 1.0 } } - link_overrides { from: MISSILE_INTERCEPTOR to: CARRIER_INTERCEPTOR diff --git a/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt b/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt index d7db79c41..957487777 100644 --- a/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt +++ b/Assets/StreamingAssets/Configs/Simulations/7_quadcopters.pbtxt @@ -117,7 +117,6 @@ communication_config { latency_std_seconds: 0.02 packet_delivery_ratio: 1.0 } - link_overrides { from: VESSEL to: CARRIER_INTERCEPTOR @@ -127,7 +126,6 @@ communication_config { packet_delivery_ratio: 1.0 } } - link_overrides { from: CARRIER_INTERCEPTOR to: MISSILE_INTERCEPTOR From 82c73d11edb4ae9975a6960daad9d6aa2134e345 Mon Sep 17 00:00:00 2001 From: Joseph Chen Date: Mon, 8 Jun 2026 23:05:44 -0700 Subject: [PATCH 4/4] [Communication] Make sure test passes --- .../Tests/EditMode/CarrierBaseMailboxTests.cs | 41 +++++++++++++++---- .../EditMode/CarrierBaseMailboxTests.cs.meta | 2 + 2 files changed, 36 insertions(+), 7 deletions(-) create mode 100644 Assets/Tests/EditMode/CarrierBaseMailboxTests.cs.meta diff --git a/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs b/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs index 184ec58e8..0905410c0 100644 --- a/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs +++ b/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs @@ -126,14 +126,17 @@ public void ReleasedInterceptor_RequestViaMailbox_ProducesCarrierAssignTargetRes // carrier to IADS, and that the requesting interceptor receives the launcher-selected target. [Test] public void ReleasedInterceptor_RequestViaMailbox_PropagatesThroughCarrierAndIads() { - SetPrivateField(_carrier, "_numSubInterceptorsRemaining", 1); + TestLauncherCarrier launcherCarrier = + CreateLauncherCarrier("LauncherCarrier", Configs.AgentType.Vessel); + SetPrivateField(launcherCarrier, "_capacityPerSubInterceptor", 1); + SetPrivateField(launcherCarrier, "_numSubInterceptorsRemaining", 1); TestReleasedInterceptor releasedInterceptor = CreateReleasedInterceptor("ReleasedInterceptor", Configs.AgentType.MissileInterceptor); - _carrier.ReleaseStrategy = - new FixedReleaseStrategy(_carrier, new List { releasedInterceptor }); - RunReleaseManagerStep(_carrier, period: 0.2f); - _iads.RegisterNewAsset(_carrier); + launcherCarrier.ReleaseStrategy = + new FixedReleaseStrategy(launcherCarrier, new List { releasedInterceptor }); + RunReleaseManagerStep(launcherCarrier, period: 0.2f); + _iads.RegisterNewLauncher(launcherCarrier); var launcher = new StubInterceptor(Configs.AgentType.Vessel, capacity: 1) { Position = Vector3.zero }; @@ -165,8 +168,8 @@ public void ReleasedInterceptor_RequestViaMailbox_PropagatesThroughCarrierAndIad withTargetOnly: false); Assert.AreEqual(1, assignedTargets.Count); Assert.AreSame(expectedLeafTarget, assignedTargets[0]); - Assert.AreSame(_carrier, releasedInterceptor.CommsParent); - Assert.AreSame(_commsAgent, _carrier.CommsParent); + Assert.AreSame(launcherCarrier, releasedInterceptor.CommsParent); + Assert.AreSame(_commsAgent, launcherCarrier.CommsParent); } // Verifies that duplicate interceptor entries in a release batch do not double-count remaining @@ -211,6 +214,18 @@ private TestReleasedInterceptor CreateReleasedInterceptor(string name, return interceptor; } + private TestLauncherCarrier CreateLauncherCarrier(string name, Configs.AgentType agentType) { + GameObject launcherObject = new GameObject(name); + _spawnedObjects.Add(launcherObject); + launcherObject.AddComponent(); + + TestLauncherCarrier launcher = launcherObject.AddComponent(); + launcher.HierarchicalAgent = new HierarchicalAgent(launcher); + launcher.InvokeAwakeForTest(); + launcher.StaticConfig = CreateStaticConfig(agentType); + return launcher; + } + private static void RunReleaseManagerStep(CarrierBase carrier, float period) { MethodInfo releaseManagerMethod = typeof(CarrierBase) @@ -287,6 +302,18 @@ void IAgent.DestroyTargetModel() {} void IAgent.UpdateTargetModel() {} } + private sealed class TestLauncherCarrier : LauncherBase, IAgent { + public void InvokeAwakeForTest() { + base.Awake(); + } + + void IAgent.CreateTargetModel(IHierarchical target) {} + + void IAgent.DestroyTargetModel() {} + + void IAgent.UpdateTargetModel() {} + } + private sealed class TestReleasedInterceptor : InterceptorBase, IAgent { public void InvokeAwakeForTest() { base.Awake(); diff --git a/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs.meta b/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs.meta new file mode 100644 index 000000000..fb0e898ae --- /dev/null +++ b/Assets/Tests/EditMode/CarrierBaseMailboxTests.cs.meta @@ -0,0 +1,2 @@ +fileFormatVersion: 2 +guid: 2bcb7fd2c8997460788772dad50fdac3 \ No newline at end of file