Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue #199: One way communication and broadcast action [WIP] #213

Draft
wants to merge 2 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/source/release_notes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ Development Version
* Improve performance of :class:`~bsk_rl.obs.Eclipse` observations by about 95%.
* Logs a warning if the initial battery charge or buffer level is incompatible with its capacity.
* Optimize communication when all satellites are communicating with each other.
* Allows communication to be one-way. Adds a :class:`~bsk_rl.act.Broadcast` action
that can be used with :class:`~bsk_rl.comm.BroadcastCommunication` to only communicate
data when the action has been called.



Expand Down
1 change: 1 addition & 0 deletions examples/_default.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ Environments
simple_environment
satellite_configuration
multiagent_envs
communication_action
cloud_environment


Expand Down
264 changes: 264 additions & 0 deletions examples/communication_action.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Broadcast Communication\n",
"\n",
"By default, communication occurs between all satellites that are specified by the communication\n",
"method. This tutorial shows how to use two classes to configure a broadcast action that must be\n",
"taken for communication to occur:\n",
"\n",
"* [Broadcast](../api_reference/act/index.html#bsk_rl.act.Broadcast), which gives satellites an action\n",
" that enables communication from them at the end of the current step.\n",
"* [BroadcastCommunication](../api_reference/comm/index.html#bsk_rl.comm.BroadcastCommunication), which\n",
" can be combined with another communication method to limit communication from broadcasters to\n",
" those satellites satisfying the requirements of the other communication method.\n",
"\n",
"## Configuring the Environment\n",
"\n",
"For this example, a multisatellite target imaging environment will be used. The goal is\n",
"to maximize the value of unique images taken. This configuration is similar to the \n",
"[Multi-Agent Environments](../examples/multiagent_envs.html) example."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from bsk_rl import sats, act, obs, scene, data, comm\n",
"from bsk_rl.sim import dyn, fsw\n",
"\n",
"\n",
"class ImagingSatellite(sats.ImagingSatellite):\n",
" observation_spec = [\n",
" obs.OpportunityProperties(\n",
" dict(prop=\"priority\"),\n",
" dict(prop=\"opportunity_open\", norm=5700.0),\n",
" n_ahead_observe=4,\n",
" )\n",
" ]\n",
" action_spec = [act.Broadcast(duration=15.0), act.Image(n_ahead_image=4)]\n",
" dyn_type = dyn.FullFeaturedDynModel\n",
" fsw_type = fsw.SteeringImagerFSWModel"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Satellite properties are set to give the satellite near-unlimited power and storage resources. To randomize some parameters in a correlated manner across satellites, a ``sat_arg_randomizer`` is set and passed to the environment. In this case, the satellites are distributed in a trivial single-plane Walker-delta constellation."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"from bsk_rl.utils.orbital import walker_delta_args\n",
"\n",
"N_AGENTS = 2\n",
"sat_args = dict(\n",
" imageAttErrorRequirement=0.01,\n",
" imageRateErrorRequirement=0.01,\n",
" batteryStorageCapacity=1e9,\n",
" storedCharge_Init=1e9,\n",
" dataStorageCapacity=1e12,\n",
" u_max=0.4,\n",
" K1=0.25,\n",
" K3=3.0,\n",
" omega_max=0.087,\n",
" servo_Ki=5.0,\n",
" servo_P=150 / 5,\n",
")\n",
"sat_arg_randomizer = walker_delta_args(\n",
" altitude=800.0, inc=60.0, n_planes=1, clustersize=N_AGENTS, clusterspacing=5.0\n",
")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Todo"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"class BroadcastLOS(comm.BroadcastCommunication, comm.LOSMultiCommunication):\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Todo"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[90;3m2024-11-12 11:26:28,059 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[mResetting environment with seed=2342335920\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,062 \u001b[0m\u001b[mscene.targets \u001b[0m\u001b[mINFO \u001b[0m\u001b[mGenerating 1000 targets\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,220 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mFinding opportunity windows from 0.00 to 600.00 seconds\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,246 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mFinding opportunity windows from 0.00 to 600.00 seconds\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,269 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[mEnvironment reset\u001b[0m\n"
]
}
],
"source": [
"from bsk_rl import ConstellationTasking\n",
"\n",
"env = ConstellationTasking(\n",
" satellites=[ImagingSatellite(f\"EO-{i+1}\", sat_args) for i in range(N_AGENTS)],\n",
" scenario=scene.UniformTargets(1000),\n",
" rewarder=data.UniqueImageReward(),\n",
" communicator=BroadcastLOS(),\n",
" sat_arg_randomizer=sat_arg_randomizer,\n",
" log_level=\"INFO\",\n",
")\n",
"_ = env.reset()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Todo"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[90;3m2024-11-12 11:26:28,276 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,277 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,278 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mTarget(tgt-475) tasked for imaging\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,280 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mTarget(tgt-475) window enabled: 207.1 to 339.7\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,280 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[msetting timed terminal event at 339.7\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,281 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,281 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mTarget(tgt-81) tasked for imaging\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,282 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mTarget(tgt-81) window enabled: 143.6 to 213.3\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,282 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[msetting timed terminal event at 213.3\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,313 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<146.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mimaged Target(tgt-81)\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,315 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<146.00> \u001b[0m\u001b[mData reward: {'EO-2': 0.1336693557001335}\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,318 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<146.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mSatellite EO-2 requires retasking\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,320 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<146.00> \u001b[0m\u001b[mStep reward: {'EO-2': 0.1336693557001335}\u001b[0m\n"
]
}
],
"source": [
"_ = env.step({env.agents[0]: 3, env.agents[1]: 2})"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Todo"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[90;3m2024-11-12 11:26:28,324 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<146.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,325 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<146.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[msetting timed terminal event at 161.0\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,328 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<146.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[msetting timed terminal event at 161.0\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,331 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mtimed termination at 161.0 for broadcast\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,332 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mtimed termination at 161.0 for broadcast\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,334 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[mData reward: {}\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,335 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[mCommunicating data through 2 satellite connections\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,336 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[mOptimizing data communication between all pairs of satellites\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,338 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mSatellite EO-1 requires retasking\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,338 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mSatellite EO-2 requires retasking\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,340 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n"
]
}
],
"source": [
"_ = env.step({env.agents[0]: 0, env.agents[1]: 0}) # Agent 1 broadcasts"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Todo"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"\u001b[90;3m2024-11-12 11:26:28,344 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,344 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,345 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mTarget(tgt-287) tasked for imaging\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,347 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[mTarget(tgt-287) window enabled: 256.8 to 406.3\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,347 \u001b[0m\u001b[36msats.satellite.EO-1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[36mEO-1: \u001b[0m\u001b[msetting timed terminal event at 406.3\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,347 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<161.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[msetting timed terminal event at 176.0\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,350 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<176.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mtimed termination at 176.0 for broadcast\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,352 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<176.00> \u001b[0m\u001b[mData reward: {}\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,353 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<176.00> \u001b[0m\u001b[mCommunicating data through 1 satellite connections\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,354 \u001b[0m\u001b[92msats.satellite.EO-2 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<176.00> \u001b[0m\u001b[92mEO-2: \u001b[0m\u001b[mSatellite EO-2 requires retasking\u001b[0m\n",
"\u001b[90;3m2024-11-12 11:26:28,356 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<176.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n"
]
}
],
"source": [
"_ = env.step({env.agents[0]: 3, env.agents[1]: 0}) # Agent 1 broadcasts"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.11"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
2 changes: 2 additions & 0 deletions src/bsk_rl/act/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ class MyActionSatellite(Satellite):

from bsk_rl.act.actions import Action
from bsk_rl.act.discrete_actions import (
Broadcast,
Charge,
Desat,
DiscreteAction,
Expand All @@ -63,4 +64,5 @@ class MyActionSatellite(Satellite):
"Downlink",
"Image",
"Scan",
"Broadcast",
]
35 changes: 34 additions & 1 deletion src/bsk_rl/act/discrete_actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@


class DiscreteActionBuilder(ActionBuilder):

def __init__(self, satellite: "Satellite") -> None:
"""Processes actions for a discrete action space.

Expand Down Expand Up @@ -302,5 +301,39 @@ def set_action_override(
return self.image(action, prev_action_key)


class Broadcast(DiscreteAction):
def __init__(
self,
name: str = "action_broadcast",
duration: Optional[float] = None,
):
"""Action to broadcast data to all satellites in the simulation.

Should be used with a :class:`~bsk_rl.comm.BroadcastCommunication`-derived
communication method to limit communication to broadcasting satellites.

Args:
name: Action name.
duration: [s] Time to idle before communicating.
"""
super().__init__(name=name, n_actions=1)
if duration is None:
duration = 1e9
self.duration = duration

def reset_post_sim_init(self) -> None:
"""Log previous action key."""
super().reset_post_sim_init()
self.broadcast_pending = False

def set_action(self, action: int, prev_action_key=None) -> str:
assert action == 0
self.broadcast_pending = True
self.satellite.update_timed_terminal_event(
self.simulator.sim_time + self.duration, info=f"for broadcast"
)
return self.name


__doc_title__ = "Discrete Backend"
__all__ = ["DiscreteActionBuilder"]
2 changes: 2 additions & 0 deletions src/bsk_rl/comm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
"""

from bsk_rl.comm.communication import (
BroadcastCommunication,
CommunicationMethod,
FreeCommunication,
LOSCommunication,
Expand All @@ -63,4 +64,5 @@
"LOSCommunication",
"MultiDegreeCommunication",
"LOSMultiCommunication",
"BroadcastCommunication",
]
Loading
Loading