302 lines
13 KiB
Python
302 lines
13 KiB
Python
|
import serial
|
||
|
import binascii
|
||
|
import math
|
||
|
import mariadb
|
||
|
import copy
|
||
|
|
||
|
|
||
|
# aktuell ist es so programmiert, dass es annimmt, dass in kg gemessen wird (andere Einheiten liefern also flasche Ergebnisse)
|
||
|
# das was man noch dazuprogrammieren kann, ist wenn mehrere Teile auf der Waage liegen, ob dann die Typen noch immer erkannt werden
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
db_config = {
|
||
|
'user': 'dbUser',
|
||
|
'password': 'dbPassword',
|
||
|
'host': 'localhost',
|
||
|
'database': 'projectGeislinger',
|
||
|
'port': 3306 # Standard port for MariaDB
|
||
|
}
|
||
|
|
||
|
# Establishing the connection
|
||
|
conn = mariadb.connect(**db_config)
|
||
|
# Create a cursor to execute queries
|
||
|
cursor = conn.cursor()
|
||
|
|
||
|
# Konfiguration der seriellen Schnittstelle
|
||
|
ser = serial.Serial('/dev/ttyUSB0', 9600)
|
||
|
|
||
|
waageEingeschwungen = False
|
||
|
|
||
|
|
||
|
|
||
|
def wahrscheinlichkeitsDichte(x,mue, var):
|
||
|
# in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable x für eine bestimmte Normalverteilung berechnet
|
||
|
standardabweichung = var**0.5
|
||
|
|
||
|
result = 1/(standardabweichung * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((x-mue)/standardabweichung)**2)
|
||
|
|
||
|
return result
|
||
|
|
||
|
def wahrscheinlichkeitsDichteMultipVar(waageMessung, numberObjectList, results):
|
||
|
# in der Funktion wird der Wahrscheinlichkeitsdichtenwert der Variable waageMessung für eine bestimmte Normalverteilung berechnet
|
||
|
|
||
|
# Mathematische Sätze, auf welchen die Berechnung basiert:
|
||
|
# seien X1,..., Xn unabhängige Zufallsvariablen mit Dichten f1,..., fn, dann hat X = (X1,...,Xn) die gemeinsame Dichte f(x1,...,xn) = f1(x1) * ... + fn(xn)
|
||
|
# seien X1,..., Xn unabhängige Zufallsvariablen die N(mue_i, sigma_i^2) verteilt sind, dann ist X = X1+...+Xn - N(mue, sigma^2) verteilt mit mue=mue1+...+mue_n, sigma^2 = sigma_1^2+...+sigma_n^2
|
||
|
|
||
|
result = 0
|
||
|
|
||
|
# Berechnung vom Gesamtmittelwert
|
||
|
mueGes = 0
|
||
|
for i in range(0, len(numberObjectList)):
|
||
|
mueGes = mueGes + numberObjectList[i] * results[i][2]
|
||
|
|
||
|
# Berechnung von der Gesamtvarianz (var = sigma^2)
|
||
|
varGes = 0
|
||
|
for i in range(0, len(numberObjectList)):
|
||
|
varGes = varGes + numberObjectList[i] * results[i][3]
|
||
|
|
||
|
# Berechnung der Wahrscheinlichkeitsdichte
|
||
|
standardabweichungGes = varGes**0.5
|
||
|
result = 1/(standardabweichungGes * (2*math.pi)**0.5 ) * math.exp(-0.5 * ((waageMessung-mueGes)/standardabweichungGes)**2)
|
||
|
|
||
|
return result
|
||
|
|
||
|
|
||
|
# die Funktion kann man vermutlich rauslöschen
|
||
|
def numberSmallerObjects(numberBiggerObjects, messungWaage, mue1,mue2, sigma2):
|
||
|
for i in range(1,10000):
|
||
|
#damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2
|
||
|
# eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen)
|
||
|
if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0:
|
||
|
if i > (messungWaage-numberBiggerObjects*mue2)/mue1:
|
||
|
return i
|
||
|
else:
|
||
|
return -1
|
||
|
|
||
|
|
||
|
def sumMaxWeightObjects(objectType, numberObjectList, results):
|
||
|
sum = 0
|
||
|
|
||
|
# die Anzahl an Bauteilen, welche dem Objekttypen zugeordnet sind, sollen nicht mit dazugerechnet werden
|
||
|
for i in range(objectType+1, len(numberObjectList)):
|
||
|
# eigentlich müsste man nur mit 3 multiplizieren, um 99,7% der Bauteile im Bereich zu haben - das gilt aber nur für eine gültige Normalverteilung
|
||
|
#sum = sum + numberObjectList[i] * (results[i][2] + 3 * math.sqrt(results[i][3]))
|
||
|
sum = sum + numberObjectList[i] * (results[i][2])
|
||
|
|
||
|
return sum
|
||
|
|
||
|
|
||
|
def numberPossibleObjects(objectType, numberObjectList, results, messungWaage):
|
||
|
# der objectType definiert, welcher der Objekte das Anschauungsobjekt ist
|
||
|
# wenn nur ein Objekt darauf gelegt wird, welches nicht vom Typen des Anschauungsobjektes ist, dann wird 1 zurück gegeben
|
||
|
|
||
|
#print(results[objectType][2]-10*math.sqrt(results[objectType][3]))
|
||
|
#print((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/results[objectType][2])
|
||
|
|
||
|
# wenn kein Gewicht auf der Waage liegt, dann soll -1 zurück gegeben werden.
|
||
|
if messungWaage <= 0:
|
||
|
return -1
|
||
|
|
||
|
#print(results[objectType][2])
|
||
|
#print(((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]+3*math.sqrt(results[objectType][3]))))
|
||
|
#print(((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]-3*math.sqrt(results[objectType][3]))))
|
||
|
#zwischenSumme = ((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]+3*math.sqrt(results[objectType][3])))
|
||
|
zwischenSumme = ((messungWaage-sumMaxWeightObjects(objectType, numberObjectList, results))/(results[objectType][2]))
|
||
|
for i in range(1,10000):
|
||
|
if zwischenSumme <= 0: #in diesem Fall wird das gesamte Gewicht der Messung durch Objekte eines anderen Typen "aufgebraucht"
|
||
|
return 0
|
||
|
if i > zwischenSumme:
|
||
|
return i # i entspricht beim returnen der Anzahl der möglichen Objekte
|
||
|
|
||
|
def anzBauteileCountFunction(numberObjectList):
|
||
|
counter = 0
|
||
|
|
||
|
for i in range(0,len(numberObjectList)):
|
||
|
if numberObjectList[i] > 0:
|
||
|
counter = counter + 1
|
||
|
|
||
|
return counter
|
||
|
|
||
|
"""
|
||
|
for i in range(1,10000):
|
||
|
#damit wird geprüft, ob eh auch ein Objekt vom Typ1 auf der Waage liegt, oder nur ein Objekt vom Typ2
|
||
|
# eigentlich müsste da 3*sigma drinnen stehen, um 99,7% der Fälle abzudecken, aber das ist nur bei einer gültigen Normalverteilung zutreffend (mit ausreichend Messungen)
|
||
|
if (messungWaage-numberBiggerObjects*(mue2+10*sigma2))/mue1 > 0:
|
||
|
if i > (messungWaage-numberBiggerObjects*mue2)/mue1:
|
||
|
return i
|
||
|
else:
|
||
|
return -1
|
||
|
"""
|
||
|
|
||
|
|
||
|
def main():
|
||
|
|
||
|
|
||
|
print("connection is open: ", ser.is_open)
|
||
|
print("port to which it is connected: ", ser.portstr)
|
||
|
|
||
|
|
||
|
#an die Waage den Befehl senden, dass sie ausgelesen werden soll
|
||
|
ser.write(b'getWeight\n')
|
||
|
#ser.write(b'tare\n')
|
||
|
serialString = ser.readline().decode('utf-8').rstrip() #Auslesen des Serial-Strings/der Messung der Waage
|
||
|
|
||
|
# wenn am Ende des Strings kg steht, dann ist die Waage eingeschwungen - das wird hiermit überprüft
|
||
|
lenString = len(serialString)-1
|
||
|
if serialString[lenString] == "g" and serialString[lenString-1] == "k":
|
||
|
print("ist eingeschwungen")
|
||
|
waageEingeschwungen = True
|
||
|
else:
|
||
|
print("die Waage ist noch nicht eingeschwungen")
|
||
|
waageEingeschwungen = False
|
||
|
|
||
|
#aus dem String werden alle Zeichen, welche nicht zur Darstellung der Zahl benötigt werden entfernt
|
||
|
intString = ""
|
||
|
for i in serialString:
|
||
|
if i=="-" or i=="0" or i=="." or i=="1" or i=="2" or i=="3" or i=="4" or i=="5" or i=="6" or i=="7" or i=="8" or i=="9":
|
||
|
intString = intString + i
|
||
|
print("Wert, welcher von der Waage ausgelesen wurde: " + intString + "kg")
|
||
|
|
||
|
|
||
|
# wenn die Waage nicht eingeschwungen ist, dann soll auch nichts weiter gemacht werden
|
||
|
if( waageEingeschwungen == True and float(intString)>0):
|
||
|
|
||
|
|
||
|
# Define the SQL query
|
||
|
sql_query = "SELECT * FROM projectGeislinger.Einzelteile"
|
||
|
# Execute the query
|
||
|
cursor.execute(sql_query)
|
||
|
# Fetch results
|
||
|
results = cursor.fetchall()
|
||
|
# Display data
|
||
|
print("Ausgabe der Daten der Datenbank:")
|
||
|
for row in results:
|
||
|
print(row)
|
||
|
|
||
|
|
||
|
anzBauteiltypen = len(results)
|
||
|
anzBauteile = anzBauteiltypen * [0] # erstellt eine Liste, in welcher die Anzahl der Bauteiltypen gespeichert ist, welche für die weiteren Schleifen verwendet wird
|
||
|
wahrscheinleichkeitsMatrix = []
|
||
|
|
||
|
# Berechnen der Anzahl an Objekten
|
||
|
for i in range(0, anzBauteiltypen):
|
||
|
#bauteilTypCounter = i+1 #zum hochzählen der Anzahlen der Bauteiltypen nach der k-Schleife
|
||
|
|
||
|
while(True):
|
||
|
if i<(anzBauteiltypen-1): # wenn i die letzte Spalte der Bauteiltypenmatrix ist, dann soll der Teil übersprungen werden
|
||
|
for k in range(0, 10000):
|
||
|
anzBauteile[i+1] = k
|
||
|
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
|
||
|
if nrObjects == -1 or nrObjects == 0:
|
||
|
break
|
||
|
anzBauteile[i] = nrObjects
|
||
|
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
|
||
|
# da die Berechnete Anzahl an möglichen Messobjekten um 0 bis +1 um den "wahren" Wert schwankt, wird in der Folge auch die Wahrscheinlichkeit mit einer um 1 verringerten Bauteilanzahl berechnet (sollte diese größer als 1 sein)
|
||
|
if(anzBauteile[i] >= 1 and anzBauteileCountFunction(anzBauteile)>1):
|
||
|
anzBauteile = anzBauteile[:]
|
||
|
anzBauteile[i] = anzBauteile[i]-1
|
||
|
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
|
||
|
|
||
|
anzBauteile[i+1] = 0
|
||
|
elif i == (anzBauteiltypen-1):
|
||
|
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
|
||
|
if nrObjects == -1 or nrObjects == 0:
|
||
|
break
|
||
|
anzBauteile[i] = nrObjects
|
||
|
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
|
||
|
if(anzBauteile[i] >= 1 and anzBauteileCountFunction(anzBauteile)>1):
|
||
|
anzBauteile = anzBauteile[:]
|
||
|
anzBauteile[i] = anzBauteile[i]-1
|
||
|
wahrscheinleichkeitsMatrix.append([wahrscheinlichkeitsDichteMultipVar(float(intString), anzBauteile[:], results), anzBauteile[:]])
|
||
|
|
||
|
|
||
|
if i >= (anzBauteiltypen-2): #wenn der Fall eintritt, dann wurden alle Fälle überprüft -> dadurch kann die i-Schleife in die letzte Runde gehen, kann das Programm sich ganz beenden
|
||
|
anzBauteile[i] = 0
|
||
|
break
|
||
|
|
||
|
|
||
|
for m in range(i+2,anzBauteiltypen):
|
||
|
anzBauteile[m] = anzBauteile[m] + 1
|
||
|
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
|
||
|
if nrObjects >= 1:
|
||
|
break
|
||
|
elif nrObjects < 1 and m == (anzBauteiltypen-1) :
|
||
|
break
|
||
|
else:
|
||
|
anzBauteile[m] = 0
|
||
|
|
||
|
|
||
|
nrObjects = numberPossibleObjects(i, anzBauteile, results, float(intString))
|
||
|
if (nrObjects == -1 or nrObjects == 0):
|
||
|
anzBauteile[anzBauteiltypen-1] = 0
|
||
|
anzBauteile[i] = 0
|
||
|
break
|
||
|
|
||
|
|
||
|
# Suchen der höchsten Wahrscheinlichkeitsdichte
|
||
|
countMaxPropDensity = 0
|
||
|
maxPropDensity = 0
|
||
|
#print(wahrscheinleichkeitsMatrix[0][0])
|
||
|
for i in range(0, len(wahrscheinleichkeitsMatrix)):
|
||
|
if(wahrscheinleichkeitsMatrix[i][0] > maxPropDensity):
|
||
|
maxPropDensity = wahrscheinleichkeitsMatrix[i][0]
|
||
|
countMaxPropDensity = i
|
||
|
if wahrscheinleichkeitsMatrix[i][0] >0:
|
||
|
print(wahrscheinleichkeitsMatrix[i])
|
||
|
print(wahrscheinleichkeitsMatrix[countMaxPropDensity][0])
|
||
|
# die Bauteilkombination mit der höchsten Wahrscheinlichkeitsdichte ausgeben
|
||
|
for i in range(0, len(wahrscheinleichkeitsMatrix[0][1])):
|
||
|
print("Bauteiltyp: ", results[i][1]," Anzahl: ", wahrscheinleichkeitsMatrix[countMaxPropDensity][1][i])
|
||
|
|
||
|
#nrObjects = numberPossibleObjects(0, anzBauteile, results, float(intString))
|
||
|
#print("number objects: ", nrObjects-1)
|
||
|
|
||
|
"""
|
||
|
for i in range(3,0,-1):
|
||
|
numberOfSmallObjects = numberSmallerObjects(1, float(intString),results[4][2], results[3][2], math.sqrt(results[3][3]))
|
||
|
print("number of smaller objects: ", numberOfSmallObjects-1)
|
||
|
"""
|
||
|
|
||
|
|
||
|
"""
|
||
|
# in der Folge wird nun berechnet, welcher Normalverteilung die Messung am ehesten entspricht
|
||
|
dBId = 0
|
||
|
maxPropDensity = 0
|
||
|
for row in results:
|
||
|
propDens = wahrscheinlichkeitsDichte(float(intString) ,row[2], row[3])
|
||
|
if propDens > maxPropDensity:
|
||
|
maxPropDensity = propDens
|
||
|
dBId = row[0]
|
||
|
|
||
|
|
||
|
#Ausgabe des Bauteiltypen, welchem die Messung am ehesten entspricht
|
||
|
for row in results:
|
||
|
if row[0] == dBId:
|
||
|
print(row[1])
|
||
|
|
||
|
#propDens = wahrscheinlichkeitsDichte(0.042 ,results[0][2], results[0][3])
|
||
|
#print(propDens)
|
||
|
"""
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
ser.close()
|
||
|
print("connection is open: ", ser.is_open)
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|
||
|
|
||
|
|
||
|
|