Skip to content

Commit

Permalink
Issue #0: Optimize communication when all satellites are talking
Browse files Browse the repository at this point in the history
  • Loading branch information
Mark2000 committed Oct 10, 2024
1 parent 2eed677 commit 53ae4c1
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 9 deletions.
30 changes: 24 additions & 6 deletions src/bsk_rl/comm/communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@

import logging
from abc import ABC, abstractmethod
from copy import copy
from itertools import combinations
from typing import TYPE_CHECKING, Optional
from typing import TYPE_CHECKING

import numpy as np
from scipy.sparse.csgraph import connected_components
from scipy.special import comb

from bsk_rl.sim.dyn import LOSCommDynModel
from bsk_rl.utils.functional import Resetable
Expand Down Expand Up @@ -60,17 +62,33 @@ def communicate(self) -> None:
return

communication_pairs = self.communication_pairs()

if len(communication_pairs) > 0:
logger.info(
f"Communicating data between {len(communication_pairs)} pairs of satellites"
)

for sat_1, sat_2 in communication_pairs:
sat_1.data_store.stage_communicated_data(sat_2.data_store.data)
sat_2.data_store.stage_communicated_data(sat_1.data_store.data)
if len(communication_pairs) == comb(len(self.satellites), 2):
self._communicate_all()
self.last_communication_time = self.satellites[0].simulator.sim_time
else:
for sat_1, sat_2 in communication_pairs:
sat_1.data_store.stage_communicated_data(sat_2.data_store.data)
sat_2.data_store.stage_communicated_data(sat_1.data_store.data)
for satellite in self.satellites:
satellite.data_store.update_with_communicated_data()
self.last_communication_time = self.satellites[0].simulator.sim_time

def _communicate_all(self):
"""Optimized communication between all pairs of satellites."""
logger.info("Optimizing data communication between all pairs of satellites")

data_type = self.satellites[0].data_store.data.__class__
final_data = data_type()
for satellite in self.satellites:
final_data += satellite.data_store.data
for satellite in self.satellites:
satellite.data_store.update_with_communicated_data()
self.last_communication_time = self.satellites[0].simulator.sim_time
satellite.data_store.data = copy(final_data)


class NoCommunication(CommunicationMethod):
Expand Down
4 changes: 4 additions & 0 deletions src/bsk_rl/data/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,10 @@ def __add__(self, other: "Data") -> "Data":
"""Define the combination of two units of data."""
pass

def __copy__(self) -> "Data":
"""Create a shallow copy of the data."""
return self.__class__() + self


class DataStore(ABC):
"""Base class for satellite data logging."""
Expand Down
29 changes: 26 additions & 3 deletions tests/unittest/comm/test_communication.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
@patch.multiple(CommunicationMethod, __abstractmethods__=set())
class TestCommunicationMethod:
def test_communicate(self):
mock_sats = [MagicMock(), MagicMock()]
mock_sats = [MagicMock(), MagicMock(), MagicMock()]
mock_sats[0].simulator.sim_time = 0.0
comms = CommunicationMethod()
comms.last_communication_time = 0.0
Expand All @@ -34,7 +34,7 @@ def test_communicate(self):
sat.data_store.update_with_communicated_data.assert_called_once()

def test_min_period_elapsed(self):
mock_sats = [MagicMock(), MagicMock()]
mock_sats = [MagicMock(), MagicMock(), MagicMock()]
comms = CommunicationMethod(min_period=1.0)
comms.link_satellites(mock_sats)
comms.communication_pairs = MagicMock(
Expand All @@ -47,7 +47,7 @@ def test_min_period_elapsed(self):
sat.data_store.update_with_communicated_data.assert_called_once()

def test_min_period_not_elapsed(self):
mock_sats = [MagicMock(), MagicMock()]
mock_sats = [MagicMock(), MagicMock(), MagicMock()]
comms = CommunicationMethod(min_period=1.0)
comms.link_satellites(mock_sats)
comms.communication_pairs = MagicMock(
Expand All @@ -59,6 +59,29 @@ def test_min_period_not_elapsed(self):
for sat in mock_sats:
sat.data_store.update_with_communicated_data.assert_not_called()

def test_override_communicate_all(self):
mock_sats = [MagicMock() for i in range(3)]
comms = FreeCommunication()
comms.last_communication_time = 0.0
mock_sats[0].simulator.sim_time = 1.0
comms.link_satellites(mock_sats)
comms._communicate_all = MagicMock()
comms.communicate()
comms._communicate_all.assert_called_once()

def test_override_communicate_all_nocall(self):
mock_sats = [MagicMock() for i in range(3)]
comms = CommunicationMethod()
comms.communication_pairs = MagicMock(
return_value=[(mock_sats[1], mock_sats[0])]
)
comms.last_communication_time = 0.0
mock_sats[0].simulator.sim_time = 1.0
comms.link_satellites(mock_sats)
comms._communicate_all = MagicMock()
comms.communicate()
comms._communicate_all.assert_not_called()


class TestNoCommunication:
def test_communicate(self):
Expand Down

0 comments on commit 53ae4c1

Please sign in to comment.