Commit 8e5165f9 authored by Mayank Yadav's avatar Mayank Yadav

Comments and README added

parent 4fe56d6e
No preview for this file type
import math
tau = 0.3
omega = 1
ga = 0.0125
lb_x0 = 2.24
ub_x0 = 4.08
a = 0.05
ae2 = 0.005
ae5 = 0.005
ae = 0.0033
ah = 0.0036
te = 12
th = 100
bound_x1 = 2
world_dim_x = 10
steps_beyond_done = None
def f(t, x0, x1):
return x1
def g(t, x0, x1, u):
return (-omega * omega * (math.sin(x0) + u * math.cos(x0)) - 2 * ga * x1)
def rungeKutta(x0, y0, z0, x, h, u):
# (0, x0, x1, tau, 0.01, u)
# Count number of iterations using step size or
# step height h
n = (int)((x - x0) / h)
# Iterate for number of iterations
y = y0
z = z0
# Here y is x0 and z is x1 and x is time(tau)
# print(n, h, tau)
for i in range(1, n + 1):
# "Apply Runge Kutta Formulas to find next value of y and z"
k0 = h * f(x0, y, z)
l0 = h * g(x0, y, z, u)
k1 = h * f(x0 + 0.5 * h, y + 0.5 * k0, z + 0.5 * l0)
l1 = h * g(x0 + 0.5 * h, y + 0.5 * k0, z + 0.5 * l0, u)
k2 = h * f(x0 + 0.5 * h, y + 0.5 * k1, z + 0.5 * l1)
l2 = h * g(x0 + 0.5 * h, y + 0.5 * k1, z + 0.5 * l1, u)
k3 = h * f(x0 + h, y + k2, z + l2)
l3 = h * g(x0 + h, y + k2, z + l2, u)
# Update next value of y and z
y = y + (1.0 / 6.0) * (k0 + 2 * k1 + 2 * k2 + k3)
z = z + (1.0 / 6.0) * (l0 + 2 * l1 + 2 * l2 + l3)
# print(y)
# print(z)
# Update next value of x
x0 = x0 + h
return y, z
def step(x, u):
if (len(x) == 2):
x0 = float(x[0])
x1 = float(x[1])
u = float(u[0])
costheta = math.cos(x0)
sintheta = math.sin(x0)
derut = rungeKutta(0, x0, x1, tau, 0.01, u)
x0 = derut[0]
x1 = derut[1]
x = (x0, x1)
done = x0 < lb_x0 \
or x0 > ub_x0 \
or x1 < -bound_x1 \
or x1 > bound_x1
done = bool(done)
if done:
print('Pole fell at x0= ', x0, ' and x1= ', x1)
if not done:
reward = 1.0
# elif steps_beyond_done is None:
# # Pole just fell!
# steps_beyond_done = 0
# reward = 1.0
# else:
# steps_beyond_done += 1
# reward = 0.0
# newu,path = classify(x0,x1)
# newu is expected to be an array
# return x,newu,path,done
return x
else:
x0 = float(x[0])
x1 = float(x[1])
x2 = float(x[2])
x3 = float(x[3])
x4 = float(x[4])
x5 = float(x[5])
x6 = float(x[6])
x7 = float(x[7])
x8 = float(x[8])
x9 = float(x[9])
dx0 = (-a - ae) * x0 + a * x1 + ae * te
dx1 = (-4 * a - ae2 - ah * u[0]) * x1 + a * x0 + a * x6 + a * x8 + a * x2 + ae2 * te + ah * th * u[0]
dx2 = (-2 * a - ae) * x2 + a * x1 + a * x3 + ae * te
dx3 = (-2 * a - ae) * x3 + a * x2 + a * x4 + ae * te
dx4 = (-4 * a - ae5 - ah * u[1]) * x4 + a * x3 + a * x7 + a * x5 + a * x9 + ae5 * te + ah * th * u[1]
dx5 = (-a - ae) * x5 + a * x4 + ae * te
dx6 = (-a - ae) * x6 + a * x1 + ae * te
dx7 = (-a - ae) * x7 + a * x4 + ae * te
dx8 = (-a - ae) * x8 + a * x1 + ae * te
dx9 = (-a - ae) * x9 + a * x4 + ae * te
x0 = x0 + dx0
x1 = x1 + dx1
x2 = x2 + dx2
x3 = x3 + dx3
x4 = x4 + dx4
x5 = x5 + dx5
x6 = x6 + dx6
x7 = x7 + dx7
x8 = x8 + dx8
x9 = x9 + dx9
return x0, x1, x2, x3, x4, x5, x6, x7, x8, x9
......@@ -53,6 +53,7 @@ from dtcontrol.pre_processing.random_pre_processor import RandomPreProcessor
import json, ast
import numpy as np
# Subset of cli.py with core_parser replaced with main_parse
def get_classifier(numeric_split, categorical_split, determinize, impurity, tolerance=1e-5, safe_pruning=False,
name=None):
......@@ -232,13 +233,13 @@ def is_valid_file_or_folder(arg):
def intoJSON(rt, parent, address):
# returns a string
# returns a string (JSON format that we need)
# address is an array of integers
rt_name = "sth"
if len(rt.children) > 0:
rt_name = rt.split.print_c()
else:
rt_name = rt.print_c_label()
# print("Working on ",rt_name," with ",len(rt.children)," children\n")
strdummy = {"name": rt_name, "parent": parent, "coleur": "white", "children": [], "address": address}
for i in range(len(rt.children)):
strdummy["children"].append(intoJSON(rt.children[i], rt_name, address+[i]))
......@@ -247,10 +248,10 @@ def intoJSON(rt, parent, address):
def main_parse(args):
# args will be passed as a dict to this function
# works exactly like core_parser in cli.py
kwargs = dict()
dataset = path.realpath(path.dirname(__file__)) + "/../examples/" + args["controller"]
# print(dataset)
is_valid_file_or_folder(dataset)
kwargs["timeout"] = 20 * 60 * 60
......@@ -305,20 +306,9 @@ def main_parse(args):
"No valid preset selected. Please try again with the correct preset name. Use 'dtcontrol preset --list' to see valid presets.")
sys.exit("Exiting...")
# suite.benchmark(classifiers)
suite.datasets[0].load_if_necessary()
# benchmark does a lot of other stuff as well, we just need load if necessary from it
classifiers[0].fit(suite.datasets[0])
# print("Tried fit now printing root")
# json_str = []
# intoJSON takes the classifier root and returns a JSON in required format
retDict = intoJSON(classifiers[0].root, "null", [])
# classifiers[0].root.predict_one_step(np.array([[3.5, 0]]))
# print((classifiers[0].get_stats()))
# print(suite.datasets[0].x_metadata)
# print(suite.datasets[0].y_metadata)
# print("Retdict type ",type(retDict))
# json_str=json.dumps(retDict)
return retDict, suite.datasets[0].x_metadata, suite.datasets[0].y_metadata, classifiers[0].root
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}
\ No newline at end of file
{
"python.pythonPath": "/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6",
"python.venvPath": "/Users/MayankY/Desktop/dtControl/dtcontrol-venv"
}
\ No newline at end of file
File descriptions:
app.py -> Countains the flask application to be run
frontFns.py -> A subset of cli.py containing all the necessary functions for app.py
CSS:
node-stylings.css -> Styling for SVG tree and nodes, divs, cards, slider
new-select.css -> Styling for select (single and multiple) tags
sidenav-my.css -> Styling for side navigation menu
JS:
heavylifting.js -> Does all the main js work
NOTE:
Ctrl(Cmd)+Click for selecting multiple entries in Numeric-predicates and Categorical-predicates selection
\ No newline at end of file
......@@ -4,27 +4,41 @@ import yaml
import json
import numpy as np
from flask import Flask, render_template, url_for, json, request, Response, jsonify, request
from dtcontrol import frontFns, cartClassify
from dtcontrol import frontFns
import sympy as sp
app = Flask(__name__)
# tree generated by dtControl is saved and used again for predictions
saved_tree = []
# list of lower and upper bounds for each of the state variables
minBounds = []
maxBounds = []
# step size (used in discretisation) for each of the state variables
stepSize = []
# contains (variable_name, value) pairs obtained from dynamics.txt file present in examples folder
variable_subs = []
# contains lambda functions generated from dynamics.txt file
lambda_list = []
# number of state variables (x's)
numVars = 0
# number of decision variables (u's)
numResults = 0
# time discretisation parameter
tau = 0
def runge_kutta(x, u, nint=10):
# matches cartClassify exactly for nint set to 30
# nint is number of times to run Runga-Kutta loop
global tau, lambda_list
h = tau / nint
# tau = 1 for 10 rooms
k0 = [None] * len(x)
k1 = [None] * len(x)
......@@ -45,6 +59,7 @@ def runge_kutta(x, u, nint=10):
return x
# returns computed value of lambda function every time Runga-Kutta needs it
def computation(index, x, u, ll):
new_vl = []
for name in ll[index][2]:
......@@ -57,15 +72,15 @@ def computation(index, x, u, ll):
return return_float
def discretise(x):
# Not in use right now
# some errors when using Greatest integer function-like discretisation
def discretize(x):
diff = []
for i in range(numVars):
diff.append(minBounds[i] + stepSize[i] * (1 + int((x[i] - minBounds[i]) / stepSize[i])))
return diff
# return x
# route when loading default simulator
@app.route("/")
def home():
return render_template("simulator.html")
......@@ -98,15 +113,17 @@ def simroute():
else:
to_parse_dict = {"controller": cont, "config": config}
# is a dict
# main_parse takes in a dictionary and returns [constructed d-tree, x_metadata, y_metadata, root]
classi = frontFns.main_parse(to_parse_dict)
# global saved_tree, minBounds, maxBounds, numVars, numResults, stepSize
# root is saved in a global variable for use later
saved_tree = classi[3]
numVars = len(classi[1]["min"])
numResults = len(classi[2]["variables"])
minBounds = classi[1]["min"]
maxBounds = classi[1]["max"]
stepSize = classi[1]["step_size"]
returnDict = {"classi": ([classi[0]]), "numVars": numVars, "numResults": numResults,
"bound": [minBounds, maxBounds]}
return jsonify(returnDict)
......@@ -117,13 +134,16 @@ def simroute():
def initroute():
data = request.get_json()
x = data['pass']
initDecision = saved_tree.predict_one_step(np.array([discretise(x)]))
# Predict_one_step returns the decision taken as well as the path (list of ints) to reach that decision
initDecision = saved_tree.predict_one_step(np.array([discretize(x)]))
returnDict = {"decision": initDecision[0], "path": initDecision[1], "dynamics": True}
is_dynamics = False
SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
dynamics_data_file = os.path.join(SITE_ROOT, '..', '..', 'examples/dynamics.txt')
# Opens dynamics file and saves obtained variables and lambda functions as lists (variable_subs and lambda_list)
try:
with open(dynamics_data_file) as f:
my_list = f.read().splitlines()
......@@ -150,6 +170,7 @@ def initroute():
lambda_list = sorted(lambda_list, key=lambda x: int(x[0].split("_")[1]))
except:
# If dynamic.txt is not present sets this to false and browser raises an exception
returnDict["dynamics"] = False
return jsonify(returnDict)
......@@ -161,9 +182,10 @@ def stepRoute():
data = request.get_json()
x = data['x_pass']
u = data['u_pass']
# x_new_non_classify = cartClassify.step(x, u)
# Returns updated states variables
x_new_non_classify = runge_kutta(list(x), u)
newu_path = saved_tree.predict_one_step(np.array([discretise(list(x_new_non_classify))]))
newu_path = saved_tree.predict_one_step(np.array([discretize(list(x_new_non_classify))]))
returnDict = {"x_new": (x_new_non_classify,) + newu_path}
return jsonify(returnDict)
......@@ -179,26 +201,28 @@ def inStepRoute():
x_new = []
dummy = [x, u, "", False]
for i in range(int(steps)):
# x_new_non_classify = cartClassify.step(dummy[0], dummy[1])
x_new_non_classify = runge_kutta(list(dummy[0]), dummy[1])
newu_path = saved_tree.predict_one_step(np.array([discretise(list(x_new_non_classify))]))
newu_path = saved_tree.predict_one_step(np.array([discretize(list(x_new_non_classify))]))
dummy = (x_new_non_classify,) + newu_path
x_new.append(dummy)
returnDict = {"x_new": x_new}
return jsonify(returnDict)
# Used to recontstruct from presets
# Used to reconstruct from presets
@app.route("/reconstructRoute1")
def rc1():
return []
# Used reconstruct from user text predicates
@app.route("/reconstructRoute2")
def rc2():
return []
# Used to get the list of unzipped examples
@app.route("/examples")
def showscs():
......@@ -222,8 +246,10 @@ def yamlread():
def runFlask():
print('##########Opening browser##########')
# Decomment this and add valid application path if you don't want to open in default browser
chrome_path = 'open -a /Applications/Google\ Chrome.app %s'
webbrowser.get(chrome_path).open('http://127.0.0.1:5000/')
# webbrowser.open('http://127.0.0.1:5000/')
app.run(debug=False)
......
Parameters:
a=0.05
ae2=0.005
ae5=0.005
ae=0.0033
ah=0.0036
te=12
th=100
tau=1
Dynamics:
dx_0=(-a-ae)*x_0+a*x_1+ae*te
dx_1=(-4*a-ae2-ah*u_0)*x_1+a*x_0+a*x_6+a*x_8+a*x_2+ae2*te+ah*th*u_0
dx_2=(-2*a-ae)*x_2+a*x_1+a*x_3+ae*te
dx_3=(-2*a-ae)*x_3+a*x_2+a*x_4+ae*te
dx_4=(-4*a-ae5-ah*u_1)*x_4+a*x_3+a*x_7+a*x_5+a*x_9+ae5*te+ah*th*u_1
dx_5=(-a-ae)*x_5+a*x_4+ae*te
dx_6=(-a-ae)*x_6+a*x_1+ae*te
dx_7=(-a-ae)*x_7+a*x_4+ae*te
dx_8=(-a-ae)*x_8+a*x_1+ae*te
dx_9=(-a-ae)*x_9+a*x_4+ae*te
\ No newline at end of file
# TODO quantisation information
# Will have number of parameters and their bounds and quantisation already present
import sympy as sp
import os
variable_subs = []
lambda_list = []
numVars = 2
numResults = 1
is_dynamics = False
SITE_ROOT = os.path.realpath(os.path.dirname(__file__))
dynamics_data_file = os.path.join(SITE_ROOT, 'test.txt')
with open(dynamics_data_file) as f:
my_list = f.read().splitlines()
for i in my_list:
i = i.strip()
if i == 'Dynamics:':
is_dynamics = True
elif i == 'Parameters:':
is_dynamics = False
else:
if i != '':
if not is_dynamics:
foo = i.split("=")
variable_subs.append((foo[0].strip(), float(foo[1])))
else:
foo = i.split("=")
tmp = sp.sympify(foo[1].strip())
tmp = tmp.subs(variable_subs)
lam_1 = sp.lambdify(tmp.free_symbols, tmp)
lambda_list.append((foo[0].strip(), lam_1, tmp.free_symbols))
print(variable_subs)
lambda_list = sorted(lambda_list, key=lambda x: int(x[0].split("_")[1]))
print(lambda_list)
def runge_kutta(x, u, tau, x0=0, nint=10):
# h is 0.01, may be adjusted later, x0 is 0
# n = int((tau - x0) / h)
h = tau/nint
# everywhere fix h as 10
# tau = 1 for 10 rooms
# Step height h, step size n
k0 = [None] * len(x)
k1 = [None] * len(x)
k2 = [None] * len(x)
k3 = [None] * len(x)
for iter in range(1, nint + 1):
# "Apply Runge Kutta Formulas to find next value of y and z"
for i in range(len(x)):
k0[i] = h * computation(i, x, u, lambda_list)
for i in range(len(x)):
k1[i] = h * computation(i, [(x[j] + 0.5 * k0[j]) for j in range(len(x))], u, lambda_list)
for i in range(len(x)):
k2[i] = h * computation(i, [(x[j] + 0.5 * k1[j]) for j in range(len(x))], u, lambda_list)
for i in range(len(x)):
k3[i] = h * computation(i, [(x[j] + k2[j]) for j in range(len(x))], u, lambda_list)
for i in range(len(x)):
x[i] = x[i] + (1.0 / 6.0) * (k0[i] + 2 * k1[i] + 2 * k2[i] + k3[i])
return x
def computation(index, x, u, ll):
new_vl = []
for name in ll[index][2]:
spilt_of_var = (str(name)).split('_')
if spilt_of_var[0] == 'x':
new_vl.append(x[int(spilt_of_var[1])])
else:
new_vl.append(u[int(spilt_of_var[1])])
return float(ll[index][1](*tuple(new_vl)))
print(runge_kutta([3.5, 0], [-3], 0.3))
Activate virtual environment(make sure flask is installed)
cd Desktop/dtcontrol-master/dtcontrol/visualise
python3 app.py
firefox http://127.0.0.1:5000/
This diff is collapsed.
......@@ -28,6 +28,7 @@
<body id="bootstrap-override">
<!-- Modal that comes on clicking 'Simulate' -->
<div class="modal fade" id="formSecondModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
......@@ -37,6 +38,7 @@
<span aria-hidden="true">&times;</span>
</button>
</div>
<!-- formSecond: Selects initial values for state variables -->
<form id="formSecond">
<div class="modal-body" id="formSecondBody">
......@@ -52,6 +54,7 @@
</div>
</div>
<!-- Modal that pops up on using the edit tree functionality -->
<div class="modal fade" id="formThirdModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
......@@ -164,6 +167,7 @@
</div>
</div>
<!-- Sidenav that is used for selecting controller, config and other fine tuning properties -->
<div id="mySidenav" class="sidenav">
<a href="javascript:void(0)" class="closebtn" onclick="closeNav()">&times;</a>
<form id="formFirst">
......@@ -267,6 +271,7 @@
<!-- Add all page content inside this div if you want the side nav to push page content to the right (not used if you only want the sidenav to sit on top of the page -->
<div id="main">
<!-- Navbar at top -->
<nav class="navbar navbar-expand-xl navbar-light" style="margin: 1.25rem;">
<button class="btn" onclick="openNav()"><i class="fa fa-cog"></i></button>
<a class="navbar-brand" href="https://gitlab.lrz.de/i7/dtcontrol">dtControl</a>
......@@ -275,6 +280,7 @@
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<!-- The four player buttons -->
<div class="btn-group btn-group-toggle" data-toggle="buttons" id="playerDiv" style="z-index:5;visibility: hidden;">
<label class="btn btn-dark">
<input type="radio" name="player" id="play" autocomplete="off" value='0'> Play
......@@ -289,17 +295,24 @@
<input type="radio" name="player" id="back" autocomplete="off" value='3'> Previous
</label>
</div>
<!-- Range slider for speed of simulation -->
<input type="range" min="50" max="2000" value="50" class="slider" id="timeRange" style="visibility: hidden;">
<!-- Instep form -->
<form id="instep" class="form-inline my-2 my-lg-0" style="visibility: hidden;">
<input class="form-control mr-sm-2" placeholder="Number of steps" aria-label="Number of steps" type="number" id="steps" name="steps" min="1">
<button class="btn btn-dark my-2 my-sm-0" type="submit">Step</button>
</form>
<!-- Tree animation toggle -->
<div id="animationDiv" class="btn-group-toggle" data-toggle="buttons" style="visibility: hidden;">
<label class="btn btn-outline-dark active" style="margin-left: 7px;">
<input id = "animateTree" type="checkbox" checked autocomplete="off"> Animation
</label>
</div>
<!-- Edit tree toggle -->
<div id="editTreeDiv" class="btn-group-toggle" data-toggle="buttons" style="visibility: hidden;">
<label class="btn btn-outline-dark" style="margin: 7px;">
<input id = "editTree" type="checkbox" autocomplete="off"> Edit Tree
......@@ -308,13 +321,16 @@
</div>
</nav>
<!-- Row in which tree and model visualisation cards get added -->
<div id="mainRow1" class="row" style="visibility: hidden;">
<!-- Column for tree -->
<div class="col-lg-12" id="expandThisDiv">
<div class="card shadow mb-4">
<div class="card-body">
<button type="button" class="btn btn-dark" onclick="expandAll(null)">Expand all</button>
<button type="button" class="btn btn-dark" onclick="collapseAll(null)">Collapse all</button>
<div class="row no-gutters align-items-center">
<!-- Tree in this div -->
<div id="treeHere">
</div>
......@@ -324,6 +340,7 @@
</div>
</div>
<!-- Column for model visualisation -->
<div class="col-lg-6" id="hideThisDiv" style="visibility:hidden">
<div class="card shadow mb-4">
<div class="card-body">
......@@ -335,11 +352,13 @@
</div>
</div>
<!-- Row for simulation table -->
<div id="mainRow2" class="row" style="visibility: hidden;">
<div class="col-lg-12">
<div class="card shadow mb-4">
<div class="card-body">
<div class="table-responsive">
<!-- Table in this div -->
<div id="tableHere">
</div>
......@@ -351,6 +370,7 @@
</div>
</div>
<!-- Row for charts with two columns -->
<div id="mainRow3" class="row" style="visibility: hidden;">
<div class="col-lg-6" id="chartsHere0">
......
Parameters:
tau = 0.3
omega = 1
ga = 0.0125
Dynamics:
dx_0=x_1
dx_1=(-omega*omega*(sin(x_0)+u_0*cos(x_0))-2*ga*x_1)
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment