Grounds

This application demonstrates a network of ground stations given geospatial locations, minimum elevation angle constraints, and operational status.

The application contains a single class, the Environment class, which waits for a message from the manager that indicates the beginning of the simulation execution. The application publishes all of the ground station information once, at the beginning of the simulation.


Class

class Environment(app, grounds)

Bases: Observer

The Environment object class inherits properties from the Observer object class in the NOS-T tools library

app

An application containing a test-run namespace, a name and description for the app, client credentials, and simulation timing instructions

Type:

ManagedApplication

grounds

DataFrame of ground station information including groundId (int), latitude-longitude location (GeographicPosition), min_elevation (float) angle constraints, and operational status (bool)

Type:

DataFrame

Environment.on_change(source, property_name, old_value, new_value)

Standard on_change callback function format inherited from Observer object class

In this instance, the callback function checks when the PROPERTY_MODE switches to EXECUTING to send a GroundLocation message to the PREFIX/ground/location topic:

        if property_name == Simulator.PROPERTY_MODE and new_value == Mode.EXECUTING:
            for index, ground in self.grounds.iterrows():
                self.app.send_message(
                    "location",
                    GroundLocation(
                        groundId=ground.groundId,
                        latitude=ground.latitude,
                        longitude=ground.longitude,
                        elevAngle=ground.elevAngle,
                        operational=ground.operational,
                    ).json(),
                )

Schema

Schema are implemented using the pydantic library. The following schema define consistent message structures between this application and other observer applications:

pydantic settings GroundLocation

Bases: BaseModel

Message 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": {
         "title": "Groundid",
         "description": "Unique ground station identifier.",
         "type": "integer"
      },
      "latitude": {
         "title": "Latitude",
         "description": "Latitude (deg) of ground station.",
         "minimum": -90,
         "maximum": 90,
         "type": "number"
      },
      "longitude": {
         "title": "Longitude",
         "description": "Longitude (deg) of ground station.",
         "minimum": -180,
         "maximum": 180,
         "type": "number"
      },
      "elevAngle": {
         "title": "Elevangle",
         "description": "Minimum elevation angle (deg) for satellite-ground communications",
         "type": "number"
      },
      "operational": {
         "title": "Operational",
         "description": "True, if this ground station is operational.",
         "default": true,
         "type": "boolean"
      }
   },
   "required": [
      "groundId",
      "latitude",
      "longitude",
      "elevAngle"
   ]
}

Fields:
  • groundId (int)

  • latitude (float)

  • longitude (float)

  • elevAngle (float)

  • operational (bool)

field groundId: int [Required]

Unique ground station identifier.

field latitude: float [Required]

Latitude (deg) of ground station.

Constraints:
  • minimum = -90

  • maximum = 90

field longitude: float [Required]

Longitude (deg) of ground station.

Constraints:
  • minimum = -180

  • maximum = 180

field elevAngle: float [Required]

Minimum elevation angle (deg) for satellite-ground communications

field operational: bool = True

True, if this ground station is operational.


Startup Script

The following code demonstrates how the ground application is started up and how the Environment Observer object class is initialized and added to the simulator:

    # Note that these are loaded from a .env file in current working directory
    credentials = dotenv_values(".env")
    HOST, PORT = credentials["HOST"], int(credentials["PORT"])
    CERTIFICATE, KEY = credentials["CERTIFICATE"], credentials["KEY"]

    # set the client credentials
    config = ConnectionConfig(HOST, PORT, CERTIFICATE, KEY)

    # create the managed application
    app = ManagedApplication("ground")

    # add the environment observer to monitor simulation for switch to EXECUTING mode
    app.simulator.add_observer(Environment(app, GROUND))

    # add a shutdown observer to shut down after a single test case
    app.simulator.add_observer(ShutDownObserver(app))

    # start up the application on PREFIX, publish time status every 10 seconds of wallclock time
    app.start_up(
        PREFIX,
        config,
        True,
        time_status_step=timedelta(seconds=10) * SCALE,
        time_status_init=datetime(2020, 1, 1, 7, 20, tzinfo=timezone.utc),
        time_step=timedelta(seconds=1) * SCALE,
    )

    while True:
        pass