{ "cells": [ { "cell_type": "markdown", "id": "hybrid-quality-00", "metadata": {}, "source": [ "# Hybrid imaging with time-varying image quality\n", "\n", "This example shows how to set up an imaging environment with targets that have heterogeneous, time-varying rewards. The underlying environment accepts hybrid actions consisting of a target index and a desired acquisition delay. Here, a custom actor produces categorical logits over target/timing pairs, and a separate critic estimates the state value. Action wrappers convert the selected pair into a target index and delay in seconds. The final section demonstrates multi-satellite coordination through shared acquisition information and task intents. This example is part of an upcoming publication.\n" ] }, { "cell_type": "code", "execution_count": 1, "id": "hybrid-quality-01", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/lorenzzo/Local/repo_updates/issue_363/.venv_issue_363/lib/python3.12/site-packages/tqdm/auto.py:21: TqdmWarning: IProgress not found. Please update jupyter and ipywidgets. See https://ipywidgets.readthedocs.io/en/stable/user_install.html\n", " from .autonotebook import tqdm as notebook_tqdm\n" ] } ], "source": [ "from collections.abc import Callable, Iterable\n", "from typing import Any, ClassVar\n", "\n", "import gymnasium as gym\n", "import numpy as np\n", "from Basilisk.architecture import bskLogging\n", "from Basilisk.utilities import orbitalMotion\n", "from scipy.interpolate import make_lsq_spline\n", "\n", "from bsk_rl import ConstellationTasking, SatelliteTasking, act, obs, sats\n", "from bsk_rl.data.unique_image_data import (\n", " GlobalReward,\n", " UniqueImageData,\n", " UniqueImageReward,\n", " UniqueImageStore,\n", ")\n", "from bsk_rl.scene.targets import CityTargets, Target\n", "from bsk_rl.sim import dyn, fsw\n", "from bsk_rl.utils.orbital import random_circular_orbit\n", "\n", "bskLogging.setDefaultLogLevel(bskLogging.BSK_WARNING)\n", "\n", "ALTITUDE_KM = 800.0\n", "EARTH_RADIUS = orbitalMotion.REQ_EARTH * 1e3\n", "ORBIT_PERIOD = (\n", " 2\n", " * np.pi\n", " * np.sqrt((orbitalMotion.REQ_EARTH + ALTITUDE_KM) ** 3 / orbitalMotion.MU_EARTH)\n", ")\n", "N_AHEAD = 40\n", "SIM_RATE = 0.5\n", "IMAGING_FRACTIONS = (0.0, 0.5, 1.0)\n", "SPLINE_DEGREE = 2\n", "SPLINE_KNOTS = np.r_[np.zeros(3), [1 / 3, 2 / 3], np.ones(3)]" ] }, { "cell_type": "markdown", "id": "hybrid-quality-02", "metadata": {}, "source": [ "## Targets and quality\n", "\n", "Acquisition quality can depend on viewing geometry or a stakeholder preference for the acquisition time. This example includes the paper's off-nadir and periodic quality models. The distance and glare models are omitted to keep the example compact.\n", "\n", "`QualityTargets` extends `CityTargets` by assigning a quality model and weight to each target. Setting `quality_weight=1.0` makes reward equal to priority times quality, while `quality_weight=0.0` makes reward depend only on priority. Setting `quality_weight=(0.0, 1.0)` samples a separate weight for each target on every reset. Choose a single model with `quality_types=(\"quality_off_nadir_angle\",)` or `quality_types=(\"quality_periodic\",)`, or sample uniformly from `quality_types=(\"quality_off_nadir_angle\", \"quality_periodic\")`. The absolute acquisition reward is\n", "\n", "$$r_i(t)=p_i\\big[1-w_{q,i}+w_{q,i}q_i(t)\\big],$$\n", "\n", "where $p_i$ is target priority, $w_{q,i}$ is its quality weight, and $q_i(t)\\in[0,1]$ is the quality at acquisition time. The rewarder below determines whether an acquisition receives this absolute reward or only its improvement over the best completed reward.\n", "\n", "Off-nadir quality uses the angle between the target's local vertical and its viewing direction: $q=\\mathrm{clip}(1-2\\theta/\\pi,0,1)$. Future samples use predicted geometric viewing directions; at the current time, realized instrument pointing is used. Periodic quality represents a known, time-varying acquisition preference, using one or two sinusoidal components with periods between 150 and 570 seconds. Frequencies in the code are angular frequencies in radians per second. These are illustrative acquisition-quality models, not a radiometric sensor simulation.\n" ] }, { "cell_type": "code", "execution_count": 2, "id": "cd228d9f", "metadata": {}, "outputs": [], "source": [ "def periodic_quality_function(t, amplitudes, frequencies, phases):\n", " \"\"\"Evaluate a window-independent sum of periodic components.\n", "\n", " ``frequencies`` are angular frequencies in radians per second.\n", " \"\"\"\n", " t = np.asarray(t, dtype=float)\n", " amplitudes = np.asarray(amplitudes, dtype=float)\n", " frequencies = np.asarray(frequencies, dtype=float)\n", " phases = np.asarray(phases, dtype=float)\n", "\n", " if amplitudes.ndim != 1 or frequencies.ndim != 1 or phases.ndim != 1:\n", " raise ValueError(\"amplitudes, frequencies, and phases must be 1-D arrays.\")\n", " if not (len(amplitudes) == len(frequencies) == len(phases)):\n", " raise ValueError(\n", " \"amplitudes, frequencies, and phases must have the same length.\"\n", " )\n", " if len(amplitudes) == 0:\n", " raise ValueError(\"At least one periodic component is required.\")\n", " if not (\n", " np.all(np.isfinite(t))\n", " and np.all(np.isfinite(amplitudes))\n", " and np.all(np.isfinite(frequencies))\n", " and np.all(np.isfinite(phases))\n", " ):\n", " raise ValueError(\"Periodic-function inputs must all be finite.\")\n", " if np.any(frequencies <= 0):\n", " raise ValueError(\"Periodic frequencies must be greater than zero.\")\n", "\n", " amplitude_sum = np.sum(np.abs(amplitudes))\n", " if amplitude_sum <= 0:\n", " raise ValueError(\"At least one periodic amplitude must be nonzero.\")\n", "\n", " quality = np.sum(\n", " np.array(\n", " [\n", " amplitudes[i] * np.sin(frequencies[i] * t + phases[i])\n", " for i in range(len(amplitudes))\n", " ]\n", " ),\n", " axis=0,\n", " )\n", "\n", " quality = (quality + amplitude_sum) / (2 * amplitude_sum)\n", "\n", " return quality.item() if np.ndim(quality) == 0 else quality\n", "\n", "\n", "def quality_periodic(sat, tgt, t, amplitudes, frequencies, phases, **kwargs):\n", "\n", " return periodic_quality_function(\n", " t,\n", " amplitudes=amplitudes,\n", " frequencies=frequencies,\n", " phases=phases,\n", " )\n", "\n", "\n", "def _positions_at_times(sat, times, trajectory_r_BP_P=None):\n", " \"\"\"Return predicted positions, using dynamics for the realized current time.\"\"\"\n", " times = np.asarray(times, dtype=float)\n", " current_mask = np.abs(times - sat.simulator.sim_time) <= 1e-6\n", "\n", " if times.ndim == 0:\n", " if current_mask:\n", " return np.asarray(sat.dynamics.r_BN_P, dtype=float)\n", " elif np.all(current_mask):\n", " return np.broadcast_to(\n", " np.asarray(sat.dynamics.r_BN_P, dtype=float),\n", " times.shape + (3,),\n", " ).copy()\n", "\n", " if trajectory_r_BP_P is None:\n", " trajectory_r_BP_P = sat.trajectory.r_BP_P\n", " positions = np.asarray(trajectory_r_BP_P(times), dtype=float)\n", "\n", " if times.ndim > 0 and np.any(current_mask):\n", " positions = positions.copy()\n", " positions[current_mask] = sat.dynamics.r_BN_P\n", " return positions\n", "\n", "\n", "def quality_off_nadir_angle(sat, tgt, t, trajectory_r_BP_P=None, **kwargs):\n", " \"\"\"Return quality based on the target-centered instrument viewing angle.\n", "\n", " At the current simulation time, use the realized instrument direction so\n", " the reward reflects the actual imaging attitude. For future profile samples,\n", " where the attitude is not yet known, use the geometric target-to-satellite\n", " direction. Quality decreases linearly from one for a target directly below\n", " the instrument to zero for a target viewed at its local horizon.\n", " \"\"\"\n", " t = np.asarray(t, dtype=float)\n", " scalar_input = t.ndim == 0\n", " r_BN_P = _positions_at_times(sat, t, trajectory_r_BP_P)\n", "\n", " target_position = np.asarray(tgt.r_LP_P, dtype=float)\n", " target_radius = np.linalg.norm(target_position)\n", " target_to_camera = r_BN_P - target_position\n", " view_norm = np.linalg.norm(target_to_camera, axis=-1, keepdims=True)\n", " if (\n", " np.any(~np.isfinite(r_BN_P))\n", " or not np.all(np.isfinite(target_position))\n", " or target_radius <= 0.0\n", " or np.any(view_norm <= 0.0)\n", " ):\n", " raise ValueError(\"Off-nadir geometry must contain finite, nonzero vectors.\")\n", "\n", " local_vertical_hat_P = target_position / target_radius\n", " view_hat_P = target_to_camera / view_norm\n", "\n", " realized_mask = np.abs(t - sat.simulator.sim_time) <= 1e-6\n", " if np.any(realized_mask):\n", " c_hat_P = np.asarray(sat.fsw.c_hat_P, dtype=float)\n", " if c_hat_P.shape != (3,) or not np.all(np.isfinite(c_hat_P)):\n", " raise ValueError(\"c_hat_P must be a finite three-component vector.\")\n", " pointing_norm = np.linalg.norm(c_hat_P)\n", " if pointing_norm <= 0.0:\n", " raise ValueError(\"c_hat_P must be nonzero.\")\n", " if scalar_input:\n", " view_hat_P = -c_hat_P / pointing_norm\n", " else:\n", " view_hat_P = view_hat_P.copy()\n", " view_hat_P[realized_mask] = -c_hat_P / pointing_norm\n", "\n", " off_nadir = np.arccos(\n", " np.clip(np.sum(view_hat_P * local_vertical_hat_P, axis=-1), -1.0, 1.0)\n", " )\n", "\n", " quality = np.clip(1 - off_nadir / (np.pi / 2), 0.0, 1.0)\n", " return quality.item() if scalar_input else quality\n", "\n", "\n", "QUALITY_FUNCTIONS = {\n", " \"quality_off_nadir_angle\": quality_off_nadir_angle,\n", " \"quality_periodic\": quality_periodic,\n", "}\n", "\n", "\n", "def get_randomized_quality_function_params(quality_function_name):\n", " if quality_function_name in [\"quality_off_nadir_angle\"]:\n", " return {}\n", " elif quality_function_name == \"quality_periodic\":\n", " n_components = np.random.randint(1, 3)\n", " amplitudes = np.random.uniform(0.1, 1.0, size=n_components)\n", " frequencies = (\n", " 2\n", " * np.pi\n", " * np.random.uniform(\n", " 10.0 / 5700.0,\n", " 1.0 / 150.0,\n", " size=n_components,\n", " )\n", " )\n", " phases = np.random.uniform(0.0, 2 * np.pi, size=n_components)\n", " return {\n", " \"amplitudes\": amplitudes,\n", " \"frequencies\": frequencies,\n", " \"phases\": phases,\n", " }\n", " else:\n", " raise ValueError(f\"Unknown quality function: {quality_function_name}\")" ] }, { "cell_type": "markdown", "id": "a17776df", "metadata": {}, "source": [ "### Assign quality models to targets\n", "\n", "`QualityTargets` extends `CityTargets`: it generates city-based targets through the parent class and then attaches a quality weight, a selected quality model, and that model's randomized parameters to each target. A scalar weight applies to all targets; a two-element range samples a separate weight for each target. A one-element tuple of quality names selects the same model for every target.\n", "\n", "On each reset, the scenario initializes the best obtained reward to `0.0` and clears the per-satellite capture timestamps. These fields support marginal rewards for re-imaging and the cooldown filter used in the coordination example below.\n" ] }, { "cell_type": "code", "execution_count": 3, "id": "hybrid-quality-03", "metadata": {}, "outputs": [], "source": [ "from copy import deepcopy\n", "\n", "\n", "class QualityTargets(CityTargets):\n", " \"\"\"City-based target scenario with per-target quality models and weights.\"\"\"\n", "\n", " def __init__(\n", " self,\n", " n_targets: int | tuple[int, int],\n", " n_select_from: int | None = None,\n", " location_offset: float = 0,\n", " priority_distribution: Callable | None = None,\n", " radius: float = orbitalMotion.REQ_EARTH * 1e3,\n", " quality_weights: float | list[float] = 0.5,\n", " quality_function_name: list[str] | None = None,\n", " quality_function_weights: None | list[float] = None,\n", " ) -> None:\n", "\n", " super().__init__(\n", " n_targets, n_select_from, location_offset, priority_distribution, radius\n", " )\n", " self.quality_weights = quality_weights\n", " if quality_function_name is None:\n", " self.quality_function_name = [\n", " \"quality_off_nadir_angle\",\n", " \"quality_periodic\",\n", " ]\n", " self.quality_function_name = deepcopy(quality_function_name)\n", " self.quality_function_weights = quality_function_weights\n", " if self.quality_function_weights is not None:\n", " assert len(self.quality_function_name) == len(quality_function_weights), (\n", " \"quality_function_weights must match quality_functions\"\n", " )\n", " self.quality_function_weights = np.array(quality_function_weights) / np.sum(\n", " np.array(quality_function_weights)\n", " )\n", "\n", " def regenerate_targets(self) -> None:\n", " super().regenerate_targets()\n", "\n", " for tgt in self.targets:\n", " if isinstance(self.quality_weights, (list, tuple, np.ndarray)):\n", " quality_weight = np.random.uniform(\n", " self.quality_weights[0], self.quality_weights[1]\n", " )\n", " else:\n", " quality_weight = self.quality_weights\n", "\n", " quality_function = np.random.choice(\n", " self.quality_function_name, p=self.quality_function_weights\n", " )\n", "\n", " quality_function_params = get_randomized_quality_function_params(\n", " quality_function\n", " )\n", "\n", " tgt.quality_weight = quality_weight\n", " tgt.quality_function_name = quality_function\n", " tgt.quality_function_params = quality_function_params\n", " tgt.highest_quality_obtained = None\n", " tgt.highest_quality_time = None\n", " tgt.highest_reward_obtained = 0.0\n", " tgt.last_img_time_per_sat = {}" ] }, { "cell_type": "markdown", "id": "hybrid-quality-04", "metadata": {}, "source": [ "## Rewarding physical captures\n", "\n", "`QualityImageStore` detects a completed acquisition from an increase in stored instrument data and evaluates quality using the target's assigned model and the satellite state at capture time. Requested acquisition time and realized capture time are recorded separately because pointing constraints can delay capture.\n", "\n", "`QualityImageReward` converts these acquisition events into step rewards. With `incremental_score=False`, a target is rewarded only for its first completed acquisition. With `incremental_score=True`, a capture earns $\\max(r_i(t)-r_{i,\\mathrm{max}},0)$, where $r_{i,\\mathrm{max}}$ is the best absolute acquisition reward completed before that capture. Pending intents affect predicted marginal profiles, but do not increase the completed-reward baseline used for actual reward allocation.\n" ] }, { "cell_type": "code", "execution_count": 4, "id": "hybrid-quality-05", "metadata": {}, "outputs": [], "source": [ "class QualityImageData(UniqueImageData):\n", " def __init__(self, imaged=None, duplicates=0, known=None, image_events=None):\n", " super().__init__(imaged=imaged, duplicates=duplicates, known=known)\n", "\n", " if image_events is None:\n", " image_events = []\n", " self.image_events = [event.copy() for event in image_events]\n", "\n", " def __add__(self, other: \"QualityImageData\") -> \"QualityImageData\":\n", " imaged = self.imaged | other.imaged\n", " image_events = self.image_events + other.image_events\n", " duplicates = (\n", " self.duplicates\n", " + other.duplicates\n", " + len(self.imaged)\n", " + len(other.imaged)\n", " - len(imaged)\n", " )\n", " known = self.known | other.known\n", " return self.__class__(\n", " imaged=imaged,\n", " duplicates=duplicates,\n", " known=known,\n", " image_events=image_events,\n", " )\n", "\n", "\n", "def get_quality(sat, tgt, t=None, **function_context):\n", " \"\"\"Evaluate the quality function assigned to a target.\"\"\"\n", " if t is None:\n", " t = sat.simulator.sim_time\n", "\n", " quality_function = tgt.quality_function_name\n", " quality_function_params = {\n", " **tgt.quality_function_params,\n", " **function_context,\n", " }\n", " return QUALITY_FUNCTIONS[quality_function](\n", " sat,\n", " tgt,\n", " t=t,\n", " **quality_function_params,\n", " )\n", "\n", "\n", "class QualityImageStore(UniqueImageStore):\n", " \"\"\"Record quality-aware target acquisitions, including repeated captures.\"\"\"\n", "\n", " data_type = QualityImageData\n", "\n", " def __init__(\n", " self,\n", " *args,\n", " record_image_profiles: bool = False,\n", " image_profile_samples: int = 25,\n", " **kwargs,\n", " ) -> None:\n", " \"\"\"Initialize image-quality logging options.\n", "\n", " Args:\n", " record_image_profiles: Sample quality over the acquisition access window.\n", " This is intended for post-test visualization and is disabled by default\n", " to avoid adding work to training environments.\n", " image_profile_samples: Number of evenly spaced samples in each profile.\n", " \"\"\"\n", " if image_profile_samples < 2:\n", " raise ValueError(\"image_profile_samples must be at least 2\")\n", " self.record_image_profiles = record_image_profiles\n", " self.image_profile_samples = image_profile_samples\n", " super().__init__(*args, **kwargs)\n", "\n", " def _access_window(self, target: \"Target\", time: float) -> tuple[float, float]:\n", " \"\"\"Return a containing window, otherwise the nearest known window or NaNs.\"\"\"\n", " candidates = []\n", " for opportunity in getattr(self.satellite, \"opportunities\", []):\n", " if opportunity.get(\"type\") != \"target\":\n", " continue\n", " opportunity_target = opportunity.get(\"object\")\n", " if opportunity_target is not target and getattr(\n", " opportunity_target, \"id\", None\n", " ) != getattr(target, \"id\", None):\n", " continue\n", " window = opportunity.get(\"window\")\n", " if window is None or len(window) != 2:\n", " continue\n", " window_open, window_close = map(float, window)\n", " if window_open <= time <= window_close:\n", " return window_open, window_close\n", " candidates.append((window_open, window_close))\n", "\n", " if candidates:\n", " return min(\n", " candidates,\n", " key=lambda window: min(\n", " abs(time - window[0]),\n", " abs(time - window[1]),\n", " ),\n", " )\n", " return np.nan, np.nan\n", "\n", " def _requested_imaging_time(self) -> float:\n", " \"\"\"Read the controller's absolute requested imaging time, when available.\"\"\"\n", " try:\n", " return float(self.satellite.fsw.insControl.imagingTime) * 1e-9\n", " except (AttributeError, TypeError, ValueError):\n", " return np.nan\n", "\n", " def _quality_profile(\n", " self,\n", " target: \"Target\",\n", " window_open: float,\n", " window_close: float,\n", " ) -> tuple[np.ndarray, np.ndarray]:\n", " \"\"\"Sample raw target quality over an access window.\"\"\"\n", " if (\n", " not self.record_image_profiles\n", " or not np.all(np.isfinite([window_open, window_close]))\n", " or window_close <= window_open\n", " or not all(\n", " hasattr(target, attribute)\n", " for attribute in (\n", " \"quality_function_name\",\n", " \"quality_function_params\",\n", " )\n", " )\n", " ):\n", " return np.asarray([], dtype=float), np.asarray([], dtype=float)\n", "\n", " profile_times = np.linspace(\n", " window_open,\n", " window_close,\n", " self.image_profile_samples,\n", " )\n", "\n", " profile_qualities = np.asarray(\n", " get_quality(\n", " self.satellite,\n", " target,\n", " t=profile_times,\n", " w_o=window_open,\n", " w_c=window_close,\n", " ),\n", " dtype=float,\n", " )\n", "\n", " if profile_qualities.shape != profile_times.shape or not np.all(\n", " np.isfinite(profile_qualities)\n", " ):\n", " return np.asarray([], dtype=float), np.asarray([], dtype=float)\n", " return profile_times, np.clip(profile_qualities, 0.0, 1.0)\n", "\n", " def get_log_state(self) -> float:\n", " \"\"\"Log the instantaneous storage unit state at the end of each step.\n", " Returns:\n", " float: storedData from satellite storage unit\n", " \"\"\"\n", " msg = self.satellite.dynamics.storageUnit.storageUnitDataOutMsg.read()\n", "\n", " return msg.storedData[0]\n", "\n", " def compare_log_states(\n", " self, old_state: float, new_state: float\n", " ) -> QualityImageData:\n", " \"\"\"Record an acquisition when stored instrument data increases.\n", "\n", " Args:\n", " old_state: Previous scalar stored-data reading.\n", " new_state: Current scalar stored-data reading.\n", "\n", " Returns:\n", " QualityImageData containing the captured target and acquisition event,\n", " or an empty record when storage does not increase. Repeated captures\n", " of the same target are recorded as separate events.\n", " \"\"\"\n", " data_increase = new_state - old_state\n", "\n", " if data_increase <= 0:\n", " return QualityImageData()\n", " else:\n", " assert self.satellite.latest_target is not None\n", " target = self.satellite.latest_target\n", " self.update_target_colors([target])\n", " image_time = float(self.satellite.simulator.sim_time)\n", " window_open, window_close = self._access_window(target, image_time)\n", "\n", " quality = get_quality(\n", " self.satellite,\n", " target,\n", " t=image_time,\n", " w_o=window_open,\n", " w_c=window_close,\n", " )\n", "\n", " target.last_quality_obtained = quality\n", " target.last_quality_time = image_time\n", " if (\n", " target.highest_quality_obtained is None\n", " or quality > target.highest_quality_obtained\n", " ):\n", " target.highest_quality_obtained = quality\n", " target.highest_quality_time = image_time\n", "\n", " target.last_img_time_per_sat[self.satellite.name] = image_time\n", "\n", " profile_times, profile_qualities = self._quality_profile(\n", " target,\n", " window_open,\n", " window_close,\n", " )\n", " image_event = {\n", " \"time\": image_time,\n", " \"requested_time\": self._requested_imaging_time(),\n", " \"target_id\": str(target.id),\n", " \"target_name\": str(target.name),\n", " \"satellite_name\": str(self.satellite.name),\n", " \"priority\": float(target.priority),\n", " \"quality\": float(quality),\n", " \"quality_function_name\": str(\n", " getattr(target, \"quality_function_name\", \"legacy_distance\")\n", " ),\n", " \"quality_function_params\": dict(\n", " getattr(target, \"quality_function_params\", {})\n", " ),\n", " \"access_window_open\": window_open,\n", " \"access_window_close\": window_close,\n", " \"imaging_time_fraction\": (image_time - window_open)\n", " / (window_close - window_open),\n", " \"profile_times\": profile_times,\n", " \"profile_qualities\": profile_qualities,\n", " \"quality_weight\": np.nan,\n", " \"reward\": 0.0,\n", " \"rewarded\": False,\n", " }\n", " return QualityImageData(\n", " imaged={target},\n", " image_events=[image_event],\n", " )\n", "\n", "\n", "class QualityImageReward(UniqueImageReward):\n", " \"\"\"Reward initial captures or positive re-imaging improvements.\"\"\"\n", "\n", " data_store_type = QualityImageStore\n", "\n", " def __init__(\n", " self,\n", " reward_fn: Callable,\n", " record_image_profiles: bool = False,\n", " image_profile_samples: int = 25,\n", " incremental_score: bool = False,\n", " ):\n", " \"\"\"Initialize the rewarder.\n", "\n", " Args:\n", " reward_fn: Callback evaluated as\n", " reward_fn(priority, quality, quality_weight=target.quality_weight).\n", " The quality weight is supplied by each target.\n", " record_image_profiles: Sample target quality over each successful image's\n", " access window for post-test visualization.\n", " image_profile_samples: Number of samples stored in each quality profile.\n", " incremental_score: If True, reward only positive improvements over\n", " the best completed reward for each target. If False, reward only\n", " the first completed acquisition of each target.\n", " \"\"\"\n", "\n", " super().__init__(reward_fn)\n", " self.data_store_kwargs.update(\n", " record_image_profiles=record_image_profiles,\n", " image_profile_samples=image_profile_samples,\n", " )\n", " self.incremental_score = incremental_score\n", "\n", " def create_data_store(self, satellite) -> None:\n", " \"\"\"Create the store, bypassing the unique-target filter for re-imaging.\"\"\"\n", " if self.incremental_score:\n", " GlobalReward.create_data_store(self, satellite)\n", " else:\n", " super().create_data_store(satellite)\n", "\n", " def _update_event_reward_info(\n", " self,\n", " event: dict[str, Any],\n", " target: \"Target\",\n", " quality_weight: float,\n", " reward: float,\n", " rewarded: bool,\n", " ) -> None:\n", " \"\"\"Attach reward information to an acquisition event in place.\"\"\"\n", " event[\"quality_weight\"] = float(quality_weight)\n", " event[\"reward\"] = float(reward)\n", " event[\"rewarded\"] = rewarded\n", "\n", " profile_qualities = np.asarray(event[\"profile_qualities\"], dtype=float)\n", " if profile_qualities.size == 0:\n", " event[\"profile_rewards\"] = np.asarray([], dtype=float)\n", " return\n", "\n", " try:\n", " profile_rewards = np.asarray(\n", " self.reward_fn(\n", " target.priority,\n", " profile_qualities,\n", " quality_weight=quality_weight,\n", " ),\n", " dtype=float,\n", " )\n", " if profile_rewards.ndim == 0:\n", " profile_rewards = np.full_like(profile_qualities, profile_rewards)\n", " except (TypeError, ValueError):\n", " profile_rewards = np.asarray(\n", " [\n", " self.reward_fn(\n", " target.priority,\n", " quality,\n", " quality_weight=quality_weight,\n", " )\n", " for quality in profile_qualities\n", " ],\n", " dtype=float,\n", " )\n", " event[\"profile_rewards\"] = profile_rewards\n", "\n", " def calculate_reward(\n", " self, new_data_dict: dict[str, QualityImageData]\n", " ) -> dict[str, float]:\n", " \"\"\"Allocate step rewards for completed acquisitions.\n", "\n", " Evaluate reward_fn(priority, quality, quality_weight=target.quality_weight).\n", " Nonincremental scoring rewards only the first acquisition of a target;\n", " incremental scoring rewards positive improvements over its best completed\n", " reward. For simultaneous captures, allocate reward among satellites tied\n", " for the highest realized quality and give the others zero.\n", "\n", " Args:\n", " new_data_dict: Acquisition data keyed by satellite name.\n", "\n", " Returns:\n", " Dictionary mapping each satellite name to its total reward this step.\n", " \"\"\"\n", "\n", " event_per_target = {}\n", " targets_by_id = {}\n", " for sat_id, new_data in new_data_dict.items():\n", " targets_by_id.update({str(target.id): target for target in new_data.imaged})\n", " for event in new_data.image_events:\n", " target_id = event[\"target_id\"]\n", " if target_id not in event_per_target:\n", " event_per_target[target_id] = []\n", " event_per_target[target_id].append((sat_id, event))\n", "\n", " reward = {sat_id: 0.0 for sat_id in new_data_dict}\n", " for tgt_id, events in event_per_target.items():\n", " target = targets_by_id.get(tgt_id)\n", "\n", " if target in self.data.imaged and not self.incremental_score:\n", " for sat_id, event in events:\n", " self._update_event_reward_info(\n", " event,\n", " target,\n", " target.quality_weight,\n", " reward=0.0,\n", " rewarded=False,\n", " )\n", " continue\n", "\n", " time_list = np.array([event[\"time\"] for _, event in events])\n", " time_events = set(time_list)\n", " time_events_sorted = sorted(time_events)\n", "\n", " for time_event in time_events_sorted:\n", " events_at_time = [\n", " (sat_id, event)\n", " for sat_id, event in events\n", " if event[\"time\"] == time_event\n", " ]\n", "\n", " max_quality = max(event[\"quality\"] for _, event in events_at_time)\n", " sat_ids_max_quality = [\n", " sat_id\n", " for sat_id, event in events_at_time\n", " if event[\"quality\"] == max_quality\n", " ]\n", "\n", " scaling_conflict_score = {\n", " sat_id: (\n", " 1.0 / len(sat_ids_max_quality)\n", " if sat_id in sat_ids_max_quality\n", " else 0.0\n", " )\n", " for sat_id, _ in events_at_time\n", " }\n", "\n", " if self.incremental_score:\n", " if target.highest_reward_obtained is None:\n", " highest_reward_obtained = 0\n", " else:\n", " highest_reward_obtained = target.highest_reward_obtained\n", "\n", " highest_new_reward = None\n", " for sat_id, event in events_at_time:\n", " quality = event.get(\"quality\", 0.0)\n", "\n", " step_reward = self.reward_fn(\n", " target.priority, quality, quality_weight=target.quality_weight\n", " )\n", "\n", " if self.incremental_score:\n", " if (\n", " highest_new_reward is None\n", " or step_reward > highest_new_reward\n", " ):\n", " highest_new_reward = step_reward\n", " step_reward = max(0.0, step_reward - highest_reward_obtained)\n", "\n", " step_reward = step_reward * scaling_conflict_score.get(sat_id, 0.0)\n", "\n", " reward[sat_id] += step_reward\n", "\n", " self._update_event_reward_info(\n", " event,\n", " target,\n", " target.quality_weight,\n", " step_reward,\n", " rewarded=step_reward > 0.0,\n", " )\n", "\n", " if (\n", " self.incremental_score\n", " and highest_new_reward > highest_reward_obtained\n", " ):\n", " target.highest_reward_obtained = highest_new_reward\n", " target.highest_reward_time = time_event\n", "\n", " return reward" ] }, { "cell_type": "markdown", "id": "hybrid-quality-06", "metadata": {}, "source": [ "## Satellite and observations\n", "\n", "Following the paper's observation representation, a quadratic B-spline approximates the estimated marginal reward over each remaining observation window. Its five coefficients are passed to the agent.\n", "\n", "The observation has 32 satellite/context features (12 spacecraft properties and 20 priority-density bins), followed by 40 target tokens with 12 features each: five reward-spline coefficients, relative position (3), pointing angle, angular rate, and opening and closing offsets. Both the spline and action wrapper parameterize the **remaining** window, using the current time as the start when the window is already open. The action wrapper enforces a minimum delay of 0.5 seconds. Opening offsets in the observation remain signed and can therefore be negative for an already-open window.\n", "\n", "`PriorityDensity` is a custom observation class that summarizes future imaging opportunities in 20 consecutive 180-second bins. Each target contributes its priority, divided by five, to the bin containing the closing time of its next available window. This provides context about upcoming opportunities beyond the 40 targets represented individually.\n", "\n", "`TargetBookkeeping` stores the best completed reward known for each target and, when the communication mode uses them, competing intended rewards. Its combined baseline is the larger of the completed and intended values. An intent changes the expected marginal benefit of an acquisition; it does not count as a completed image or increase the obtained reward.\n", "\n", "`estimate_quality_profile` samples absolute predicted reward at 25 times over the remaining window, subtracts the satellite's current bookkeeping baseline, and clips the result to [0, 1] before fitting the spline. With empty bookkeeping, the baseline is zero. Absolute predictions are cached, but the baseline is read on every call. The coordination loop updates bookkeeping and clears the observation cache before requesting a new observation, so the spline values change while the observation dimensions remain fixed." ] }, { "cell_type": "code", "execution_count": 5, "id": "hybrid-quality-07", "metadata": {}, "outputs": [], "source": [ "class PriorityDensity(obs.Observation):\n", " \"\"\"Priority sums in twenty future 180-second opportunity-closing bins.\"\"\"\n", "\n", " def __init__(self):\n", " super().__init__(name=\"priority_density\")\n", "\n", " def get_obs(self):\n", " now = self.simulator.sim_time\n", " self.satellite.calculate_additional_windows(\n", " now + 21 * 180 - self.satellite.window_calculation_time\n", " )\n", " upcoming = self.satellite.upcoming_opportunities_dict(types=\"target\")\n", " density = np.zeros(20)\n", " for target, windows in upcoming.items():\n", " index = int(np.floor((windows[0][1] - now) / 180))\n", " if 0 <= index < len(density):\n", " density[index] += target.priority / 5.0\n", " return density\n", "\n", "\n", "class TargetBookkeeping:\n", " def __init__(self):\n", " self._reset()\n", "\n", " def _reset(self):\n", " self.bookkeeping = {}\n", " self.bookkeeping_imaged = {}\n", " self.bookkeeping_intended = {}\n", "\n", " def update(\n", " self,\n", " tgt_id: str,\n", " obtained_reward: float,\n", " time: float,\n", " ) -> None:\n", " if tgt_id not in self.bookkeeping_imaged:\n", " self.bookkeeping_imaged[tgt_id] = {\"reward\": obtained_reward, \"time\": time}\n", "\n", " else:\n", " if obtained_reward > self.bookkeeping_imaged[tgt_id][\"reward\"]:\n", " self.bookkeeping_imaged[tgt_id] = {\n", " \"reward\": obtained_reward,\n", " \"time\": time,\n", " }\n", "\n", " self._update()\n", "\n", " def update_intended(\n", " self,\n", " tgt_id: str,\n", " expected_reward: float,\n", " time: float,\n", " ) -> None:\n", "\n", " if (\n", " tgt_id in self.bookkeeping_imaged\n", " and expected_reward <= self.bookkeeping_imaged[tgt_id][\"reward\"]\n", " ):\n", " return\n", "\n", " if tgt_id not in self.bookkeeping_intended:\n", " self.bookkeeping_intended[tgt_id] = {\n", " \"reward\": expected_reward,\n", " \"time\": time,\n", " }\n", "\n", " else:\n", " if expected_reward > self.bookkeeping_intended[tgt_id][\"reward\"]:\n", " self.bookkeeping_intended[tgt_id] = {\n", " \"reward\": expected_reward,\n", " \"time\": time,\n", " }\n", "\n", " self._update()\n", "\n", " def delete_intended(self):\n", " self.bookkeeping_intended = {}\n", " self._update()\n", "\n", " def _update(self):\n", " self.bookkeeping = copy(self.bookkeeping_imaged)\n", " tgt_ids_imaged = set(self.bookkeeping_imaged.keys())\n", " tgt_ids_intended = set(self.bookkeeping_intended.keys())\n", " for tgt_id in tgt_ids_intended:\n", " if tgt_id not in tgt_ids_imaged:\n", " self.bookkeeping[tgt_id] = self.bookkeeping_intended[tgt_id]\n", " else:\n", " if (\n", " self.bookkeeping_intended[tgt_id][\"reward\"]\n", " > self.bookkeeping_imaged[tgt_id][\"reward\"]\n", " ):\n", " self.bookkeeping[tgt_id] = self.bookkeeping_intended[tgt_id]\n", "\n", " def get_reward(self, tgt_id: str) -> float:\n", " if tgt_id not in self.bookkeeping:\n", " return 0.0\n", " else:\n", " return self.bookkeeping[tgt_id][\"reward\"]\n", "\n", "\n", "def _quality_profile_context(sat):\n", " \"\"\"Cache trajectory data shared by all quality profiles at one simulation step.\"\"\"\n", " trajectory = sat.trajectory\n", " cache_key = (\n", " id(trajectory),\n", " sat.simulator.sim_time,\n", " trajectory.sim_time,\n", " len(trajectory.times),\n", " )\n", " cache = getattr(sat, \"_quality_profile_context\", None)\n", "\n", " if cache is None or cache[\"key\"] != cache_key:\n", " cache = {\n", " \"key\": cache_key,\n", " \"trajectory_r_BP_P\": trajectory.r_BP_P,\n", " \"full_reward_profiles\": {},\n", " }\n", " sat._quality_profile_context = cache\n", "\n", " return cache\n", "\n", "\n", "def estimate_absolute_reward(sat, tgt, times):\n", " \"\"\"Predict acquisition reward without completed or intended reward baselines.\n", "\n", " ``times`` contains absolute simulator times. Use the same trajectory and\n", " quality assumptions as the observation profiles, but do not infer reward\n", " from their clipped marginal splines.\n", " \"\"\"\n", " profile_context = _quality_profile_context(sat)\n", " raw_quality = QUALITY_FUNCTIONS[tgt.quality_function_name](\n", " sat,\n", " tgt,\n", " np.asarray(times, dtype=float),\n", " **tgt.quality_function_params,\n", " trajectory_r_BP_P=profile_context[\"trajectory_r_BP_P\"],\n", " )\n", " return np.asarray(\n", " reward_function(tgt.priority, raw_quality, quality_weight=tgt.quality_weight),\n", " dtype=float,\n", " )\n", "\n", "\n", "def estimate_quality_profile(sat, opp, return_rewards: bool = False):\n", " tgt = opp[\"object\"]\n", " window = opp[\"window\"]\n", " window_open = np.max([window[0], sat.simulator.sim_time])\n", " window_close = window[1]\n", " profile_context = _quality_profile_context(sat)\n", "\n", " profile_key = (\n", " str(tgt.id),\n", " float(window_open),\n", " float(window_close),\n", " )\n", " profile = profile_context[\"full_reward_profiles\"].get(profile_key)\n", "\n", " if profile is None:\n", " times = np.linspace(window_open, window_close, 25)\n", " full_reward = estimate_absolute_reward(sat, tgt, times)\n", " profile = {\n", " \"times\": times,\n", " \"full_reward\": full_reward,\n", " }\n", " profile_context[\"full_reward_profiles\"][profile_key] = profile\n", "\n", " obtained_reward = (\n", " sat.bookkeeping.get_reward(tgt.id) if hasattr(sat, \"bookkeeping\") else 0.0\n", " )\n", "\n", " marginal_reward = np.clip(\n", " profile[\"full_reward\"] - obtained_reward,\n", " a_min=0.0,\n", " a_max=1.0,\n", " )\n", "\n", " if return_rewards:\n", " return marginal_reward\n", "\n", " # Normalize sample times to [0, 1] over the remaining access window.\n", " x_vector = (profile[\"times\"] - window_open) / (window_close - window_open)\n", "\n", " spline = make_lsq_spline(x_vector, marginal_reward, t=SPLINE_KNOTS, k=SPLINE_DEGREE)\n", "\n", " return spline.c" ] }, { "cell_type": "markdown", "id": "22e1ea2d", "metadata": {}, "source": [ "### Define the satellite\n", "\n", "`QualitySatellite` combines the spacecraft dynamics and flight software with the observations defined above. Its observation specification includes spacecraft properties, `PriorityDensity`, and the next `N_AHEAD` target opportunities. The opportunity callback uses `estimate_quality_profile` to supply the five reward-spline coefficients alongside each target's geometry and window offsets. Each satellite has its own bookkeeping, which is cleared when the environment resets.\n", "\n", "The action specification uses `act.Image(n_ahead_image=N_AHEAD, hybrid=True)`. This enables a native imaging action containing a target-opportunity index and a desired acquisition delay in seconds. The wrappers below expose normalized timing fractions and, optionally, a categorical action over target/timing pairs. `satellite_args` supplies the orbit, pointing constraints, timing tolerances, and spacecraft resource settings shared by training and evaluation.\n" ] }, { "cell_type": "code", "execution_count": 6, "id": "6e515629", "metadata": {}, "outputs": [], "source": [ "from functools import partial\n", "\n", "\n", "class QualitySatellite(sats.ImagingSatellite):\n", " dyn_type = dyn.FullFeaturedDynModel\n", " fsw_type = fsw.SteeringImagerFSWModel\n", " observation_spec: ClassVar = [\n", " obs.SatProperties(\n", " dict(prop=\"omega_BN_B\", norm=0.03),\n", " dict(prop=\"c_hat_H\"),\n", " dict(prop=\"r_BN_P\", norm=EARTH_RADIUS),\n", " dict(prop=\"v_BN_P\", norm=7616.5),\n", " ),\n", " PriorityDensity(),\n", " obs.OpportunityProperties(\n", " dict(fn=partial(estimate_quality_profile)),\n", " dict(prop=\"r_LB_H\", norm=EARTH_RADIUS),\n", " dict(prop=\"target_angle\", norm=np.pi / 2),\n", " dict(prop=\"target_angle_rate\", norm=0.03),\n", " dict(prop=\"opportunity_open\", norm=300),\n", " dict(prop=\"opportunity_close\", norm=300),\n", " n_ahead_observe=N_AHEAD,\n", " ),\n", " ]\n", " action_spec: ClassVar = [act.Image(n_ahead_image=N_AHEAD, hybrid=True)]\n", "\n", " def __init__(self, *args, **kwargs):\n", " super().__init__(*args, **kwargs)\n", " self.bookkeeping = TargetBookkeeping()\n", "\n", " def reset_pre_sim_init(self) -> None:\n", " super().reset_pre_sim_init()\n", " self.bookkeeping._reset()\n", "\n", "\n", "def satellite_args():\n", " return QualitySatellite.default_sat_args(\n", " oe=lambda: random_circular_orbit(alt=ALTITUDE_KM, i=45),\n", " imageAttErrorRequirement=0.01,\n", " imageRateErrorRequirement=0.01,\n", " imageTargetMinimumElevation=np.arctan(800 / 500),\n", " timeToleranceLower=1.0, # Seconds; BSK-RL converts to nanoseconds.\n", " timeToleranceUpper=0.0, # Zero disables the upper bound, allowing late capture.\n", " u_max=0.4,\n", " K1=0.25,\n", " K3=3.0,\n", " servo_P=30,\n", " omega_max=np.radians(5),\n", " rwBasePower=20,\n", " disturbance_vector=np.zeros(3),\n", " batteryStorageCapacity=80 * 3600 * 2 * 1000,\n", " storedCharge_Init=0.99 * 80 * 3600 * 2 * 1000,\n", " maxWheelSpeed=15000,\n", " wheelSpeeds=lambda: np.random.uniform(-1, 1, 3),\n", " dataStorageCapacity=2 * 8e6 * 25 * 1000,\n", " storageInit=0,\n", " transmitterPacketSize=0,\n", " )" ] }, { "cell_type": "markdown", "id": "hybrid-quality-08", "metadata": {}, "source": [ "## Minimal wrappers and environment factory\n", "\n", "With `hybrid=True` and at least one imaging time tolerance enabled, the native imaging action accepts a target index and a desired acquisition delay in seconds. This delay specifies when to try to acquire the image; it is not the exposure duration. If both tolerances are zero, the continuous value instead specifies the maximum imaging action duration in seconds, capped by `max_duration` and with a minimum of one simulator time step. The wrappers let a policy select a target and a normalized position within its remaining observation window.\n", "\n", "### From a discrete option to a target and timing fraction\n", "\n", "Let $N$ be the number of upcoming target opportunities and let $F=(F_0,\\ldots,F_{D-1})$ contain $D$ predefined timing fractions. The policy selects one categorical action $a\\in\\{0,\\ldots,ND-1\\}$. `WrapperDiscreteToHybridAction` decodes it as\n", "\n", "$$\n", "i=\\left\\lfloor\\frac{a}{D}\\right\\rfloor,\\qquad\n", "k=a\\bmod D,\\qquad f=F_k.\n", "$$\n", "\n", "Here $i$ is the zero-based target-opportunity index and $k$ is the timing-option index. The inverse mapping is $a=iD+k$. Timing options vary fastest within each target. With `N_AHEAD=40` and `IMAGING_FRACTIONS=(0.0, 0.5, 1.0)`, each satellite has `Discrete(120)`:\n", "\n", "| Discrete action | Target index | Timing fraction |\n", "|---|---|---|\n", "| 6 | 2 | 0.0 |\n", "| 7 | 2 | 0.5 |\n", "| 8 | 2 | 1.0 |\n", "\n", "The actor therefore needs a categorical distribution over 120 choices. Although these choices are translated into real-valued delays, the policy only chooses among the three listed fractions; it does not output an arbitrary continuous timing value.\n", "\n", "### From a timing fraction to seconds\n", "\n", "For current simulation time $t_{\\mathrm{now}}$ and the selected opportunity's physical window $[t_{\\mathrm{open}},t_{\\mathrm{close}}]$, define the remaining opening and closing offsets\n", "\n", "$$\n", "u=\\max(0,t_{\\mathrm{open}}-t_{\\mathrm{now}}),\\qquad\n", "v=t_{\\mathrm{close}}-t_{\\mathrm{now}}.\n", "$$\n", "\n", "`WrapperActionDuration` clips $f$ to $[0,1]$ and returns\n", "\n", "$$\n", "\\Delta t_{\\mathrm{img}}=\\max\\bigl(0.5,\\;u+f(v-u)\\bigr),\\qquad\n", "t_d=t_{\\mathrm{now}}+\\Delta t_{\\mathrm{img}}.\n", "$$\n", "\n", "The native action receives `(i, delta_t_img)` and the controller uses the absolute desired acquisition time $t_d$. For example, if the current time is 100 seconds and target opportunity 2 spans [120, 180] seconds, action 7 selects the midpoint: a 50-second delay and a desired acquisition time of 150 seconds. If the window instead spans [90, 140] seconds, the same fraction selects the midpoint of the remaining window: a 20-second delay and a desired acquisition time of 120 seconds. Fraction zero requests the earliest remaining time, subject to the 0.5-second minimum delay.\n", "\n", "The wrapper stack processes actions in this order:\n", "\n", "```text\n", "discrete action a\n", " -> WrapperDiscreteToHybridAction: (target index i, fraction f)\n", " -> WrapperActionDuration: (target index i, delay in seconds)\n", " -> WrapperActionLogging\n", " -> native imaging action: absolute desired time = now + delay\n", "```\n", "\n", "For a constellation, this conversion is applied separately to each supplied entry in the satellite-name action dictionary.\n", "\n", "### Acquisition tolerances and action limits\n", "\n", "Acquisition also requires the pointing-angle and angular-rate constraints to be satisfied. When both timing bounds are enabled, the allowed acquisition times satisfy\n", "\n", "$$\n", "t_d-\\tau_{\\mathrm{lower}}\\leq t\\leq t_d+\\tau_{\\mathrm{upper}},\n", "$$\n", "\n", "where the positive tolerances are configured in seconds through `timeToleranceLower` and `timeToleranceUpper`. A zero tolerance disables its corresponding bound independently. The current settings, `timeToleranceLower=1.0` and `timeToleranceUpper=0.0`, allow acquisition from one second before $t_d$ onward, without an instrument upper timing bound. A late acquisition is therefore possible if the pointing requirements are met later. Setting both tolerances to zero removes both timing gates and makes the continuous action value a maximum imaging duration. The action can finish sooner if an image is captured. The mode is selected once per environment reset from the initialized controller tolerances, which must remain fixed during an episode; enabling either bound emits a warning explaining the capture-time interpretation.\n", "\n", "Physical access, action-duration limits, and simulation stepping still apply. A positive upper tolerance also lets the native imaging action limit its timeout using the requested delay plus that tolerance. With the upper tolerance disabled, this example retains the physical window and existing action/environment limits; the fraction does not impose a new upper deadline.\n" ] }, { "cell_type": "code", "execution_count": 7, "id": "hybrid-quality-09", "metadata": {}, "outputs": [], "source": [ "from bsk_rl.gym import is_no_action\n", "\n", "\n", "def clean_action(\n", " action: tuple[int, float | np.ndarray | list],\n", ") -> tuple[int, float]:\n", " if action is None:\n", " return None\n", " discrete = action[0].item() if isinstance(action[0], np.generic) else action[0]\n", " val = action[1][0] if isinstance(action[1], (list, np.ndarray)) else action[1]\n", " continuous = val.item() if isinstance(val, np.generic) else val\n", "\n", " return (discrete, continuous)\n", "\n", "\n", "class WrapperActionDuration(gym.ActionWrapper):\n", " \"\"\"Convert a fraction into an acquisition delay over the remaining window.\n", "\n", " The returned delay is in seconds and has a minimum of 0.5 seconds.\n", " \"\"\"\n", "\n", " def __init__(\n", " self,\n", " env,\n", " ) -> None:\n", " super().__init__(env)\n", " self.env = env\n", "\n", " self._n_ahead = {}\n", " for sat in self.env.satellites:\n", " obs_class = next(\n", " item\n", " for item in sat.observation_spec\n", " if isinstance(item, (obs.OpportunityProperties))\n", " and item.type == \"target\"\n", " )\n", " self._n_ahead[sat.name] = obs_class.n_ahead_observe\n", "\n", " def get_image_window(\n", " self, target_index: int, sat_name: str | None\n", " ) -> tuple[float, float]:\n", "\n", " if sat_name is not None:\n", " sat = next(sat for sat in self.unwrapped.satellites if sat.name == sat_name)\n", " else:\n", " sat = self.unwrapped.satellite\n", "\n", " opps = sat.find_next_opportunities(\n", " n=self._n_ahead[sat.name],\n", " types=\"target\",\n", " pad=True,\n", " )\n", "\n", " if isinstance(target_index, (int, np.integer)):\n", " opp = opps[target_index]\n", " else:\n", " opp = [\n", " tgt_i\n", " for tgt_i in opps\n", " if not isinstance(tgt_i[\"object\"], str)\n", " and tgt_i[\"object\"].id == target_index\n", " ]\n", " if len(opp) > 0:\n", " opp = opp[0]\n", " else:\n", " for i in range(5):\n", " opps = sat.find_next_opportunities(\n", " n=self._n_ahead[sat.name] * (i + 1),\n", " types=\"target\",\n", " pad=True,\n", " )\n", " opp = [\n", " tgt_i\n", " for tgt_i in opps\n", " if not isinstance(tgt_i[\"object\"], str)\n", " and tgt_i[\"object\"].id == target_index\n", " ]\n", " if len(opp) > 0:\n", " opp = opp[0]\n", " break\n", "\n", " window_start = opp[\"window\"][0] - self.unwrapped.simulator.sim_time\n", " window_start = np.max([window_start, 0.0])\n", " window_end = opp[\"window\"][1] - self.unwrapped.simulator.sim_time\n", "\n", " return (window_start, window_end)\n", "\n", " def get_imaging_time(\n", " self, target_index: int, window_fraction: float, sat_name: str | None\n", " ) -> float:\n", " window_start, window_end = self.get_image_window(target_index, sat_name)\n", " window_fraction = np.clip(window_fraction, 0.0, 1.0)\n", " return np.clip(\n", " float(window_start + (window_end - window_start) * window_fraction),\n", " 0.5,\n", " np.inf,\n", " )\n", "\n", " def _set_action_duration(\n", " self, action, sat_name: str | None\n", " ) -> str | None | tuple[int, float]:\n", " if isinstance(action, str) or action is None:\n", " return action\n", "\n", " action = clean_action(action)\n", " target_index = action[0]\n", " duration = self.get_imaging_time(target_index, action[1], sat_name)\n", "\n", " return (action[0], float(duration))\n", "\n", " def action(\n", " self, action: tuple[int, float]\n", " ) -> tuple[int, float] | dict | str | None:\n", "\n", " if isinstance(action, dict):\n", " action_dict = {}\n", " for sat_name, sat_action in action.items():\n", " action_dict[sat_name] = self._set_action_duration(sat_action, sat_name)\n", " return action_dict\n", "\n", " else:\n", " return self._set_action_duration(action, None)\n", "\n", "\n", "class WrapperDiscreteToHybridAction(gym.ActionWrapper, gym.Wrapper):\n", " \"\"\"Decode a categorical choice into a target index and imaging fraction.\n", "\n", " Timing options vary fastest within each target: action = target * D + timing.\n", "\n", " Args:\n", " env: Imaging environment with a native hybrid action space.\n", " discrete_imaging_fraction: Predefined timing fractions for each target.\n", " \"\"\"\n", "\n", " def __init__(\n", " self,\n", " env,\n", " discrete_imaging_fraction: Iterable[float],\n", " ) -> None:\n", " super().__init__(env)\n", " self.discrete_imaging_fraction = list(discrete_imaging_fraction)\n", " self.discretization = len(self.discrete_imaging_fraction)\n", " self.env = env\n", " if not isinstance(env.action_space, gym.spaces.Tuple):\n", " action_space = env.action_spaces\n", " # Assumes all satellites have the same action space\n", " self.n_hybrid_actions = action_space[env.satellites[0].name][0].n\n", " else:\n", " action_space = env.action_space[0]\n", " self.n_hybrid_actions = action_space.n\n", " self.n_discrete_actions = self.n_hybrid_actions * self.discretization\n", " space = gym.spaces.Discrete(self.n_discrete_actions)\n", " if isinstance(env.action_space, gym.spaces.Tuple):\n", " self.action_space = space\n", " else:\n", " self.action_space = lambda sat_name: space\n", "\n", " def _split_action(self, action):\n", " if action is None or is_no_action(action):\n", " return None\n", "\n", " action = int(action)\n", " if not 0 <= action < self.n_discrete_actions:\n", " raise ValueError(\n", " f\"Action index {action} out of range for {self.n_discrete_actions} choices.\"\n", " )\n", " target_index, continuous_action = divmod(action, self.discretization)\n", " return (target_index, self.discrete_imaging_fraction[continuous_action])\n", "\n", " def action(\n", " self, action: int | dict\n", " ) -> (\n", " tuple[int, float]\n", " | tuple[str, float]\n", " | dict[str, tuple[int, float]]\n", " | dict[str, tuple[str, float]]\n", " | None\n", " ):\n", " if isinstance(action, dict):\n", " action_dict = {}\n", " for sat_name, sat_action in action.items():\n", " action_dict[sat_name] = self._split_action(sat_action)\n", " return action_dict\n", " else:\n", " return self._split_action(action)\n", "\n", "\n", "class WrapperActionLogging(gym.Wrapper):\n", " def __init__(self, env):\n", "\n", " super().__init__(env)\n", " self.env = env\n", "\n", " if not isinstance(env.action_space, gym.spaces.Tuple):\n", " action_space = env.action_spaces\n", " self.n_discrete = action_space[env.satellites[0].name][0].n\n", " else:\n", " action_space = env.action_space\n", " self.n_discrete = action_space[0].n\n", "\n", " self._initialize_action_logger()\n", "\n", " def _initialize_action_logger(self):\n", "\n", " self.action_duration_logger_list = {\n", " sat.name: {\n", " \"duration_image\": [],\n", " }\n", " for sat in self.env.satellites\n", " }\n", "\n", " self.action_log_discrete_count = {i: 0 for i in range(self.n_discrete)}\n", " self.action_duration_log = {i: 0.0 for i in range(self.n_discrete)}\n", "\n", " def return_loggers(self):\n", "\n", " duration_list_image_all = [\n", " self.action_duration_logger_list[sat.name][\"duration_image\"]\n", " for sat in self.env.satellites\n", " ]\n", "\n", " return {\n", " \"action_log_discrete_count\": self.action_log_discrete_count,\n", " \"action_duration_log\": self.action_duration_log,\n", " \"action_duration_logger_list\": self.action_duration_logger_list,\n", " \"action_duration_image_list_all\": np.concatenate(duration_list_image_all),\n", " }\n", "\n", " def reset(self, *, seed: int | None = None, options: dict[str, Any] | None = None):\n", " self._initialize_action_logger()\n", " return self.env.reset(seed=seed, options=options)\n", "\n", " def _store_action_info(self, action: tuple[int, float], sat_name: str):\n", "\n", " action = clean_action(action)\n", " if action is None:\n", " return\n", "\n", " self.action_duration_logger_list[sat_name][\"duration_image\"].append(action[1])\n", "\n", " if isinstance(action[0], str):\n", " return\n", " discrete_action = int(action[0])\n", " self.action_log_discrete_count[discrete_action] += 1\n", " self.action_duration_log[discrete_action] += (\n", " action[1] - self.action_duration_log[discrete_action]\n", " ) / self.action_log_discrete_count[discrete_action]\n", "\n", " def step(self, action: dict | tuple[int, float]):\n", "\n", " if isinstance(action, dict):\n", " for sat_name, sat_action in action.items():\n", " self._store_action_info(sat_action, sat_name)\n", " else:\n", " self._store_action_info(action, self.env.satellite.name)\n", "\n", " return self.env.step(action)\n", "\n", "\n", "ENV_CONFIG = dict(\n", " n_targets=(100, 3000),\n", " orbits=3,\n", " quality_weight=(0.0, 1.0), # Scalar for a common weight; 0.0 disables quality.\n", " quality_types=(\"quality_off_nadir_angle\", \"quality_periodic\"),\n", ")\n", "\n", "\n", "def reward_function(priority, quality, quality_weight=0.5):\n", "\n", " quality_weight = np.clip(quality_weight, 0.0, 1.0)\n", "\n", " quality = (1 - quality_weight) + quality_weight * np.clip(\n", " quality, a_min=0.0, a_max=1.0\n", " )\n", " reward = priority * quality\n", "\n", " return reward" ] }, { "cell_type": "markdown", "id": "bafcc03a", "metadata": {}, "source": [ "### Create consistent training and evaluation environments\n", "\n", "`make_env` combines the target scenario, rewarder, and simulation settings from a common configuration. In evaluation mode it returns a `ConstellationTasking` environment with the requested number of satellites, including a per-satellite dictionary interface when only one satellite is used. With `train=True`, it returns the construction arguments for a single-satellite `SatelliteTasking` environment; the RLlib wrapper below uses these arguments to instantiate the training environment.\n", "\n", "`setup_wrapper_stack` then adds duration logging and converts a normalized imaging fraction into a delay in seconds. Setting `discrete_action_space=True` also adds the outer wrapper that decodes an integer into a target and one of the supplied timing fractions. Keeping environment construction and action conversion in these helpers makes the settings and action convention explicit when creating a training or evaluation instance.\n" ] }, { "cell_type": "code", "execution_count": 8, "id": "cc633071", "metadata": {}, "outputs": [], "source": [ "def make_env(\n", " env_config=None,\n", " n_sats=1,\n", " incremental_score=False,\n", " n_targets: int | None = None,\n", " train: bool = False,\n", " time_limit: float | None = None,\n", "):\n", " config = {**ENV_CONFIG, **dict(env_config or {})}\n", " env_config = dict(\n", " scenario=QualityTargets(\n", " n_targets=config[\"n_targets\"] if n_targets is None else n_targets,\n", " quality_weights=config[\"quality_weight\"],\n", " quality_function_name=config[\"quality_types\"],\n", " ),\n", " rewarder=QualityImageReward(\n", " reward_fn=reward_function, incremental_score=incremental_score\n", " ),\n", " sim_rate=SIM_RATE,\n", " max_step_duration=500.0,\n", " time_limit=config[\"orbits\"] * ORBIT_PERIOD\n", " if time_limit is None\n", " else time_limit,\n", " failure_penalty=0.0,\n", " log_level=\"INFO\",\n", " )\n", " if train:\n", " # Training uses a single satellite configuration\n", " env_config.update(\n", " dict(satellite=QualitySatellite(\"EO\", sat_args=satellite_args()))\n", " )\n", " return env_config\n", " else:\n", " env = ConstellationTasking(\n", " satellites=[\n", " QualitySatellite(f\"EO_{i}\", sat_args=satellite_args())\n", " for i in range(n_sats)\n", " ],\n", " **env_config,\n", " )\n", " return env\n", "\n", "\n", "def setup_wrapper_stack(\n", " env,\n", " discrete_action_space=False,\n", " discrete_imaging_fraction=None,\n", "):\n", "\n", " env = WrapperActionLogging(env)\n", " env = WrapperActionDuration(env)\n", " if discrete_action_space:\n", " env = WrapperDiscreteToHybridAction(\n", " env,\n", " discrete_imaging_fraction=discrete_imaging_fraction,\n", " )\n", "\n", " return env" ] }, { "cell_type": "markdown", "id": "hybrid-quality-10", "metadata": {}, "source": [ "## Try a few imaging actions\n", "\n", "This short rollout selects target opportunity 0, the first upcoming opportunity, and requests the midpoint of its remaining access window with `(0, 0.5)`. It uses `discrete_action_space=False`, so the action contains a target index and a timing fraction directly. The action is supplied in a dictionary keyed by satellite name, and the duration wrapper converts the fraction into seconds. This exercises the physical environment without RLlib or a trained checkpoint. Increase the loop length to run a longer rollout.\n" ] }, { "cell_type": "code", "execution_count": 9, "id": "hybrid-quality-11", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[90;3m2026-10-26 21:02:03,844 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[mResetting environment with seed=3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:03,846 \u001b[0m\u001b[mscene.targets \u001b[0m\u001b[mINFO \u001b[0m\u001b[mGenerating 1742 targets\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,129 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mFinding opportunity windows from 0.00 to 18600.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,419 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[mEnvironment reset\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,421 \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;3m2026-10-26 21:02:04,422 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,422 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Villa Aberastain, AR) imaging timing: requested capture at 417.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,423 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Villa Aberastain, AR) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,424 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Villa Aberastain, AR) window enabled: 374.8 to 459.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,425 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 459.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,503 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Villa Aberastain, AR)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,505 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.024999692474987952)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,506 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[mOptimizing data communication between all pairs of satellites\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,506 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,537 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.024999692474987952)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,538 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,539 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,542 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Recreo, AR) imaging timing: requested capture at 458.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,544 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Recreo, AR) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,547 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Recreo, AR) window enabled: 366.0 to 500.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,547 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<417.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 500.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,561 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Recreo, AR)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,562 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.49907471357643646)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,563 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[mOptimizing data communication between all pairs of satellites\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,564 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,594 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.49907471357643646)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,595 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,596 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,596 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Huinca Renancó, AR) imaging timing: requested capture at 500.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,597 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Huinca Renancó, AR) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,598 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Huinca Renancó, AR) window enabled: 467.5 to 533.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,598 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<461.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 533.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,608 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Huinca Renancó, AR)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,608 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.3474319715528675)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,609 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[mOptimizing data communication between all pairs of satellites\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,610 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,642 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.3474319715528675)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,643 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,644 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,645 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Romang, AR) imaging timing: requested capture at 525.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,645 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Romang, AR) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,646 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Romang, AR) window enabled: 463.8 to 540.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,647 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<510.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 540.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,657 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 540.6 for Target(Romang, AR) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,658 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,658 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[mOptimizing data communication between all pairs of satellites\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,659 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,686 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,687 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,687 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,688 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rufino, AR) imaging timing: requested capture at 556.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,688 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rufino, AR) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,689 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rufino, AR) window enabled: 457.1 to 571.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,690 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<541.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 571.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,700 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<571.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 571.5 for Target(Rufino, AR) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,701 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<571.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,701 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<571.50> \u001b[0m\u001b[mOptimizing data communication between all pairs of satellites\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,702 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<571.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:04,731 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<571.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n" ] } ], "source": [ "env = make_env()\n", "\n", "env = setup_wrapper_stack(\n", " env,\n", " discrete_action_space=False,\n", " discrete_imaging_fraction=IMAGING_FRACTIONS,\n", ")\n", "\n", "observation, info = env.reset(seed=3)\n", "try:\n", " for _ in range(5):\n", " # Each satellite receives (target index, window fraction).\n", " # With the discrete wrapper, each dictionary value is an action index.\n", " action = {env.satellites[0].name: (0, 0.5)}\n", " observation, reward, terminated, truncated, info = env.step(action)\n", " if all(terminated.values()) or all(truncated.values()):\n", " break\n", "finally:\n", " env.close()" ] }, { "cell_type": "markdown", "id": "hybrid-quality-12", "metadata": {}, "source": [ "## Categorical policy over target/timing pairs\n", "\n", "Because timing choices are discrete, the policy only needs RLlib's standard `TorchCategorical`. The actor produces one logit per target and timing option, then flattens them into the same target-major order as the wrapper. A single softmax represents the joint distribution $\\pi(i,k\\mid o)$, so timing preferences can depend on the target without a custom conditional distribution class.\n", "\n", "A `MultiDiscrete([N, D])` policy with separate categorical factors would impose independence between target and timing choices. The flattened categorical avoids that restriction. A custom distribution would become useful if capture times were continuous and conditioned on the chosen target.\n" ] }, { "cell_type": "code", "execution_count": 10, "id": "hybrid-quality-13", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "2026-10-26 21:02:05,406\tINFO util.py:154 -- Missing packages: ['ipywidgets']. Run `pip install -U ipywidgets`, then restart the notebook server for rich notebook output.\n", "2026-10-26 21:02:07,388\tINFO util.py:154 -- Missing packages: ['ipywidgets']. Run `pip install -U ipywidgets`, then restart the notebook server for rich notebook output.\n" ] } ], "source": [ "from ray.rllib.algorithms.ppo import PPOConfig\n", "from ray.rllib.algorithms.ppo.torch.ppo_torch_rl_module import PPOTorchRLModule\n", "from ray.rllib.core import Columns\n", "from ray.rllib.core.rl_module.rl_module import RLModuleSpec\n", "from ray.rllib.models.torch.torch_distributions import TorchCategorical\n", "from ray.rllib.utils.framework import try_import_torch\n", "\n", "from bsk_rl.utils.rllib.discounting import TimeDiscountedGAEPPOTorchLearner\n", "\n", "torch, nn = try_import_torch()" ] }, { "cell_type": "markdown", "id": "hybrid-quality-15", "metadata": {}, "source": [ "## Configurable actor, critic, and combined RL module\n", "\n", "The following definitions construct a custom actor, which outputs $ND$ logits, and a custom critic:\n", "\n", "* **Actor:** separate target and satellite MLPs; multi-head target self-attention with a residual connection and LayerNorm; mean/max target pooling; and one logit per target/timing pair.\n", "* **Critic:** a separate target MLP, mean/max pooling, and an MLP combining these embeddings with the raw satellite/context features to predict a scalar value.\n", "\n", "Both networks accept keyword arguments for their dimensions, depths, activation, and dropout. `HybridQualityModule` combines them and reads those arguments from\n", "RLlib's `model_config_dict`; critic arguments use the `critic_` prefix. The module checks that its target count and timing discretization agree with the environment. The training forward pass returns logits and values so PPO can evaluate the actions stored in its rollout batch." ] }, { "cell_type": "code", "execution_count": 11, "id": "hybrid-quality-16", "metadata": {}, "outputs": [], "source": [ "def build_mlp(\n", " input_size,\n", " width,\n", " depth,\n", " output_size,\n", " *,\n", " act_function=\"ReLU\",\n", " dropout=0.0,\n", " dropout_before_output=0.0,\n", " output_activation=False,\n", "):\n", " \"\"\"Configurable hidden layers, preserving the research parameter layout.\"\"\"\n", " if depth < 0 or width <= 0 or output_size <= 0:\n", " raise ValueError(\"MLP dimensions must be positive and depth nonnegative.\")\n", " activation = getattr(nn, act_function)\n", " layers = []\n", " for _ in range(depth):\n", " layers.extend([nn.Linear(input_size, width), activation()])\n", " if dropout:\n", " layers.append(nn.Dropout(dropout))\n", " input_size = width\n", " if dropout_before_output:\n", " layers.append(nn.Dropout(dropout_before_output))\n", " layers.append(nn.Linear(input_size, output_size))\n", " if output_activation:\n", " layers.append(activation())\n", " return nn.Sequential(*layers)\n", "\n", "\n", "class TargetSelfAttention(nn.Module):\n", " def __init__(self, input_dim, attention_dim, num_heads):\n", " super().__init__()\n", " if num_heads <= 0 or attention_dim <= 0 or attention_dim % num_heads:\n", " raise ValueError(\n", " \"attention_dim must be positive and divisible by num_heads.\"\n", " )\n", " self.num_heads = num_heads\n", " self.head_dim = attention_dim // num_heads\n", " self.attention_dim = attention_dim\n", " self.qkv = nn.Linear(input_dim, 3 * attention_dim, bias=False)\n", " self.out = nn.Linear(attention_dim, input_dim, bias=False)\n", "\n", " def forward(self, tokens):\n", " batch_size, n_targets, _ = tokens.shape\n", " qkv = self.qkv(tokens).view(\n", " batch_size, n_targets, 3, self.num_heads, self.head_dim\n", " )\n", " q, k, v = qkv.permute(2, 0, 3, 1, 4).unbind(dim=0)\n", " attended = nn.functional.scaled_dot_product_attention(\n", " q, k, v, dropout_p=0.0, is_causal=False\n", " )\n", " attended = (\n", " attended.transpose(1, 2)\n", " .contiguous()\n", " .view(batch_size, n_targets, self.attention_dim)\n", " )\n", " return self.out(attended)\n", "\n", "\n", "class ImagingActor(nn.Module):\n", " def __init__(\n", " self,\n", " target_size,\n", " context_size,\n", " n_times,\n", " *,\n", " width_phi=256,\n", " depth_phi=2,\n", " tgt_encoded_dim=64,\n", " attention_dim=64,\n", " num_heads=2,\n", " width_phi_sat=256,\n", " depth_phi_sat=2,\n", " sat_encoded_dim=64,\n", " width_psi_img=128,\n", " depth_psi_img=4,\n", " act_function=\"ReLU\",\n", " dropout=0.0,\n", " psi_img_dropout_last_layer=0.1,\n", " ):\n", " super().__init__()\n", " self.phi = build_mlp(\n", " target_size,\n", " width_phi,\n", " depth_phi,\n", " tgt_encoded_dim,\n", " act_function=act_function,\n", " dropout=dropout,\n", " )\n", " self.self_attention = TargetSelfAttention(\n", " tgt_encoded_dim, attention_dim, num_heads\n", " )\n", " self.norm_self_attention = nn.LayerNorm(tgt_encoded_dim)\n", " self.psi_img = build_mlp(\n", " 3 * tgt_encoded_dim + sat_encoded_dim,\n", " width_psi_img,\n", " depth_psi_img,\n", " tgt_encoded_dim,\n", " act_function=act_function,\n", " dropout=dropout,\n", " dropout_before_output=psi_img_dropout_last_layer,\n", " output_activation=True,\n", " )\n", " self.out_layer_psi_img = nn.Linear(tgt_encoded_dim, n_times)\n", " self.phi_sat = build_mlp(\n", " context_size,\n", " width_phi_sat,\n", " depth_phi_sat,\n", " sat_encoded_dim,\n", " act_function=act_function,\n", " dropout=dropout,\n", " )\n", "\n", " def forward(self, context, targets):\n", " tokens = self.phi(targets)\n", " satellite = self.phi_sat(context)\n", " tokens = self.norm_self_attention(tokens + self.self_attention(tokens))\n", " n_targets = tokens.shape[1]\n", " mean_targets = tokens.mean(dim=1, keepdim=True).expand(-1, n_targets, -1)\n", " max_targets = tokens.max(dim=1, keepdim=True).values.expand(-1, n_targets, -1)\n", " features = torch.cat(\n", " [\n", " tokens,\n", " mean_targets,\n", " max_targets,\n", " satellite.unsqueeze(1).expand(-1, n_targets, -1),\n", " ],\n", " dim=-1,\n", " )\n", " logits = self.out_layer_psi_img(self.psi_img(features))\n", " return logits.flatten(start_dim=1)\n", "\n", "\n", "class ImagingCritic(nn.Module):\n", " def __init__(\n", " self,\n", " target_size,\n", " context_size,\n", " *,\n", " width_phi=256,\n", " depth_phi=2,\n", " tgt_encoded_dim=128,\n", " width_psi=64,\n", " depth_psi=3,\n", " act_function=\"ReLU\",\n", " dropout=0.0,\n", " ):\n", " super().__init__()\n", " self.phi = build_mlp(\n", " target_size,\n", " width_phi,\n", " depth_phi,\n", " tgt_encoded_dim,\n", " act_function=act_function,\n", " dropout=dropout,\n", " )\n", " self.psi = build_mlp(\n", " context_size + 2 * tgt_encoded_dim,\n", " width_psi,\n", " depth_psi,\n", " 1,\n", " act_function=act_function,\n", " dropout=dropout,\n", " )\n", "\n", " def forward(self, context, targets):\n", " tokens = self.phi(targets)\n", " features = torch.cat(\n", " [context, tokens.mean(dim=1), tokens.max(dim=1).values], dim=-1\n", " )\n", " return self.psi(features).squeeze(-1)\n", "\n", "\n", "class HybridQualityModule(PPOTorchRLModule):\n", " \"\"\"Combine independently configurable actor and critic heads for PPO.\"\"\"\n", "\n", " def setup(self):\n", " config = self.config.model_config_dict\n", " self.n_targets = int(config[\"n_targets\"])\n", " self.context_size = int(config[\"obs_sat\"])\n", " self.n_times = int(config[\"discretization\"])\n", " target_features = self.config.observation_space.shape[0] - self.context_size\n", " if (\n", " self.n_targets <= 0\n", " or self.context_size < 0\n", " or target_features <= 0\n", " or target_features % self.n_targets\n", " ):\n", " raise ValueError(\n", " \"Observation size must match context plus equal target tokens.\"\n", " )\n", " self.target_size = target_features // self.n_targets\n", " if (\n", " not isinstance(self.config.action_space, gym.spaces.Discrete)\n", " or self.n_times <= 0\n", " or self.config.action_space.n != self.n_targets * self.n_times\n", " ):\n", " raise ValueError(\"Expected Discrete(n_targets * discretization) actions.\")\n", " actor_keys = (\n", " \"width_phi\",\n", " \"depth_phi\",\n", " \"tgt_encoded_dim\",\n", " \"attention_dim\",\n", " \"num_heads\",\n", " \"width_phi_sat\",\n", " \"depth_phi_sat\",\n", " \"sat_encoded_dim\",\n", " \"width_psi_img\",\n", " \"depth_psi_img\",\n", " \"act_function\",\n", " \"dropout\",\n", " \"psi_img_dropout_last_layer\",\n", " )\n", " self.pi_head = ImagingActor(\n", " self.target_size,\n", " self.context_size,\n", " self.n_times,\n", " **{key: config[key] for key in actor_keys if key in config},\n", " )\n", " self.vf = ImagingCritic(\n", " self.target_size,\n", " self.context_size,\n", " width_phi=config.get(\"critic_width_phi\", 256),\n", " depth_phi=config.get(\"critic_depth_phi\", 2),\n", " tgt_encoded_dim=config.get(\"critic_tgt_encoded_dim\", 128),\n", " width_psi=config.get(\"critic_width_psi\", 64),\n", " depth_psi=config.get(\"critic_depth_psi\", 3),\n", " act_function=config.get(\"act_function\", \"ReLU\"),\n", " dropout=config.get(\"critic_dropout\", config.get(\"dropout\", 0.0)),\n", " )\n", " self.action_dist_cls = TorchCategorical\n", " self._inference_only_state_dict_keys = {}\n", "\n", " def get_initial_state(self):\n", " return {}\n", "\n", " def split_observation(self, batch):\n", " values = batch[Columns.OBS].float()\n", " context = values[:, : self.context_size]\n", " targets = values[:, self.context_size :].reshape(\n", " -1, self.n_targets, self.target_size\n", " )\n", " return context, targets\n", "\n", " def compute_values(self, batch, embeddings=None):\n", " return self.vf(*self.split_observation(batch))\n", "\n", " def _forward_inference(self, batch, **kwargs):\n", " return {\n", " Columns.ACTION_DIST_INPUTS: self.pi_head(*self.split_observation(batch))\n", " }\n", "\n", " def _forward_exploration(self, batch, **kwargs):\n", " return self._forward_train(batch)\n", "\n", " def _forward_train(self, batch, **kwargs):\n", " context, targets = self.split_observation(batch)\n", " return {\n", " Columns.ACTION_DIST_INPUTS: self.pi_head(context, targets),\n", " Columns.VF_PREDS: self.vf(context, targets),\n", " }" ] }, { "cell_type": "markdown", "id": "hybrid-quality-17", "metadata": {}, "source": [ "## PPO configuration\n", "\n", "The configuration below supplies the model dimensions and PPO hyperparameters for three timing options per target. `Env_wrapped` adapts the custom environment for RLlib: it accepts `env_config`, constructs the single-satellite environment, applies the action-wrapper stack, and initializes the optional episode-data logging callbacks. Passing the class directly as `env=Env_wrapped` lets RLlib create each environment instance without registering a separate Gym environment ID.\n", "\n", "`TimeDiscountedGAEPPOTorchLearner` uses the reported step duration `d_ts`, in seconds, to apply the duration-dependent discount $\\gamma^{\\Delta t}$. Here `gamma=0.995` is the per-second factor, and the learner discounts raw capture rewards at the end of each step. The evaluation loop accumulates undiscounted rewards, as in the paper's reported comparisons.\n", "\n", "Defining `ppo_config` does not build or train an algorithm. The inference demonstration at the end of the cell creates a separate wrapped environment and a fresh module with random initial weights, then executes one categorical action. Its output checks the inference interface and does not represent trained-policy performance.\n" ] }, { "cell_type": "code", "execution_count": 12, "id": "hybrid-quality-18", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[90;3m2026-10-26 21:02:08,848 \u001b[0m\u001b[m \u001b[0m\u001b[93mWARNING \u001b[0m\u001b[93mCreating logger for new env on PID=71679. Old environments in process may now log times incorrectly.\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:08,851 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[mResetting environment with seed=7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:08,855 \u001b[0m\u001b[mscene.targets \u001b[0m\u001b[mINFO \u001b[0m\u001b[mGenerating 390 targets\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:08,986 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mFinding opportunity windows from 0.00 to 18600.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,092 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[mEnvironment reset\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,141 \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;3m2026-10-26 21:02:09,142 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 38 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,143 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bougara, DZ) imaging timing: requested capture at 3638.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,144 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bougara, DZ) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,144 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bougara, DZ) window enabled: 3589.0 to 3688.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,145 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 3688.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,234 \u001b[0m\u001b[msim.simulator \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<500.00> \u001b[0m\u001b[mMax step duration reached\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,235 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<500.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,235 \u001b[0m\u001b[mcomm.communication \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<500.00> \u001b[0m\u001b[mOptimizing data communication between all pairs of satellites\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,267 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<500.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "Untrained policy: 115 Target: 38 Imaging fraction: 0.5 Reward: {'EO_0': 0.0}\n" ] } ], "source": [ "from bsk_rl.utils.rllib.callbacks import EpisodeDataLogger\n", "\n", "MODEL_CONFIG = {\n", " \"n_targets\": N_AHEAD,\n", " \"obs_sat\": 32,\n", " \"discretization\": len(IMAGING_FRACTIONS),\n", " \"width_phi\": 256,\n", " \"depth_phi\": 2,\n", " \"tgt_encoded_dim\": 64,\n", " \"attention_dim\": 64,\n", " \"num_heads\": 2,\n", " \"width_phi_sat\": 256,\n", " \"depth_phi_sat\": 2,\n", " \"sat_encoded_dim\": 64,\n", " \"width_psi_img\": 128,\n", " \"depth_psi_img\": 4,\n", " \"act_function\": \"ReLU\",\n", " \"dropout\": 0.0,\n", " \"psi_img_dropout_last_layer\": 0.1,\n", " \"critic_tgt_encoded_dim\": 128,\n", " \"critic_width_phi\": 256,\n", " \"critic_depth_phi\": 2,\n", " \"critic_width_psi\": 64,\n", " \"critic_depth_psi\": 3,\n", "}\n", "TRAINING_CONFIG = {\n", " \"gamma\": 0.995,\n", " \"lr\": [[0, 0.00012122027544761331], [117126, 3.707168645103191e-06]],\n", " \"entropy_coeff\": [[0, 0.047466805372264546], [734487, 0.0]],\n", " \"train_batch_size\": 9000,\n", " \"num_sgd_iter\": 15,\n", " \"lambda_\": 0.8713548569911232,\n", " \"use_kl_loss\": False,\n", " \"clip_param\": 0.24943882616708635,\n", " \"grad_clip\": 0.3104924935285628,\n", " \"vf_clip_param\": 2.0,\n", "}\n", "\n", "\n", "module_spec = RLModuleSpec(\n", " module_class=HybridQualityModule, model_config_dict=dict(MODEL_CONFIG)\n", ")\n", "\n", "\n", "class Env_wrapped(EpisodeDataLogger, gym.Wrapper):\n", " def __init__(self, env_config):\n", "\n", " env_config = dict(env_config)\n", " episode_data_callback = env_config.pop(\"episode_data_callback\", None)\n", " satellite_data_callback = env_config.pop(\"satellite_data_callback\", None)\n", " env_args = make_env(env_config, n_sats=1, train=True)\n", " env = SatelliteTasking(**env_args)\n", " env = WrapperActionLogging(\n", " env,\n", " )\n", " env = WrapperActionDuration(\n", " env,\n", " )\n", " env = WrapperDiscreteToHybridAction(\n", " env,\n", " discrete_imaging_fraction=IMAGING_FRACTIONS,\n", " )\n", " EpisodeDataLogger.__init__(self, episode_data_callback, satellite_data_callback)\n", " gym.Wrapper.__init__(self, env)\n", "\n", "\n", "ppo_config = (\n", " PPOConfig()\n", " .environment(\n", " env=Env_wrapped,\n", " env_config=dict(ENV_CONFIG),\n", " normalize_actions=False,\n", " clip_actions=False,\n", " )\n", " .framework(\"torch\")\n", " .api_stack(\n", " enable_rl_module_and_learner=True,\n", " enable_env_runner_and_connector_v2=True,\n", " )\n", " .env_runners(num_env_runners=0, rollout_fragment_length=32)\n", " .training(learner_class=TimeDiscountedGAEPPOTorchLearner, **TRAINING_CONFIG)\n", " .rl_module(rl_module_spec=module_spec)\n", ")\n", "\n", "env = make_env()\n", "\n", "env = setup_wrapper_stack(\n", " env,\n", " discrete_action_space=True,\n", " discrete_imaging_fraction=IMAGING_FRACTIONS,\n", ")\n", "\n", "env.reset(seed=7)\n", "module = RLModuleSpec(\n", " module_class=HybridQualityModule,\n", " observation_space=env.observation_space(env.satellites[0].name),\n", " action_space=env.action_space(env.satellites[0].name),\n", " model_config_dict=dict(MODEL_CONFIG),\n", ").build()\n", "\n", "\n", "def policy(satellite, *args, **kwargs):\n", " obs = torch.as_tensor(satellite.get_obs())\n", "\n", " module.eval()\n", " with torch.no_grad():\n", " output = module.forward_inference({Columns.OBS: obs[None]})\n", " distribution = module.get_inference_action_dist_cls().from_logits(\n", " output[Columns.ACTION_DIST_INPUTS]\n", " )\n", " action = distribution.to_deterministic().sample()\n", "\n", " return int(action.item())\n", "\n", "\n", "action = policy(env.satellites[0])\n", "\n", "_, reward, _, _, info = env.step({env.satellites[0].name: action})\n", "target_index, timing_index = divmod(action, len(IMAGING_FRACTIONS))\n", "print(\n", " \"Untrained policy:\",\n", " action,\n", " \"Target:\",\n", " target_index,\n", " \"Imaging fraction:\",\n", " IMAGING_FRACTIONS[timing_index],\n", " \"Reward:\",\n", " reward,\n", ")" ] }, { "cell_type": "markdown", "id": "cc0d54d2", "metadata": {}, "source": [ "## Multi-satellite coordination through communication\n", "\n", "A policy trained for one satellite can be evaluated independently on each satellite, with coordination handled by the decision loop below. This example models ideal, instantaneous sharing of completed acquisitions and intended tasks. It does not simulate message transmission delays or communication outages. The `policy` function below uses deterministic inference from the **untrained module** created above; load trained weights to evaluate a learned RL policy.\n", "\n", "An **intent** identifies a target another satellite is currently tasked to image. Reward-aware intents also carry the **expected absolute reward** at the requested acquisition time. This prediction is not an obtained reward and does not guarantee capture at the requested time.\n", "\n", "The human-readable mode names correspond to these `multisat_comm_config[\"mode\"]` values:\n", "\n", "| Mode | Code value | Coordination rule |\n", "|---|---|---|\n", "| **Intent** | `\"intent\"` | Exclude globally imaged targets and targets currently intended by other satellites. A new decision selects from the remaining targets; there is no comparison of competing reward predictions. |\n", "| **Intent-incremental** | `\"incremental_intent\"` | Keep re-imaging candidates when their predicted reward can exceed both the best completed reward and the largest relevant competing intent reward. Store this maximum in bookkeeping and use the clipped marginal profile to test whether an opportunity has a useful improvement. Several satellites may retain intents for the same target; this mode does not forcibly choose a single claimant. |\n", "| **Intent-greedy** | `\"greedy\"` | Exclude globally imaged targets. If a satellite selects an already intended target, compare the two expected **absolute** rewards at their respective requested acquisition times. A strictly larger prediction replaces the previous claimant and schedules that satellite to choose again. Otherwise, temporarily exclude the contested target for the challenger and ask it to choose again. Equal predictions retain the existing claimant. |\n", "| **Intent-greedy-incremental** | `\"greedy_incremental\"` | Use the same conflict-resolution rule as intent-greedy while allowing useful re-imaging. The marginal profile is measured against the best **completed** reward; pending intents are handled by the explicit greedy comparison rather than subtracted from this baseline. |\n", "\n", "The additional `\"imaged\"` mode shares completed acquisitions only: it excludes globally imaged targets without reserving targets through intents. Nonincremental modes are intended to use `incremental_score=False`; the two incremental modes require `incremental_score=True`. Select rewarder scoring explicitly when creating the environment—the communication-mode string does not change it automatically.\n", "\n", "For a given target and the satellite currently choosing an action, intent-incremental computes:\n", "\n", "```python\n", "baseline = max(best_obtained_reward, highest_competing_intent_reward)\n", "marginal_reward = max(absolute_reward_at_t - baseline, 0)\n", "```\n", "\n", "With no competing intent, the baseline is simply the best obtained reward. Intent-greedy-incremental uses that completed-reward baseline and resolves competing intents separately. Advertising an intent does not increase obtained reward. Actual incremental reward is the improvement over the best completed reward, not over an intent prediction.\n", "\n", "Before each decision, the loop refreshes the satellite's completed/intended bookkeeping and clears the cached observation. Intent-based exclusion changes which target opportunities are available. Incremental modes additionally use `estimate_quality_profile(..., return_rewards=True)` to retain opportunities whose maximum predicted marginal reward exceeds `0.001`. This is an opportunity-level check; it does not guarantee a positive reward at the policy's chosen timing option. `cooldown_s` is a separate intended restriction on rapid captures of the same target by the same satellite.\n", "\n", "**Observation wiring:** `QualitySatellite` binds its spline observation to `estimate_quality_profile`. After the loop updates bookkeeping and clears the observation cache, the next observation fits the marginal profile using that satellite's current completed/intended reward baseline. The estimator caches absolute predictions but subtracts the current bookkeeping baseline on every call, so same-time bookkeeping changes affect the spline coefficients. This changes observation values while preserving the 512-value observation shape. The successful-capture handler also records `last_img_time_per_sat`, which supplies the cooldown filter.\n" ] }, { "cell_type": "markdown", "id": "cb564573", "metadata": {}, "source": [ "### Helpers for decoding and comparing imaging actions\n", "\n", "`get_imaging_action` decodes an action into a target index and normalized timing fraction, or returns `None` when no imaging action is supplied. `get_time` uses the duration wrapper to convert that fraction into a delay in seconds for the selected satellite and target opportunity.\n", "\n", "`get_expected_absolute_reward` adds the current simulation time to this delay and evaluates the predicted absolute reward at the requested acquisition time. The coordination loop uses this prediction to advertise reward-aware intents and compare competing tasks. It is evaluated independently of the bookkeeping baseline: marginal reward is computed separately from completed or intended rewards. The requested time remains a prediction point; it does not guarantee that the instrument will capture the image at that time.\n" ] }, { "cell_type": "code", "execution_count": 13, "id": "25a4f434", "metadata": {}, "outputs": [], "source": [ "def get_expected_absolute_reward(env, satellite, target_index, action_fraction):\n", " \"\"\"Predict absolute reward at the wrapper-decoded desired acquisition time.\n", "\n", " The wrapper returns a delay, whereas quality functions expect absolute\n", " simulator time. The prediction is independent of reward bookkeeping and\n", " does not guarantee acquisition at the desired time or within the window.\n", " \"\"\"\n", " target = satellite.parse_target_selection(target_index)\n", " imaging_delay = float(\n", " env.get_imaging_time(target_index, action_fraction, satellite.name)\n", " )\n", " if not np.isfinite(imaging_delay) or imaging_delay < 0.0:\n", " raise ValueError(f\"Invalid desired imaging delay: {imaging_delay}\")\n", " desired_time = satellite.simulator.sim_time + imaging_delay\n", " predicted_reward = estimate_absolute_reward(\n", " satellite, target, np.array([desired_time], dtype=float)\n", " )\n", " if predicted_reward.size != 1 or not np.all(np.isfinite(predicted_reward)):\n", " raise ValueError(\n", " f\"Invalid expected acquisition reward for target {target.id}: \"\n", " f\"{predicted_reward}\"\n", " )\n", " return float(predicted_reward.item())\n", "\n", "\n", "def get_imaging_action(env, action):\n", " \"\"\"Decode a target index, or return None for a non-imaging action.\"\"\"\n", " action_parsed = (\n", " env._split_action(action)\n", " if isinstance(env, WrapperDiscreteToHybridAction)\n", " else action\n", " )\n", " if action_parsed is None:\n", " return None\n", " tgt_index, fraction = action_parsed\n", " return tgt_index, fraction\n", "\n", "\n", "def get_time(env, action: int | tuple[int, float], sat_name: str) -> float:\n", "\n", " action_parsed = get_imaging_action(env, action)\n", " if action_parsed is None:\n", " raise ValueError(\"Non-imaging actions do not have an imaging time.\")\n", "\n", " action_time = env.get_imaging_time(action_parsed[0], action_parsed[1], sat_name)\n", "\n", " return action_time" ] }, { "cell_type": "markdown", "id": "c73f1e2f", "metadata": {}, "source": [ "### Configure satellite access filters\n", "\n", "The following block creates the constellation and configures each satellite's access filters for the selected communication mode. These filters determine which target opportunities are available when forming observations and selecting actions. Depending on the mode, they exclude completed or competing intended targets, temporarily exclude targets lost in greedy comparisons, or retain opportunities with useful predicted marginal reward.\n", "\n", "The displayed configuration uses two satellites, 1000 targets, and `incremental_intent` with incremental scoring enabled. Its filters require a maximum predicted marginal reward greater than `0.001` over the remaining window and more than `cooldown_s=15.0` seconds since the same satellite last captured that target. These checks select eligible opportunities; they do not guarantee positive reward at the chosen timing fraction. The 15-second cooldown is an explicit setting of this example; the current paper draft does not specify a cooldown value.\n" ] }, { "cell_type": "code", "execution_count": null, "id": "b1eed896", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[90;3m2026-10-26 21:02:09,304 \u001b[0m\u001b[m \u001b[0m\u001b[93mWARNING \u001b[0m\u001b[93mCreating logger for new env on PID=71679. Old environments in process may now log times incorrectly.\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,307 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[mResetting environment with seed=1042\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,311 \u001b[0m\u001b[mscene.targets \u001b[0m\u001b[mINFO \u001b[0m\u001b[mGenerating 1000 targets\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,499 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mFinding opportunity windows from 0.00 to 1800.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,561 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mFinding opportunity windows from 0.00 to 1800.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,647 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mFinding opportunity windows from 1800.00 to 4200.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,703 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mFinding opportunity windows from 1800.00 to 4200.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,837 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[mEnvironment reset\u001b[0m\n" ] } ], "source": [ "from copy import copy\n", "\n", "setup_env_args = {}\n", "incremental_score = True\n", "cooldown_s = 15.0 # set to 0 to disable cooldown\n", "seed = 42\n", "n_targets = 1000\n", "n_sats = 2\n", "multisat_comm_config = {\"mode\": \"incremental_intent\"}\n", "\n", "env = make_env(\n", " setup_env_args,\n", " n_sats=n_sats,\n", " incremental_score=incremental_score,\n", " n_targets=n_targets,\n", " time_limit=ORBIT_PERIOD * 0.1,\n", ")\n", "\n", "env = setup_wrapper_stack(\n", " env, discrete_action_space=True, discrete_imaging_fraction=IMAGING_FRACTIONS\n", ")\n", "\n", "seed_case = seed + n_targets\n", "_, info = env.reset(seed=seed_case)\n", "\n", "sat_last_decision_time = {sat.name: 0.0 for sat in env.satellites}\n", "reward_cumulative = 0.0\n", "\n", "intents = {sat.name: None for sat in env.satellites}\n", "intents_quality = {sat.name: None for sat in env.satellites}\n", "\n", "comm_mode = multisat_comm_config[\"mode\"]\n", "if len(env.satellites) > 1:\n", "\n", " def filter_intent(opp, sat):\n", " return opp[\"object\"] not in sat.intent_set_shared\n", "\n", " def filter_imaged(opp, sat):\n", " return opp[\"object\"] not in sat.imaged_set_shared\n", "\n", " def filter_minimum_reward(opp, sat):\n", " rewards = estimate_quality_profile(sat, opp, return_rewards=True)\n", " minimum_quality = np.max(rewards) > 1e-3\n", " return minimum_quality\n", "\n", " def filter_time(opp, sat):\n", " tgt = opp[\"object\"]\n", " current_time = sat.simulator.sim_time\n", " time_diff = current_time - tgt.last_img_time_per_sat.get(sat.name, -np.inf)\n", " return time_diff > cooldown_s\n", "\n", " def filter_lower_reward(opp, sat):\n", " return opp[\"object\"] not in sat.temp_filter_set\n", "\n", " for sat in env.satellites:\n", " sat.intent_set_shared = set()\n", " sat.imaged_set_shared = set()\n", "\n", " if comm_mode == \"imaged\":\n", " for sat in env.satellites:\n", " sat.add_access_filter(lambda opp, sat=sat: filter_imaged(opp, sat))\n", "\n", " elif comm_mode == \"intent\":\n", " for sat in env.satellites:\n", " sat.add_access_filter(lambda opp, sat=sat: filter_intent(opp, sat))\n", " sat.add_access_filter(lambda opp, sat=sat: filter_imaged(opp, sat))\n", "\n", " elif comm_mode == \"incremental_intent\":\n", " for sat in env.satellites:\n", " if multisat_comm_config.get(\"filter_minimum_quality\", True):\n", " sat.add_access_filter(\n", " lambda opp, sat=sat: filter_minimum_reward(opp, sat)\n", " )\n", " if cooldown_s > 0:\n", " sat.add_access_filter(lambda opp, sat=sat: filter_time(opp, sat))\n", "\n", " elif comm_mode == \"greedy\":\n", " # Retask an existing claimant when another satellite predicts higher reward.\n", "\n", " for sat in env.satellites:\n", " sat.temp_filter_set = set()\n", " sat.add_access_filter(lambda opp, sat=sat: filter_imaged(opp, sat))\n", " sat.add_access_filter(lambda opp, sat=sat: filter_lower_reward(opp, sat))\n", "\n", " elif comm_mode == \"greedy_incremental\":\n", " for sat in env.satellites:\n", " sat.temp_filter_set = set()\n", " sat.add_access_filter(lambda opp, sat=sat: filter_lower_reward(opp, sat))\n", " if multisat_comm_config.get(\"filter_minimum_quality\", True):\n", " sat.add_access_filter(\n", " lambda opp, sat=sat: filter_minimum_reward(opp, sat)\n", " )\n", " if cooldown_s > 0:\n", " sat.add_access_filter(lambda opp, sat=sat: filter_time(opp, sat))" ] }, { "cell_type": "markdown", "id": "bfbee619", "metadata": {}, "source": [ "### Run the coordination loop\n", "\n", "At each step, the loop identifies satellites that require a new task, refreshes their shared acquisition information and mode-specific bookkeeping, and clears cached observations before selecting actions. It records new intents and their expected rewards; greedy modes can also displace a competing intent and request another decision. The action dictionary advances the constellation, rewards are accumulated across satellites, and the loop stops when the environment reports termination or truncation.\n", "\n", "The current `policy` runs the actor defined above with randomly initialized weights and selects its highest-logit target/timing pair through a deterministic categorical distribution. It therefore demonstrates coordination with an untrained policy, rather than uniformly sampling random actions. Load trained module weights to evaluate a learned policy with the same loop.\n" ] }, { "cell_type": "code", "execution_count": 15, "id": "37c501d9", "metadata": {}, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[90;3m2026-10-26 21:02:09,946 \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;3m2026-10-26 21:02:09,948 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 3 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,948 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Māhta, IN) imaging timing: requested capture at 11.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,949 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Māhta, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,950 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Māhta, IN) window enabled: 0.0 to 23.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,950 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 23.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,952 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,953 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(San Sebastián de la Gomera, ES) imaging timing: requested capture at 430.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,953 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(San Sebastián de la Gomera, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,954 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(San Sebastián de la Gomera, ES) window enabled: 371.5 to 489.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,955 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<0.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 489.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,967 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 23.7 for Target(Māhta, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,968 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:09,969 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,037 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,066 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,067 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,069 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Nawāshahr, IN) imaging timing: requested capture at 31.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,070 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Nawāshahr, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,071 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Nawāshahr, IN) window enabled: 0.0 to 38.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,072 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<24.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 38.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,080 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 38.9 for Target(Nawāshahr, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,082 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,083 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,159 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,190 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,191 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,192 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Gadarpur, IN) imaging timing: requested capture at 66.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,192 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Gadarpur, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,193 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Gadarpur, IN) window enabled: 16.6 to 93.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,193 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<39.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 93.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,209 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Gadarpur, IN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,211 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.5571039239604911)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,211 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,288 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.5571039239604911)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,323 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,324 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 3 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,325 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Koini, IN) imaging timing: requested capture at 149.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,326 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Koini, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,327 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Koini, IN) window enabled: 98.0 to 200.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,327 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<83.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 200.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,348 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Koini, IN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,349 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.724379742733913)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,349 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,421 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.724379742733913)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,466 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,466 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 6 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,467 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Jitpur, NP) imaging timing: requested capture at 180.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,468 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Jitpur, NP) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,469 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Jitpur, NP) window enabled: 80.5 to 211.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,469 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<149.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 211.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,482 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Jitpur, NP)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,483 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.005747950399001029)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,484 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,551 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.005747950399001029)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,582 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,583 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 8 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,584 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bāsopatti, IN) imaging timing: requested capture at 204.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,585 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bāsopatti, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,586 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bāsopatti, IN) window enabled: 104.0 to 228.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,587 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<180.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 228.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,598 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Bāsopatti, IN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,600 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.6400027666600737)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,601 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,680 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.6400027666600737)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,715 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,716 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 8 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,717 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Simaria, IN) imaging timing: requested capture at 217.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,717 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Simaria, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,718 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Simaria, IN) window enabled: 126.9 to 231.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,718 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<204.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 231.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,728 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Simaria, IN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,730 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.6273504569748937)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,731 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,810 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.6273504569748937)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,878 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,879 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 14 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,882 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Kasba, IN) imaging timing: requested capture at 242.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,882 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Kasba, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,884 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Kasba, IN) window enabled: 128.7 to 257.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,884 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<227.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 257.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,893 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Kasba, IN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,894 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.03568579182674939)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,895 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,967 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.03568579182674939)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:10,999 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,000 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,000 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rāghopur, IN) imaging timing: requested capture at 250.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,001 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rāghopur, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,002 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rāghopur, IN) window enabled: 134.3 to 250.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,003 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<249.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 250.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,007 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 250.9 for Target(Rāghopur, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,008 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,009 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,077 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,112 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,113 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 3 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,113 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Mohanpur Gaughāta, IN) imaging timing: requested capture at 254.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,114 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Mohanpur Gaughāta, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,114 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Mohanpur Gaughāta, IN) window enabled: 136.2 to 256.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,115 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<251.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 256.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,119 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 256.9 for Target(Mohanpur Gaughāta, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,120 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,120 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,207 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,238 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,239 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,240 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Mālior, IN) imaging timing: requested capture at 261.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,240 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Mālior, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,241 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Mālior, IN) window enabled: 139.0 to 265.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,242 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<257.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 265.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,246 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 265.4 for Target(Mālior, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,247 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,248 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,327 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,353 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,354 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,355 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Pemagatshel, BT) imaging timing: requested capture at 276.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,355 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Pemagatshel, BT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,356 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Pemagatshel, BT) window enabled: 166.6 to 287.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,357 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<265.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 287.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,359 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Pemagatshel, BT)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,360 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.011399764508251285)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,361 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,438 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.011399764508251285)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,464 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,465 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,466 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bāwāli, IN) imaging timing: requested capture at 266.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,466 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bāwāli, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,467 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bāwāli, IN) window enabled: 214.2 to 266.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,467 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 266.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,471 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 266.0 for Target(Bāwāli, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,472 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,473 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,551 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,578 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,581 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,581 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bagulā, IN) imaging timing: requested capture at 276.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,582 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bagulā, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,583 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bagulā, IN) window enabled: 184.7 to 286.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,584 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<266.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 286.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,594 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 286.0 for Target(Bagulā, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,595 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,596 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,672 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,712 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,713 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,716 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Gobārdānga, IN) imaging timing: requested capture at 286.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,716 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Gobārdānga, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,718 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Gobārdānga, IN) window enabled: 196.6 to 287.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,719 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<286.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 287.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,721 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 287.6 for Target(Gobārdānga, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,722 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,723 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,786 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,813 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,814 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,814 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Faradābād, BD) imaging timing: requested capture at 306.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,815 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Faradābād, BD) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,815 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Faradābād, BD) window enabled: 191.8 to 324.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,816 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<288.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 324.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,828 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Faradābād, BD)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,829 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.4171109179135972)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,830 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,895 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.4171109179135972)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,927 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,928 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,929 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Kakching, IN) imaging timing: requested capture at 333.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,929 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Kakching, IN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,930 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Kakching, IN) window enabled: 222.9 to 348.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,931 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<318.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 348.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,946 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 348.1 for Target(Kakching, IN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,947 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:11,948 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,026 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,053 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,054 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,055 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Chandanais, BD) imaging timing: requested capture at 351.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,055 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Chandanais, BD) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,056 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Chandanais, BD) window enabled: 226.4 to 353.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,057 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<348.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 353.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,062 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 353.6 for Target(Chandanais, BD) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,063 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,063 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,124 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,152 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,154 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,155 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban Pae, TH) imaging timing: requested capture at 420.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,155 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban Pae, TH) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,156 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban Pae, TH) window enabled: 349.6 to 486.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,157 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<354.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 486.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,182 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Ban Pae, TH)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,184 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.10437116422746319)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,184 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,252 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.10437116422746319)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,292 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,296 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,297 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban San Phak Wan Luang, TH) imaging timing: requested capture at 452.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,298 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban San Phak Wan Luang, TH) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,299 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban San Phak Wan Luang, TH) window enabled: 348.2 to 484.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,299 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<420.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 484.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,306 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(San Sebastián de la Gomera, ES)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,308 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.795573591049628)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,308 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,312 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mFinding opportunity windows from 4200.00 to 4800.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,359 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mFinding opportunity windows from 4200.00 to 4800.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,418 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.795573591049628)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,458 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,460 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,460 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Machico, PT) imaging timing: requested capture at 488.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,461 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Machico, PT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,462 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Machico, PT) window enabled: 420.9 to 546.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,462 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<430.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 546.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,470 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Ban San Phak Wan Luang, TH)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,472 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.19947173638520796)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,473 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,543 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.19947173638520796)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,572 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,573 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 4 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,574 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ratchaburi, TH) imaging timing: requested capture at 496.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,574 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ratchaburi, TH) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,575 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ratchaburi, TH) window enabled: 440.2 to 541.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,576 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<452.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 541.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,589 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Machico, PT)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,591 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.38370711429960774)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,591 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,656 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.38370711429960774)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,685 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,699 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,703 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(San Sebastián de la Gomera, ES) imaging timing: requested capture at 488.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,704 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(San Sebastián de la Gomera, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,709 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(San Sebastián de la Gomera, ES) window enabled: 371.5 to 489.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,714 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<488.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 489.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,718 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 489.9 for Target(San Sebastián de la Gomera, ES) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,719 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,719 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,798 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,839 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,841 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,842 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Amdel, MA) imaging timing: requested capture at 569.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,842 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Amdel, MA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,843 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Amdel, MA) window enabled: 529.1 to 610.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,845 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<490.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 610.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,852 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Ratchaburi, TH)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,853 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.019042621930721183)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,853 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,865 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mFinding opportunity windows from 4800.00 to 5400.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:12,971 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.019042621930721183)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,011 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,012 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 3 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,013 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Samrong, TH) imaging timing: requested capture at 529.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,014 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Samrong, TH) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,014 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Samrong, TH) window enabled: 440.3 to 557.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,015 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<501.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 557.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,025 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Samrong, TH)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,026 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.3456253471201201)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,027 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,127 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.3456253471201201)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,159 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,161 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,162 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban Bang Lamung, TH) imaging timing: requested capture at 547.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,163 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban Bang Lamung, TH) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,164 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Ban Bang Lamung, TH) window enabled: 453.9 to 566.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,164 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<529.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 566.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,171 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Ban Bang Lamung, TH)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,172 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.1966497718953449)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,173 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,248 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.1966497718953449)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,276 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,277 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,278 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Koh Kong, KH) imaging timing: requested capture at 580.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,278 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Koh Kong, KH) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,279 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Koh Kong, KH) window enabled: 492.1 to 614.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,280 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<547.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 614.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,310 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Amdel, MA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,311 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.7745063964760883)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,312 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,395 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.7745063964760883)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,435 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,451 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,456 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(’Ali Ben Sliman, MA) imaging timing: requested capture at 595.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,460 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(’Ali Ben Sliman, MA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,464 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(’Ali Ben Sliman, MA) window enabled: 567.9 to 621.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,465 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<569.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 621.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,471 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Koh Kong, KH)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,473 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.00857099491719181)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,474 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,569 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.00857099491719181)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,606 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,606 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 3 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,607 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Cần Thơ, VN) imaging timing: requested capture at 628.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,608 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Cần Thơ, VN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,609 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Cần Thơ, VN) window enabled: 540.1 to 673.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,610 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<583.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 673.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,618 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(’Ali Ben Sliman, MA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,620 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.48662061623566244)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,621 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,733 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.48662061623566244)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,771 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,773 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,774 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Oulad Yaïch, MA) imaging timing: requested capture at 617.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,774 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Oulad Yaïch, MA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,775 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Oulad Yaïch, MA) window enabled: 581.5 to 639.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,776 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<595.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 639.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,786 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Oulad Yaïch, MA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,789 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.6838681854948269)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,789 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,873 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.6838681854948269)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,901 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,902 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 4 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,903 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ain Kansara, MA) imaging timing: requested capture at 656.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,904 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ain Kansara, MA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,905 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ain Kansara, MA) window enabled: 594.7 to 695.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,905 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<617.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 695.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,913 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Cần Thơ, VN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,915 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.3663438367949623)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,918 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:13,985 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.3663438367949623)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,011 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,012 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,032 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rạch Giá, VN) imaging timing: requested capture at 645.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,036 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rạch Giá, VN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,038 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Rạch Giá, VN) window enabled: 534.7 to 662.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,039 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<628.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 662.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,045 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Rạch Giá, VN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,047 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.6520300383357149)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,048 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,134 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.6520300383357149)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,175 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,176 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,177 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bình Minh, VN) imaging timing: requested capture at 659.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,177 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bình Minh, VN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,178 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Bình Minh, VN) window enabled: 539.2 to 673.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,179 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<645.00> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 673.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,184 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Ain Kansara, MA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,186 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.5837788834463559)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,186 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,258 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.5837788834463559)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,305 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,307 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 7 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,313 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Algeciras, ES) imaging timing: requested capture at 688.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,314 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Algeciras, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,316 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Algeciras, ES) window enabled: 586.9 to 721.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,316 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<656.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 721.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,319 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mimaged Target(Bình Minh, VN)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,321 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[mTotal reward: {'EO_0': np.float64(0.6409562025459951)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,321 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,390 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[mStep reward: {'EO_0': np.float64(0.6409562025459951)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,417 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,418 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,419 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Long Thành, VN) imaging timing: requested capture at 667.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,420 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Long Thành, VN) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,421 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Long Thành, VN) window enabled: 541.8 to 677.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,421 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<658.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 677.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,431 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtimed termination at 677.3 for Target(Long Thành, VN) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,432 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,433 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mSatellite EO_0 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,509 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,548 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,549 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 20 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,551 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Tena, CO) imaging timing: requested capture at 3964.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,552 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Tena, CO) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,553 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Tena, CO) window enabled: 3901.7 to 4027.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,554 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<677.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 4027.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,559 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Algeciras, ES)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,561 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.025730269188953946)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,562 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,661 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.025730269188953946)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,703 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,706 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,706 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ain Kansara, MA) imaging timing: requested capture at 692.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,707 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ain Kansara, MA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,708 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ain Kansara, MA) window enabled: 594.7 to 695.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,708 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<688.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 695.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,712 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 695.7 for Target(Ain Kansara, MA) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,713 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,715 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,804 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,846 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,847 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,848 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Teroual, MA) imaging timing: requested capture at 699.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,848 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Teroual, MA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,849 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Teroual, MA) window enabled: 585.4 to 702.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,849 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<696.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 702.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,854 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Teroual, MA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,854 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.07431902323793338)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,854 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,945 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.07431902323793338)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,991 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,992 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,992 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Dar El Kebdani, MA) imaging timing: requested capture at 714.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,993 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Dar El Kebdani, MA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:14,996 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Dar El Kebdani, MA) window enabled: 618.3 to 727.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,000 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<701.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 727.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,030 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Dar El Kebdani, MA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,031 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.046522390704619956)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,033 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,135 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.046522390704619956)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,165 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,167 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 5 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,169 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Atarfe, ES) imaging timing: requested capture at 739.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,170 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Atarfe, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,171 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Atarfe, ES) window enabled: 617.5 to 753.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,171 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<725.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 753.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,188 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 753.7 for Target(Atarfe, ES) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,190 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,190 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,272 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,304 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,307 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,308 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Maracena, ES) imaging timing: requested capture at 754.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,309 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Maracena, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,311 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Maracena, ES) window enabled: 618.1 to 754.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,312 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 754.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,314 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 754.2 for Target(Maracena, ES) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,315 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,315 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,424 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,460 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,462 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 4 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,464 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Alhama de Murcia, ES) imaging timing: requested capture at 770.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,465 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Alhama de Murcia, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,466 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Alhama de Murcia, ES) window enabled: 651.4 to 786.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,466 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<754.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 786.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,468 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Alhama de Murcia, ES)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,470 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.002593261933429352)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,471 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,558 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.002593261933429352)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,590 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,592 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,593 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Almería, ES) imaging timing: requested capture at 759.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,594 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Almería, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,595 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Almería, ES) window enabled: 632.4 to 763.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,596 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<755.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 763.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,602 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 763.1 for Target(Almería, ES) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,603 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,604 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,703 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,739 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,741 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,742 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Villarrobledo, ES) imaging timing: requested capture at 772.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,744 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Villarrobledo, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,745 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Villarrobledo, ES) window enabled: 650.0 to 781.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,745 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<763.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 781.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,752 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 781.6 for Target(Villarrobledo, ES) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,753 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,754 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,836 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,873 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,875 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 4 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,876 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Valencia, ES) imaging timing: requested capture at 797.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,876 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Valencia, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,882 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Valencia, ES) window enabled: 676.7 to 812.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,894 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<782.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 812.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,915 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Valencia, ES)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,917 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.060854626884254755)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:15,918 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,004 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.060854626884254755)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,042 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,044 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,046 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Benifayó, ES) imaging timing: requested capture at 811.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,048 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Benifayó, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,051 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Benifayó, ES) window enabled: 674.3 to 810.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,065 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<810.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 810.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,071 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 810.6 for Target(Benifayó, ES) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,074 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,075 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,165 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,198 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,200 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 4 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,201 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Binisalem, ES) imaging timing: requested capture at 832.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,201 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Binisalem, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,202 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Binisalem, ES) window enabled: 717.7 to 853.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,202 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 853.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,205 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Binisalem, ES)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,207 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.8723150559752924)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,207 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,287 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.8723150559752924)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,326 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,328 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 3 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,329 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Calviá, ES) imaging timing: requested capture at 830.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,331 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Calviá, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,332 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Calviá, ES) window enabled: 712.8 to 848.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,333 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<811.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 848.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,347 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Calviá, ES)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,349 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.06112811158338784)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,351 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,418 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.06112811158338784)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,506 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,508 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,509 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Binisalem, ES) imaging timing: requested capture at 848.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,510 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Binisalem, ES) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,511 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Binisalem, ES) window enabled: 717.7 to 853.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,511 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<843.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 853.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,517 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Binisalem, ES)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,519 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,520 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,595 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,639 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,641 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 9 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,643 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Noceto, IT) imaging timing: requested capture at 907.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,644 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Noceto, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,645 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Noceto, IT) window enabled: 855.4 to 959.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,645 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<852.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 959.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,664 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Noceto, IT)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,666 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.7179888850051652)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,666 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,772 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.7179888850051652)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,817 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,818 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,819 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Volvera, IT) imaging timing: requested capture at 910.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,820 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Volvera, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,821 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Volvera, IT) window enabled: 839.4 to 913.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,821 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<907.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 913.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,828 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 913.7 for Target(Volvera, IT) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,830 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,834 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,919 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,958 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,960 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,960 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Terralba, IT) imaging timing: requested capture at 916.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,962 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Terralba, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,964 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Terralba, IT) window enabled: 800.6 to 918.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,964 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<914.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 918.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,970 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 918.6 for Target(Terralba, IT) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,971 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:16,972 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,055 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,098 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,100 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,100 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Gallarate, IT) imaging timing: requested capture at 919.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,101 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Gallarate, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,102 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Gallarate, IT) window enabled: 871.6 to 920.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,103 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<919.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 920.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,106 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 920.0 for Target(Gallarate, IT) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,107 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,108 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,187 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,219 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,220 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 5 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,221 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Castelfranco di Sotto, IT) imaging timing: requested capture at 946.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,222 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Castelfranco di Sotto, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,222 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Castelfranco di Sotto, IT) window enabled: 844.1 to 972.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,223 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<920.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 972.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,233 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Castelfranco di Sotto, IT)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,235 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.11166066216117564)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,236 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,322 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.11166066216117564)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,354 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,355 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,356 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(La Spezia, IT) imaging timing: requested capture at 952.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,356 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(La Spezia, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,357 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(La Spezia, IT) window enabled: 839.7 to 958.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,358 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<946.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 958.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,365 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(La Spezia, IT)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,366 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.5782403085024662)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,367 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,452 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.5782403085024662)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,485 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,487 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,488 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Santa Croce sull’ Arno, IT) imaging timing: requested capture at 963.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,488 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Santa Croce sull’ Arno, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,489 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Santa Croce sull’ Arno, IT) window enabled: 844.5 to 972.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,490 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<955.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 972.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,495 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Santa Croce sull’ Arno, IT)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,496 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.6116193943991023)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,497 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,579 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.6116193943991023)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,608 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,610 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,611 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Castelvetro di Modena, IT) imaging timing: requested capture at 968.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,612 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Castelvetro di Modena, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,615 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Castelvetro di Modena, IT) window enabled: 856.9 to 972.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,616 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<964.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 972.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,624 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 972.9 for Target(Castelvetro di Modena, IT) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,625 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,626 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,703 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,742 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,744 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 6 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,745 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Marano di Napoli, IT) imaging timing: requested capture at 984.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,746 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Marano di Napoli, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,747 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Marano di Napoli, IT) window enabled: 879.8 to 995.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,748 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<973.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 995.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,757 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 995.1 for Target(Marano di Napoli, IT) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,759 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,759 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,852 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,896 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,898 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,899 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Potenza, IT) imaging timing: requested capture at 1001.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,899 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Potenza, IT) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,901 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Potenza, IT) window enabled: 907.4 to 1007.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,902 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<995.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1007.2\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,910 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 1007.2 for Target(Potenza, IT) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,912 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,913 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:17,982 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,018 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,020 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 5 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,021 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Rogatec, SI) imaging timing: requested capture at 1017.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,021 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Rogatec, SI) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,022 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Rogatec, SI) window enabled: 932.6 to 1026.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,023 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1007.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1026.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,036 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 1026.7 for Target(Rogatec, SI) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,037 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,038 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,078 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mFinding opportunity windows from 4800.00 to 5400.00 seconds\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,151 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,191 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,193 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 10 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,194 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ljubovija, RS) imaging timing: requested capture at 1055.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,195 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ljubovija, RS) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,196 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Ljubovija, RS) window enabled: 948.3 to 1084.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,197 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1027.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1084.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,209 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Ljubovija, RS)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,213 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.005514410220247971)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,216 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,295 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.005514410220247971)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,334 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,336 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 13 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,338 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Rankovce, MK) imaging timing: requested capture at 1082.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,339 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Rankovce, MK) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,340 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Rankovce, MK) window enabled: 987.4 to 1102.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,340 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1062.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1102.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,352 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Rankovce, MK)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,353 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.023765420073078768)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,354 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,429 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.023765420073078768)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,460 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,462 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 10 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,463 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Covasna, RO) imaging timing: requested capture at 1134.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,465 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Covasna, RO) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,466 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Covasna, RO) window enabled: 1039.9 to 1169.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,467 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1099.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1169.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,487 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Covasna, RO)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,489 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.0030979265085962784)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,489 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,555 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.0030979265085962784)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,590 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,592 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,593 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Boldeşti-Scăeni, RO) imaging timing: requested capture at 1157.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,593 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Boldeşti-Scăeni, RO) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,594 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Boldeşti-Scăeni, RO) window enabled: 1033.4 to 1169.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,597 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1145.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1169.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,604 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Boldeşti-Scăeni, RO)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,606 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.2270585561858818)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,607 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,685 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.2270585561858818)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,721 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,722 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,723 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Bilozerka, UA) imaging timing: requested capture at 1199.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,724 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Bilozerka, UA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,724 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Bilozerka, UA) window enabled: 1120.7 to 1242.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,725 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1157.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1242.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,744 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Bilozerka, UA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,746 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.10296013415656079)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,746 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,814 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.10296013415656079)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,880 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,881 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mtarget index 17 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,882 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Aquitania, CO) imaging timing: requested capture at 3995.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,882 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Aquitania, CO) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,884 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[mTarget(Aquitania, CO) window enabled: 3929.0 to 4061.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,884 \u001b[0m\u001b[36msats.satellite.EO_0 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[36mEO_0: \u001b[0m\u001b[msetting timed terminal event at 4061.5\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,885 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,886 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Zelenodolsk, UA) imaging timing: requested capture at 1224.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,887 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Zelenodolsk, UA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,887 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Zelenodolsk, UA) window enabled: 1146.8 to 1245.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,888 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1203.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1245.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,899 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Zelenodolsk, UA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,901 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.525948564551845)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,902 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:18,971 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.525948564551845)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,002 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,004 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,004 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Pokrovsk, UA) imaging timing: requested capture at 1248.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,005 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Pokrovsk, UA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,006 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Pokrovsk, UA) window enabled: 1206.6 to 1268.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,006 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1228.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1268.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,023 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Pokrovsk, UA)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,026 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.38900071434681843)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,026 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,105 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.38900071434681843)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,140 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,142 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,143 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Yuvileine, UA) imaging timing: requested capture at 1267.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,143 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Yuvileine, UA) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,144 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Yuvileine, UA) window enabled: 1248.0 to 1272.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,145 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1263.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1272.4\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,151 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 1272.4 for Target(Yuvileine, UA) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,152 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,153 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,223 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,258 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,261 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,262 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Sokhumi, GE) imaging timing: requested capture at 1313.0\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,263 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Sokhumi, GE) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,263 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Sokhumi, GE) window enabled: 1229.6 to 1353.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,264 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1272.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1353.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,283 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Sokhumi, GE)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,285 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.20551218533976295)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,288 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,348 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.20551218533976295)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,381 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,382 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 1 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,383 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Saatlı, AZ) imaging timing: requested capture at 1396.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,384 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Saatlı, AZ) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,385 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Saatlı, AZ) window enabled: 1384.9 to 1408.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,385 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1323.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1408.3\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,416 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Saatlı, AZ)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,419 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.7923814938276732)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,419 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,495 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.7923814938276732)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,520 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,522 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,523 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Corat, AZ) imaging timing: requested capture at 1426.1\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,523 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Corat, AZ) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,524 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Corat, AZ) window enabled: 1368.1 to 1455.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,525 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1396.50> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1455.7\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,535 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Corat, AZ)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,537 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.8375055149095487)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,538 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,614 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.8375055149095487)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,648 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,650 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,651 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Xudat, AZ) imaging timing: requested capture at 1438.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,651 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Xudat, AZ) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,652 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Xudat, AZ) window enabled: 1337.2 to 1451.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,652 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1426.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1451.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,660 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mimaged Target(Xudat, AZ)\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,663 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[mTotal reward: {'EO_1': np.float64(0.7590256629768871)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,664 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,735 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[mStep reward: {'EO_1': np.float64(0.7590256629768871)}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,770 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,773 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 0 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,777 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Əmircan, AZ) imaging timing: requested capture at 1452.9\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,778 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Əmircan, AZ) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,779 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Əmircan, AZ) window enabled: 1374.4 to 1457.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,779 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1448.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1457.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,784 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtimed termination at 1457.8 for Target(Əmircan, AZ) window\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,789 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,789 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mSatellite EO_1 requires retasking\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,865 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,901 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[93;1m=== STARTING STEP ===\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,905 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mtarget index 2 tasked\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,908 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Gurlan, UZ) imaging timing: requested capture at 1541.6\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,908 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Gurlan, UZ) tasked for imaging\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,910 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[mTarget(Gurlan, UZ) window enabled: 1474.4 to 1608.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,910 \u001b[0m\u001b[92msats.satellite.EO_1 \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1458.00> \u001b[0m\u001b[92mEO_1: \u001b[0m\u001b[msetting timed terminal event at 1608.8\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:19,934 \u001b[0m\u001b[mdata.base \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1513.50> \u001b[0m\u001b[mTotal reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:20,005 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1513.50> \u001b[0m\u001b[mStep reward: {}\u001b[0m\n", "\u001b[90;3m2026-10-26 21:02:20,006 \u001b[0m\u001b[mgym \u001b[0m\u001b[mINFO \u001b[0m\u001b[33m<1513.50> \u001b[0m\u001b[mEpisode truncated: ['EO_0', 'EO_1']\u001b[0m\n" ] } ], "source": [ "while True:\n", " actions = {}\n", " current_time = env.simulator.sim_time\n", "\n", " old_intents = copy(intents)\n", " intents = {}\n", "\n", " intents_quality_old = copy(intents_quality)\n", " intents_quality = {}\n", "\n", " imaged_set = env.rewarder.data.imaged\n", "\n", " satellites_needing_retask = []\n", " for satellite in env.satellites:\n", " needs_retask = (\n", " satellite.name in info and info[satellite.name][\"requires_retasking\"]\n", " )\n", " exceeded_time_limit = (\n", " current_time - sat_last_decision_time[satellite.name] >= 500.0\n", " )\n", " intent_imaged = (\n", " old_intents[satellite.name] in imaged_set\n", " if old_intents[satellite.name] is not None\n", " else False\n", " ) and comm_mode not in [\"incremental_intent\", \"greedy_incremental\"]\n", "\n", " if needs_retask or exceeded_time_limit or intent_imaged:\n", " satellites_needing_retask.append(satellite.name)\n", " intents[satellite.name] = None\n", " intents_quality[satellite.name] = None\n", " else:\n", " intents[satellite.name] = old_intents[satellite.name]\n", " intents_quality[satellite.name] = intents_quality_old[satellite.name]\n", "\n", " while len(satellites_needing_retask) > 0:\n", " for satellite in env.satellites:\n", " if satellite.name in satellites_needing_retask:\n", " if comm_mode == \"imaged\":\n", " satellite.imaged_set_shared = imaged_set\n", "\n", " if comm_mode == \"intent\":\n", " satellite.imaged_set_shared = imaged_set\n", " satellite.intent_set_shared = set(intents.values()) - {None}\n", "\n", " if comm_mode == \"incremental_intent\":\n", " satellite.bookkeeping.delete_intended()\n", " for tgt in env.rewarder.data.imaged:\n", " satellite.bookkeeping.update(\n", " tgt.id, tgt.highest_reward_obtained, current_time\n", " )\n", " for intent_quality in intents_quality.values():\n", " if intent_quality is not None:\n", " satellite.bookkeeping.update_intended(\n", " intent_quality[0].id,\n", " intent_quality[1],\n", " intent_quality[2],\n", " )\n", "\n", " if comm_mode == \"greedy\":\n", " satellite.temp_filter_set = set()\n", " satellite.imaged_set_shared = imaged_set\n", "\n", " if comm_mode == \"greedy_incremental\":\n", " satellite.temp_filter_set = set()\n", " satellite.bookkeeping.delete_intended()\n", " for tgt in env.rewarder.data.imaged:\n", " satellite.bookkeeping.update(\n", " tgt.id, tgt.highest_reward_obtained, current_time\n", " )\n", "\n", " satellite.observation_builder.obs_dict_cache = (\n", " None # Clear cache to force re-evaluation of the observation\n", " )\n", "\n", " sat_last_decision_time[satellite.name] = current_time\n", " action = policy(satellite)\n", " imaging_action = get_imaging_action(env, action)\n", " if (\n", " comm_mode in [\"greedy\", \"greedy_incremental\"]\n", " and imaging_action is not None\n", " ):\n", " target_index, action_fraction = imaging_action\n", " target_parsed = satellite.parse_target_selection(target_index)\n", "\n", " while target_parsed in intents.values():\n", " expected_absolute_reward = get_expected_absolute_reward(\n", " env, satellite, target_index, action_fraction\n", " )\n", "\n", " intent_rewards = {\n", " val[0].id: (key, val[1])\n", " for key, val in intents_quality.items()\n", " if val is not None\n", " }\n", "\n", " prev_data = intent_rewards.get(target_parsed.id)\n", " prev_sat_name = prev_data[0]\n", " prev_reward = prev_data[1]\n", "\n", " if expected_absolute_reward > prev_reward:\n", " # Assigns the new satellite's intent since it has a better expected reward than the previous satellite's intent\n", " intents[satellite.name] = target_parsed\n", " intents_quality[satellite.name] = (\n", " target_parsed,\n", " expected_absolute_reward,\n", " get_time(env, action, satellite.name),\n", " )\n", "\n", " # Removes old satellites intent if the new satellite has a better expected reward\n", " intents[prev_sat_name] = None\n", " intents_quality[prev_sat_name] = None\n", " actions[prev_sat_name] = None\n", " satellites_needing_retask.append(prev_sat_name)\n", " break\n", " else:\n", " satellite.temp_filter_set.add(target_parsed)\n", " satellite.observation_builder.obs_dict_cache = None # Clear cache to force re-evaluation of the observation\n", " action = policy(satellite)\n", "\n", " imaging_action = get_imaging_action(env, action)\n", " if imaging_action is None:\n", " break\n", " target_index, action_fraction = imaging_action\n", " target_parsed = satellite.parse_target_selection(\n", " target_index\n", " )\n", "\n", " actions[satellite.name] = action\n", " imaging_action = get_imaging_action(env, action)\n", " if imaging_action is not None:\n", " target_index, action_fraction = imaging_action\n", " target_parsed = satellite.parse_target_selection(target_index)\n", " intents[satellite.name] = target_parsed\n", " if comm_mode in [\n", " \"incremental_intent\",\n", " \"greedy\",\n", " \"greedy_incremental\",\n", " ]:\n", " expected_absolute_reward = get_expected_absolute_reward(\n", " env, satellite, target_index, action_fraction\n", " )\n", " intents_quality[satellite.name] = (\n", " target_parsed,\n", " expected_absolute_reward,\n", " get_time(env, action, satellite.name),\n", " )\n", "\n", " satellites_needing_retask.remove(satellite.name)\n", "\n", " _, reward, terminated, truncated, info = env.step(actions) # type: ignore\n", "\n", " reward_cumulative += sum(reward.values())\n", "\n", " if any(terminated.values()) or any(truncated.values()):\n", " break" ] } ], "metadata": { "kernelspec": { "display_name": ".venv_issue_363 (3.12.7)", "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.12.7" } }, "nbformat": 4, "nbformat_minor": 5 }