diff --git a/__init__.py b/__init__.py index 2253a07952dc605ffa662b625265c4b68b841e53..22406df62d6971c8d5ba7f5c05edc8f9f702ebdd 100644 --- a/__init__.py +++ b/__init__.py @@ -1,3 +1,5 @@ +from flask_restx import Api, fields +from flask import Flask import os @@ -6,3 +8,70 @@ __all__ = [ for x in os.listdir(os.path.dirname(__file__)) if x.endswith(".py") and x != "__init__.py" ] + +app = Flask(__name__) +api = Api(app) + +message_types = [ + "vehicle_status" +] # TODO: Add full range of message types once scoped out + +message_header_schema = api.model( + "MessageHeader", + { + "timestamp": fields.String( # TODO: Update to Datetime UTC format + required=True, + description="Timestamp of message", + example="2022-11-16T00:00:00Z", + ), + "source": fields.String( + required=True, + description="Where is this message from", + example="autonomy_engine", + ), + "destination": fields.String( + required=True, + description="What is the destination of this message", + example="ah-1", + ), + "encoded": fields.Boolean( + required=True, + description="Indicate that message raw (encoded) or decoded. " + + "Options: encoded=True, decoded=False", + example=False, + ), + "type": fields.String( + required=True, + description="Type of message", + example="vehicle_status", + ), + }, +) + +vehicle_schema = api.model( + "VehicleSchema", + { + "vehicle_ID": fields.Integer( + required=True, + description="vehicle serial number", + example="ah-1", + ), + "serial": fields.Integer( + required=True, + description="vehicle serial number", + example="ah-1", + ), + "model": fields.Integer( + required=True, + description="vehicle serial number", + example="ah-1", + ), + "active": fields.Boolean( + required=False, + description="Vehicle in mission", + example=True, + ), + }, +) +# TODO: Add generic positions schema +# TODO: Define units for all schemas diff --git a/autonomy_configuration.py b/autonomy_configuration.py index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..3cbadf9d9451594e745209e1ed9941596eecbc17 100644 --- a/autonomy_configuration.py +++ b/autonomy_configuration.py @@ -0,0 +1,100 @@ +""" + schemas: configuration sent to Autonomy Engine (i.e. during an emergency, + if a vehicle needs to be removed from the mission planning) +""" +from . import api, message_header_schema, vehicle_schema +from flask_restx import fields + + +squad_metadata_schema = api.model( + "SquadMetadataSchema", + { + "squad_ID": fields.Integer( + required=True, + description="vehicle serial number", + example="ah-1", + ), + "no_of_vehicles": fields.Integer( + required=True, + description="number of vehicle serial number", + example="ah-1", + ), + "vehicles": fields.List( + fields.Nested(vehicle_schema), + required=True, + description="Metadata pf each vehicle", + ), + "squad_mission_type": fields.String( + required=True, + description="Survey or Detail", + example="survey", + ), + "squad_execution": fields.Boolean( + required=True, + description="True if Squad of survey executed by Autonomy Engine", + example=False, + ), + }, +) + +constraints_schema = api.model( + "ConstraintsSchema", + # TODO: Should this be per vehicle instead of squad? + { + "min_altitude": fields.Float( + required=True, + description="Minimum altitude set for squad.", + example=15.2, + ), + "min_velocity": fields.Float( + required=True, + description="Minimum velocity set for squad.", + example=0.1, + ), + "max_velocity": fields.Float( + required=True, + description="Maximum altitude set for squad.", + example=0.9, + ), + }, +) + +environment_config_schema = api.model( # TODO: Discuss how regions are defined + "EnvironmentConfig", + { + "region_of_interest": fields.String(), + "exclusion_zone": fields.String(), + }, +) +# Main Autonomy Configuration Schema +autonomy_configuration_schema = api.model( + "SquadConfigurationSchema", + { + "message": fields.Nested( + message_header_schema, + required=True, + description="Message header", + ), + "ID": fields.Integer( + required=True, + description="Unique identifier tagged to version of this" + + " configuration plan", + example=3, + ), + "time": fields.String( + required=True, + description="", + example="", + ), + "squads": fields.Nested( + squad_metadata_schema, + required=False, + description="Details of each squad", + ), + "environment": fields.Nested( + environment_config_schema, + required=False, + description="Region of interest and exclusion zone", + ), + }, +) diff --git a/vehicle_status.py b/vehicle_status.py new file mode 100644 index 0000000000000000000000000000000000000000..4b5314abec9cae918c2123d575e94a5a909e31a7 --- /dev/null +++ b/vehicle_status.py @@ -0,0 +1,124 @@ +""" + schema: vehicle-specific decoded status message (DRAFT) +""" +from . import message_header_schema, api +from flask_restx import fields + + +vehicle_status_message_schema = api.model( + "VehicleStatusMessage", + { + "message": fields.Nested( + message_header_schema, + required=True, + description="Message header", + ), + "serial_number": fields.String( + required=True, + description="vehicle serial number", + example="ah-1", + ), + "time": fields.String( + required=True, + description="Timestamp of message", + example="2022-11-16T00:00:00Z", + ), + "version": fields.Integer( + required=False, + description="", # we can track the version of the AE plan? + example="", + ), + "platform_ID": fields.Integer( + required=True, + description="Platform ID", + example=2, + ), + "platform_type": fields.String( + required=True, + description="The high level type of this vehicle", + example="alr", + ), + "platform_state": fields.String( + required=True, + description="", + example="SAFETY_STOP", + ), + "mission_track_number": fields.Integer( + required=True, + description=( + "Track number - stage in mission (e.g. " + + "4 --> Waypoint 3 to Waypoint 4)" + ), + example=4, + ), + "range_to_go": fields.Float( + required=False, + description="Estimated distance to reach next waypoint", + example=124.3, + ), + "vehicle_state": fields.String( + required=True, + description="Current state executed by vehicle. E.g. " + + "STOP, IDLE, ABORT.", + example="IDLE", + ), + "c2_health_status": fields.String( + required=True, + description="Health status determined by vehicle's C2 " + + "checks on sensors", + example="Warning", + ), + "gps_source": fields.Float( + required=True, + description="Source of gps position. E.g. Beacon", + example="internal", + ), + "latitude": fields.Float( + required=True, + description="Latitude in <insert units>", + example="", + ), + "longitude": fields.Float( + required=True, + description="Longitude in <insert units>", + example="", + ), + "depth": fields.Float( + required=True, + description="", + example="", + ), + "gps_fix_seconds_ago": fields.String( + required=True, + description="", + example="", + ), + "battery_voltage": fields.Float( + required=True, + description="Volts", + example=23.0, + ), + "battery_current": fields.Float( + required=False, + description="Amps", + example=1.2, + ), + "battery_current_per_hour": fields.Float( + required=False, + description="Amp-Hours", + example=1.2, + ), + "battery_wattage": fields.Float( + required=False, + description="Watts", + example=23.0, + ), + "battery_wattage_per_hour": fields.Float( + required=False, + description="Watt-Hours", + example=23.0, + ), + }, +) + +# TBD: Do we append beacon positions with vehicle positions? diff --git a/vehicle_status_schema.py b/vehicle_status_schema.py deleted file mode 100644 index a44eb2d550a051974d696e3007734d3630d902f7..0000000000000000000000000000000000000000 --- a/vehicle_status_schema.py +++ /dev/null @@ -1,84 +0,0 @@ -""" - schemas: vehicle-specific decoded status message (DRAFT ONLY) -""" -from flask_restx import Api, fields -from flask import Flask - -app = Flask(__name__) -api = Api(app) - -vehicle_status_message_schema = api.model( - "VehicleStatusMessage", - { - "message_source": fields.String( - required=True, - description="Where is this message from", - example="autonomy_engine", - ), - "message_destination": fields.String( - required=True, - description="What is the destination of this message", - example="ah-1", - ), - "encoded": fields.Boolean( - required=True, - description="Is this message encoded (encoded=True, decoded=False)", - example=False, - ), - "serial_number": fields.String( - required=True, - description="vehicle serial number", - example="ah-1", - ), - "time": fields.String( - required=True, - description="Timestamp of message", - example="2022-11-16T00:00:00Z", - ), - "version": fields.Integer( - required=True, - description="", # we can track the version of the AE plan? - example="", - ), - "platform_ID": fields.Integer( - required=True, - description="Platform ID", - example=2, - ), - "platform_type": fields.String( - required=True, - description="The high level type of this vehicle", - example="alr", - ), - "platform_state": fields.String( - required=True, - description="", - example="SAFETY_STOP", - ), - "current_mission_state": fields.String( - required=True, - description="", - example="", - ), - "gps_source": fields.Float( - required=True, - description="", - example="", - ), - "gps_lat": fields.Float( - required=True, - description="", - example="", - ), - "gps_lon": fields.Float( - required=True, - description="", - example="", - ), - "gps_fix_seconds_ago": fields.String( - required=True, - description="", - example="", - ), - }, -)