diff --git a/AMR_Interop_Standard.json b/AMR_Interop_Standard.json index e50dc46..ce2f31c 100644 --- a/AMR_Interop_Standard.json +++ b/AMR_Interop_Standard.json @@ -1,6 +1,4 @@ { - "$schema": "http://json-schema.org/draft/2020-12/schema#", - "definitions": { "quaternion": { "description": "Quaternion representation of an angle", @@ -228,4 +226,4 @@ { "$ref": "#/identityReport" }, { "$ref": "#/statusReport" } ] -} \ No newline at end of file +} diff --git a/MassRobotics-AMR-Receiver/server/schema/schema.json b/MassRobotics-AMR-Receiver/server/schema/schema.json deleted file mode 100644 index 612847f..0000000 --- a/MassRobotics-AMR-Receiver/server/schema/schema.json +++ /dev/null @@ -1,218 +0,0 @@ -{ - "definitions": { - "quaternion": { - "description": "Quaternion representation of an angle", - "type": "object", - "required": ["x", "y", "z", "w"], - "properties": { - "x": { "type": "number" }, - "y": { "type": "number" }, - "z": { "type": "number" }, - "w": { "type": "number" } - } - }, - "location": { - "description": "Location of an object or AMR", - "type": "object", - "required": ["x", "y", "z", "angle", "planarDatum"], - "properties": { - "x": { "type": "number" }, - "y": { "type": "number" }, - "z": { "type": "number" }, - "angle" : { "$ref": "#/definitions/quaternion" }, - "planarDatum": { - "description": "Id of planarDatum AMR is referencing", - "type": "string", - "format": "uuid" - } - } - }, - "predictedLocation": { - "description": "Predicted future location of an object or AMR", - "type": "object", - "required": ["timestamp", "x", "y", "z", "angle"], - "properties": { - "timestamp": { - "description": "Predicted UTC time AMR will reach this location", - "type": "string", - "format": "date-time" - }, - "x": { "type": "number" }, - "y": { "type": "number" }, - "z": { "type": "number" }, - "angle" : { "$ref": "#/definitions/quaternion" }, - "planarDatumUUID": { - "description": "Only necessary if different from AMRs current planarDatum", - "type": "string", - "format": "uuid" - } - } - } - }, - - "identityReport": { - "type": "object", - "required": ["uuid", "timestamp", "manufacturerName", "robotModel", "robotSerialNumber", "baseRobotEnvelope"], - "properties": { - "uuid": { - "description": "UUID specified by RFC4122 that all subsequent messages should reference", - "type": "string", - "format": "uuid" - }, - "timestamp": { "type": "string", "format": "date-time" }, - "manufacturerName": { "type": "string" }, - "robotModel": { "type": "string" }, - "robotSerialNumber": { - "description": "Unique robot identifier that ideally can be physically linked to the AMR", - "type": "string" }, - "baseRobotEnvelope": { - "description": "Footprint of robot based on orientation - centered on current location.", - "type": "object", - "required": ["x", "y"], - "properties": { - "x": { "type": "number" }, - "y": { "type": "number" }, - "z": { "type": "number" } - } - }, - - "maxSpeed": { - "description": "Max robot speed in m/s", - "type": "number" - }, - "maxRunTime": { - "description": "Estimated Runtime in hours", - "type": "number" - }, - "emergencyContactInformation": { - "description": "Emergency Contact - preferrably phone number", - "type": "string" - }, - "chargerType": { - "description": "Type of charger", - "type": "string" - }, - "supportVendorName": { - "description": "Vendor that supplied robot", - "type": "string" - }, - "supportVendorContactInformation": { - "description": "Contect information for vendor", - "type": "string" - }, - "productDocumentation": { - "description": "Link to product documenation", - "type": "string", - "format": "uri" - }, - "thumbnailImage": { - "description": "Link to thumbnail graphic stored as PNG", - "type": "string", - "format": "uri" - }, - "cargoType": { - "description": "Discription of cargo", - "type": "string" - }, - "cargoMaxVolume": { - "description": "Max volume of cargo in meters", - "type": "object", - "required": ["x", "y"], - "properties": { - "x": { "type": "number" }, - "y": { "type": "number" }, - "z": { "type": "number" } - } - }, - "cargoMaxWeight": { - "description": "Max weight of cargo in kg", - "type": "string" - } - } - }, - - "statusReport": { - "type": "object", - "required": ["uuid", "timestamp", "operationalState", "location" ], - "properties": { - "uuid": { - "description": "UUID specified in the identityAndCapability message", - "type": "string", - "format": "uuid" - }, - "timestamp": { "type": "string", "format": "date-time" }, - "operationalState": { - "description": "Current action the robot is performing", - "type": "string", - "enum": ["navigating", "idle", "disabled", "offline", "charging", "waiting", "loadingUnloading", "manualOveride"] - }, - "location": { - "description": "Current Location of AMR", - "$ref": "#/definitions/location" - }, - "velocity": { - "description": "Current velocity of AMR", - "type": "object", - "required": ["linear"], - "properties": { - "linear": { - "description": "Linear velocity in m/s in heading direction, forward is postive", - "type": "number" - }, - "angular" : { - "description": "Angular velocity in quaternions per second", - "$ref": "#/definitions/quaternion" - } - } - }, - "batteryPercentage" : { - "description": "Percentage of battery remaining", - "type": "number", - "minimum": 0, - "inclusiveMaximum": 100 - }, - "remainingRunTime" : { - "description": "Estimated remaining runtime in hours", - "type": "number", - "minimum": 0 - }, - "loadPercentageStillAvailable" : { - "description": "Percentage of capacity still available", - "type": "number", - "minimum": 0, - "inclusiveMaximum": 100 - }, - "errorCodes" : { - "description": "List of current error states - should be omitted for normal operation", - "type": "array", - "items": { - "type": "string" - }, - "uniqueItems": true - }, - "destinations" : { - "description": "Target destination(s) of AGV", - "type": "array", - "items": { - "$ref": "#/definitions/predictedLocation" - }, - "maxItems": 10, - "uniqueItems": true - }, - "path" : { - "description": "Short term path of AGV ~10 sec", - "type": "array", - "items": { - "$ref": "#/definitions/predictedLocation" - }, - "maxItems": 10, - "uniqueItems": true - } - } - }, - - "oneOf": [ - { "$ref": "#/identityReport" }, - { "$ref": "#/statusReport" } - ] -} diff --git a/MassRobotics-AMR-Receiver/server/schema/schema.json b/MassRobotics-AMR-Receiver/server/schema/schema.json new file mode 120000 index 0000000..c2cac40 --- /dev/null +++ b/MassRobotics-AMR-Receiver/server/schema/schema.json @@ -0,0 +1 @@ +../../../AMR_Interop_Standard.json \ No newline at end of file diff --git a/MassRobotics-AMR-Receiver/server/schema/test-message.json b/MassRobotics-AMR-Receiver/server/schema/test-message.json deleted file mode 100644 index 75e0a06..0000000 --- a/MassRobotics-AMR-Receiver/server/schema/test-message.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "uuid": "6948DF80-14BD-4E04-8842-7668D9C001F5", - "timestamp": "2012-04-21T18:25:43-05:00", - "operationalState": "navigating", - "location" : { - "x" : 0.5, - "y" : 1, - "z" : 0, - "angle" : { - "w" : 0.924, - "x" : 0.000, - "y" : 0.000, - "z" : 0.383 - }, - "planarDatum":"4B8302DA-21AD-401F-AF45-1DFD956B80B5" - } -} diff --git a/MassRobotics-AMR-Receiver/server/schema/test-message.json b/MassRobotics-AMR-Receiver/server/schema/test-message.json new file mode 120000 index 0000000..f64f5b7 --- /dev/null +++ b/MassRobotics-AMR-Receiver/server/schema/test-message.json @@ -0,0 +1 @@ +../../../examples/statusReport1.json \ No newline at end of file diff --git a/MassRobotics-AMR-Sender/client.py b/MassRobotics-AMR-Sender/client.py index b18a556..38a442b 100644 --- a/MassRobotics-AMR-Sender/client.py +++ b/MassRobotics-AMR-Sender/client.py @@ -22,14 +22,14 @@ async def sendMessage(): identity["uuid"] = str(uid) # Attach a timestamp - identity["timestamp"] = datetime.now().strftime("%Y-%m-%dT%H:%M:%S%z") + identity["timestamp"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S%z") # Send the identity message once await websocket.send(json.dumps(identity)) status = {"uuid": str(uid)} while True: - status["timestamp"] = datetime.now().strftime("%Y-%m-%dT%H:%M:%S%z") + status["timestamp"] = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%S%z") # The following information would need to be pulled out in a vendor-specific way, for this example it is just hard-coded # Get the current operational state and put it in the status message diff --git a/README.md b/README.md new file mode 100644 index 0000000..9dd0743 --- /dev/null +++ b/README.md @@ -0,0 +1,9 @@ +# MassRobotics Autonomous Mobile Robot Interoperability Standard + +[![MassRobotics AMR Interop](https://www.massrobotics.org/wp-content/uploads/2015/05/AMR_interop_MR-logo-scaled.jpg)](https://www.massrobotics.org/project/amrinteroperability/) + +The MassRobotics AMR Interoperability Standard aims to help enable organizations to deploy autonomous mobile robots AMRs from multiple vendors and have them coexist effectively, better realizing the promise of warehouse and factory automation. This standard will allow autonomous vehicles of different types to share information about their robot(s) location, speed, direction, health, tasking / availability and other performance characteristics with other similar vehicles to help them be better teammates on a warehouse or factory floor. Furthermore, it allows human agents to provide a similar set of information (through the use of external mobile devices) so that their work can be orchestrated alongside robots. + +This project contains a schema definition file (AMR_Interop_Standard.json), an example implemetation of a client (MassRobotics-AMR-Sender), server (MassRobotics-AMR-Receiver), and some example messages. The client and server each have their own README files describing their installation and usage. + +For more information or to provide feedback on the standard, please visit: https://www.massrobotics.org/project/amrinteroperability/. diff --git a/identityReport1.json b/examples/identityReport1.json similarity index 100% rename from identityReport1.json rename to examples/identityReport1.json diff --git a/statusReport1.json b/examples/statusReport1.json similarity index 85% rename from statusReport1.json rename to examples/statusReport1.json index c3f1c70..b396acb 100644 --- a/statusReport1.json +++ b/examples/statusReport1.json @@ -1,5 +1,5 @@ { - "uuid": "6948DF80-14BD-4E04-8842-7668D9C001F5", + "uuid": "6948DF80-14BD-4E04-8842-7668D9C001F5", "timestamp": "2012-04-21T18:25:43-05:00", "operationalState": "navigating", "location" : { @@ -13,4 +13,4 @@ }, "planarDatum":"4B8302DA-21AD-401F-AF45-1DFD956B80B5" } -} \ No newline at end of file +}