Skip to content

Controller Design

Akshay Dahiya edited this page Aug 22, 2017 · 2 revisions

This page explains the design, architecture and the implementation of Controller Component for the simulation.

Table of contents

The central controller is a Hydra based API server acting as a central datastore and control center for all the drones. All active drones submit their status updates every 15 seconds to the central controller. Just like drones the central controller also has a client part that can be used to issue commands to different drones.

Main Features

  • It acts as a central database for all the drones to store their logs and sensor data. This is being done using the drone client side, drones issue POST/PUT requests after every 15 seconds or upon some status change. The central controller has different endpoints for different types of data.
    • /api/DroneCollection/<drone_id> Each active drone updates their drone object using PUT/POST requests here, every 15 seconds.
    • /api/DatastreamCollection/ Datastream from the drone sensors is stored here.
    • /api/DroneLogCollection/ Logs related to drones are stored here.
    • /api/ControllerLogCollection Logs related to the controller are stored here.
    • /api/HttpApiLogCollection Logs related to general interactions between different components are stored here.
  • The user can issue a message to the central controller at /api/MessageCollection/ in a structured format. The message is then parsed and commands are issued to the respective drones.
  • The server will act as an intermediate if different drones want to interact with each other. For example - If some drone wants to know the position of all nearby drones.
  • The central controller acts as the main docking station to recharge drones.

Central controller is driven by a 17 second time loop (2 second delay to let drones finish updating their status at the controller).

Main Loop design

"""Main loop for the central controller."""
    print("Controller Simulation Loop")
    try:
        handle_messages()
        handle_anomalies()

    except Exception as e:
        print(e)

    finally:
        threading.Timer(LOOP_TIME, main).start()

In the main Loop, the controller tries to handle two things.

  • The messages submitted by the user
  • Anomalies detected by drones

Handling Messages

"""Handle messages in the MessageCollection."""
    try:
        message_collection = get_message_collection()
        print(message_collection)

        for message in message_collection:
            regex = r'/(.*)/(\d*)'
            matchObj = re.match(regex, message["@id"])
            if matchObj:
                message_id = matchObj.group(2)
                message_details = get_message(message_id)

                # parse message
                message_string = message_details["MessageString"]
                parsed_message = parse_message(message_string)

                if parsed_message is not None:
                    drone_id, prop, value = parsed_message
                    if not validate_message_prop_value(prop, value):

                          delete_message(message_id)
                    else:
                        command = generate_command(drone_id, prop, value)
                          try:
                            RES, NAMESPACE = find_res(drone_id)
                            if RES is not None and NAMESPACE is not None:
                                issue_command(RES, NAMESPACE, command)

                        except:
                            controllerlog = gen_ControllerLog(
                                "Drone with id %s not found, deleting message." % (str(drone_id)), "")

                            send_controllerlog(controllerlog)

                            delete_message(message_id)

                # delete message
                delete_message(message_id)
    except Exception as e:
        print(e)

Parsing a Message

""" Parsing a given message string.
    Messages will be in format 'Set Drone <DroneID> <Property> <Value>'.
    DroneID is the drone identifier assigned by the central controller.
    Property can be Direction, Speed or Status and values can be anything
    supported by that respective Property."""

    message_items = message_string.lower().split(" ")
    try:
        drone_id = message_items[message_items.index("drone") + 1]
        prop = message_items[message_items.index(drone_id) + 1]
        value = message_items[message_items.index(prop) + 1]

        return (drone_id, prop.title(), value.title())
    except Exception as e:
        print(e)

        return None

Handling Anomalies

    """Handling the anomalies in AnomalyCollection."""
    try:
        anomaly_collection = get_anomaly_collection()
        drone_collection = get_drone_collection()

        non_confirmed_anomalies, negative_anomalies = find_non_confirmed_and_negative_anomalies(
            anomaly_collection)

        # Handle non_confirmed_anomalies
        for anomaly in non_confirmed_anomalies:
            handle_anomaly(anomaly, drone_collection)

        # Delete Negative anomalies
        for anomaly in negative_anomalies:
            delete_anomaly(anomaly["AnomalyID"])
    except Exception as e:
        print(e)

The full implementation of the main loop is available at flock_controller.mechanics.simulate. Full source code for the controller component is available here.

Clone this wiki locally