{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Getting Started\n", "This tutorial demonstrates the configuration and use of a simple BSK-RL environment.\n", "BSK-RL and dependencies should already be installed at this point (see [Installation](../install.rst)\n", "if you haven't installed the package yet).\n", "\n", "## Load Modules\n", "In this tutorial, the environment will be created with `gym.make`, so it is necessary to\n", "import the top-level `bsk_rl` module as well as `gym` and `bsk_rl` components." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "import gymnasium as gym\n", "import numpy as np\n", "from bsk_rl import act, data, obs, scene, sats\n", "from bsk_rl.sim import dyn, fsw\n", "\n", "from Basilisk.architecture import bskLogging\n", "bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "If no errors were raised, you have a functional installation of `bsk_rl`.\n", "\n", "## Configure the Satellite\n", "[Satellites](../api_reference/sats/index.rst) are configurable agents in the environment.\n", "To make a new environment, start by specifying the [observations](../api_reference/obs/index.rst)\n", "and [actions](../api_reference/act/index.rst) of a satellite type, as well as the underlying\n", "Basilisk [simulation](../api_reference/sim/index.rst) models used by the satellite." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "class MyScanningSatellite(sats.AccessSatellite):\n", " observation_spec = [\n", " obs.SatProperties(\n", " dict(prop=\"storage_level_fraction\"),\n", " dict(prop=\"battery_charge_fraction\")\n", " ),\n", " obs.Eclipse(),\n", " ]\n", " action_spec = [\n", " act.Scan(duration=60.0), # Scan for 1 minute\n", " act.Charge(duration=600.0), # Charge for 10 minutes\n", " ]\n", " dyn_type = dyn.ContinuousImagingDynModel\n", " fsw_type = fsw.ContinuousImagingFSWModel" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Based on this class specification, a list of configurable parameters for the satellite\n", "can be generated." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "MyScanningSatellite.default_sat_args()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "When instantiating a satellite, these parameters can be overriden with a constant or \n", "rerandomized every time the environment is reset using the ``sat_args`` dictionary." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "sat_args = {}\n", "\n", "# Set some parameters as constants\n", "sat_args[\"imageAttErrorRequirement\"] = 0.05\n", "sat_args[\"dataStorageCapacity\"] = 1e10\n", "sat_args[\"instrumentBaudRate\"] = 1e7\n", "sat_args[\"storedCharge_Init\"] = 50000.0\n", "\n", "# Randomize the initial storage level on every reset\n", "sat_args[\"storageInit\"] = lambda: np.random.uniform(0.25, 0.75) * 1e10\n", "\n", "# Make the satellite\n", "sat = MyScanningSatellite(name=\"EO1\", sat_args=sat_args)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Making the Environment\n", "For this example, we will be using the single-agent [SatelliteTasking](../api_reference/index.rst) \n", "environment. Along with passing the satellite that we configured, the environment takes\n", "a [scenario](../api_reference/scene/index.rst), which defines the environment the\n", "satellite is acting in, and a [rewarder](../api_reference/data/index.rst), which defines\n", "how data collected from the scenario is rewarded." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "env = gym.make(\n", " \"SatelliteTasking-v1\",\n", " satellite=sat,\n", " scenario=scene.UniformNadirScanning(),\n", " rewarder=data.ScanningTimeReward(),\n", " time_limit=5700.0, # approximately 1 orbit\n", " log_level=\"INFO\",\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interacting with the Environment\n", "\n", "First, the environment is reset." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "observation, info = env.reset(seed=1)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, we take the scan action (`action=0`) a few times. This allows for the satellite to\n", "settle its attitude in the nadir pointing mode to satisfy imaging conditions. Note that \n", "the logs show little or no data accumulated in the first two steps as it settles, but\n", "achieves 60 reward (corresponding to 60 seconds of imaging) by the third step." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "print(\"Initial data level:\", observation[0], \"(randomized by sat_args)\")\n", "for _ in range(3):\n", " observation, reward, terminated, truncated, info = env.step(action=0)\n", "print(\" Final data level:\", observation[0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The observation reflects the increase in stored data. The first element, corresponding\n", "to `storage_level_fraction`, starts at a random value set by the `storageInit` function\n", "in `sat_args` and increases based on the time spent imaging.\n", "\n", "Finally, the charging mode is tasked repeatedly in 10-minute increments until the\n", "environment time limit is reached." ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "while not truncated:\n", " observation, reward, terminated, truncated, info = env.step(action=1)\n", " print(f\"Charge level: {observation[1]:.3f} ({env.unwrapped.simulator.sim_time:.1f} seconds)\\n\\tEclipse: start: {observation[2]:.1f} end: {observation[3]:.1f}\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "It is observed that the battery decrease while the satellite is in eclipse, but once the\n", "satellite is out of eclipse, the battery quickly increases to full charge." ] } ], "metadata": { "kernelspec": { "display_name": ".venv_refactor", "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 }