Newer
Older
from scipy import log, sqrt, linspace, logspace, meshgrid, zeros, absolute
import numpy as np
"""
:param model: (F,G,H)
:return: 2GH + H^2 - 2F, > 0 if stable; < 0 if unstable
"""
return 2 * model[1] * model[2] + model[2] * model[2] - 2 * model[0]
Return the complex value of the linearized transfer function T(jw)
"""
return (g*1j*w + f)/(-w*w + (g+h)*1j*w + f)
def tflogmag(model, w):
"""
Return the log of the magnitude of the linearized transfer function
log[ |T(jw)| ]
"""
"""
Return the log of the magnitude of the linearized headway transfer function
log[ |1-T(jw)| ]
"""
def btf(human, robot, gamma, w):
"""
Return the complex value of the linearized transfer function T(jw)
of a bilateral robot controller [ followed by a human ]:
Y(robot) = gamma Tr Y(forward) + (1-gamma) Tr Y(behind)
Y(behind) = Th Y(robot)
Y(robot) = gamma Tr Y(forward) + (1-gamma) Tr Th Y(robot)
Y(robot) = [ gamma Tr ] / [ 1 - (1-gamma) Tr Th ] Y(forward)
"""
tr = tf(robot, w)
th = tf(human, w)
t = gamma * tr / (1 - (1-gamma)*tr*th)
return t
def btflogmag(human, robot, gamma, w):
"""
Return the log of the magnitude of the linearized transfer function
log[ |T(jw)| ]
of a bilateral robot controller [ followed by a human ]
"""
return log(absolute(btf(human, robot, gamma, w)))
def bhtflogmag(human, robot, gamma, w):
"""
Return the log of the magnitude of the linearized headway transfer function
log[ |1-T(jw)| ]
of a bilateral robot controller [ followed by a human ]
"""
return log(absolute(1-btf(human, robot, gamma, w)))
def kstable(human, robot, w, eta=2):
"""
Return the maximum number of human cars
that can be string-stabilized by a single robot car
for an oscillatory perturbation of frequency w
"""
that can be "safely" followed by a single robot car
for an oscillatory perturbation of frequency w
by a safety parameter eta
:param human:
:param robot:
:param w:
:param eta: safety margin
:return:
return (log(eta) - htflogmag(robot, w)) / tflogmag(human, w)
Find the maximum number of humans cars that can be handled by a
single robot car for any frequency (all w)
:param human:
:param robot:
:param eta:
:param kfn: function { ksafe for safety | kstable for string stability }
maxw = sqrt(-isstable(human))
return minimize(lambda w : kfn(human, robot, w, eta), 1, bounds=[(TOL,maxw-TOL)])#.fun[0]
"""
Min of maxksafe and maxkstable
:param human:
:param robot:
:param eta:
:return:
"""
return min(maxkfn(human, robot, eta, kstable), maxkfn(human, robot, eta, ksafe))
def best_robot_at_w(human, w, optfun, eta=2, fbound=(0, 0.2), gbound=(0, 0.2),
hbound=(0, 0.2)):
return minimize(lambda robot: -optfun(human, robot, w, eta),
[0.001, 0.001, 0.001], constraints=cons,
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def bestrobot(human, eta=2, fbound=(0, 0.2), gbound=(0, 0.2), hbound=(0, 0.2)):
cons = ({'type': 'ineq', 'fun': lambda x: isstable(x)},)
mink = minimize(lambda robot: -maxk(human, robot, eta).fun[0],
[0.001, 0.001, 0.001], constraints=cons,
bounds=[fbound, gbound, hbound])
# robot = mink.x
# print maxksafe(human, robot, eta=eta)
# print maxkstable(human, robot, eta=eta)
return mink
def plot_kmax_vs_w(human, eta=2):
"""
I think this plot is not meaningful (after the fact)
:param human:
:param eta:
:return:
"""
# ws = linspace(0,1,10)
maxw = sqrt(-isstable(human))
ws = linspace(TOL, maxw - TOL, 101)
kstablerobots = [-best_robot_at_w(human, w, kstable).fun for w in ws]
ksaferobots = [-best_robot_at_w(human, w, ksafe, eta).fun for w in ws]
# kst = kstable(human, robot, ws)
# ksf = ksafe(human, robot, ws, eta)
# print "kstable = ", kstable(human, robot, ws)
print ksaferobots, kstablerobots
plt.plot(ws, kstablerobots, 'k.')
plt.plot(ws, ksaferobots, 'r.')
plt.axis([0, maxw, 0, 200])
plt.show()
def plot_kmaxs_vs_FGH(human, robotopt, eta=2, res=100, fbound=(0, 0.2),
gbound=(0, 0.2), hbound=(0, 0.3)):
"""
How do the two optimality conditions (stability and safety) vary as the
robot parameters are deviated from the optimal robot controller?
:param human:
:param robotopt: (F,G,H) for the optimal robot controller given human
:param eta:
:param res: resolution for plotting, how fine to plot along the x-axis
:param fbound:
:param gbound:
:param hbound:
:return:
"""
robotFs = linspace(fbound[0], fbound[1], res)
robotGs = linspace(gbound[0], gbound[1], res)
robotHs = linspace(hbound[0], hbound[1], res)
for i, robotXs in enumerate([robotFs, robotGs, robotHs]):
robots = np.tile(robotopt, (res, 1))
robots[:, i] = robotXs
kstablerobots = np.array(
[maxkfn(human, robot, eta, kstable).fun[0] for robot in robots])
ksaferobots = [maxkfn(human, robot, eta, ksafe).fun[0] for robot in robots]
kstablerobots[kstablerobots < 0] = 0
plt.plot(robotXs, kstablerobots, 'k.')
plt.plot(robotXs, ksaferobots, 'r.')
plt.vlines(robotopt[i], 0, max(max(kstablerobots), max(ksaferobots)))
plt.axis([0, max(robotXs), 0, 100])
plt.show()
if __name__ == "__main__":
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import pyplot as plt
from cfm import IDM, CFM
hmodel.go(0.5)
human = (hmodel.f, hmodel.g, hmodel.h)
robotopt = bestrobot(human, eta)
plot_kmaxs_vs_FGH(human, robotopt.x)