Complex Mission Orchestration

Consider a scenario where a mission commands two agents to collaborate on several assignments in a specific order. In this scenario, the calculation of the assignments must take into account the current yard state just before the assignment starts.

../_images/assignment_orchestration.png


To acomplish this, we employed the following microservices:

Microservice 1
from flask import Flask, jsonify, request
from calculations_1 import calculateA, calculateB
app = Flask(__name__)

@app.post("/plan_job/")
def getPath():
    request_body = request.get_json() 
    request_data = request_body['request']
    context = request_body['context']

    assignment1A = calculateA(request_data, context)
    assignment1B = calculateB(request_data, context)
    
    response =  {
                "status" : "ready",
                "results":[{
                            "agent_uuid": 'AGENT-A',
                            "assignment": assignment1A
                            "assignment_order": 1
                            },
                            {
                            "agent_uuid": 'AGENT-B',
                            "assignment": assignment1B
                            "assignment_order": 2
                            }],
                }
    
    return jsonify(response)
Microservice 2
from flask import Flask, jsonify, request
from calculations_2 import calculateA, calculateB
app = Flask(__name__)

@app.post("/plan_job/")
def getPath():
    request_body = request.get_json() 
    request_data = request_body['request']
    context = request_body['context']

    assignment2A = calculateA(request_data, context)
    assignment2B = calculateB(request_data, context)
    
    response =  {
                "status" : "ready",
                "results":[{
                            "agent_uuid": 'AGENT-A',
                            "assignment": assignment2A,
                            "assignment_order": 1
                            },
                            {
                            "agent_uuid": 'AGENT-B',
                            "assignment": assignment2B,
                            "assignment_order": 1
                            }],
                }
    
    return jsonify(response)
Microservice 3
from flask import Flask, jsonify, request
from my_calculations import calculate_analytics, save_database
app = Flask(__name__)

@app.post("/storage/")
def getPath():
    request_body = request.get_json() 
    request_data = request_body['request']
    context = request_body['context']

    analytics = calculate_analytics(request_data, context)
    save_database(analytics)
    
    response =  {
                "status" : "ready"
                }
    
    return jsonify(response)

Microservice 1 and 2 are Assignmnent Planners, while 3 is a Storage Server. The microservice 1 produces two assignments that are executed sequentially by the agents. The microservice 2 produces two assigments that are executed in parallel. The order of that the assignments are dispatched to the agents is defined within the microservice through the property assignment_order, you can read more about it in Service Response: from Microservices to helyOS.

Note

The Microservice 1 and 2 could also be merged into a single service which is called at two different steps in the mission. One can retrieve the mission recipe property step from the context and use as a parameter. The developer should decide the best approach taking into account the principle of separation of concerns, team responsabilities, etc.

The order of that microservices are executed is defined by the misssion recipe:

version: '2.0'

missions:

    complex_mission:
        maxagents: 2
        description: "drive to multiple locations"
        on_assignment_failure: "FAIL_MISSION"

        recipe:
            steps:
                - step: "Microservice_1"
                  service_type: "drive"
                  request_order: 1
                  apply_result: true
                  override_config: "{}"

                - step: "Microservice_2"
                  service_type: "imaging"
                  request_order: 2
                  apply_result: true
                  wait_assignments: true
                  dependencies: '["Microservice_1"]'

                - step: "Microservice_3"
                  service_type: "statistics"
                  request_order: 3
                  wait_assignments: true
                  dependencies: '["Microservice_2"]'

Note that the wait_assignments property is set to true, meaning the calculation step will only start after the successful completion of all assignments produced in the previous step. Learn more at “Missions Recipes” View.

More Examples of Missions using helyOS

  1. Application requests a map update.

../_images/application-example-A.png
  1. Application requests truck to drive from A to B using an online path planner.

../_images/application-example-B.png
  1. Application requests truck to drive from A to B using an online path planner but employing the most recent map data in the path calculation.

../_images/application-example-C.png
  1. Application requests robot to take pictures and update the map objects.

../_images/application-example-D.png