{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "Copyright (c) 2024 Massachusetts Institute of Technology\n", "\n", "SPDX-License-Identifier: MIT" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Observing a Satellite with a Custom Ground Sensor\n", "In the previous example, we learned how to use `madlib` utilities to define and propagate a satellite. Now we will use `madlib` to define a custom ground-based optical sensor and use it to generate realistic astrometric observations." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining Satellites\n", "Let's quickly define 3 satellites:\n", "1. A LEO object similar to the ISS\n", "2. A GEO satellite at 0 degrees longitude\n", "3. A GEO satellite at 270 degrees longitude" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [], "source": [ "import madlib\n", "import numpy as np" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "epoch_mjd = 60197.5\n", "\n", "leo_alt_km = 430.0\n", "leo_speed_kms = 27500.0 / 3600 # Converting from km/h to km/s\n", "earth_radius_km = 6378.0\n", "\n", "leo_pos_teted = np.array([leo_alt_km + earth_radius_km, 0, 0])\n", "leo_vel_teted = leo_speed_kms * np.array([0, 2**-0.5, 2**-0.5])\n", "\n", "leo_satellite = madlib.Satellite(epoch=epoch_mjd, pos=leo_pos_teted, vel=leo_vel_teted)\n", "\n", "geo_satellite_0 = madlib.Satellite.from_GEO_longitude(lon=0, epoch=epoch_mjd)\n", "geo_satellite_270 = madlib.Satellite.from_GEO_longitude(lon=270, epoch=epoch_mjd)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Defining a Sensor\n", "Now let's take a look at how `madlib` lets us define sensors. Currently, only optical sensors are supported, and these sensors can only measure satellite's angular positions, not their brightnesses or radial distances. `madlib` lets us create both ground-based sensors and sensors in Earth orbit, but we'll focus on the former for now.\n", "\n", "Ground-based optical sensors are defined with the following parameters:\n", "* **lat** - The geodetic latitude of the sensor, in degrees\n", "* **lon** - The geodetic longitude of the sensor, in degrees (measured East of the Prime Meridian)\n", "* **alt** - The altitude of the sensor, in km (measured above WGS-84 reference ellipsoid)\n", "* **dra** - Metric accuracy of the sensor in the right ascension direction, measured in **arcseconds\n", "* **ddec** - Metric accuracy of the sensor in the declination direction, measured in arcseconds\n", "* **obs_per_collect** - Typical number of observations per collect (either fixed or randomly sampled from an interval)\n", "* **obs_time_spacing** - The time in seconds between observations within a collect\n", "* **collect_gap_mean** - Average time in seconds between collects\n", "* **collect_gap_std** - Standard deviation of seconds between collects\n", "* **obs_limits** - Various limits on what the sensor can observe, such as elevation limits\n", "* **id** - A unique sensor ID string\n", "\n", "Let's go step-by-step through these parameters to build an imaginary sensor near the [Haystack Observatory](https://en.wikipedia.org/wiki/Haystack_Observatory):" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "sensor_1_params = {}\n", "\n", "# We'll start with the ID\n", "sensor_1_params[\"id\"] = \"Needle\"\n", "\n", "# In degrees, the coordinates of Haystack are 42.6233 N, 71.4882 W\n", "sensor_1_params[\"lat\"] = 42.6233\n", "sensor_1_params[\"lon\"] = -71.4882\n", "\n", "# The altitude of the observatory is 131 m\n", "sensor_1_params[\"alt\"] = 0.131\n", "\n", "# Our imaginary telescope has mediocre imaginary funding, so our astrometric\n", "# measurements are accurate to within ten arcseconds.\n", "sensor_1_params[\"dra\"] = 10.0\n", "sensor_1_params[\"ddec\"] = 10.0\n", "\n", "# At each pointing of our scanning pattern, we'll take 3 observations, spaced 1 second apart\n", "sensor_1_params[\"obs_per_collect\"] = 3\n", "sensor_1_params[\"obs_time_spacing\"] = 1\n", "\n", "# On average, we'll return to each pointing every 1 minute, give or take 5 seconds\n", "sensor_1_params[\"collect_gap_mean\"] = 60\n", "sensor_1_params[\"collect_gap_std\"] = 5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "