SatelliteStorage
This application monitors a subset of satellites with continuous data collection and is used to track the state of each satellite’s solid-state recorder while its orbital position is propagated from Two-Line Elements (TLEs).
The application contains one SatelliteStorage (Entity) object class and one SatStatePublisher (WallclockTimeIntervalPublisher) object. The application also contains two global methods outside of these classes, which contain standardized calculations sourced from Ch. 5 of Space Mission Analysis and Design by Wertz and Larson.
NOTE: For example code demonstrating how an application is started up and how the Entity and WallclockTimeIntervalPublisher object classes are initialized and added to the simulator, see FireSat+ Constellations.
Methods
- main_satelliteStorage.get_elevation_angle(sat, loc)
Returns the elevation angle (degrees) of satellite with respect to the topocentric horizon
- Parameters:
t (
Time) – Time object of skyfield.timelib modulesat (
EarthSatellite) – Skyview EarthSatellite object from skyfield.sgp4lib moduleloc (
GeographicPosition) – Geographic location on surface specified by latitude-longitude from skyfield.toposlib module
- Returns:
- alt.degrees
Elevation angle (degrees) of satellite with respect to the topocentric horizon
- Return type:
- main_satelliteStorage.check_in_range(satellite, grounds)
Checks if the satellite is in range of any of the operational ground stations
- Parameters:
t (
Time) – Time object of skyfield.timelib modulesatellite (
EarthSatellite) – Skyview EarthSatellite object from skyfield.sgp4lib modulegrounds (
DataFrame) – Dataframe of ground station locations, minimum elevation angles for communication, and operational status (T/F)
- Returns:
- isInRange
True/False indicating visibility of satellite to any operational ground station
- groundId
groundId of the ground station currently in comm range (NOTE: If in range of two ground stations simultaneously, will return first groundId)
- Return type:
Classes
While the latter methods are globally defined, the following classes have built-in methods that are unique to each object. The SatelliteStorage class tracks state transitions for the satellites in the constellation, while the SatStatePublisher standardizes the message structure and frequency of published messages updating these states.
SatelliteStorage
- class SatelliteStorage(cName, app, id, names, ES=None, tles=None)
Bases:
EntityThis object class inherits properties from the Entity object class in the NOS-T tools library
- Parameters:
cName (str) – A string containing the name for the application that tracks the constituent EarthSatellites for this simulation
app (
ManagedApplication) – An application containing a test-run namespace, a name and description for the app, client credentials, and simulation timing instructionsid (
list) – List of unique int ids for each constituent satellitenames (
list) – List of unique str for each constituent satellite (must be same length as id)ES (
list) – Optional list ofEarthSatelliteobjects to be included in the simulation (NOTE: at least one of ES or tles MUST be specified, or an exception will be thrown)tles (
list) – Optional list of Two-Line Element str to be converted intoEarthSatelliteobjects and included in the simulation
- groundTimes
Dictionary with keys corresponding to unique satellite name and values corresponding to sequential list of ground access opportunities - NOTE: each value is initialized as an empty
listand opportunities are appended chronologically- Type:
- grounds
Dataframe containing information about ground stations with unique groundId (int), latitude-longitude location (
GeographicPosition), min_elevation (float) angle constraints, and operational status (bool) - NOTE: initialized as None- Type:
DataFrame
- positions
List of current latitude-longitude-altitude locations (
GeographicPosition) of each constituent satellite - NOTE: must be same length as id- Type:
- next_positions
List of next latitude-longitude-altitude locations (
GeographicPosition) of each constituent satellite - NOTE: must be same length as id- Type:
- ssr_capacity
List of fixed Solid-State Recorder (SSR) capacities in Gigabits (int) for each constituent satellite - NOTE: must be same length as id
- Type:
- capacity_used
list of values (float) representing current fraction of SSR capacity used for each constituent satellite, continuously updated through simulation - NOTE: must be same length as id
- Type:
- instrument_rates
list of fixed instrument data collection rates in Gigabits/second (float) for each constituent satellite - NOTE: must be same length as id
- Type:
- cost_mode
list of str representing one of three cost modes used to update cumulative costs:
discrete(per downlink),continuous(fixed contract), orboth- NOTE: must be same length as id- Type:
- fixed_rates
list of fixed rates of cost accumulation in dollars/second for
continuouscost_mode for each constituent satellite - NOTE: must be same length as id, but ignored if cost_mode for corresponding satellite isdiscrete- Type:
- linkCounts
list of cumulative counts of link opportunies (int) for each constituent satellite - NOTE: must be same length as id, initialized as list of zeros
- Type:
- linkStatus
list of states (bool) indicating whether or not each constituent satellite is currently in view of an available ground station - NOTE: must be same length as id, each satellite state initialized as
False- Type:
- cumulativeCostBySat
Dictionary with keys corresponding to unique satellite name and values corresponding to current cumulative costs in dollars (float) accrued by each constituent satellite, continuously updated throughout the simulation - NOTE: must be same length as id, each satellite cost initialized as zero dollars
- Type:
- SatelliteStorage.initialize(init_time)
Activates the
SatelliteStorageobject with all constituent satellites at a specified initial scenario time- Parameters:
init_time (
datetime) – Initial scenario time for simulating propagation of satellites
- SatelliteStorage.tick(time_step)
Computes the next
SatelliteStoragestate after the specified scenario duration and the next simulation scenario time- Parameters:
time_step (
timedelta) – Duration between current and next simulation scenario time
- SatelliteStorage.tock()
Commits the next
SatelliteStoragestate and advances simulation scenario time
- SatelliteStorage.on_ground(ch, method, properties, body)
Callback function appends a dictionary of information for a new ground station to grounds
listwhen message detected on the PREFIX/ground/location topic.Ground station information is published at beginning of simulation, and the
listis converted to aDataFramewhen the Constellation is initialized.- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used)
message (
message) – Contains topic the client subscribed to and payload message content as attributes
- SatelliteStorage.on_linkStart(ch, method, properties, body)
Callback function when message detected on the PREFIX/ground/linkStart topic.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used)
message (
message) – Contains topic the client subscribed to and payload message content as attributes
- SatelliteStorage.on_linkCharge(ch, method, properties, body)
Callback function when message detected on the PREFIX/ground/linkCharge topic.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used)
message (
message) – Contains topic the client subscribed to and payload message content as attributes
- SatelliteStorage.on_outage(ch, method, properties, body)
Callback function when message detected on the PREFIX/outage/report topic.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used)
message (
message) – Contains topic the client subscribed to and payload message content as attributes
- SatelliteStorage.on_restore(ch, method, properties, body)
Callback function when message detected on the PREFIX/outage/restore topic.
- Parameters:
client (
MQTT Client) – Client that connects application to the event broker using the MQTT protocol. Includes user credentials, tls certificates, and host server-port information.userdata – User defined data of any type (not currently used)
message (
message) – Contains topic the client subscribed to and payload message content as attributes
SatStatePublisher
- class SatStatePublisher(app, constellation, time_status_step=None, time_status_init=None)
Bases:
WallclockTimeIntervalPublisherThis object class inherits properties from the WallclockTimeIntervalPublisher object class from the publisher template in the NOS-T tools library
The user can optionally specify the wallclock
timedeltabetween message publications and the scenariodatetimewhen the first of these messages should be published.- Parameters:
app (
ManagedApplication) – An application containing a test-run namespace, a name and description for the app, client credentials, and simulation timing instructionsconstellation (
SatelliteStorage) – SatelliteStorageEntityobject class with all constituent satellitestime_status_step (
timedelta) – Optional duration between time status ‘heartbeat’ messagestime_status_init (
datetime) – Optional scenariodatetimefor publishing the first time status ‘heartbeat’ message
- SatStatePublisher.publish_message()
Abstract publish_message method inherited from the WallclockTimeIntervalPublisher object class from the publisher template in the NOS-T tools library
This method sends a message to the PREFIX/constellation/location topic for each constituent satellite (
SatelliteStorage), which includes:- Parameters:
id (int) – Unique id for satellite in constellation
name (str) – Unique str name for satellite in constellation
latitude (float) – Latitude in degrees for satellite in constellation at current scenario time
longitude (float) – Longitude in degrees for satellite in constellation at current scenario time
altitude (float) – Altitude above sea-level in meters for satellite in constellation at current scenario time
capacity_used (float) – Fraction of solid-state recorder capacity used for satellite in constellation at current scenario time
commRange (bool) – Boolean state variable indicating if satellite in constellaton is in view of a ground station at current scenario time
groundId (int) – Optional unique id for ground station in view of satellite in constellation at current scenario time (if commRange = False, the groundId = None)
totalLinkCount (int) – Unique count of downlink opportunities for satellite in constellation
cumulativeCostBySat (float) – Cumulative costs incurred for downlinks and/or fixed cost contracts for satellite in constellation at current scenario time
Schema
Schema are implemented using the pydantic library. The following schema define consistent message structures between this application and other observer applications:
- pydantic settings SatelliteReady
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized initializing message for each satellite in the constellation includes:
Show JSON schema
{ "title": "SatelliteReady", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized initializing message for each satellite in the constellation includes: ", "type": "object", "properties": { "id": { "description": "Unique satellite identifier", "title": "Id", "type": "integer" }, "name": { "description": "Satellite name for labeling", "title": "Name", "type": "string" }, "ssr_capacity": { "description": "Capacity of onboard Solid State Recorder in Gigabytes", "title": "Ssr Capacity", "type": "number" } }, "required": [ "id", "name", "ssr_capacity" ] }
- Fields:
id (int)name (str)ssr_capacity (float)
- field id: int [Required]
Unique satellite identifier
- field name: str [Required]
Satellite name for labeling
- field ssr_capacity: float [Required]
Capacity of onboard Solid State Recorder in Gigabytes
- pydantic settings SatelliteAllReady
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized trigger message indicating
SatelliteReadymessages have been received for all satellites in the constellation:Show JSON schema
{ "title": "SatelliteAllReady", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized trigger message indicating :obj:`SatelliteReady` messages have been received for all satellites in the constellation: ", "type": "object", "properties": { "ready": { "default": "allReady", "description": "Indicates completion of SatelliteReady messages", "title": "Ready", "type": "string" } } }
- Fields:
ready (str)
- field ready: str = 'allReady'
Indicates completion of SatelliteReady messages
- pydantic settings SatelliteState
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized satellite status message includes:
Show JSON schema
{ "title": "SatelliteState", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized satellite status message includes: \n ", "type": "object", "properties": { "id": { "description": "Unique satellite identifier", "title": "Id", "type": "integer" }, "name": { "description": "Satellite name for labeling", "title": "Name", "type": "string" }, "latitude": { "description": "Latitude (deg) of satellite subpoint location.", "maximum": 90, "minimum": -90, "title": "Latitude", "type": "number" }, "longitude": { "description": "Longitude (deg) of satellite subpoint location.", "maximum": 180, "minimum": -180, "title": "Longitude", "type": "number" }, "altitude": { "description": "Altitude (meters) of satellite above sea level", "title": "Altitude", "type": "number" }, "capacity_used": { "description": "GB of solid state recorder capacity used", "title": "Capacity Used", "type": "number" }, "commRange": { "default": false, "description": "Boolean for if satellite is in ground stations view", "title": "Commrange", "type": "boolean" }, "groundId": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "description": "Ground Station id in view (None if not in view)", "title": "Groundid" }, "totalLinkCount": { "anyOf": [ { "type": "integer" }, { "type": "null" } ], "description": "Running count of downlink opportunity per satellite", "title": "Totallinkcount" }, "cumulativeCostBySat": { "description": "Cumulative cost of downlinks and/or fixed cost contracts per satellite", "title": "Cumulativecostbysat", "type": "number" }, "time": { "description": "Time in satellite reference frame", "format": "date-time", "title": "Time", "type": "string" } }, "required": [ "id", "name", "latitude", "longitude", "altitude", "capacity_used", "groundId", "totalLinkCount", "cumulativeCostBySat", "time" ] }
- Fields:
id (int)name (str)latitude (float)longitude (float)altitude (float)capacity_used (float)commRange (bool)groundId (int | None)totalLinkCount (int | None)cumulativeCostBySat (float)time (datetime.datetime)
- field id: int [Required]
Unique satellite identifier
- field name: str [Required]
Satellite name for labeling
- field latitude: float [Required]
Latitude (deg) of satellite subpoint location.
- Constraints:
ge = -90
le = 90
- field longitude: float [Required]
Longitude (deg) of satellite subpoint location.
- Constraints:
ge = -180
le = 180
- field altitude: float [Required]
Altitude (meters) of satellite above sea level
- field capacity_used: float [Required]
GB of solid state recorder capacity used
- field commRange: bool = False
Boolean for if satellite is in ground stations view
- field cumulativeCostBySat: float [Required]
Cumulative cost of downlinks and/or fixed cost contracts per satellite
- field time: datetime [Required]
Time in satellite reference frame
- pydantic settings GroundLocation
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message for ground station information includes:
Show JSON schema
{ "title": "GroundLocation", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message for ground station information includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "latitude": { "description": "Latitude (deg) of ground station.", "maximum": 90, "minimum": -90, "title": "Latitude", "type": "number" }, "longitude": { "description": "Longitude (deg) of ground station.", "maximum": 180, "minimum": -180, "title": "Longitude", "type": "number" }, "elevAngle": { "description": "Minimum elevation angle (deg) for satellite-ground communications", "title": "Elevangle", "type": "number" }, "operational": { "default": true, "description": "True, if this ground station is operational", "title": "Operational", "type": "boolean" }, "downlinkRate": { "description": "Downlink rate for this ground station in Megabytes per second", "title": "Downlinkrate", "type": "number" }, "costPerSecond": { "description": "Cost in $ per second for downlinks", "title": "Costpersecond", "type": "number" }, "costMode": { "default": "discrete", "description": "Could be a boolean, options are discrete or fixed, default to discrete", "title": "Costmode", "type": "string" } }, "required": [ "groundId", "latitude", "longitude", "elevAngle", "downlinkRate", "costPerSecond" ] }
- Fields:
groundId (int)latitude (float)longitude (float)elevAngle (float)operational (bool)downlinkRate (float)costPerSecond (float)costMode (str)
- field groundId: int [Required]
Unique ground station identifier
- field latitude: float [Required]
Latitude (deg) of ground station.
- Constraints:
ge = -90
le = 90
- field longitude: float [Required]
Longitude (deg) of ground station.
- Constraints:
ge = -180
le = 180
- field elevAngle: float [Required]
Minimum elevation angle (deg) for satellite-ground communications
- field operational: bool = True
True, if this ground station is operational
- field downlinkRate: float [Required]
Downlink rate for this ground station in Megabytes per second
- field costPerSecond: float [Required]
Cost in $ per second for downlinks
- field costMode: str = 'discrete'
Could be a boolean, options are discrete or fixed, default to discrete
- pydantic settings LinkStart
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the beginning of a downlink opportunity includes:
Show JSON schema
{ "title": "LinkStart", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the beginning of a downlink opportunity includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "satId": { "description": "Unique satellite identifier that performed the downlink", "title": "Satid", "type": "integer" }, "satName": { "description": "Name of satellite that performed the downlink", "title": "Satname", "type": "string" }, "linkId": { "description": "Unique downlink counter for the specific spacecraft that downlinked", "title": "Linkid", "type": "integer" }, "start": { "description": "Start time in ground network reference frame", "format": "date-time", "title": "Start", "type": "string" }, "data": { "description": "Current amount of data on-board the satellite that needs to be offloaded", "title": "Data", "type": "number" } }, "required": [ "groundId", "satId", "satName", "linkId", "start", "data" ] }
- Fields:
groundId (int)satId (int)satName (str)linkId (int)start (datetime.datetime)data (float)
- field groundId: int [Required]
Unique ground station identifier
- field satId: int [Required]
Unique satellite identifier that performed the downlink
- field satName: str [Required]
Name of satellite that performed the downlink
- field linkId: int [Required]
Unique downlink counter for the specific spacecraft that downlinked
- field start: datetime [Required]
Start time in ground network reference frame
- field data: float [Required]
Current amount of data on-board the satellite that needs to be offloaded
- pydantic settings LinkCharge
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the end of a downlink opportunity and updating cost ledgers includes:
Show JSON schema
{ "title": "LinkCharge", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the end of a downlink opportunity and updating cost ledgers includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "satId": { "description": "Unique satellite identifier that performed the downlink", "title": "Satid", "type": "integer" }, "satName": { "description": "Name of satellite that performed the downlink", "title": "Satname", "type": "string" }, "linkId": { "description": "Unique downlink counter for the specific spacecraft that downlinked", "title": "Linkid", "type": "integer" }, "end": { "description": "Time stamp for end of downlink when charge is sent", "format": "date-time", "title": "End", "type": "string" }, "duration": { "description": "Time duration of satellite in view for this downlink (s)", "title": "Duration", "type": "number" }, "dataOffload": { "description": "Amount of data offloaded based on linear downlink rates unique to each ground station (GB)", "title": "Dataoffload", "type": "number" }, "downlinkCost": { "description": "Cost of data downlink based on per-second cost rates unique to each ground station", "title": "Downlinkcost", "type": "number" }, "cumulativeCostBySat": { "description": "Dictionary of running totals for downlink costs per satellite", "title": "Cumulativecostbysat", "type": "number" }, "cumulativeCosts": { "description": "Running total of ALL downlink costs for the entirety of the Test Case", "title": "Cumulativecosts", "type": "number" } }, "required": [ "groundId", "satId", "satName", "linkId", "end", "duration", "dataOffload", "downlinkCost", "cumulativeCostBySat", "cumulativeCosts" ] }
- Fields:
groundId (int)satId (int)satName (str)linkId (int)end (datetime.datetime)duration (float)dataOffload (float)downlinkCost (float)cumulativeCostBySat (float)cumulativeCosts (float)
- field groundId: int [Required]
Unique ground station identifier
- field satId: int [Required]
Unique satellite identifier that performed the downlink
- field satName: str [Required]
Name of satellite that performed the downlink
- field linkId: int [Required]
Unique downlink counter for the specific spacecraft that downlinked
- field end: datetime [Required]
Time stamp for end of downlink when charge is sent
- field duration: float [Required]
Time duration of satellite in view for this downlink (s)
- field dataOffload: float [Required]
Amount of data offloaded based on linear downlink rates unique to each ground station (GB)
- field downlinkCost: float [Required]
Cost of data downlink based on per-second cost rates unique to each ground station
- field cumulativeCostBySat: float [Required]
Dictionary of running totals for downlink costs per satellite
- field cumulativeCosts: float [Required]
Running total of ALL downlink costs for the entirety of the Test Case
- pydantic settings OutageReport
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the beginning of an outage at a ground station includes:
Show JSON schema
{ "title": "OutageReport", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the beginning of an outage at a ground station includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier experiencing outage", "title": "Groundid", "type": "integer" }, "outageStart": { "description": "Initial time of outage report", "format": "date-time", "title": "Outagestart", "type": "string" }, "outageDuration": { "description": "Duration of the reported outage", "format": "duration", "title": "Outageduration", "type": "string" }, "outageEnd": { "description": "outageStart + outageDuration", "format": "date-time", "title": "Outageend", "type": "string" } }, "required": [ "groundId", "outageStart", "outageDuration", "outageEnd" ] }
- Fields:
groundId (int)outageStart (datetime.datetime)outageDuration (datetime.timedelta)outageEnd (datetime.datetime)
- field groundId: int [Required]
Unique ground station identifier experiencing outage
- field outageStart: datetime [Required]
Initial time of outage report
- field outageDuration: timedelta [Required]
Duration of the reported outage
- field outageEnd: datetime [Required]
outageStart + outageDuration
- pydantic settings OutageRestore
Bases:
BaseModelMessage schema object class with properties inherited from the pydantic library’s BaseModel
Standardized message indicating the end of an outage with restored service at a ground station includes:
Show JSON schema
{ "title": "OutageRestore", "description": "*Message schema object class with properties inherited from the pydantic library's BaseModel*\n\nStandardized message indicating the end of an outage with restored service at a ground station includes:", "type": "object", "properties": { "groundId": { "description": "Unique ground station identifier", "title": "Groundid", "type": "integer" }, "outageEnd": { "description": "outageStart + outageDuration", "format": "date-time", "title": "Outageend", "type": "string" } }, "required": [ "groundId", "outageEnd" ] }
- Fields:
groundId (int)outageEnd (datetime.datetime)
- field groundId: int [Required]
Unique ground station identifier
- field outageEnd: datetime [Required]
outageStart + outageDuration