Last active
December 23, 2015 19:09
-
-
Save Slater-Victoroff/6681032 to your computer and use it in GitHub Desktop.
Simple Flask Server for parsing LabView XML and doing some scant logic.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import flask | |
import sys | |
from flask import Flask, request | |
import random | |
from lxml import etree | |
import xmltodict | |
import numpy as np | |
import operator | |
app = Flask(__name__) | |
app.config['DEBUG'] = True | |
V_MAP = np.array([[6,7,8],[5,0,1],[4,3,2]]) | |
# Worlds will ultimately be a mapping of IP to current World Memory Map | |
WORLDS = {} | |
@app.route('/setup', methods=['GET', 'POST']) | |
def reset(): | |
""" | |
Small endpoint to reset the graph. Gratuitously used to set the minimum level bound, hence the zero. | |
""" | |
ip = request.remote_addr | |
WORLDS[ip] = np.empty((10,10)) | |
# 0.1 is just some small value to prefer discovery | |
WORLDS[ip].fill(0.1) | |
return "0" | |
@app.route('/', methods=['POST']) | |
def think(): | |
""" | |
General endpoint for robot food finding algorithm | |
""" | |
# Parsing the XML | |
request_dict = xmltodict.parse(str(request.form.keys()[0]))['Cluster'] | |
sensor_array = np.reshape([int(float(item['Val'])) for item in request_dict['Array']['DBL']], (3,3), order='C') | |
state = {variable['Name']: variable['Val'] for variable in request_dict['DBL']} | |
update_world(state, sensor_array, request.remote_addr) | |
return str(get_ideal_next_move(state, request.remote_addr)) | |
def update_world(state, sensor_array, ip): | |
""" | |
Given the information in the sensor_array, updates the global WORLD representation | |
""" | |
x = int(float(state['X'])) | |
y = int(float(state['Y'])) | |
if y < 1: | |
sensor_array = sensor_array[1:,:] | |
elif y > 8: | |
sensor_array = sensor_array[:2,:] | |
if x < 1: | |
sensor_array = sensor_array[:,1:] | |
elif x > 8: | |
sensor_array = sensor_array[:,:2] | |
WORLDS[ip][max(0,y-1):min(y+2,10),max(0,x-1):min(x+2,10)] = sensor_array | |
def get_ideal_next_move(state, ip): | |
""" | |
Given the current location, moves towards the square with the highest weighting | |
Extra logic to convert this into a V_Heading | |
""" | |
x = int(float(state['X'])) | |
y = int(float(state['Y'])) | |
position_values = {} | |
for i in range(max(0,y-1),min(y+2,10)): | |
for j in range(max(0,x-1),min(x+2,10)): | |
position_values[(j,i)] = calculate_square_weighting((j,i), ip) | |
heading_keys = position_values.keys() | |
heading_values = position_values.values() | |
next_move = heading_keys[heading_values.index(max(heading_values))] | |
x_heading = 1+(next_move[0]-x) | |
y_heading = 1+(next_move[1]-y) | |
return V_MAP[y_heading, x_heading] | |
def calculate_square_weighting(position, ip): | |
""" | |
Given a position, accesses the WORLD variable and determines how optimal that location is. | |
Optimality is basically total distance weighted by value of all other points. | |
position should be an x,y tuple | |
""" | |
total = 0 | |
# Since we can move diagonally, the distance is just the maximum of the distance in either direction. | |
distance = lambda a, b: max(abs(a[0]-b[0]), abs(a[1]-b[1])) | |
local_world = WORLDS[ip] | |
for y in xrange(len(local_world)): | |
for x in xrange(len(local_world[0])): | |
total += float(local_world[y,x])/(1+distance(position, (x,y))) | |
return total | |
if __name__ == '__main__': | |
app.run(host='0.0.0.0') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Relevant LabView can be found here:
http://imgur.com/dM6SAH8 (Think Block)
http://imgur.com/yxoSfar (World Reset)