From f7ad53eacc715bf4f4fefb5c38fbc021a761eb66 Mon Sep 17 00:00:00 2001 From: Trishna Saeharaseelan <trishna.saeharaseelan@noc.ac.uk> Date: Wed, 14 Dec 2022 17:25:36 +0000 Subject: [PATCH] fix: examples for hydrosurv and correct SOAR_README.md --- __init__.py | 2 +- docs/generate_swagger.py | 181 +++++++++++------- ...knowledgment.json => acknowledgement.json} | 6 +- examples/all/compiled_mission_plan.json | 0 examples/all/compiled_observation.json | 0 examples/all/compiled_platform_status.json | 0 examples/all/emergency.json | 0 examples/all/mission_plan.json | 10 +- examples/all/observation.json | 8 +- examples/all/planning_configuration.json | 6 +- examples/all/platform_status.json | 40 ++-- examples/autonomy_engine/mission_plan.json | 25 --- .../planning_configuration.json | 101 ---------- examples/autonomy_engine/platform_status.json | 51 ----- examples/ecosub_c2/mission_plan.json | 25 +++ .../observation.json | 8 +- examples/ecosub_c2/platform_status.json | 44 +++++ ...knowledgment.json => acknowledgement.json} | 6 +- examples/hydrosurv_adapter/mission_plan.json | 10 +- .../hydrosurv_adapter/platform_status.json | 40 ++-- formats/__init__.py | 25 ++- formats/acknowledgement.py | 5 +- formats/mission_plan.py | 16 +- formats/observation.py | 11 +- formats/planning_configuration.py | 6 +- formats/platform_status.py | 48 +++-- project/SOAR_README.md | 143 +++++++++++--- 27 files changed, 430 insertions(+), 387 deletions(-) rename examples/all/{acknowledgment.json => acknowledgement.json} (52%) create mode 100644 examples/all/compiled_mission_plan.json create mode 100644 examples/all/compiled_observation.json create mode 100644 examples/all/compiled_platform_status.json create mode 100644 examples/all/emergency.json delete mode 100644 examples/autonomy_engine/mission_plan.json delete mode 100644 examples/autonomy_engine/planning_configuration.json delete mode 100644 examples/autonomy_engine/platform_status.json create mode 100644 examples/ecosub_c2/mission_plan.json rename examples/{autonomy_engine => ecosub_c2}/observation.json (63%) create mode 100644 examples/ecosub_c2/platform_status.json rename examples/hydrosurv_adapter/{acknowledgment.json => acknowledgement.json} (52%) diff --git a/__init__.py b/__init__.py index 61ab515..7a18f10 100644 --- a/__init__.py +++ b/__init__.py @@ -2,6 +2,7 @@ from flask_restx import Api from flask import Flask + # import os __all__ = [ @@ -11,4 +12,3 @@ __all__ = [ app = Flask(__name__) api = Api(app) # api = Marshmallow(app) - diff --git a/docs/generate_swagger.py b/docs/generate_swagger.py index ba5f7e3..cd442c0 100644 --- a/docs/generate_swagger.py +++ b/docs/generate_swagger.py @@ -18,7 +18,8 @@ swagger_template = dict( "title": LazyString(lambda: "SoAR Backbone Message Formats"), "version": LazyString(lambda: "0.1"), "description": LazyString( - lambda: "Backbone Message Format component for the Squad of Autonomous Robots (SoAR) message definitions." + lambda: "Backbone Message Format component for the Squad of" + + " Autonomous Robots (SoAR) message definitions." ), }, host=LazyString(lambda: request.host), @@ -28,11 +29,21 @@ swagger_template = dict( full_message_schema = api.model( "FullMessageSchema", { + "message_ID": fields.String( + required=True, + description="UUID assigned to this message", + example="b427003c-7bc8-11ed-a1eb-0242ac120002", + ), "timestamp": fields.DateTime( required=True, description="Timestamp of message", example="2022-11-16T00:00:00Z", ), + "version": fields.Float( + required=True, + description="Version of comms bacbone messaging format protocol", + example=2.0, + ), "source": fields.String( required=True, description="Where is this message from", @@ -61,7 +72,30 @@ full_message_schema = api.model( ), }, ) - +sensor_schema = api.model( + "SensorSchema", + { + "sensor_ID": fields.Integer( + required=True, + description="unique identifier for platform", + example=2, + ), + "serial": fields.String( + required=False, + description="serial number of sensor", + example="mbes-001", + ), + "sensor_status": fields.Boolean( + required=False, + description="Sensor switched on (True) or off (False)", + example=True, + ), + "additional_data": fields.Raw( + required=False, + description="Any addition fields/data to be added here", + ), + }, +) constraints_schema = api.model( "ConstraintsSchema", { @@ -89,27 +123,23 @@ platform_schema = api.model( "platform_ID": fields.Integer( required=True, description="unique identifier for platform", - example="ah-1", + example=1, ), - "serial": fields.Integer( + "serial": fields.String( required=True, description="platform serial number", - example="ah-1", + example="reav-60", ), - "model": fields.Integer( + "model": fields.String( required=True, description="platform serial number", - example="ah-1", + example="reav", ), "constraints": fields.Nested(constraints_schema), - "active": fields.Boolean( - required=False, - description="When a platform is in deployment (executing a mission plan) this should be True", - example=True, - ), }, ) + action_schema = api.model( "AutonomyEngineAction", { @@ -121,7 +151,8 @@ action_schema = api.model( ), "flight_style": fields.String( required=False, - description="Platform-specific modes/flight styles to perform next action", + description="Platform-specific modes/flight styles to perform" + + " next action", example="orbit", ), "latitude_waypoint": fields.Float( @@ -152,17 +183,8 @@ action_schema = api.model( ), "send_environmental_data": fields.Boolean( required=False, - description="To trigger the platform to send list of observations if any found", - example=False, - ), - "scanline": fields.Boolean( - required=False, - description="To trigger the platform to scan-line", - example=False, - ), - "scanpoint": fields.Boolean( - required=False, - description="To trigger the platform to send list of observations if any found", + description="DO WE NEED THIS? To trigger the platform to send" + + " list of observations if any found", example=False, ), }, @@ -189,8 +211,8 @@ mission_plan_schema = api.model( "plan": fields.List( fields.Nested(action_schema), required=True, - description="Sequence of actions/instructions generated by the " + - " Autonomy Engine that should be compiled by the respective C2.", + description="Sequence of actions/instructions generated by the " + + " Autonomy Engine that should be compiled by the respective C2.", ), }, ) @@ -212,17 +234,20 @@ observation_schema = api.model( # properties of each observation? "points_of_interest": fields.Float( required=False, - description="Points from features of interest identified by platform if any found. DEFINE FORMAT.", + description="Points from features of interest identified by" + + " platform if any found. DEFINE FORMAT.", example="", ), "region_surveyed": fields.Float( required=False, - description="Region surveyed by given platform. DEFINE FORMAT. GEOJSON?", + description="Region surveyed by given platform. DEFINE FORMAT." + + " GEOJSON?", example="", ), "quality_of_points": fields.Float( required=False, - description="Quality/strength of points from features of interest identified by platform. DEFINE FORMAT.", + description="Quality/strength of points from features of interest" + + " identified by platform. DEFINE FORMAT.", example=0.98, ), "additional_data": fields.Raw( @@ -239,7 +264,8 @@ region_schema = api.model( { "region": fields.Raw( required=True, - description="Using GEOJSON, exact region of interest in rectangle format polygon", + description="Using GEOJSON, exact region of interest in rectangle" + + " format polygon", example={ "type": "FeatureCollection", "features": [ @@ -284,7 +310,8 @@ squad_metadata_schema = api.model( ), "squad_mission_type": fields.String( required=True, - description="Mission of given squad: `tracking`, `survey`, `inspection`", + description="Mission of given squad: `tracking`, `survey`," + + " `inspection`", example="survey", ), "squad_state": fields.Boolean( @@ -334,7 +361,8 @@ gps_schema = api.model( { "gps_source": fields.Float( # TODO: TBD with partners required=False, - description="Source of gps position. E.g. USBL (external), platform itself (internal)", + description="Source of gps position. E.g. USBL (external), " + + "platform itself (internal)", example="internal", ), "latitude_type": fields.String( @@ -371,26 +399,6 @@ gps_schema = api.model( }, ) -sensor_schema = api.model( - "Sensor", - { - "sensor_name": fields.String( - required=False, - description="Name of sensor (e.g. MBES for AH1 and SideScan for Ecosub", - example="MBES", - ), - "sensor_status": fields.Boolean( - required=False, - description="Sensor switched on (True) or off (False)", - example=True, - ), - "additional_data": fields.Raw( - required=False, - description="Add any additional sensor-related data here.", - example={"sensor_loadtime_seconds": 30.0}, - ), - }, -) platform_status_message_schema = api.model( "platformStatusMessage", { @@ -399,7 +407,17 @@ platform_status_message_schema = api.model( required=True, description="Message header", ), - "platform": fields.Nested(platform_schema), + "platform_ID": fields.Integer( + required=True, + description="unique identifier for platform", + example=1, + ), + "active": fields.Boolean( + required=False, + description="When a platform is in deployment (executing a mission" + + " plan) this should be True", + example=True, + ), "platform_state": fields.String( # TODO: Define dictionary with potential STATES of each platform required=False, @@ -409,7 +427,8 @@ platform_status_message_schema = api.model( ), "autonomy_plan_ID": fields.Integer( required=False, - description="Last mission plan ID (according to Autonomy Engine's mission plan number) executed by platform", + description="Last mission plan ID (according to Autonomy Engine's " + + "mission plan number) executed by platform", example=1, ), "mission_track_ID": fields.Integer( @@ -452,9 +471,8 @@ platform_status_message_schema = api.model( example="Warning", ), "gps_data": fields.List( - fields.Nested( - gps_schema - ), # TODO: TBD Do we want a list of gps readings to allow > 1 reading i.e. platform + usbl + fields.Nested(gps_schema), # TODO: TBD Do we want a list of gps + # readings to allow > 1 reading i.e. platform + usbl required=True, description="Metadata pf each platform", ), @@ -470,7 +488,8 @@ platform_status_message_schema = api.model( ), "battery_remaining_capacity": fields.Float( required=True, - description="Battery remaining capacity % provided by respective platform/C2.", + description="Battery remaining capacity % provided by respective" + + " platform/C2.", example=80.0, ), "sensor_config": fields.Nested( @@ -495,14 +514,14 @@ acknowledgement_schema = api.model( ), "status": fields.String( required=True, - description="Highest level of acknowledgement. I.e. `c2_received`: Received by C2," - + " `c2_sent`: Sent from C2->Platform, `executed`: Executed by platform", + description="Highest level of acknowledgement. I.e. `c2_received`:" + + " Received by C2,`c2_sent`: Sent from C2" + + " ->Platform, `executed`: Executed by platform", ), }, ) - swagger_config = { "headers": [], "specs": [ @@ -530,7 +549,11 @@ swagger_config = { swagger = Swagger(app, template=swagger_template, config=swagger_config) -ns1 = api.namespace("message", description="Message Wrapper (Full Message Schema) Format") +ns1 = api.namespace( + "message", description="Message Wrapper (Full Message Schema) Format" +) + + @ns1.route("/wrapper") class MessageWrapper(Resource): @ns1.response(200, "Success", full_message_schema) @@ -538,7 +561,12 @@ class MessageWrapper(Resource): pass -ns2 = api.namespace("platform_status", description="platform Status Message Format") +ns2 = api.namespace( + "platform_status", + description="platform Status Message Format", +) + + @ns2.route("") class platformStatus(Resource): @ns2.response(200, "Success", platform_status_message_schema) @@ -547,9 +575,12 @@ class platformStatus(Resource): ns3 = api.namespace( - "planning_configuration", description="Planning Configuration Format. Do we want region of interest to be per squad, per platform or in the main schema?" + "planning_configuration", + description="Planning Configuration Format. Do we want region of " + + "interest to be per squad, per platform or in the main schema?", ) + @ns3.route("") class PlanningConfiguration(Resource): @ns3.response(200, "Success", planning_configuration_schema) @@ -558,8 +589,13 @@ class PlanningConfiguration(Resource): # @api.route('/mission-plan/<str:platform_type') -# @api.doc(params={"platform_type": "The type of platform of the mission plan to target."}) -ns4 = api.namespace("mission_plan", description="Mission Plan Format Per platform") +# @api.doc(params={"platform_type": "The type of platform of the +# mission plan to target."}) +ns4 = api.namespace( + "mission_plan", + description="Mission Plan Format Per platform", +) + @ns4.route("") class MissionPlan(Resource): @@ -567,18 +603,29 @@ class MissionPlan(Resource): def get(self): pass -ns5 = api.namespace("observation", description="Observation Format --> Per platform or generic?") + +ns5 = api.namespace( + "observation", + description="Observation Format --> Per platform or generic?", +) + + @ns5.route("") class Observation(Resource): @ns5.response(200, "Success", observation_schema) def get(self): pass + + ns6 = api.namespace("acknowledgement", description="Acknowledgment Format") + + @ns6.route("") class Acknowledgment(Resource): @ns6.response(200, "Success", acknowledgement_schema) def get(self): pass + if __name__ == "__main__": app.run() diff --git a/examples/all/acknowledgment.json b/examples/all/acknowledgement.json similarity index 52% rename from examples/all/acknowledgment.json rename to examples/all/acknowledgement.json index 3c7b91f..4052202 100644 --- a/examples/all/acknowledgment.json +++ b/examples/all/acknowledgement.json @@ -1,11 +1,13 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", + "version": 1, "source": "hydrosurv_adapter", "destination": "autonomy_engine", "encoded": false, - "type": "platform_status", + "type": "acknowledgement", "payload": { - "message_ID": 202, + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac999999", "status": "executed" } } \ No newline at end of file diff --git a/examples/all/compiled_mission_plan.json b/examples/all/compiled_mission_plan.json new file mode 100644 index 0000000..e69de29 diff --git a/examples/all/compiled_observation.json b/examples/all/compiled_observation.json new file mode 100644 index 0000000..e69de29 diff --git a/examples/all/compiled_platform_status.json b/examples/all/compiled_platform_status.json new file mode 100644 index 0000000..e69de29 diff --git a/examples/all/emergency.json b/examples/all/emergency.json new file mode 100644 index 0000000..e69de29 diff --git a/examples/all/mission_plan.json b/examples/all/mission_plan.json index e97e553..add7383 100644 --- a/examples/all/mission_plan.json +++ b/examples/all/mission_plan.json @@ -1,7 +1,9 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", - "source": "hydrosurv_adapter", - "destination": "autonomy_engine", + "version": 2, + "source": "autonomy_engine", + "destination": "ah-1", "encoded": false, "type": "platform_status", "payload": { @@ -16,9 +18,7 @@ "altitude": 0, "depth": 0, "activate_payload": false, - "send_environmental_data": false, - "scanline": false, - "scanpoint": false + "send_environmental_data": false } ] } diff --git a/examples/all/observation.json b/examples/all/observation.json index bbbde99..a4a8574 100644 --- a/examples/all/observation.json +++ b/examples/all/observation.json @@ -1,13 +1,15 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", - "source": "hydrosurv_adapter", + "version": 2, + "source": "ecosub_c2", "destination": "autonomy_engine", "encoded": false, "type": "platform_status", "payload": { "platform_serial":"ecosub-3", - "points_of_interest": "", - "region_surveyed": "", + "points_of_interest": [], + "region_surveyed": [], "quality_of_points": 0.98, "additional_data": { "sensor_x": false diff --git a/examples/all/planning_configuration.json b/examples/all/planning_configuration.json index df60421..a6576ce 100644 --- a/examples/all/planning_configuration.json +++ b/examples/all/planning_configuration.json @@ -1,7 +1,9 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", - "source": "gui", - "destination": "autonomy_engine", + "version": 2, + "source": "autonomy_engine", + "destination": "ah-1", "encoded": false, "type": "platform_status", "payload": { diff --git a/examples/all/platform_status.json b/examples/all/platform_status.json index 78a156b..b459ecb 100644 --- a/examples/all/platform_status.json +++ b/examples/all/platform_status.json @@ -1,29 +1,22 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", + "version": 1, "source": "hydrosurv_adapter", "destination": "autonomy_engine", "encoded": false, "type": "platform_status", "payload": { - "platform": { - "platform_ID": 2, - "serial": "ah-1", - "model": "ah-1", - "constraints": { - "min_altitude": 15.2, - "min_velocity": 0.1, - "max_velocity": 0.9 - }, - "active": true - }, - "platform_state": "IDLE", + "platform_ID": 1, + "active": true, + "platform_state": "ORBIT", "autonomy_plan_ID": 1, "mission_track_ID": 4, "mission_action_ID": 1, - "range_to_go": 124.3, - "speed_over_ground": 124.3, - "water_current_velocity": 124.3, - "thrust_applied": 124.3, + "range_to_go": 0.3, + "speed_over_ground": 0.3, + "water_current_velocity": 0.3, + "thrust_applied": 0.3, "health_status": "Warning", "gps_data": [ { @@ -36,16 +29,13 @@ "altitude": 0.0 } ], - "localisation_error": 0.008, - "usbl_fix_seconds_ago": 20.3, + "localisation_error": null, + "usbl_fix_seconds_ago": null, "battery_remaining_capacity": 80, "sensor_config": { - "sensor_name": "MBES", - "sensor_status": false, - "additional_data": { - "sensor_loadtime_seconds": 30 - } - } + "sensor_name": null, + "sensor_status": false, + "additional_data": null } } -} \ No newline at end of file + } \ No newline at end of file diff --git a/examples/autonomy_engine/mission_plan.json b/examples/autonomy_engine/mission_plan.json deleted file mode 100644 index e97e553..0000000 --- a/examples/autonomy_engine/mission_plan.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "timestamp": "2022-11-16T00:00:00Z", - "source": "hydrosurv_adapter", - "destination": "autonomy_engine", - "encoded": false, - "type": "platform_status", - "payload": { - "plan_ID": 1, - "platform_serial": "reav-60", - "plan": [ - { - "action": "move", - "flight_style": "orbit", - "latitude_waypoint": -4.187143188645706, - "longitude_waypoint": 50.37072283932642, - "altitude": 0, - "depth": 0, - "activate_payload": false, - "send_environmental_data": false, - "scanline": false, - "scanpoint": false - } - ] - } -} \ No newline at end of file diff --git a/examples/autonomy_engine/planning_configuration.json b/examples/autonomy_engine/planning_configuration.json deleted file mode 100644 index df60421..0000000 --- a/examples/autonomy_engine/planning_configuration.json +++ /dev/null @@ -1,101 +0,0 @@ -{ - "timestamp": "2022-11-16T00:00:00Z", - "source": "gui", - "destination": "autonomy_engine", - "encoded": false, - "type": "platform_status", - "payload": { - "ID": 3, - "squads": { - "squad_ID": 23, - "no_of_platforms": 3, - "platforms": [ - { - "platform_ID": 1, - "serial": "ah-1", - "model": "ah-1", - "constraints": { - "min_altitude": 15.2, - "min_velocity": 0.1, - "max_velocity": 0.9 - }, - "active": true - } - ], - "squad_mission_type": "survey", - "squad_state": false, - "region_of_interest": [ - { - "region": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "properties": {}, - "geometry": { - "coordinates": [ - [ - [ - -4.187143188645706, - 50.37072283932642 - ], - [ - -4.202697005964865, - 50.368816892405874 - ], - [ - -4.203156724702808, - 50.365640144076906 - ], - [ - -4.19449868846155, - 50.362267670845654 - ] - ] - ], - "type": "Polygon" - } - } - ] - } - } - ], - "exclusion_zones": [ - { - "region": { - "type": "FeatureCollection", - "features": [ - { - "type": "Feature", - "properties": {}, - "geometry": { - "coordinates": [ - [ - [ - -4.187143188645706, - 50.37072283932642 - ], - [ - -4.202697005964865, - 50.368816892405874 - ], - [ - -4.203156724702808, - 50.365640144076906 - ], - [ - -4.19449868846155, - 50.362267670845654 - ] - ] - ], - "type": "Polygon" - } - } - ] - } - } - ] - } - } -} \ No newline at end of file diff --git a/examples/autonomy_engine/platform_status.json b/examples/autonomy_engine/platform_status.json deleted file mode 100644 index 78a156b..0000000 --- a/examples/autonomy_engine/platform_status.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "timestamp": "2022-11-16T00:00:00Z", - "source": "hydrosurv_adapter", - "destination": "autonomy_engine", - "encoded": false, - "type": "platform_status", - "payload": { - "platform": { - "platform_ID": 2, - "serial": "ah-1", - "model": "ah-1", - "constraints": { - "min_altitude": 15.2, - "min_velocity": 0.1, - "max_velocity": 0.9 - }, - "active": true - }, - "platform_state": "IDLE", - "autonomy_plan_ID": 1, - "mission_track_ID": 4, - "mission_action_ID": 1, - "range_to_go": 124.3, - "speed_over_ground": 124.3, - "water_current_velocity": 124.3, - "thrust_applied": 124.3, - "health_status": "Warning", - "gps_data": [ - { - "gps_source": "internal", - "latitude_type": "", - "longitude_type": "", - "latitude": -7.432, - "longitude": 50.365, - "depth": 0.0, - "altitude": 0.0 - } - ], - "localisation_error": 0.008, - "usbl_fix_seconds_ago": 20.3, - "battery_remaining_capacity": 80, - "sensor_config": { - "sensor_name": "MBES", - "sensor_status": false, - "additional_data": { - "sensor_loadtime_seconds": 30 - } - } - } - } -} \ No newline at end of file diff --git a/examples/ecosub_c2/mission_plan.json b/examples/ecosub_c2/mission_plan.json new file mode 100644 index 0000000..07591cf --- /dev/null +++ b/examples/ecosub_c2/mission_plan.json @@ -0,0 +1,25 @@ +{ + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", + "timestamp": "2022-11-16T00:00:00Z", + "version": 2, + "source": "autonomy_engine", + "destination": "ecosub_c2", + "encoded": false, + "type": "mission_plan", + "payload": { + "plan_ID": 3, + "platform_serial": "ecosub-4", + "plan": [ + { + "action": "move", + "flight_style": "dive", + "latitude_waypoint": -4.187143188645706, + "longitude_waypoint": 50.37072283932642, + "altitude": 20, + "depth": null, + "activate_payload": true, + "send_environmental_data": false + } + ] + } +} \ No newline at end of file diff --git a/examples/autonomy_engine/observation.json b/examples/ecosub_c2/observation.json similarity index 63% rename from examples/autonomy_engine/observation.json rename to examples/ecosub_c2/observation.json index bbbde99..a4a8574 100644 --- a/examples/autonomy_engine/observation.json +++ b/examples/ecosub_c2/observation.json @@ -1,13 +1,15 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", - "source": "hydrosurv_adapter", + "version": 2, + "source": "ecosub_c2", "destination": "autonomy_engine", "encoded": false, "type": "platform_status", "payload": { "platform_serial":"ecosub-3", - "points_of_interest": "", - "region_surveyed": "", + "points_of_interest": [], + "region_surveyed": [], "quality_of_points": 0.98, "additional_data": { "sensor_x": false diff --git a/examples/ecosub_c2/platform_status.json b/examples/ecosub_c2/platform_status.json new file mode 100644 index 0000000..460bc82 --- /dev/null +++ b/examples/ecosub_c2/platform_status.json @@ -0,0 +1,44 @@ +{ + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", + "timestamp": "2022-11-16T00:00:00Z", + "version": 1, + "source": "hermes_ecosub", + "destination": "autonomy_engine", + "encoded": false, + "type": "platform_status", + "payload": { + "platform_ID": 2, + "active": true, + "platform_state": "IDLE", + "autonomy_plan_ID": 1, + "mission_track_ID": 4, + "mission_action_ID": 1, + "range_to_go": 12.3, + "speed_over_ground": 10.3, + "water_current_velocity": 10.3, + "thrust_applied": 0.3, + "health_status": "Warning", + "gps_data": [ + { + "gps_source": "internal", + "latitude_type": "", + "longitude_type": "", + "latitude": -7.432, + "longitude": 50.365, + "depth": 5.0, + "altitude": 20.0 + } + ], + "localisation_error": null, + "usbl_fix_seconds_ago": null, + "battery_remaining_capacity": 80, + "sensor_config": { + "sensor_ID": 22, + "serial": "sidescan-2x", + "sensor_status": true, + "additional_data": { + "whiskers_on": true + } + } + } + } \ No newline at end of file diff --git a/examples/hydrosurv_adapter/acknowledgment.json b/examples/hydrosurv_adapter/acknowledgement.json similarity index 52% rename from examples/hydrosurv_adapter/acknowledgment.json rename to examples/hydrosurv_adapter/acknowledgement.json index 3c7b91f..4052202 100644 --- a/examples/hydrosurv_adapter/acknowledgment.json +++ b/examples/hydrosurv_adapter/acknowledgement.json @@ -1,11 +1,13 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", + "version": 1, "source": "hydrosurv_adapter", "destination": "autonomy_engine", "encoded": false, - "type": "platform_status", + "type": "acknowledgement", "payload": { - "message_ID": 202, + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac999999", "status": "executed" } } \ No newline at end of file diff --git a/examples/hydrosurv_adapter/mission_plan.json b/examples/hydrosurv_adapter/mission_plan.json index e97e553..add7383 100644 --- a/examples/hydrosurv_adapter/mission_plan.json +++ b/examples/hydrosurv_adapter/mission_plan.json @@ -1,7 +1,9 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", - "source": "hydrosurv_adapter", - "destination": "autonomy_engine", + "version": 2, + "source": "autonomy_engine", + "destination": "ah-1", "encoded": false, "type": "platform_status", "payload": { @@ -16,9 +18,7 @@ "altitude": 0, "depth": 0, "activate_payload": false, - "send_environmental_data": false, - "scanline": false, - "scanpoint": false + "send_environmental_data": false } ] } diff --git a/examples/hydrosurv_adapter/platform_status.json b/examples/hydrosurv_adapter/platform_status.json index ab1a23a..b459ecb 100644 --- a/examples/hydrosurv_adapter/platform_status.json +++ b/examples/hydrosurv_adapter/platform_status.json @@ -1,29 +1,22 @@ { + "message_ID": "b427003c-7bc8-11ed-a1eb-0242ac120002", "timestamp": "2022-11-16T00:00:00Z", + "version": 1, "source": "hydrosurv_adapter", "destination": "autonomy_engine", "encoded": false, "type": "platform_status", "payload": { - "platform": { - "platform_ID": 23, - "serial": "ah-1", - "model": "ah-1", - "constraints": { - "min_altitude": 15.2, - "min_velocity": 0.1, - "max_velocity": 0.9 - }, - "active": true - }, - "platform_state": "IDLE", + "platform_ID": 1, + "active": true, + "platform_state": "ORBIT", "autonomy_plan_ID": 1, "mission_track_ID": 4, "mission_action_ID": 1, - "range_to_go": 124.3, - "speed_over_ground": 124.3, - "water_current_velocity": 124.3, - "thrust_applied": 124.3, + "range_to_go": 0.3, + "speed_over_ground": 0.3, + "water_current_velocity": 0.3, + "thrust_applied": 0.3, "health_status": "Warning", "gps_data": [ { @@ -36,16 +29,13 @@ "altitude": 0.0 } ], - "localisation_error": 0.008, - "usbl_fix_seconds_ago": 20.3, + "localisation_error": null, + "usbl_fix_seconds_ago": null, "battery_remaining_capacity": 80, "sensor_config": { - "sensor_name": "MBES", - "sensor_status": false, - "additional_data": { - "sensor_loadtime_seconds": 30 - } - } + "sensor_name": null, + "sensor_status": false, + "additional_data": null } } -} \ No newline at end of file + } \ No newline at end of file diff --git a/formats/__init__.py b/formats/__init__.py index bf46b07..fda3a30 100644 --- a/formats/__init__.py +++ b/formats/__init__.py @@ -21,11 +21,21 @@ message_types = [ full_message_schema = api.model( "FullMessageSchema", { + "message_ID": fields.String( + required=True, + description="UUID assigned to this message", + example="b427003c-7bc8-11ed-a1eb-0242ac120002", + ), "timestamp": fields.DateTime( required=True, description="Timestamp of message", example="2022-11-16T00:00:00Z", ), + "version": fields.Float( + required=True, + description="Version of comms bacbone messaging format protocol", + example=2.0, + ), "source": fields.String( required=True, description="Where is this message from", @@ -82,23 +92,18 @@ platform_schema = api.model( "platform_ID": fields.Integer( required=True, description="unique identifier for platform", - example="ah-1", + example=1, ), - "serial": fields.Integer( + "serial": fields.String( required=True, description="platform serial number", - example="ah-1", + example="reav-60", ), - "model": fields.Integer( + "model": fields.String( required=True, description="platform serial number", - example="ah-1", + example="reav", ), "constraints": fields.Nested(constraints_schema), - "active": fields.Boolean( - required=False, - description="When a platform is in deployment (executing a mission plan) this should be True", - example=True, - ), }, ) diff --git a/formats/acknowledgement.py b/formats/acknowledgement.py index b7f887e..af0cff0 100644 --- a/formats/acknowledgement.py +++ b/formats/acknowledgement.py @@ -22,8 +22,9 @@ acknowledgement_schema = api.model( ), "status": fields.String( required=True, - description="Highest level of acknowledgement. I.e. `c2_received`: Received by C2," - + " `c2_sent`: Sent from C2->Platform, `executed`: Executed by platform", + description="Highest level of acknowledgement. I.e. `c2_received`:" + + " Received by C2, `c2_sent`: Sent from C2->Platform, `executed`:" + + " Executed by platform", ), }, ) diff --git a/formats/mission_plan.py b/formats/mission_plan.py index acd10e7..c6af384 100644 --- a/formats/mission_plan.py +++ b/formats/mission_plan.py @@ -18,7 +18,8 @@ action_schema = api.model( ), "flight_style": fields.String( required=False, - description="Platform-specific modes/flight styles to perform next action", + description="Platform-specific modes/flight styles to perform" + + " next action", example="orbit", ), "latitude_waypoint": fields.Float( @@ -49,17 +50,8 @@ action_schema = api.model( ), "send_environmental_data": fields.Boolean( required=False, - description="To trigger the platform to send list of observations if any found", - example=False, - ), - "scanline": fields.Boolean( - required=False, - description="To trigger the platform to scan-line", - example=False, - ), - "scanpoint": fields.Boolean( - required=False, - description="To trigger the platform to send list of observations if any found", + description="To trigger the platform to send list of observations" + + " if any found", example=False, ), }, diff --git a/formats/observation.py b/formats/observation.py index 88306e4..6889b15 100644 --- a/formats/observation.py +++ b/formats/observation.py @@ -1,7 +1,7 @@ """ schema: platform-specific decoded status message (DRAFT) """ -from . import full_message_schema, platform_schema, api +from . import full_message_schema, api from flask_restx import fields @@ -22,17 +22,20 @@ observation_schema = api.model( # properties of each observation? "points_of_interest": fields.Float( required=False, - description="Points from features of interest identified by platform if any found. DEFINE FORMAT.", + description="Points from features of interest identified by" + + " platform if any found. DEFINE FORMAT.", example="", ), "region_surveyed": fields.Float( required=False, - description="Region surveyed by given platform. DEFINE FORMAT. GEOJSON?", + description="Region surveyed by given platform. DEFINE FORMAT." + + " GEOJSON?", example="", ), "quality_of_points": fields.Float( required=False, - description="Quality/strength of points from features of interest identified by platform. DEFINE FORMAT.", + description="Quality/strength of points from features of interest" + + " identified by platform. DEFINE FORMAT.", example=0.98, ), "additional_data": fields.Raw( diff --git a/formats/planning_configuration.py b/formats/planning_configuration.py index ff336dc..b46cc32 100644 --- a/formats/planning_configuration.py +++ b/formats/planning_configuration.py @@ -11,7 +11,8 @@ region_schema = api.model( { "region": fields.Raw( required=True, - description="Using GEOJSON, exact region of interest in rectangle format polygon", + description="Using GEOJSON, exact region of interest in rectangle" + + " format polygon", example={ "type": "FeatureCollection", "features": [ @@ -56,7 +57,8 @@ squad_metadata_schema = api.model( ), "squad_mission_type": fields.String( required=True, - description="Mission of given squad: `tracking`, `survey`, `inspection`", + description="Mission of given squad: `tracking`, `survey`" + + ", `inspection`", example="survey", ), "squad_state": fields.Boolean( diff --git a/formats/platform_status.py b/formats/platform_status.py index e11af4f..761b0fc 100644 --- a/formats/platform_status.py +++ b/formats/platform_status.py @@ -1,7 +1,7 @@ """ schema: platform-specific decoded status message (DRAFT) """ -from . import full_message_schema, platform_schema, api +from . import full_message_schema, api from flask_restx import fields gps_schema = api.model( @@ -9,7 +9,10 @@ gps_schema = api.model( { "gps_source": fields.Float( # TODO: TBD with partners required=False, - description="Source of gps position. E.g. USBL (external), platform itself (internal)", + description=( + "Source of gps position. E.g. USBL (external)," + + "platform itself (internal)" + ), example="internal", ), "latitude_type": fields.String( @@ -47,12 +50,17 @@ gps_schema = api.model( ) sensor_schema = api.model( - "Sensor", + "SensorSchema", { - "sensor_name": fields.String( + "sensor_ID": fields.Integer( + required=True, + description="unique identifier for platform", + example=2, + ), + "serial": fields.String( required=False, - description="Name of sensor (e.g. MBES for AH1 and SideScan for Ecosub", - example="MBES", + description="serial number of sensor", + example="mbes-001", ), "sensor_status": fields.Boolean( required=False, @@ -61,11 +69,12 @@ sensor_schema = api.model( ), "additional_data": fields.Raw( required=False, - description="Add any additional sensor-related data here.", - example={"sensor_loadtime_seconds": 30.0}, + description="Any addition fields/data to be added here", ), }, ) + + platform_status_message_schema = api.model( "platformStatusMessage", { @@ -74,7 +83,17 @@ platform_status_message_schema = api.model( required=True, description="Message header", ), - "platform": fields.Nested(platform_schema), + "platform_ID": fields.Integer( + required=True, + description="unique identifier for platform", + example=1, + ), + "active": fields.Boolean( + required=False, + description="When a platform is in deployment (executing a" + + " mission plan) this should be True", + example=True, + ), "platform_state": fields.String( # TODO: Define dictionary with potential STATES of each platform required=False, @@ -84,7 +103,8 @@ platform_status_message_schema = api.model( ), "autonomy_plan_ID": fields.Integer( required=False, - description="Last mission plan ID (according to Autonomy Engine's mission plan number) executed by platform", + description="Last mission plan ID (according to Autonomy Engine's" + + " mission plan number) executed by platform", example=1, ), "mission_track_ID": fields.Integer( @@ -127,9 +147,8 @@ platform_status_message_schema = api.model( example="Warning", ), "gps_data": fields.List( - fields.Nested( - gps_schema - ), # TODO: TBD Do we want a list of gps readings to allow > 1 reading i.e. platform + usbl + fields.Nested(gps_schema), # TODO: TBD Do we want a list of + # gps readings to allow > 1 reading i.e. platform + usbl required=True, description="Metadata pf each platform", ), @@ -145,7 +164,8 @@ platform_status_message_schema = api.model( ), "battery_remaining_capacity": fields.Float( required=True, - description="Battery remaining capacity % provided by respective platform/C2.", + description="Battery remaining capacity % provided by respective" + + " platform/C2.", example=80.0, ), "sensor_config": fields.Nested( diff --git a/project/SOAR_README.md b/project/SOAR_README.md index a8c623f..6fb0815 100644 --- a/project/SOAR_README.md +++ b/project/SOAR_README.md @@ -3,29 +3,120 @@ Squad of Adaptive Robots Project ----------------------------------- ## Message Data Flow Summary -| Partner | Message Type | Source | Destination | Via Comms Backbone? | Contains Serialized Vehicle-Specific File? | -| ------------ | ---------------------- | --------------------------- | --------------------------- | ------------------- | ------------------------------------------ | -| RHU | platform status | C2’s (Hydrosurv/Ecosub/Ah1) | Autonomy Engine | Yes | No | -| RHU | mission plan | Autonomy Engine | C2’s (Hydrosurv/Ecosub/Ah1) | Yes | No | -| RHU | planning configuration | GUI | Autonomy Engine | Yes | No | -| RHU | observation | Ecosub C2 | Autonomy Engine | Yes | No | -| Hydro-Surv | platform status | Reav-60 | Hydrosurv C2 | No | Yes | -| Hydro-Surv | platform status | Hydrosurv C2 | Autonomy Engine | Yes | No | -| Hydro-Surv | mission plan | Autonomy Engine | Hydrosurv C2 | Yes | No | -| Hydro-Surv | mission plan | Hydrosurv C2 | Reav-60 | No | Yes | -| Hydro-Surv | acknowledgement | Hydrosurv C2 | Comms Backbone (Audit) | Yes | No | -| Planet Ocean | platform status | Ecosub | Hydrosurv Adapter | No | Yes | -| Planet Ocean | platform status | Hydrosurv Adapter | Ecosub C2 | Yes | Yes | -| Planet Ocean | platform status | Ecosub C2 | Autonomy Engine | Yes | No | -| Planet Ocean | mission plan | Autonomy Engine | Ecosub C2 | Yes | No | -| Planet Ocean | mission plan | Ecosub C2 | Hydrosurv Adapter | Yes | Yes | -| Planet Ocean | mission plan | Hydrosurv Adapter | Ecosub | No | Yes | -| Planet Ocean | observation | Ecosub | Hydrosurv Adapter | No | Yes | -| Planet Ocean | observation | Hydrosurv Adapter | Ecosub C2 | Yes | Yes | -| Planet Ocean | observation | Ecosub C2 | Autonomy Engine | Yes | No | -| NOC | platform status | Ecosub | Hydrosurv Adapter | No | Yes | -| NOC | platform status | Hydrosurv Adapter | Ecosub C2 | Yes | Yes | -| NOC | platform status | Ecosub C2 | Autonomy Engine | Yes | No | -| NOC | mission plan | Autonomy Engine | Ecosub C2 | Yes | No | -| NOC | mission plan | Ecosub C2 | Hydrosurv Adapter | Yes | Yes | -| NOC | mission plan | Hydrosurv Adapter | Ecosub | No | Yes | +| Partner | Message Type | Source | Destination | Via Comms Backbone? | Contains Serialized Vehicle-Specific File? | Comment | +| --------------------- | ------------------------ | --------------------- | ------------------------------------------ | ------------------- | ------------------------------------------ | ---------------------------------------------------------------------------------------- | +| Hydrosurv (reav) | platform status-compiled | Reav-60 | Hydrosurv Adapter | No | Yes | N/A | +| Hydrosurv (reav) | platform status | Hydrosurv Adapter | Autonomy Engine | Yes | No | N/A | +| Hydrosurv (reav) | mission plan | Autonomy Engine | Hydrosurv Adapter | Yes | No | N/A | +| Hydrosurv (reav) | mission plan-compiled | Hydrosurv Adapter | Reav-60 | No | Yes | N/A | +| Hydrosurv (reav) | acknowledgement | Hydrosurv Adapter | Comms Backbone (Audit) | Yes | No | When hydrosurv adapter has (a) Received, (b) Sent Plan to Reav, and (c) Executed by Reav | +| RHU (autonomy engine) | platform status | C2’s Hydrosurv/Ecosub | Autonomy Engine | Yes | No | N/A | +| RHU (autonomy engine) | mission plan | Autonomy Engine | C2’s Hydrosurv/Ecosub | Yes | No | N/A | +| RHU (autonomy engine) | planning configuration | GUI | Autonomy Engine | Yes | No | N/A | +| RHU (autonomy engine) | observation | Ecosub C2 | Autonomy Engine | Yes | No | N/A | +| RHU (autonomy engine) | survey progress | Ecosub/AH1 C2 | Autonomy Engine | TBD | TBD | N/A | +| RHU (autonomy engine) | scanline | TBD | TBD | TBD | TBD | N/A | +| RHU (autonomy engine) | emergency | GUI | TBD – all | TBD | TBD | TBD – all platforms pre-compiled ABORT via Black box | +| Planet Ocean (ecosub) | platform status-compiled | Ecosub | Black Box TBC | No | Yes | Via Hermes + Router | +| Planet Ocean (ecosub) | platform status-compiled | Black Box TBC | Ecosub C2 | Yes | Yes | N/A | +| Planet Ocean (ecosub) | platform status | Ecosub C2 | Autonomy Engine | Yes | No | N/A | +| Planet Ocean (ecosub) | mission plan | Autonomy Engine | Ecosub C2 | Yes | No | N/A | +| Planet Ocean (ecosub) | mission plan | Ecosub C2 | Black Box TBC | Yes | Yes | N/A | +| Planet Ocean (ecosub) | mission plan-compiled | Black Box TBC | Ecosub | No | Yes | Via Hermes + Router | +| Planet Ocean (ecosub) | observation-compiled | Ecosub | Black Box TBC | No | Yes | Via Hermes + Router | +| Planet Ocean (ecosub) | observation-compiled | Black Box TBC | Ecosub C2 | Yes | Yes | N/A | +| Planet Ocean (ecosub) | observation | Ecosub C2 | Autonomy Engine | Yes | No | N/A | +| Planet Ocean (ecosub) | survey progress | TBD | TBD | TBD | TBD | N/A | +| Planet Ocean (ecosub) | survey progress | TBD | TBD | TBD | TBD | N/A | +| Planet Ocean (ecosub) | scanline | TBD | TBD | TBD | TBD | N/A | +| Planet Ocean (ecosub) | scanline | TBD | TBD | TBD | TBD | N/A | +| Planet Ocean (ecosub) | emergency | GUI | TBD – Ecosub (ABORT command via Black Box) | TBD | TBD | TBD – all platforms pre-compiled ABORT via Black box | +| NOC (AH1) | platform status-compiled | AH1 | Black Box TBC | No | Yes | Via Hermes + Router | +| NOC (AH1) | platform status-compiled | Black Box TBC | NOC C2 | Yes | Yes | N/A | +| NOC (AH1) | platform status | NOC C2 | Autonomy Engine | Yes | No | N/A | +| NOC (AH1) | scan point | Autonomy Engine | NOC C2 | Yes | No | N/A | +| NOC (AH1) | scan point-compiled | NOC C2 | Black Box TBC | Yes | Yes | Would this technically be a mission plan-compiled? | +| NOC (AH1) | scan point | Black Box TBC | Ecosub | No | Yes | Via Hermes + Router | +| NOC (AH1) | survey progress | TBD | TBD | TBD | TBD | TBD | +| NOC (AH1) | survey progress | TBD | TBD | TBD | TBD | TBD | +| NOC (AH1) | emergency | GUI | TBD – AH1 (ABORT command via Black Box) | TBD | TBD | TBD – all platforms pre-compiled ABORT via Black box | +| NOC (GUI) | planning configuration | GUI | Autonomy Engine | Yes | No | N/A | +| NOC (GUI) | emergency | GUI | TBD | TBD | TBD | TBD | + + +## Breakdown of Message Sources & Types + +### 1/ Autonomy Engine +#### Transmit +* mission plan _(sent per platform??)_ +* TBD: + * Will emergency commands be sent via the autonomy engine (from the GUI) or directly to the C2s? + +#### Receive +* configuration file +* emergency stop all +* decoded ecosub status message +* decoded reav status message +* decoded autosub-hover status message +* decoded ecosub observation data _(from squad 1 platforms)_ + +---------------------------------- + +### 2/ Ecosub C2 +#### Transmit +* compiled ecosub mission plan +* decoded ecosub status message +* autonomy configuration file +* decoded ecosub observation data + + +#### Receive +* mission plan +* encoded ecosub status message +* encoded ecosub observation data + +---------------------------------- + +### 3/ Autosub C2 +#### Transmit +* compiled autosub-hover mission plan +* decoded autosub-hover status message +* autonomy configuration file + + +#### Receive +* mission plan +* encoded autosub-hover status message + + +---------------------------------- + +### 4/ Reav C2 +#### Transmit +* decoded reav-60 status message? + + +#### Receive +* mission plan +* encoded reav-60 status message? + +---------------------------------- + +### 5/ Hermes Box/Hydrosurv Smart Router? +#### Transmit +* encoded ecosub status message +* encoded (or is this already decoded?) reav status message +* encoded autosub status message +* encoded ecosub observation data +* TBD: + * are there acknowledgment messages from platforms? + * how are we receiving beacon messages per platform? + +#### Receive +* compiled ecosub mission plan +* compiled reav mission plan +* compiled autosub mission plan +* compiled ecosub emergency command +* compiled reav emergency command +* compiled autosub emergency command +------------------------------------ \ No newline at end of file -- GitLab