import numpy as np
import matplotlib.pyplot as plt
def gaussian(x, mu=0., sig=1.):
return np.exp(-np.power(x - mu, 2.) / (2 * np.power(sig, 2.)))
def fuzzy_and(a, b, type="max"):
if type == "max":
return np.fmax(a, b)
def fuzzy_and_array(a, type="max"):
if type == "max":
return np.max(a, axis=0)
def fuzzy_or(a, b, type="min"):
if type == "min":
return np.fmin(a, b)
class FuzzyControl:
def __init__(self):
self.resolution = 50
self.go_left = 0.
self.no_change = 0.
self.go_right = 0.
self.r = 30
self.sample_points = np.linspace(-self.r, self.r, self.resolution)
def fuzzify(self, angle, angular_speed):
angle_memberships = []
angular_speed_memberships = []
#
if angle > 50:
angle = 50
if angle < -50:
angle = -50
if angular_speed > 45:
angular_speed = 45
if angular_speed < -45:
angular_speed = -45
angle_mu = [-50., -18., -3., 3., 18., 50.]
angle_sig = [15., 9.5, 2.5, 2.5, 9.5, 15.]
for i in range(6):
angle_memberships.append(gaussian(angle, angle_mu[i], sig=angle_sig[i]))
angular_speed_mu = [-45., -15., -3., 3., 15., 45.]
angular_speed_sig = [14., 7.5, 3., 3., 7.5, 14.]
for i in range(6):
angular_speed_memberships.append(gaussian(angular_speed, angular_speed_mu[i], sig=angular_speed_sig[i]))
return angle_memberships, angular_speed_memberships
def inference(self, angle_memberships, angular_speed_membership):
#
# How to interpret the rule base:
# NB: negative big, NM: negative medium, NS: negative small
# PB: positive big, PM: positive medium, PS: positive small
# The table:
# NB, NM, NS, PS, PM, PB angular speed
# NB 0 0 0 1 2 3
# NM 0 0 1 2 3 3
# NS 0 1 2 3 3 4
# PS 1 2 2 3 4 5
# PM 2 2 3 4 5 5
# PB 2 3 4 5 5 5
# angle
#
# One cell contains the control force:
# 0 NB, 1 NM, 2 NS, 3 PS, 4 PM, 5 PB
rule_base = [[0, 0, 0, 1, 2, 3],
[0, 0, 1, 2, 3, 3],
[0, 1, 2, 3, 3, 4],
[1, 2, 2, 3, 4, 5],
[2, 2, 3, 4, 5, 5],
[2, 3, 4, 5, 5, 5]]
fuzzy_control_force = [0., 0., 0., 0., 0., 0.]
for i in range(6):
for k in range(6):
pt = fuzzy_or(angle_memberships[i], angular_speed_membership[k])
fuzzy_control_force[rule_base[i][k]] = fuzzy_and(fuzzy_control_force[rule_base[i][k]], pt)
for i, mu in enumerate([h * 10 for h in [-3, -2., -1., 1., 2., 3]]):
fuzzy_control_force[i] = fuzzy_or(gaussian(self.sample_points, mu, sig=2.), fuzzy_control_force[i])
fuzzy_control_force = fuzzy_and_array(np.asarray(fuzzy_control_force))
return fuzzy_control_force
def defuzzify(self, fuzzy_control_force):
rv = (np.sum(self.sample_points * fuzzy_control_force) + 1e-8) / (np.sum(fuzzy_control_force) + 1e-8)
return rv
@staticmethod
def draw_member_functions():
resolution = 1000
angle = np.linspace(-90, 90, resolution)
angular_speed = np.linspace(-50, 50, resolution)
angle_memberships = []
angular_speed_memberships = []
for i in range(resolution):
a, b = FuzzyControl.fuzzify(angle[i], angular_speed[i])
angle_memberships.append(a)
angular_speed_memberships.append(b)
angle_memberships = np.asarray(angle_memberships)
angular_speed_memberships = np.asarray(angular_speed_memberships)
for i in range(angle_memberships.shape[1]):
plt.plot(angle, angle_memberships[:, i])
plt.title("Angle Memberships")
plt.xlabel("Degree")
plt.ylabel("Membership value")
plt.show()
for i in range(angular_speed_memberships.shape[1]):
plt.plot(angular_speed, angular_speed_memberships[:, i])
plt.title("Angular Speed Memberships")
plt.xlabel("Degree/sec")
plt.ylabel("Membership value")
plt.show()