#!/usr/bin/env python # -*- coding: utf-8 -*- # This example shows how to set up a fuzzy controller for # the temperature in a container in which we can put cold or warm water (through the mixer). # The container is modeled as a PT1-System which means the final value is # asymptotically with ongoing time. # Weitere Arbeiten: # # 1. Darstellung der Eingangs- und Ausgangsvariablen # 2. Fahren eines Fuzzy-Reglers über einen veränderbaren Sollwert # 3. Randbedingungen für die Variablen bei der Start- und Endefunktion # 4. Verarbeitung von beliebig gro0en Fuzzysets # 5. Verarbeitungen von mehreren Eingangs- und Ausgangsvariablen class Controller(object): def __init__(self,target,cold,hot): """Create fuzzy system.""" import fuzzy.System import fuzzy.InputVariable import fuzzy.fuzzify.Plain import fuzzy.OutputVariable import fuzzy.defuzzify.COG import fuzzy.Adjective import fuzzy.Rule import fuzzy.operator.Input import fuzzy.norm.Min import fuzzy.set.Triangle import fuzzy.set.SFunction import fuzzy.set.ZFunction #import fuzzy.set.PiFunction # create system object self.system = fuzzy.System.System() self.target = target self.target_diff = 0. self.target_diff_integrator = 0. # definition of input variable input_temp = fuzzy.InputVariable.InputVariable( fuzzify=fuzzy.fuzzify.Plain.Plain(), description="temperature", min=-100.0,max=100.0, unit="degrees" ) # add variable to system self.system.variables["input_temperature"] = input_temp # create fuzzy set # make it to an adjective # and add it to the input variable input_temp.adjectives["too cold"] = fuzzy.Adjective.Adjective(fuzzy.set.ZFunction.ZFunction(a=0.,delta=10.)) #ignore, not used #input_temp.adjectives["warm"] = fuzzy.Adjective.Adjective(fuzzy.set.PiFunction.PiFunction(a=target,delta=10.)) input_temp.adjectives["too hot"] = fuzzy.Adjective.Adjective(fuzzy.set.SFunction.SFunction(a=0.,delta=10.)) # definition of output variable # we want use later the center of gravity method output_temp = fuzzy.OutputVariable.OutputVariable( defuzzify=fuzzy.defuzzify.COG.COG(), description="temperature", min=0.0,max=100.0, unit="degrees" ) # more properties could be # - output as value or membership of adjectives in a dictionary # (input could work this way too.) # add to system self.system.variables["output_temperature"] = output_temp # make set -> adjective -> add to variable output_temp.adjectives["cold"] = fuzzy.Adjective.Adjective(fuzzy.set.Triangle.Triangle(m=cold)) output_temp.adjectives["hot"] = fuzzy.Adjective.Adjective(fuzzy.set.Triangle.Triangle(m=hot)) # create a fuzzy rule rule1 = fuzzy.Rule.Rule( # it sets putput_temperature hot adjective=self.system.variables["output_temperature"].adjectives["hot"], # it gets it value from here operator=fuzzy.operator.Input.Input( # and this get it value from here self.system.variables["input_temperature"].adjectives["too cold"], ), certainty=1.0, CER=fuzzy.norm.Min.Min() ) # using another style of referencing the adjectives (by looking up the names at runtime) rule2 = fuzzy.Rule.Rule( adjective=self.system.variables["output_temperature"].adjectives["cold"], operator=fuzzy.operator.Input.Input( self.system.variables["input_temperature"].adjectives["too hot"] ), certainty=1.0, CER=fuzzy.norm.Min.Min() ) # add rules to system self.system.rules["too cold"] = rule1 self.system.rules["too warm"] = rule2 # system ready to use def getFuzzySystem(self): return self.system def limit(self,value,lower_limit,upper_limit): return max(lower_limit,min(value,upper_limit)) def calculate(self,input): # dictionaries as container for transfer of parameters # a is for named output values! self.target_diff = input-self.target self.target_diff_integrator += self.target_diff self.target_diff_integrator = self.limit(self.target_diff_integrator,-100.,+100.) input_values = { "input_temperature" : self.target_diff, "integrator": self.target_diff_integrator } output_values = {"output_temperature" : 0.0} # calculation in fuzzy controller self.system.calculate(input=input_values,output=output_values) result = output_values["output_temperature"] # if next turn not calculable use last value (= current in this turn) self.system.variables["output_temperature"].failsafe = result return result