Benutzer-Werkzeuge

Webseiten-Werkzeuge


Seitenleiste

ss2021:project4:brueckensimulation

Brückensimulation

Gruppenmitglieder

Jakob Berschneider, Emma Galow

Ziel

Unser Projektziel ist es, das Verhalten verschiedener Brücken abhängig von verschiedenen Ausgangsbedingungen zu simulieren. Dabei soll der Benutzer selbst einstellen können, welches Material verbaut wurde, wie die Belastung ist und wie die Brücke konstruiert ist. Mit der Software soll es möglich sein, zu überprüfen, ob die Brücke stabil ist und eine Belastung aushalten würde. Das Ergebnis soll dann entsprechend visualisiert werden.

Protokolle

Dokumentation

Mechanische Grundlagen

Vereinfachungen / Annahmen

Wir haben uns für das Projekt dazu entschieden, dass wir uns zunächst auf zweidimensionale Fachwerkbrücken beschränken. Außerdem soll das Programm für den Nutzer bereits die Lagerung der Brücke festlegen (Festlager auf der linken Seite und Loslager auf der rechten Seite). Die Brückenkonstruktionen sollen statisch bestimmt sein, was durch das Programm überprüft werden soll. Diese Annahmen erleichtern uns die Berechnung der Lager-und Stabkräfte und die Implementierung im Code.

Ideales Fachwerk

Das ideale Fachwerk besteht aus Stäben, Lagern und Knoten. Sind die Stäbe eines Stabwerks nur auf Druck oder Zug beansprucht, so spricht man von einem Fachwerk. Die Knoten sind die Endpunkte der Stäbe, in denen mehrere Stäbe freibeweglich und gelenkig verbunden werden. An den Lagern werden Kräfte aus dem Stabwerk selbst an die Umgebung übertragen. Abhängig von der Anzahl der verschiedenen Kraftkomponenten ergibt sich die Wertigkeit der Lager(einwertig, zweiwertig usw.)

Bei einem idealen Fachwerk sind alle Stäbe reibungsfrei gelenkig verbunden. Zudem greifen alle Kräfte nur in den Knoten an, weswegen man auch davon ausgehen muss, dass die Stäbe gewichtlos sind. Die Stäbe selbst werden nur auf Normalkraft(Kraft in Richtung der Stabachse) beansprucht. Stäbe sind auf Zug bei positiver Normalkraft und auf Druck bei negativer Normalkraft belastet.

Statische Bestimmtheit

Durch die statische Bestimmtheit lässt sich überprüfen, ob sich ein System mechanischen Gleichgewicht befindet. Mechanisches Gleichgewicht herrscht vor, wenn die Summe aller einwirkenden Kräfte (horizontal, vertikal und Drehmoment) gleich Null ist. Das heißt, die statische Bestimmtheit gibt Auskunft darüber, ob ein System in seiner Beweglichkeit eingeschränkt ist z.B. durch Lager oder Gelenke.

Die notwendige Bedingung für statische Bestimmtheit ist, dass die Zahl der Freiheitsgrade gleich der Summe der Wertigkeiten aller Lager und Verbindungselemente ist. Ein Tragwerk ist statisch bestimmt, wenn alle Lagerreaktionen eindeutig aus den Gleichgewichtsbedingungen bestimmt werden können. Die Anzahl der Freiheitsgrade ist die Zahl der unabhängigen Bewegungsmöglichkeiten eines Körpers. Ein Punkt im Raum hat bspw. 3 Freiheitsgrade, während ein starrer Körper im Raum Raum 6 Freiheitsgrade hat.

Die notwendige Bedingung für statische Bestimmtheit bei Stabwerken ist: $2k = s + r$. Wobei k die Anzahl der Knoten, s die Anzahl der Stäbe und r die Anzahl der Lagerreaktionen(Wertigkeit) ist. Die hinreichende Bedingung für statische Bestimmtheit bei Stabwerken ergibt sich aus Bildungsgesetzen und Polplan. Für einfache Stabwerke gilt das Bildungsgesetz, dass von einem starren Körper ein einer Knoten durch zwei Stäbe, die nicht auf einer Geraden liegen, angeschlossen wird. Man kann das beliebig fortsetzen. Beim Polplan darf der geometrische Ort (Wirkungslinie Loslager) nicht durch den Pol (Festlager / Schnittpunkt zweier geometrischer Orte) verlaufen, damit das System statisch bestimmt sein kann.

Knotenpunktverfahren

Das Knotenpunktverfahren ist das allgemeine Standardverfahren zur Ermittlung der Stabkräfte in einem Fachwerk:

  • Alle Knoten und Stäbe nummerieren
  • Nullstäbe (Stäbe ohne Belastung) bestimmen
  • System freischneiden, Lagerreaktionen bestimmen
  • Alle Knoten einzeln freischneiden und Stabkräfte auftragen
  • Kräftegleichwicht(horizontal, vertikal) für jeden einzelnen Knoten aufstellen
  • Gleichungssystem lösen

Bibliotheken

Wir haben folgende Bibliotheken eingebunden:

  • numpy
  • math
  • pygame

Während uns numpy und math schon aus dem Crashkurs als Bibliotheken, die hilfreich für das Lösen mathematischer Probleme sind, bekannt waren, mussten wir uns in pygame zunächst einarbeiten. Mit Hilfe von pygame ist es möglich, Grafiken zu bewegen, Töne abzuspielen oder auch Eingaben, wie z.B. Mausklicks oder Tastendrücke, abzufragen. Letzteres war für uns am wichtigsten, da so der Nutzer seine Vorstellung einer Fachwerkbrücke gut übermitteln kann. Wie der Name „pygame“ vermuten lässt, wird diese Bibliothek häufig für das Erstellen von Spielen genutzt. Unsere Anwendung ist zwar kein richtiges Spiel, aber wie ein einfaches, mit Hilfe von pygame programmiertes Spiel aufgebaut. Hauptbestandteil ist dabei eine while-Schleife, die die gesamte Zeit läuft, es sei denn, das Event „pygame.Quit“ findet statt. In dieser while-Schleife befindet sich eine große for-Schleife, in der die Art einer jeden stattfindenden Eingabe abgefragt und daraufhin spezifische Aktionen ausgeführt werden. Einige dieser Aktionen sind außerhalb der while-Schleife als Funktonen definiert.

Einige ausgewählte Funktionen aus pygame, die wir häufig genutzt haben oder als besonders wichtig erachten, sind folgende:

  • pygame.event.get(): dient zur Übermittlung einer jeden getätigten Eingabe
  • pygame.Rect(x-Koordinate links, y-Koordinate oben, Breite, Höhe): Erstellen eines Rechtecks
  • pygame.draw.rect(Zeichenfenster, Farbe, Rechteck): Zeichnen des erstellten Rechtecks
  • pygame.KEYDOWN: Wird eine Taste auf der Tastatur gedrückt, so ist das der type der jeweiligen Eingabe; jede einzelne Taste an sich hat nochmals eigene Bezeichnungen (z.B. Enter = pygame.K_RETURN, P = pygame.K_p, … )
  • pygame.MOUSEBUTTONDOWN: Wird eine Taste auf der Maus gedrückt, so ist das der type der jeweiligen Eingabe

Unsere Infos zu Funktionen aus pygame haben wir aus der pygame-Dokumentation gezogen.

Entwicklung des Programms

Programmstruktur

Berechnungen

Überprüfung nach statischer Bestimmtheit

Bevor die einzelnen Stab-und Lagerkräfte bestimmt werden können, muss zunächst die statische Bestimmtheit überprüft werden. Im Code haben wir das in der Funktion statisch_bestimmt umgesetzt:

def statisch_bestimmt():
    points = []
    points.append(knotenpunkte[0])
    for i in knotenpunkte[2:]:
        points.append(tuple(i))
    # Anzahl einzigartiger Knotenpunkte, Liste einzigartiger Knotenpunkte
    amount_knoten = len(set(points))
    knoten = list(set(points))
    # Alle Verbindungen zwischen 2 Punkten
    connections = []
    for i in range(len(points) - 1):
        if [points[i], points[i+1]] and [points[i+1], points[i]] not in connections:
            connections.append([points[i], points[i+1]])
 
    # Alle Verbindungen werden geordnet
    for i in connections:
        if i[0][0] > i[1][0]:
            i[0], i[1] = i[1], i[0]
    # Parameter, ob das System statisch bestimmt ist
    statisch = True
    # notwendige Bedingung der statischen Bestimmtheit
    if 2 * amount_knoten != len(connections) + 3:
        return False
    # Es werden alle Verbindungen von jeweils 2 Verbindungspunkten in Listen gespeichert und die Schnittmenge wird zusammengeführt
    for i in connections:
        connected = []
        connected1 = []
        connected2 = []
        for k in connections:
            if i != k:
                if i[0] == k[0]:
                    connected1.append(k[1])
                if i[0] == k[1]:
                    connected1.append(k[0])
                if i[1] == k[0]:
                    connected2.append(k[1])
                if i[1] == k[1]:
                    connected2.append(k[0])
        connected1 = set(connected1)
        connected2 = set(connected2)
        connected = connected1 & connected2
        connected = list(connected)
 
    # Es wird überprüft, ob die Konstruktion statisch bestimmt ist
        if len(connected) > 2 or len(connected) == 0:
            return False
            break
        if len(connected) == 2 and i[0][0] != i[1][0]:
            m = ((i[1][1] - i[0][1])/(i[1][0] - i[0][0]))
            if connected[0][1] > m * connected[0][0] + i[0][1] - m * i[0][0] and connected[1][1] > m * connected[1][0] + i[0][1] - m * i[0][0]:
                return False
                break
            if  connected[0][1] < m * connected[0][0] + i[0][1] - m * i[0][0] and connected[1][1] < m * connected[1][0] + i[0][1] - m * i[0][0]:
                return False
                break
        if len(connected) == 2 and i[0][0] == i[1][0]:
            if (connected[0][0] > i[0][0] and connected[1][0] > i[0][0]) or (connected[0][0] < i[0][0] and connected[1][0] < i[0][0]):
                return False
                break
 
        if statisch:
            return True

Zunächst wird eine Liste connections erstellt, in der alle vorhandenen Verbindungen zwischen zwei Punkten, jeweils aufsteigend nach x-Wert geordnet, gespeichert werden. Dann wird die notwendige Bedingung für statische Bestimmtheit abgefragt.

Entsprechend der hinreichenden Bedingung für statische Bestimmtheit darf es höchstens einen gemeinsamen Verbindungspunkt oberhalb und unterhalb der Wirkungslinie eines Stabes geben. Auch um Überschneidungen von Stäben zu verhindern. Durch die Funktion wird für jeden Stab in der Konstruktion überprüft, welche gemeinsamen Verbindungspunkte beide Stabpunkte haben. Dazu wird für beide Stabpunkte eine Liste (connected1 und connected2) mit allen Verbindungspunkten erstellt. Die Schnittmenge der beiden Listen wird dann in connected gespeichert und abschließend wird überprüft, ob es höchstens einen Verbindungspunkt oberhalb und unterhalb der Verbindung gibt. Dazu werden die beiden Stabpunkte jeweils als Punkte einer linearen Funktion betrachtet. Die Verbindungspunkte in connected werden, dann danach untersucht, ob zwei Punkte oberhalb oder unterhalb dieser Funktion liegen bzw. bei einer Senkrechten rechts und links von dieser.

Lager- Stabkräfte berechnen

Für die Berechnung der Stab-und Lagerkräfte haben wir uns am Knotenpunktverfahren orientiert. Dazu haben wir zwei numpy-Arrays erstellt (N, y), um das Gleichungssystem mit np.linalg.solve(N, y) zu lösen. Den Aufbau des Gleichungssystems kann man sich folgender Maßen vorstellen:

Anhand dieser Struktur lässt sich auch erkennen, dass es im Vergleich zum Knotenpunktverfahren wie zuvor beschrieben einige Vereinfachungen gibt. So sind viele Zwischenschritte, die beim händischen Lösungsverfahren den Prozess erleichtern, nicht mehr nötig. Das heißt, man muss die Knoten und Stäbe nicht mehr nummerieren oder zuvor die Auflagerreaktionen und Nullstäbe bestimmen, da dies alles in einem Schritt als Gleichungssystem berechnet wird. Anhand dieser Struktur kann man auch sehen, dass die statische Bestimmtheit insofern wichtig ist, als dass es gleich viele Unbekannte wie Gleichung gibt, um das Gleichungssystem zu lösen. Der Lösungsvektor $x$ hat $s+r$ Unbekannte und es gibt insgesamt $2*k$ Gleichungen.

Die Berechnung wird mit der Funktion click_berechnen durchgeführt.

def click_berechnen():
 
    points = []
    points.append(knotenpunkte[0])
    for i in knotenpunkte[2:]:
        points.append(tuple(i))
    force_val = kraft_liste
    start_cords = knotenpunkte[0]
    end_cords = knotenpunkte[1]
    force_cords = kraft_punkt_liste
 
    # Maximal zulässige Belastungen
    A_x_zul = lagerkraft_betrag
    A_y_zul = lagerkraft_betrag
    B_y_zul = lagerkraft_betrag
    stab_zul = stabkraft_betrag
 
    # Richtung der Kraft
    force_dir = kraft_dir
 
    # Anzahl einzigartiger Knotenpunkte, Liste einzigartiger Knotenpunkte
    amount_knoten = len(set(points))
    knoten = list(set(points))
    # Alle Verbindungen zwischen 2 Punkten
    connections = []
    for i in range(len(points) - 1):
        if [points[i], points[i+1]] and [points[i+1], points[i]] not in connections:
            connections.append([points[i], points[i+1]])
 
    # Arrays zur Berechnung der Stab-und Lagerkräfte
    N = np.zeros((amount_knoten * 2, amount_knoten * 2))
    y = np.zeros((amount_knoten * 2))
 
    # Stabrichtung
    s_dir = (0, 0)
 
    # Berechnung der Werte der Arrays zur Berechnung der Stab-und Lagerkräfte
    for i in range(len(knoten)):
 
        for j in range(len(connections)):
            if knoten[i] in connections[j]:
                if knoten[i] == connections[j][0]:
                    s_dir = vector(connections[j])
                if knoten[i] == connections[j][1]:
                    s_dir = vector([connections[j][1], connections[j][0]])
                N[i * 2, j] = s_dir[0] / (np.sqrt(s_dir[0] ** 2 + s_dir[1] ** 2))
                N[i * 2 + 1, j] = s_dir[1] / (np.sqrt(s_dir[0] ** 2 + s_dir[1] ** 2))
                if knoten[i] == end_cords:
                    N[i * 2 + 1, len(connections) + 2] = 1
                if knoten[i] == start_cords:
                    N[i * 2, len(connections)] = 1
                    N[i * 2 + 1, len(connections) + 1] = 1
                for k in range(len(force_val)):
                    print(knoten[i])
                    print(force_cords[k])
                    if knoten[i] == tuple(force_cords[k]):
                        y[i * 2] += - f_x(force_dir[k], force_val[k])
                        y[i * 2 + 1] += - f_y(force_dir[k], force_val[k])
 
    # Array mit den Ergebnissen, die vorderen Einträge geben die einzelnen Stabkräfte an, die letzten drei die Auflagerkräfte
    staebe = np.linalg.solve(N, y)
    stabil = True
 
    for i in staebe[:amount_knoten * 2 - 3]:
        if abs(i) > stab_zul:
            stabil = False
            print("Belastung zu groß (Stabkraft)")
 
    if abs(staebe[amount_knoten * 2 - 3]) > A_x_zul:
        stabil = False
        print("Belastung zu groß (Ax)")
 
    if abs(staebe[amount_knoten * 2 - 2]) > A_y_zul:
        stabil = False
        print("Belastung zu groß (Ay)")
 
    if abs(staebe[amount_knoten * 2 - 1]) > B_y_zul:
        stabil = False
        print("Belastung zu groß (By)")
 
    if stabil:
        meldung_stabil()
    else:
        meldung_instabil()

Dazu wird nach der zuvor dargestellten Struktur den Arrays N und y ihre Werte zugeordnet. Abschließend wird überprüft, ob diese Werte die angegebenen zulässigen Grenzwerte für Stab-und Lagerkräfte nicht überschreiten. Je nach Ergebnis wird dann eine entsprechende Meldung ausgegeben.

Visualisierung

Der Nutzer des Programmes hat zu Beginn eine bestimmte Vorstellung eines zweidimensionalen Fachwerks. Diese muss er irgendwie übermitteln können. Dazu gäbe es mehrere Optionen:

  • Es könnte eine Auswahl von Fachwerken zur Verfügung gestellt werden, aus der der User sich ein Fachwerk aussucht. Dann wären die Möglichkeiten jedoch sehr begrenzt und das Fachwerk könnte häufig nicht der Vorstellung des Nutzers entsprechen.
  • Eine andere Möglichkeit wäre, den User dazu aufzufordern, Koordinaten für die Knotenpunkte als Zahlenwerte und die Anzahl der Stäbe einzugeben. Das wäre jedoch etwas unintuitiv.
  • Die Möglichkeit, für die wir uns letztlich entschieden haben, ist die, dass wir den Nutzer das Fachwerk selber zeichnen lassen. So können alle Werte gut übermittelt werden und der Nutzer hat genügend kreativen Freiraum.

Das ganze läuft dann in ungefähr 10 Schritten ab:

Das Startlager ist einfachheitshalber in jedem Fall das Festlager. Sobald ein Knotenpunkt als Startpunkt dient, wird er für diesen Zeitraum rot markiert. Damit es möglich ist, wirklich parallele Stäbe zu zeichnen, gibt es die Optionen „Horizontal“ und „Vertikal“. Eine weitere Zeichenhilfe ist die, dass wenn ungefähr auf einen schon existierenden Knotenpunkt geklickt wird, genau dieser wieder ausgewählt wird, bzw. dass wenn, je nachdem ob horizontal oder vertikal ausgewählt wurde, auf einen bereits existierenden Knotenpunkt geklickt wird, die x- oder y-Koordinaten übernommen werden. Die Ausgabe der Rechenergebnisse erfolgt als Liste über die Konsole.

Der gesamte Code befindet sich in dieser Datei: brueckensimulationen.zip

Verlauf der Projektarbeit

Den Verlauf unserer Projektarbeit kann man den im Laufe der Zeit angefertigten Protokollen entnehmen: Protokolle

  • ab 27.05.2021: Themenfindung, Planung und Recherche
  • ab 17.06.2021: Arbeitsteilung Code zur Berechnung, Code zur Visualisierung
  • ab 7.10.2021: Zusammenführen beider Programme

Fazit und Ausblick

Das Programm weist immer noch ein paar kleine Defizite auf. So kann man beispielsweise noch keine Zahleneingabe abbrechen oder eine gerade geschrieben Zahl löschen. Auch die Reset-Funktion und die Undo-Option arbeiten an manchen Stellen noch nicht so, wie sie es eigentlich soll. Zudem kommt, dass ein paar Stellen im Code noch etwas unstrukturiert sind und möglicherweise mehr mit Klassen gearbeitet hätte werden sollen. Im Allgemeinen haben wir jedoch viel geschafft und ein funktionierendes Programm entwickelt, das sich größtenteils gut bedienen lässt und unseren Vorstellungen entspricht.

Unserer Projekt bietet aber auch Potential, es weiter zu entwickeln. Weiterführende Ideen wären zum einen die Umsetzung des Ganzen im dreidimensionalen Raum. Auch eine Ausweitung auf andere Brückentypen wie Hängebrücken oder Balkenbrücken wäre denkbar. Außerdem könnte man noch versuchen, die Finite Elemente Methode, die unteranderem die Verformung von Festkörpern untersucht, mit einzubringen, um die Ergebnisse genauer und auch realistischer werden zu lassen.

Literaturangaben

Grundlagen Stabwerke

StudyHelp: Statische Bestimmtheit

Popov, Valentin: Statik und elementare Festigkeitslehre (Mechanik I) Vorlesungsnotizen WiSe 2020/21:vorlesungsskript_ws_2020_21.pdf

Pygame

ss2021/project4/brueckensimulation.txt · Zuletzt geändert: 2021/10/14 12:27 von berscjak