zusammenfügen 02.2.
This commit is contained in:
@@ -1,30 +1,55 @@
|
||||
from typing import Any
|
||||
|
||||
import numpy as np
|
||||
from numpy import ndarray, dtype
|
||||
import sympy as sp
|
||||
from sympy import MutableDenseMatrix
|
||||
from sympy.matrices.expressions.matexpr import MatrixElement
|
||||
from typing import Any
|
||||
|
||||
from Datenbank import Datenbankzugriff
|
||||
import sympy as sp
|
||||
from Export import Export
|
||||
from Berechnungen import Berechnungen
|
||||
import numpy as np
|
||||
import importlib
|
||||
from Datenbank import Datenbankzugriff
|
||||
from Export import Export
|
||||
from Koordinatentransformationen import Transformationen
|
||||
from pathlib import Path
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
import sympy as sp
|
||||
|
||||
|
||||
|
||||
|
||||
class FunktionalesModell:
|
||||
"""Aufstellung von Beobachtungsgleichungen und der Jacobi-Matrix.
|
||||
|
||||
Die Klasse stellt Methoden zur Verfügung für:
|
||||
|
||||
- symbolische Aufstellung der Jacobi-Matrix für Tachymeter-, GNSS- und Nivellementbeobachtungen,
|
||||
- numerische Auswertung der symbolischen Jacobi-Matrix über Substitutionen und Lambdify,
|
||||
- Aufbau des Beobachtungsvektors (numerisch) und des Näherungs-Beobachtungsvektors (symbolisch/numerisch),
|
||||
- Aufbau des Unbekanntenvektors (symbolisch/numerisch) inklusive Iterationsfortschreibung,
|
||||
- Berechnung des Verbesserungsvektors dl = l − f(x0) mit Winkel-Normierung für Richtungen,
|
||||
- Erstellung und Aktualisierung eines Substitutions-Dictionaries für alle im Modell verwendeten Symbole.
|
||||
|
||||
Die grundlegende Funktionsweise der Matrixdefinition lautet:
|
||||
|
||||
1) Einmaligen Aufbauen der Symbolischen Matrix einmalig
|
||||
2) In jeder Iteration Substituieren der Symbolischen Matrizen in Numerische np.asarrays
|
||||
"""
|
||||
|
||||
def __init__(self, pfad_datenbank: str, a: float, b: float, pfad_tif_quasigeoidundolation: str = None) -> None:
|
||||
"""Initialisiert das funktionale Modell.
|
||||
|
||||
Legt die Ellipsoidparameter a und b fest, initialisiert Hilfsklassen (Berechnungen, Datenbankzugriff, Transformationen)
|
||||
und erzeugt das Substitutions-Dictionary für das geozentrisch-kartesische System.
|
||||
|
||||
:param pfad_datenbank: Pfad zur SQLite-Datenbank.
|
||||
:type pfad_datenbank: str
|
||||
:param a: Große Halbachse a des Referenzellipsoids in Meter.
|
||||
:type a: float
|
||||
:param b: Kleine Halbachse b des Referenzellipsoids in Meter.
|
||||
:type b: float
|
||||
:param pfad_tif_quasigeoidundolation: Pfad zu Quasigeoidundulationsdaten als GeoTIFF vom BKG für Transformationen (optional).
|
||||
:type pfad_tif_quasigeoidundolation: str | None
|
||||
:return: None
|
||||
:rtype: None
|
||||
"""
|
||||
self.pfad_datenbank = pfad_datenbank
|
||||
self.a = a
|
||||
self.b = b
|
||||
self.berechnungen = Berechnungen(self.a, self.b)
|
||||
self.db_zugriff = Datenbankzugriff(self.pfad_datenbank)
|
||||
self.trafos = Transformationen(pfad_datenbank)
|
||||
self.pfad_tif_quasigeoidundolation = pfad_tif_quasigeoidundolation
|
||||
self.substitutionen_dict = self.dict_substitutionen_uebergeordnetes_system()
|
||||
@@ -35,25 +60,43 @@ class FunktionalesModell:
|
||||
self.func_u0 = None
|
||||
self.liste_beobachtungsvektor_symbolisch = None
|
||||
|
||||
|
||||
def jacobi_matrix_symbolisch(self, datumsfestlegung: str = None, liste_unbekannte_datumsfestlegung: list = None) -> tuple[MutableDenseMatrix | MatrixElement | list[Any] | Any, list[Any], list[Any]] | None:
|
||||
#liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel"]
|
||||
"""Erstellt die symbolische Jacobi-Matrix (A-Matrix) für die Ausgleichung.
|
||||
|
||||
Es werden die in der Datenbank vorhandenen Beobachtungen (Tachymeter: Distanz/Richtung/Zenitwinkel,
|
||||
GNSS: Basislinienkomponenten bx/by/bz, Geometrisches Nivellement: dh) eingelesen, daraus die benötigten Unbekannten
|
||||
(X, Y, Z je Punkt sowie Orientierungen O je Richtungs-Beobachtungsgruppe) aufgebaut und anschließend
|
||||
die symbolischen Gleichungen zur Jacobi-Matrix zusammengesetzt.
|
||||
|
||||
Bei datumsfestlegung == "weiche Lagerung" werden Unbekannte so umsortiert, dass die zur Lagerung
|
||||
zu verwendenden Unbekannten rechts stehen. Zusätzlich werden die Gleichungen der Anschlusspunkte (lA_*) als
|
||||
Zusatzzeilen an A angehängt.
|
||||
|
||||
Die symbolische Jacobi-Matrix wird als CSV in Zwischenergebnisse\\Jacobi_Matrix_Symbolisch.csv exportiert.
|
||||
|
||||
:param datumsfestlegung: Art der Datumsfestlegung (aktuell nur "weiche Lagerung").
|
||||
:type datumsfestlegung: str | None
|
||||
:param liste_unbekannte_datumsfestlegung: Liste der Symbolnamen der zur Lagerung zu verwendenden Unbekannten (z. B. ["X100", "Y100", "Z100"]).
|
||||
:type liste_unbekannte_datumsfestlegung: list | None
|
||||
:return: Tupel aus symbolischer Jacobi-Matrix, Liste der Unbekannten (Symbole) und Liste der Zeilenbeschriftungen (Beobachtungskennungen). Falls keine Beobachtungen vorliegen: None.
|
||||
:rtype: tuple[MutableDenseMatrix | MatrixElement | list[Any] | Any, list[Any], list[Any]] | None
|
||||
"""
|
||||
|
||||
# Über die liste_beobachtungsarten wird festgelegt, welche Beobachtungsarten in der Ausgleichung verwendet werden.
|
||||
liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel", "gnss_basislinien", "geometrisches_nivellement"]
|
||||
#liste_beobachtungsarten = ["tachymeter_distanz", "tachymeter_richtung", "tachymeter_zenitwinkel", "gnss_basislinien"]
|
||||
db_zugriff = Datenbankzugriff(self.pfad_datenbank)
|
||||
|
||||
# Initialisieren der zu befüllenden Listen
|
||||
liste_beobachtungen_rohdaten_gnssbasislinien = []
|
||||
liste_beobachtungen_rohdaten_tachymeter = []
|
||||
liste_beobachtungen_rohdaten_nivellement = []
|
||||
liste_punktnummern =[]
|
||||
|
||||
liste_orientierungsunbekannte = []
|
||||
|
||||
# Für jede Beobachtungsart wird aus der Datenbank abgefragt, welche Beobachtungen vorliegen. Von diesen werden der Stand- und Zielpunkt gespeichert, um diese im weiteren Verlauf dieser Methode zu verarbeiten.
|
||||
for beobachtungsart in liste_beobachtungsarten:
|
||||
#Tachymeter Block
|
||||
if beobachtungsart.startswith("tachymeter"):
|
||||
liste_id_standpunkt_zielpunkt = db_zugriff.get_beobachtungen_id_beobachtungsgruppe_standpunkt_zielpunkt(beobachtungsart)
|
||||
liste_id_standpunkt_zielpunkt = self.db_zugriff.get_puntknummern_beobachtungen_tachymeter(beobachtungsart)
|
||||
|
||||
for beobachtungenID, beobachtungsgruppeID, standpunkt, zielpunkt in liste_id_standpunkt_zielpunkt:
|
||||
liste_beobachtungen_rohdaten_tachymeter.append(
|
||||
@@ -68,23 +111,10 @@ class FunktionalesModell:
|
||||
if beobachtungsart == "tachymeter_richtung":
|
||||
if beobachtungsgruppeID not in liste_orientierungsunbekannte:
|
||||
liste_orientierungsunbekannte.append(beobachtungsgruppeID)
|
||||
#GNSS Block
|
||||
#if beobachtungsart == "gnss_basislinien":
|
||||
# liste_id_standpunkt_zielpunkt = db_zugriff.get_gnss_beobachtungen_punktnummern()
|
||||
|
||||
# for beobachtungenID, standpunkt, zielpunkt in liste_id_standpunkt_zielpunkt:
|
||||
# standpunkt = str(standpunkt).strip()
|
||||
# zielpunkt = str(zielpunkt).strip()
|
||||
# liste_beobachtungen_rohdaten_gnssbasislinien.append((beobachtungsart, beobachtungenID, standpunkt, zielpunkt))
|
||||
|
||||
# if standpunkt not in liste_punktnummern:
|
||||
# liste_punktnummern.append(standpunkt)
|
||||
# if zielpunkt not in liste_punktnummern:
|
||||
# liste_punktnummern.append(zielpunkt)
|
||||
|
||||
#GNSS Block
|
||||
if beobachtungsart == "gnss_basislinien":
|
||||
liste_id_standpunkt_zielpunkt = db_zugriff.get_gnss_beobachtungen_punktnummern("gnss_bx")
|
||||
liste_id_standpunkt_zielpunkt = self.db_zugriff.get_gnss_beobachtungen_punktnummern("gnss_bx")
|
||||
for beobachtungenID, standpunkt, zielpunkt in liste_id_standpunkt_zielpunkt:
|
||||
standpunkt = str(standpunkt).strip()
|
||||
zielpunkt = str(zielpunkt).strip()
|
||||
@@ -94,7 +124,7 @@ class FunktionalesModell:
|
||||
if zielpunkt not in liste_punktnummern:
|
||||
liste_punktnummern.append(zielpunkt)
|
||||
|
||||
liste_id_standpunkt_zielpunkt = db_zugriff.get_gnss_beobachtungen_punktnummern("gnss_by")
|
||||
liste_id_standpunkt_zielpunkt = self.db_zugriff.get_gnss_beobachtungen_punktnummern("gnss_by")
|
||||
for beobachtungenID, standpunkt, zielpunkt in liste_id_standpunkt_zielpunkt:
|
||||
standpunkt = str(standpunkt).strip()
|
||||
zielpunkt = str(zielpunkt).strip()
|
||||
@@ -104,7 +134,7 @@ class FunktionalesModell:
|
||||
if zielpunkt not in liste_punktnummern:
|
||||
liste_punktnummern.append(zielpunkt)
|
||||
|
||||
liste_id_standpunkt_zielpunkt = db_zugriff.get_gnss_beobachtungen_punktnummern("gnss_bz")
|
||||
liste_id_standpunkt_zielpunkt = self.db_zugriff.get_gnss_beobachtungen_punktnummern("gnss_bz")
|
||||
for beobachtungenID, standpunkt, zielpunkt in liste_id_standpunkt_zielpunkt:
|
||||
standpunkt = str(standpunkt).strip()
|
||||
zielpunkt = str(zielpunkt).strip()
|
||||
@@ -116,7 +146,7 @@ class FunktionalesModell:
|
||||
|
||||
|
||||
if beobachtungsart == "geometrisches_nivellement":
|
||||
liste_id_standpunkt_zielpunkt = db_zugriff.get_nivellement_beobachtungen_punktnummern()
|
||||
liste_id_standpunkt_zielpunkt = self.db_zugriff.get_nivellement_beobachtungen_punktnummern()
|
||||
|
||||
for beobachtungenID, standpunkt, zielpunkt in liste_id_standpunkt_zielpunkt:
|
||||
standpunkt = str(standpunkt).strip()
|
||||
@@ -129,13 +159,7 @@ class FunktionalesModell:
|
||||
if zielpunkt not in liste_punktnummern:
|
||||
liste_punktnummern.append(zielpunkt)
|
||||
|
||||
|
||||
|
||||
#if liste_beobachtungen_rohdaten_tachymeter == []:
|
||||
# return None
|
||||
|
||||
|
||||
#dict_punkt_symbole = {}
|
||||
# Erstellen der Symbole für die Unbekannten (X, Y, Z und Orientierung)
|
||||
liste_unbekannte = []
|
||||
|
||||
for punkt in liste_punktnummern:
|
||||
@@ -151,6 +175,7 @@ class FunktionalesModell:
|
||||
dict_orientierung_symbole[orientierungsunbekannte] = O
|
||||
liste_unbekannte.append(O)
|
||||
|
||||
# Erstellen der Symbolischen Gleichungen für die Jacobimatrix
|
||||
liste_beobachtungsgleichungen_distanz =[]
|
||||
liste_zeilenbeschriftungen_distanz = []
|
||||
|
||||
@@ -161,39 +186,30 @@ class FunktionalesModell:
|
||||
liste_zeilenbeschriftungen_zenitwinkel = []
|
||||
|
||||
liste_beobachtungsgleichungen_gnssbasislinien = []
|
||||
liste_A_gnssbasislinien_zeilen = []
|
||||
liste_zeilenbeschriftungen_gnssbasislinien = []
|
||||
|
||||
liste_beobachtungsgleichungen_nivellement = []
|
||||
liste_A_nivellement_zeilen = []
|
||||
liste_zeilenbeschriftungen_nivellement = []
|
||||
|
||||
if liste_beobachtungen_rohdaten_tachymeter != []:
|
||||
for beobachtungsart, beobachtungenID, beobachtungsgruppeID, standpunkt, zielpunkt in liste_beobachtungen_rohdaten_tachymeter:
|
||||
# Symbole erstellen
|
||||
X_sp, Y_sp, Z_sp = self.dict_punkt_symbole[standpunkt]
|
||||
X_zp, Y_zp, Z_zp = self.dict_punkt_symbole[zielpunkt]
|
||||
B_sp, L_sp = sp.symbols(f"B{standpunkt} L{standpunkt}")
|
||||
|
||||
alpha = sp.symbols(f"{beobachtungenID}_R_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
zw = sp.symbols(f"{beobachtungenID}_ZW_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
s = sp.symbols(f"{beobachtungenID}_SD_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
|
||||
azimut_berechnet = sp.symbols(f"azimut_berechnet_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
zw_berechnet = sp.symbols(f"zw_berechnet_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
s_berechnet = sp.symbols(f"strecke_berechnet_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
|
||||
|
||||
# Symbolische Gleichungen aufstellen
|
||||
if beobachtungsart == "tachymeter_distanz":
|
||||
beobachtungsgleichung = sp.sqrt((X_zp - X_sp) ** 2 + (Y_zp - Y_sp) ** 2 + (Z_zp - Z_sp) ** 2)
|
||||
liste_beobachtungsgleichungen_distanz.append(beobachtungsgleichung)
|
||||
liste_zeilenbeschriftungen_distanz.append(
|
||||
f"{beobachtungenID}_SD_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
|
||||
|
||||
|
||||
elif beobachtungsart == "tachymeter_richtung":
|
||||
|
||||
# for beobachtungenID, beobachtungsgruppeID, standpunkt, zielpunkt in liste_id_standpunkt_zielpunkt:
|
||||
d_r_dX_zp = (
|
||||
(sp.sin(B_sp) * sp.cos(L_sp) * sp.sin(azimut_berechnet) - sp.sin(L_sp) * sp.cos(azimut_berechnet)) / (
|
||||
s_berechnet * sp.sin(zw_berechnet)))
|
||||
@@ -207,6 +223,8 @@ class FunktionalesModell:
|
||||
d_r_dO_sp = -1
|
||||
|
||||
zeile_A_Matrix = []
|
||||
|
||||
# Symbolische Gleichungen zur Jacobimatrix hinzufügen
|
||||
for punkt in liste_punktnummern:
|
||||
if punkt == standpunkt:
|
||||
zeile_A_Matrix.extend([d_r_dX_sp, d_r_dY_sp, d_r_dZ_sp])
|
||||
@@ -228,7 +246,7 @@ class FunktionalesModell:
|
||||
|
||||
|
||||
elif beobachtungsart == "tachymeter_zenitwinkel":
|
||||
|
||||
# Symbolische Gleichungen aufstellen
|
||||
d_r_dX_zp = ((X_zp - X_sp) * sp.cos(zw_berechnet) - s_berechnet * sp.cos(B_sp) * sp.cos(L_sp)) / (s_berechnet ** 2 * sp.sin(zw_berechnet))
|
||||
d_r_dX_sp = - d_r_dX_zp
|
||||
d_r_dY_zp = ((Y_zp - Y_sp) * sp.cos(zw_berechnet) - s_berechnet * sp.cos(B_sp) * sp.sin(L_sp)) / (s_berechnet ** 2 * sp.sin(zw_berechnet))
|
||||
@@ -237,6 +255,8 @@ class FunktionalesModell:
|
||||
d_r_dZ_sp = - d_r_dZ_zp
|
||||
|
||||
zeile_A_Matrix = []
|
||||
|
||||
# Symbolische Gleichungen zur Jacobimatrix hinzufügen
|
||||
for punkt in liste_punktnummern:
|
||||
if punkt == standpunkt:
|
||||
zeile_A_Matrix.extend([d_r_dX_sp, d_r_dY_sp, d_r_dZ_sp])
|
||||
@@ -253,27 +273,10 @@ class FunktionalesModell:
|
||||
f"{beobachtungenID}_ZW_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}"
|
||||
)
|
||||
|
||||
#if liste_beobachtungen_rohdaten_gnssbasislinien != []:
|
||||
# for beobachtungsart, beobachtungenID, standpunkt, zielpunkt in liste_beobachtungen_rohdaten_gnssbasislinien:
|
||||
# X_sp, Y_sp, Z_sp = self.dict_punkt_symbole[standpunkt]
|
||||
# X_zp, Y_zp, Z_zp = self.dict_punkt_symbole[zielpunkt]
|
||||
|
||||
# if beobachtungsart == "gnss_basislinien":
|
||||
# beobachtungsgleichung_bx = X_zp - X_sp
|
||||
# beobachtungsgleichung_by = Y_zp - Y_sp
|
||||
# beobachtungsgleichung_bz = Z_zp - Z_sp
|
||||
# liste_beobachtungsgleichungen_gnssbasislinien.append(beobachtungsgleichung_bx)
|
||||
# liste_beobachtungsgleichungen_gnssbasislinien.append(beobachtungsgleichung_by)
|
||||
# liste_beobachtungsgleichungen_gnssbasislinien.append(beobachtungsgleichung_bz)
|
||||
# liste_zeilenbeschriftungen_gnssbasislinien.append(
|
||||
# f"{beobachtungenID}_gnssbx_{standpunkt}_{zielpunkt}")
|
||||
# liste_zeilenbeschriftungen_gnssbasislinien.append(
|
||||
# f"{beobachtungenID}_gnssby_{standpunkt}_{zielpunkt}")
|
||||
# liste_zeilenbeschriftungen_gnssbasislinien.append(
|
||||
# f"{beobachtungenID}_gnssbz_{standpunkt}_{zielpunkt}")
|
||||
|
||||
# GNSS-Basislinien
|
||||
if liste_beobachtungen_rohdaten_gnssbasislinien != []:
|
||||
for beobachtungsart, beobachtungenID, standpunkt, zielpunkt in liste_beobachtungen_rohdaten_gnssbasislinien:
|
||||
# Symbolische Gleichungen aufstellen
|
||||
X_sp, Y_sp, Z_sp = self.dict_punkt_symbole[standpunkt]
|
||||
X_zp, Y_zp, Z_zp = self.dict_punkt_symbole[zielpunkt]
|
||||
|
||||
@@ -296,10 +299,10 @@ class FunktionalesModell:
|
||||
f"{beobachtungenID}_gnssbz_{standpunkt}_{zielpunkt}")
|
||||
|
||||
|
||||
# Geometrisches Nivellement
|
||||
if liste_beobachtungen_rohdaten_nivellement != []:
|
||||
for beobachtungsart, beobachtungenID, standpunkt, zielpunkt in liste_beobachtungen_rohdaten_nivellement:
|
||||
X_sp, Y_sp, Z_sp = self.dict_punkt_symbole[standpunkt]
|
||||
X_zp, Y_zp, Z_zp = self.dict_punkt_symbole[zielpunkt]
|
||||
# Symbolische Gleichungen aufstellen
|
||||
B_sp, L_sp = sp.symbols(f"B{standpunkt} L{standpunkt}")
|
||||
B_zp, L_zp = sp.symbols(f"B{zielpunkt} L{zielpunkt}")
|
||||
|
||||
@@ -312,6 +315,7 @@ class FunktionalesModell:
|
||||
d_r_dZ_zp = sp.sin(B_zp)
|
||||
d_r_dZ_sp = -sp.sin(B_sp)
|
||||
|
||||
# Symbolische Gleichungen zur Jacobimatrix hinzufügen
|
||||
zeile_A_Matrix = []
|
||||
for punkt in liste_punktnummern:
|
||||
if punkt == standpunkt:
|
||||
@@ -329,6 +333,7 @@ class FunktionalesModell:
|
||||
f"{beobachtungenID}_niv_{standpunkt}_{zielpunkt}"
|
||||
)
|
||||
|
||||
# Jacobimatrix aus den einzelnen Listen zusammensetzen, Sy,bolischen Unbekanntenvektor erstellen
|
||||
if liste_beobachtungsgleichungen_distanz:
|
||||
f_matrix_dist = sp.Matrix(liste_beobachtungsgleichungen_distanz)
|
||||
unbekanntenvektor = sp.Matrix(liste_unbekannte)
|
||||
@@ -354,15 +359,13 @@ class FunktionalesModell:
|
||||
A_gnssbasislinien = None
|
||||
|
||||
if liste_A_nivellement_zeilen:
|
||||
#f_matrix_nivellement = sp.Matrix(liste_beobachtungsgleichungen_nivellement)
|
||||
#unbekanntenvektor = sp.Matrix(liste_unbekannte)
|
||||
#A_nivellement = f_matrix_nivellement.jacobian(unbekanntenvektor)
|
||||
A_nivellement = sp.Matrix(liste_A_nivellement_zeilen)
|
||||
else:
|
||||
A_nivellement = None
|
||||
|
||||
|
||||
A_gesamt = None
|
||||
# liste_zeilenbeschriftungen_gesamt enthält die Symbolischen Beobachtungen
|
||||
liste_zeilenbeschriftungen_gesamt = []
|
||||
|
||||
if A_dist is not None:
|
||||
@@ -400,9 +403,9 @@ class FunktionalesModell:
|
||||
if A_gesamt is None:
|
||||
return None
|
||||
|
||||
# Wenn eine weiche Lagerung erfolgt, werden die Unbekannten umsortiert, sodass die für die Lagerung zu verwendenden Unbekannten rechts in der Matrix aufgeführt werden.
|
||||
# Zudem werden für die Anschlusspunkte weiter Gleichungen als "Beobachtungen" unten an die Jacobimatrix angefügt.
|
||||
if datumsfestlegung == "weiche Lagerung":
|
||||
vertauschung = list(range(len(liste_unbekannte)))
|
||||
|
||||
if liste_unbekannte_datumsfestlegung is not None and liste_unbekannte_datumsfestlegung != []:
|
||||
liste_unbekannte_alt = list(liste_unbekannte)
|
||||
liste_unbekannte_datumsfestlegung = [str(u).strip() for u in liste_unbekannte_datumsfestlegung]
|
||||
@@ -420,7 +423,7 @@ class FunktionalesModell:
|
||||
A_gesamt = A_gesamt[:, vertauschung]
|
||||
liste_unbekannte = [liste_unbekannte_alt[i] for i in vertauschung]
|
||||
|
||||
# Zusatzgeleichungen der weichen Lagerung
|
||||
# Zusatzgeleichungen der weichen Lagerung für die Anschlusspunkte
|
||||
anzhl_einheitsmatrix = len(liste_unbekannte_datumsfestlegung)
|
||||
if anzhl_einheitsmatrix > 0:
|
||||
nullenmatrix = sp.zeros(anzhl_einheitsmatrix, A_gesamt.shape[1] - anzhl_einheitsmatrix)
|
||||
@@ -430,24 +433,49 @@ class FunktionalesModell:
|
||||
for unbekannte_datumsfestlegung in liste_unbekannte_datumsfestlegung:
|
||||
liste_zeilenbeschriftungen_gesamt.append(f"lA_{unbekannte_datumsfestlegung}")
|
||||
|
||||
|
||||
# Symbolische Liste der Unbekannten speichern
|
||||
self.liste_unbekanntenvektor_symbolisch = liste_unbekannte
|
||||
|
||||
# Symbolische Jacobimatrix speichern
|
||||
Export.matrix_to_csv(r"Zwischenergebnisse\Jacobi_Matrix_Symbolisch.csv", liste_unbekannte,
|
||||
liste_zeilenbeschriftungen_gesamt, A_gesamt, "Beobachtung")
|
||||
return A_gesamt, liste_unbekannte, liste_zeilenbeschriftungen_gesamt
|
||||
|
||||
|
||||
def jacobi_matrix_zahlen_iteration_0(self, A_symbolisch: sp.Matrix, koordinatenart: str,
|
||||
liste_unbekannte: list = None,
|
||||
liste_zeilenbeschriftungen_gesamt: list = None,
|
||||
iterationsnummer: int = 0) -> ndarray[tuple[Any, ...], dtype[Any]] | None:
|
||||
def jacobi_matrix_numerisch(self, A_symbolisch: sp.Matrix, koordinatenart: str,
|
||||
liste_unbekannte: list = None,
|
||||
liste_zeilenbeschriftungen_gesamt: list = None,
|
||||
iterationsnummer: int = 0) -> ndarray[tuple[Any, ...], dtype[Any]] | None:
|
||||
"""Erstellt eine numerische Matrix aus einer symbolischen Jacobi-Matrix.
|
||||
|
||||
Es wird sympy.lambdify verwendet, um die symbolische Matrix
|
||||
mit den aktuellen Substitutionen effizient als Numpy-Array auszuwerten. Die Lambdify-Funktion wird
|
||||
gecached (self.func_A0), um Rechenzeit bei Ausführen mehrerer Iterationen zu sparen.
|
||||
|
||||
Die numerische Jacobi-Matrix wird als CSV in den Ordner Zwischenergebnisse exportiert.
|
||||
|
||||
:param A_symbolisch: Symbolische Jacobi-Matrix.
|
||||
:type A_symbolisch: sp.Matrix
|
||||
:param koordinatenart: Bezeichnung der Koordinatenart (aktuell implementiert: "naeherung_us").
|
||||
:type koordinatenart: str
|
||||
:param liste_unbekannte: Liste der Unbekannten (Symbole) in der Spaltenreihenfolge.
|
||||
:type liste_unbekannte: list | None
|
||||
:param liste_zeilenbeschriftungen_gesamt: Liste der Zeilenbeschriftungen (Beobachtungskennungen).
|
||||
:type liste_zeilenbeschriftungen_gesamt: list | None
|
||||
:param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse.
|
||||
:type iterationsnummer: int
|
||||
:return: Numerische Jacobi-Matrix als Numpy-Array.
|
||||
:rtype: ndarray[tuple[Any, ...], dtype[Any]] | None
|
||||
:raises ValueError: Falls Symbole in A_symbolisch enthalten sind, für die keine Substitutionen vorhanden sind.
|
||||
"""
|
||||
|
||||
# Symbolischen Beobachtungsvektor als Instanzvariable speichern
|
||||
self.liste_beobachtungsvektor_symbolisch = [str(x) for x in liste_zeilenbeschriftungen_gesamt]
|
||||
|
||||
# Wenn es sich um geozentrisch-kartesischen Koordinaten handelt, wird die Sympy-Methode Lambdify verwendet, um die Symbole aus der vorherigen Methode jacobi_matrix_symbolisch in Numerische Zahlen umzuwandeln.
|
||||
# Zur Ersparnis von Rechenzeit werden die numerischen Zahlen als Numpy-Werte behandelt.
|
||||
if koordinatenart == "naeherung_us":
|
||||
#A_numerisch = A_symbolisch.xreplace(self.substitutionen_dict)
|
||||
if self.func_A0 is None:
|
||||
#self.liste_symbole_lambdify = sorted(self.substitutionen_dict.keys(), key=lambda s: str(s))
|
||||
self.func_A0 = sp.lambdify(
|
||||
self.liste_symbole_lambdify,
|
||||
A_symbolisch,
|
||||
@@ -455,45 +483,43 @@ class FunktionalesModell:
|
||||
cse=True
|
||||
)
|
||||
|
||||
# Überprüfung, ob alle in der Symbolischen Matrix enthaltenen Symbole substituiert werden können. Ist ein Symbol nicht durch einen numerischen Wert ersetzbar, wird eine Fehlermeldung ausgegeben.
|
||||
fehlend = [s for s in self.liste_symbole_lambdify if s not in self.substitutionen_dict]
|
||||
if fehlend:
|
||||
Export.matrix_to_csv(
|
||||
r"Zwischenergebnisse\fehlende_substitutionen_A.csv",
|
||||
[""],
|
||||
[str(s) for s in fehlend],
|
||||
sp.Matrix([[str(s)] for s in fehlend]),
|
||||
"fehlend"
|
||||
)
|
||||
raise ValueError(f"Fehlende Substitutionen in A: {[str(s) for s in fehlend[:30]]}")
|
||||
|
||||
|
||||
liste_werte = [self.substitutionen_dict[s] for s in self.liste_symbole_lambdify]
|
||||
#A_numerisch = sp.Matrix(self.func_A0(*liste_werte))
|
||||
A_numerisch = np.asarray(self.func_A0(*liste_werte), dtype=float)
|
||||
|
||||
Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}Jacobi_Matrix_Numerisch_Iteration0.csv", liste_unbekannte,
|
||||
Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}Jacobi_Matrix_Numerisch.csv", liste_unbekannte,
|
||||
liste_zeilenbeschriftungen_gesamt, A_numerisch, "Beobachtung")
|
||||
|
||||
condA = float(np.linalg.cond(A_numerisch))
|
||||
rankA = int(np.linalg.matrix_rank(A_numerisch))
|
||||
Export.matrix_to_csv(
|
||||
fr"Zwischenergebnisse\{iterationsnummer}_Jacobi_Matrix_Stats.csv",
|
||||
[""],
|
||||
["condA", "rankA"],
|
||||
np.array([[condA], [rankA]], dtype=float),
|
||||
"Wert"
|
||||
)
|
||||
|
||||
return A_numerisch
|
||||
else:
|
||||
print("Koordinaten noch nicht implementiert!")
|
||||
print(f"Die Koordinatenart {koordinatenart} ist noch nicht im Programm implementiert!")
|
||||
|
||||
def beobachtungsvektor_numerisch(self, liste_beobachtungsvektor_symbolisch: list) -> MutableDenseMatrix:
|
||||
"""Erstellt den numerischen Beobachtungsvektor aus symbolischen Beobachtungskennungen.
|
||||
|
||||
Die Einträge des symbolischen Beobachtungsvektors werden über self.substitutionen_dict substituiert.
|
||||
Anschlusspunkte der weichen Lagerung (lA_*) werden gesondert behandelt, indem das Präfix entfernt wird.
|
||||
|
||||
Der numerische Beobachtungsvektor wird als CSV-Datei in Zwischenergebnisse\\Beobachtungsvektor_Numerisch.csv exportiert.
|
||||
|
||||
:param liste_beobachtungsvektor_symbolisch: Liste symbolischer Beobachtungsbezeichnungen (Strings).
|
||||
:type liste_beobachtungsvektor_symbolisch: list
|
||||
:return: Numerischer Beobachtungsvektor als SymPy-Matrix (Spaltenvektor).
|
||||
:rtype: MutableDenseMatrix
|
||||
"""
|
||||
|
||||
liste_beobachtungsvektor_numerisch = []
|
||||
for beobachtung_symbolisch in liste_beobachtungsvektor_symbolisch:
|
||||
beobachtung_symbolisch = str(beobachtung_symbolisch).strip()
|
||||
# Die Anschlusspunkte für die weiche Lagerung (lA) werden gesondert bearbeitet, weil die Symbole anders aufgebaut sind.
|
||||
if beobachtung_symbolisch.startswith("lA_"):
|
||||
beobachtung_symbolisch = str(beobachtung_symbolisch.split("_", 1)[1]).strip()
|
||||
# Substituieren des symbolischen Beobachtungsvektors
|
||||
liste_beobachtungsvektor_numerisch.append(self.substitutionen_dict[sp.Symbol(beobachtung_symbolisch)])
|
||||
|
||||
beobachtungsvektor_numerisch = sp.Matrix(liste_beobachtungsvektor_numerisch)
|
||||
@@ -501,10 +527,24 @@ class FunktionalesModell:
|
||||
return beobachtungsvektor_numerisch
|
||||
|
||||
def beobachtungsvektor_naeherung_symbolisch(self, liste_beobachtungsvektor_symbolisch: list) -> sp.Matrix:
|
||||
"""Erstellt den symbolischen Näherungs-Beobachtungsvektor f(x0).
|
||||
|
||||
Aus den Beobachtungskennungen werden Stand-/Zielpunkte und Beobachtungsarten abgeleitet und die
|
||||
entsprechenden symbolischen Beobachtungsgleichungen aufgebaut (z. B. geometrische Distanz, GNSS-Differenzen,
|
||||
Richtungs-/Zenitwinkel-Symbole, Geometrisches Nivellement über Normalhöhen).
|
||||
|
||||
Der symbolische Näherungs-Beobachtungsvektor wird als CSV <-Datei in Zwischenergebnisse\\Beobachtungsvektor_Näherung_Symbolisch.csv exportiert.
|
||||
|
||||
:param liste_beobachtungsvektor_symbolisch: Liste symbolischer Beobachtungskennungen (Strings).
|
||||
:type liste_beobachtungsvektor_symbolisch: list
|
||||
:return: Symbolischer Näherungs-Beobachtungsvektor als SymPy-Matrix.
|
||||
:rtype: sp.Matrix
|
||||
"""
|
||||
liste_beobachtungsgleichungen = []
|
||||
self.dict_punkt_symbole = {}
|
||||
liste_punktnummern = []
|
||||
|
||||
# Speichern der Punktnummern der Stand- und Zeilpunkte der Beobachtungen, um daraus später die Symbole für die Unbekannten zu erstellen.
|
||||
for beobachtung_symbolisch in liste_beobachtungsvektor_symbolisch:
|
||||
aufgeteilt = str(beobachtung_symbolisch).strip().split("_")
|
||||
if aufgeteilt[0] == "lA":
|
||||
@@ -528,6 +568,7 @@ class FunktionalesModell:
|
||||
if zielpunkt not in liste_punktnummern:
|
||||
liste_punktnummern.append(zielpunkt)
|
||||
|
||||
# Erstellen der Symbole für die Unbekannten
|
||||
for punkt in liste_punktnummern:
|
||||
X, Y, Z = sp.symbols(f"X{punkt} Y{punkt} Z{punkt}")
|
||||
self.dict_punkt_symbole[str(punkt)] = (X, Y, Z)
|
||||
@@ -541,60 +582,30 @@ class FunktionalesModell:
|
||||
continue
|
||||
|
||||
if aufgeteilt[1] == "SD" or aufgeteilt[1] == "R" or aufgeteilt[1] == "ZW":
|
||||
|
||||
#beobachtungen_ID = aufgeteilt[0]
|
||||
beobachtungsart = aufgeteilt[1] # "SD", "R", "ZW"
|
||||
beobachtungsgruppeID = aufgeteilt[2]
|
||||
standpunkt = str(aufgeteilt[3]).strip()
|
||||
zielpunkt = str(aufgeteilt[4]).strip()
|
||||
|
||||
# Hinzufügen der Symbole zum dict_punkt_symbole als Vorbereitung auf die spätere Substitution der Symbole durch numerische Werte
|
||||
X_sp, Y_sp, Z_sp = self.dict_punkt_symbole[standpunkt]
|
||||
X_zp, Y_zp, Z_zp = self.dict_punkt_symbole[zielpunkt]
|
||||
|
||||
# Aufstellen der Symbolischen Gleichungen
|
||||
dX = X_zp - X_sp
|
||||
dY = Y_zp - Y_sp
|
||||
dZ = Z_zp - Z_sp
|
||||
s = sp.sqrt(dX ** 2 + dY ** 2 + dZ ** 2) # Schrägstrecke
|
||||
|
||||
B_sp = sp.Symbol(f"B{standpunkt}")
|
||||
L_sp = sp.Symbol(f"L{standpunkt}")
|
||||
|
||||
if beobachtungsart == "SD":
|
||||
|
||||
s_geom = sp.sqrt(dX ** 2 + dY ** 2 + dZ ** 2)
|
||||
liste_beobachtungsgleichungen.append(s_geom)
|
||||
|
||||
elif beobachtungsart == "R":
|
||||
|
||||
#O_sp = sp.Symbol(f"O_{beobachtungsgruppeID}")
|
||||
r_sp_zp = sp.Symbol(f"richtung_berechnet_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
|
||||
# Lokales System: x_loc = Nord, y_loc = Ost
|
||||
#x_loc = (-sp.sin(B_sp) * sp.cos(L_sp)) * dX + (-sp.sin(B_sp) * sp.sin(L_sp)) * dY + (sp.cos(B_sp)) * dZ
|
||||
#y_loc = (-sp.sin(L_sp)) * dX + (sp.cos(L_sp)) * dY
|
||||
|
||||
#a12 = sp.atan2(y_loc, x_loc)
|
||||
|
||||
# Richtung nach Otepka: r = a12 - O
|
||||
liste_beobachtungsgleichungen.append(r_sp_zp)
|
||||
|
||||
|
||||
elif beobachtungsart == "ZW":
|
||||
|
||||
#dX = X_zp - X_sp
|
||||
|
||||
#dY = Y_zp - Y_sp
|
||||
|
||||
#dZ = Z_zp - Z_sp
|
||||
|
||||
#s_geom = sp.sqrt(dX ** 2 + dY ** 2 + dZ ** 2)
|
||||
|
||||
#z_loc = (sp.cos(B_sp) * sp.cos(L_sp)) * dX + (sp.cos(B_sp) * sp.sin(L_sp)) * dY + (sp.sin(B_sp)) * dZ
|
||||
|
||||
#zw = sp.acos(z_loc / s_geom)
|
||||
|
||||
zw_sp_zp = sp.Symbol(f"zw_berechnet_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
|
||||
liste_beobachtungsgleichungen.append(zw_sp_zp)
|
||||
|
||||
if aufgeteilt[1] == "gnssbx" or aufgeteilt[1] == "gnssby" or aufgeteilt[1] == "gnssbz":
|
||||
@@ -617,7 +628,6 @@ class FunktionalesModell:
|
||||
liste_beobachtungsgleichungen.append(dZ)
|
||||
|
||||
if aufgeteilt[1] == "niv":
|
||||
beobachtungsart = aufgeteilt[1]
|
||||
standpunkt = str(aufgeteilt[2]).strip()
|
||||
zielpunkt = str(aufgeteilt[3]).strip()
|
||||
|
||||
@@ -628,18 +638,36 @@ class FunktionalesModell:
|
||||
|
||||
liste_beobachtungsgleichungen.append(niv_sp_zp)
|
||||
|
||||
# Finalisieren des Symbolischen Beobachtungsvektors und exportieren als csv-Datei.
|
||||
beobachtungsvektor_naeherung_symbolisch = sp.Matrix(liste_beobachtungsgleichungen)
|
||||
Export.matrix_to_csv(r"Zwischenergebnisse\Beobachtungsvektor_Näherung_Symbolisch.csv", [""],
|
||||
liste_beobachtungsvektor_symbolisch, beobachtungsvektor_naeherung_symbolisch, "Beobachtungsvektor")
|
||||
|
||||
return beobachtungsvektor_naeherung_symbolisch
|
||||
|
||||
def beobachtungsvektor_naeherung_numerisch_iteration0(self, liste_beobachtungsvektor_symbolisch: list,
|
||||
beobachtungsvektor_naeherung_symbolisch: sp.Matrix,
|
||||
iterationsnummer: int = 0) -> ndarray[tuple[int, int], Any]:
|
||||
#beobachtungsvektor_naeherung_numerisch_iteration0 = beobachtungsvektor_naeherung_symbolisch.xreplace(self.substitutionen_dict)
|
||||
def beobachtungsvektor_naeherung_numerisch(self, liste_beobachtungsvektor_symbolisch: list,
|
||||
beobachtungsvektor_naeherung_symbolisch: sp.Matrix,
|
||||
iterationsnummer: int = 0) -> ndarray[tuple[int, int], Any]:
|
||||
"""Erstellt einen numerischen Vektor aus dem smbolischen Näherungs-Beobachtungsvektor.
|
||||
|
||||
Es wird sympy.lambdify verwendet, um den in beobachtungsvektor_naeherung_symbolisch erzeugten
|
||||
symbolischen Vektor effizient als Numpy-Array auszuwerten. Die Lambdify-Funktion wird gecached
|
||||
(self.func_beob0), um Rechenzeit in Iterationen zu sparen.
|
||||
|
||||
Der numerische Näherungs-Beobachtungsvektor wird als CSV-Datei im Ordner Zwischenergebnisse exportiert.
|
||||
|
||||
:param liste_beobachtungsvektor_symbolisch: Liste symbolischer Beobachtungskennungen (Strings).
|
||||
:type liste_beobachtungsvektor_symbolisch: list
|
||||
:param beobachtungsvektor_naeherung_symbolisch: Symbolischer Näherungs-Beobachtungsvektor f(x0).
|
||||
:type beobachtungsvektor_naeherung_symbolisch: sp.Matrix
|
||||
:param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse.
|
||||
:type iterationsnummer: int
|
||||
:return: Numerischer Näherungs-Beobachtungsvektor als Numpy-Array (Spaltenvektor).
|
||||
:rtype: ndarray[tuple[int, int], Any]
|
||||
"""
|
||||
# Es wird die Sympy-Methode Lambdify verwendet, um die Symbole aus der vorherigen Methode beobachtungsvektor_naeherung_symbolisch in Numerische Zahlen umzuwandeln.
|
||||
# Zur Ersparnis von Rechenzeit werden die numerischen Zahlen als Numpy-Werte behandelt.
|
||||
if self.func_beob0 is None:
|
||||
#self.liste_symbole_lambdify = sorted(self.substitutionen_dict.keys(), key=lambda s: str(s))
|
||||
self.func_beob0 = sp.lambdify(
|
||||
self.liste_symbole_lambdify,
|
||||
beobachtungsvektor_naeherung_symbolisch,
|
||||
@@ -648,17 +676,26 @@ class FunktionalesModell:
|
||||
)
|
||||
|
||||
liste_werte = [self.substitutionen_dict[s] for s in self.liste_symbole_lambdify]
|
||||
#beobachtungsvektor_naeherung_numerisch_iteration0 = sp.Matrix(self.func_beob0(*liste_werte))
|
||||
beobachtungsvektor_naeherung_numerisch_iteration0 = np.asarray(self.func_beob0(*liste_werte),
|
||||
beobachtungsvektor_naeherung_numerisch = np.asarray(self.func_beob0(*liste_werte),
|
||||
dtype=float).reshape(-1, 1)
|
||||
|
||||
Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}_Beobachtungsvektor_Näherung_Numerisch_Iteration0.csv", [""],
|
||||
liste_beobachtungsvektor_symbolisch, beobachtungsvektor_naeherung_numerisch_iteration0,
|
||||
liste_beobachtungsvektor_symbolisch, beobachtungsvektor_naeherung_numerisch,
|
||||
"Beobachtungsvektor")
|
||||
|
||||
return beobachtungsvektor_naeherung_numerisch_iteration0
|
||||
return beobachtungsvektor_naeherung_numerisch
|
||||
|
||||
def unbekanntenvektor_symbolisch(self, liste_unbekannte: list) -> sp.Matrix:
|
||||
"""Erstellt den symbolischen Unbekanntenvektor.
|
||||
|
||||
Der Unbekanntenvektor wird als SymPy-Matrix aufgebaut und als CSV-Datei in
|
||||
Zwischenergebnisse\\Unbekanntenvektor_Symbolisch.csv exportiert.
|
||||
|
||||
:param liste_unbekannte: Liste der Unbekannten (Symbole).
|
||||
:type liste_unbekannte: list
|
||||
:return: Symbolischer Unbekanntenvektor als SymPy-Matrix.
|
||||
:rtype: sp.Matrix
|
||||
"""
|
||||
unbekanntenvektor_symbolisch = sp.Matrix(liste_unbekannte)
|
||||
Export.matrix_to_csv(r"Zwischenergebnisse\Unbekanntenvektor_Symbolisch.csv", [""], liste_unbekannte, unbekanntenvektor_symbolisch,
|
||||
"Unbekanntenvektor")
|
||||
@@ -666,64 +703,82 @@ class FunktionalesModell:
|
||||
|
||||
def unbekanntenvektor_numerisch(self, liste_unbekanntenvektor_symbolisch: list,
|
||||
unbekanntenvektor_symbolisch: sp.Matrix,
|
||||
dX_Vektor: np.Matrix = None,
|
||||
unbekanntenvektor_neumerisch_vorherige_Iteration: np.Matrix = None,
|
||||
dX_Vektor: np.asarray = None,
|
||||
unbekanntenvektor_numerisch_vorherige_Iteration: np.asarray = None,
|
||||
iterationsnummer: int = 0) -> ndarray[tuple[int, int], Any] | ndarray[tuple[Any, ...], dtype[Any]]:
|
||||
"""Erstellt den numerischen Unbekanntenvektor jeder Iteration.
|
||||
|
||||
Wenn keine Iterationsfortschreibung übergeben wird (dX_Vektor und unbekanntenvektor_numerisch_vorherige_Iteration sind None),
|
||||
werden die aktuellen Substitutionen genutzt und daraus der numerische Unbekanntenvektor aufgebaut.
|
||||
|
||||
Wenn dX_Vektor und ein Unbekanntenvektor der vorherigen Iteration übergeben werden, wird der neue
|
||||
Unbekanntenvektor aus der Summe gebildet: x_neu = x_alt + dX.
|
||||
|
||||
Anschließend wird self.substitutionen_dict auf Basis des neuen Unbekanntenvektors aktualisiert.
|
||||
Der numerische Unbekanntenvektor wird als CSV-Datei in den Ordner Zwischenergebnisse exportiert.
|
||||
|
||||
:param liste_unbekanntenvektor_symbolisch: Liste der Unbekannten (Symbole) in der Reihenfolge des numerischen Vektors.
|
||||
:type liste_unbekanntenvektor_symbolisch: list
|
||||
:param unbekanntenvektor_symbolisch: Symbolischer Unbekanntenvektor.
|
||||
:type unbekanntenvektor_symbolisch: sp.Matrix
|
||||
:param dX_Vektor: Verbesserungsvektor der aktuellen Iteration (optional).
|
||||
:type dX_Vektor: np.asarray | None
|
||||
:param unbekanntenvektor_numerisch_vorherige_Iteration: Numerischer Unbekanntenvektor der vorherigen Iteration (optional).
|
||||
:type unbekanntenvektor_numerisch_vorherige_Iteration: np.asarray | None
|
||||
:param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse.
|
||||
:type iterationsnummer: int
|
||||
:return: Numerischer Unbekanntenvektor als Numpy-Array
|
||||
:rtype: ndarray[tuple[int, int], Any] | ndarray[tuple[Any, ...], dtype[Any]]
|
||||
"""
|
||||
|
||||
self.liste_unbekanntenvektor_symbolisch = liste_unbekanntenvektor_symbolisch
|
||||
|
||||
#if not hasattr(self, "liste_unbekanntenvektor_symbolisch"):
|
||||
# self.liste_unbekanntenvektor_symbolisch = liste_unbekanntenvektor_symbolisch
|
||||
|
||||
if dX_Vektor is None and unbekanntenvektor_neumerisch_vorherige_Iteration is None:
|
||||
#unbekanntenvektor_numerisch = unbekanntenvektor_symbolisch.xreplace(self.substitutionen_dict)
|
||||
#if self.func_u0 is None:
|
||||
# self.func_u0 = sp.lambdify(
|
||||
# self.liste_symbole_lambdify,
|
||||
# unbekanntenvektor_symbolisch,
|
||||
# modules="numpy",
|
||||
# cse=True
|
||||
# )
|
||||
# Überprüfung, ob dX und der unbekanntenvektor aus der vorhigen Iteration übergeben wurden. Wenn ja, wird daraus der neue unbekanntenvektor nach der Iteration berechnet.
|
||||
if dX_Vektor is None and unbekanntenvektor_numerisch_vorherige_Iteration is None:
|
||||
unbekanntenvektor_numerisch = np.asarray(
|
||||
[[float(self.substitutionen_dict[sym])] for sym in self.liste_unbekanntenvektor_symbolisch],
|
||||
dtype=float
|
||||
).reshape(-1, 1)
|
||||
|
||||
#liste_werte = [self.substitutionen_dict[s] for s in self.liste_symbole_lambdify]
|
||||
#unbekanntenvektor_numerisch = sp.Matrix(self.func_u0(*liste_werte))
|
||||
#unbekanntenvektor_numerisch = np.asarray(self.func_u0(*liste_werte), dtype=float).reshape(-1, 1)
|
||||
|
||||
|
||||
else:
|
||||
#unbekanntenvektor_numerisch = unbekanntenvektor_neumerisch_vorherige_Iteration + dX_Vektor
|
||||
unbekanntenvektor_neumerisch_vorherige_Iteration = np.asarray(
|
||||
unbekanntenvektor_neumerisch_vorherige_Iteration, dtype=float).reshape(-1, 1)
|
||||
unbekanntenvektor_numerisch_vorherige_Iteration = np.asarray(
|
||||
unbekanntenvektor_numerisch_vorherige_Iteration, dtype=float).reshape(-1, 1)
|
||||
dX_Vektor = np.asarray(dX_Vektor, dtype=float).reshape(-1, 1)
|
||||
unbekanntenvektor_numerisch = unbekanntenvektor_numerisch_vorherige_Iteration + dX_Vektor
|
||||
|
||||
unbekanntenvektor_numerisch = unbekanntenvektor_neumerisch_vorherige_Iteration + dX_Vektor
|
||||
|
||||
# Aktualisieren des Dictionaries für die Subsitutionen in den anderen Methoden.
|
||||
self.substitutionen_dict = self.dict_substitutionen_uebergeordnetes_system(unbekanntenvektor_numerisch)
|
||||
|
||||
Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}_Unbekanntenvektor_Numerisch_Iteration0.csv", [""],
|
||||
Export.matrix_to_csv(fr"Zwischenergebnisse\{iterationsnummer}_Unbekanntenvektor_Numerisch.csv", [""],
|
||||
liste_unbekanntenvektor_symbolisch, unbekanntenvektor_numerisch,
|
||||
"Unbekanntenvektor")
|
||||
return unbekanntenvektor_numerisch
|
||||
|
||||
def unbekanntenvektor_numerisch_to_dict_unbekanntenvektor(self, liste_unbekanntenvektor_symbolisch: list, unbekanntenvektor_numerisch: np.Matrix) -> dict:
|
||||
dict_unbekanntenvektor_numerisch = {}
|
||||
#index = 0
|
||||
"""Wandelt einen numerischen Unbekanntenvektor in ein Koordinatendictionary um.
|
||||
|
||||
Aus dem numerischen Unbekanntenvektor werden für alle Punkte die Koordinaten (X, Y, Z) extrahiert
|
||||
und als sp.Matrix([X, Y, Z]) in einem Dictionary gespeichert.
|
||||
|
||||
:param liste_unbekanntenvektor_symbolisch: Liste der Unbekannten (Symbole) in der Reihenfolge des numerischen Vektors.
|
||||
:type liste_unbekanntenvektor_symbolisch: list
|
||||
:param unbekanntenvektor_numerisch: Numerischer Unbekanntenvektor.
|
||||
:type unbekanntenvektor_numerisch: np.Matrix
|
||||
:return: Dictionary {punktnummer: sp.Matrix([X, Y, Z])}.
|
||||
:rtype: dict
|
||||
"""
|
||||
unbekanntenvektor_numerisch = np.asarray(unbekanntenvektor_numerisch, dtype=float).reshape(-1, 1)
|
||||
|
||||
idx = {str(sym): i for i, sym in enumerate(liste_unbekanntenvektor_symbolisch)}
|
||||
|
||||
punktnummern = []
|
||||
for sym in liste_unbekanntenvektor_symbolisch:
|
||||
name = str(sym)
|
||||
for symbol in liste_unbekanntenvektor_symbolisch:
|
||||
name = str(symbol)
|
||||
if name.startswith("X"):
|
||||
pn = name[1:]
|
||||
if pn not in punktnummern:
|
||||
punktnummern.append(pn)
|
||||
|
||||
# Annahme: Für jeden Punkt, für den eine X-Koordinate vorliegt, gibt es auch immer zwingend eine Y- und Z-Koordinate
|
||||
dict_koordinaten = {}
|
||||
for pn in punktnummern:
|
||||
iX = idx.get(f"X{pn}", None)
|
||||
@@ -739,19 +794,33 @@ class FunktionalesModell:
|
||||
float(unbekanntenvektor_numerisch[iZ, 0]),
|
||||
])
|
||||
|
||||
#dict_unbekanntenvektor_numerisch[punktnummer] = sp.Matrix([
|
||||
# float(unbekanntenvektor_numerisch[index, 0]),
|
||||
# float(unbekanntenvektor_numerisch[index + 1, 0]),
|
||||
# float(unbekanntenvektor_numerisch[index + 2, 0])
|
||||
#])
|
||||
#index += 3
|
||||
return dict_koordinaten
|
||||
|
||||
def berechnung_dl(self, beobachtungsvektor_numerisch: np.Matrix, beobachtungsvektor_naeherung_numerisch: sp.Matrix,
|
||||
liste_beobachtungsvektor_symbolisch: list = None, iterationsnummer: int = 0) -> np.Matrix:
|
||||
liste_beobachtungsvektor_symbolisch: list = None, iterationsnummer: int = 0) -> np.asarray:
|
||||
"""Berechnet den Verbesserungsvektor dl = l − f(x0).
|
||||
|
||||
Der Vektor wird als Differenz aus numerischem Beobachtungsvektor und numerischem Näherungs-Beobachtungsvektor gebildet.
|
||||
Für Richtungsbeobachtungen wird dl normiert.
|
||||
|
||||
Der Vektor dl wird als CSV-Datei in den Ordner Zwischenergebnisse exportiert.
|
||||
|
||||
:param beobachtungsvektor_numerisch: Numerischer Beobachtungsvektor l.
|
||||
:type beobachtungsvektor_numerisch: np.Matrix
|
||||
:param beobachtungsvektor_naeherung_numerisch: Numerischer Näherungs-Beobachtungsvektor f(x0).
|
||||
:type beobachtungsvektor_naeherung_numerisch: sp.Matrix
|
||||
:param liste_beobachtungsvektor_symbolisch: Optional: Liste der Beobachtungskennungen.
|
||||
:type liste_beobachtungsvektor_symbolisch: list | None
|
||||
:param iterationsnummer: Iterationsnummer für Dateinamen der Zwischenergebnisse.
|
||||
:type iterationsnummer: int
|
||||
:return: Verbesserungsvektor dl.
|
||||
:rtype: np.asarray
|
||||
"""
|
||||
dl = beobachtungsvektor_numerisch - beobachtungsvektor_naeherung_numerisch
|
||||
# Umwandeln in einen Numpy-Array, um Rechenzeit im Vergleich zu einer sympy.MAtrix zu sparen
|
||||
dl = np.asarray(dl, dtype=float)
|
||||
|
||||
# Wird keine liste_beobachtungsvektor_symbolisch übergeben, wird diese aus der Instanzvariable verwendet.
|
||||
if liste_beobachtungsvektor_symbolisch is None:
|
||||
liste_beobachtungsvektor_symbolisch = self.liste_beobachtungsvektor_symbolisch
|
||||
|
||||
@@ -770,11 +839,25 @@ class FunktionalesModell:
|
||||
return dl
|
||||
|
||||
def dict_substitutionen_uebergeordnetes_system(self,
|
||||
unbekanntenvektor_aus_iteration: np.Matrix = None) -> dict[Any, Any]:
|
||||
db_zugriff = Datenbankzugriff(self.pfad_datenbank)
|
||||
berechnungen = Berechnungen(self.a, self.b)
|
||||
unbekanntenvektor_aus_iteration: np.asarray = None) -> dict[Any, Any]:
|
||||
"""Erstellt das Substitutions-Dictionary für das geozentrisch-kartesische System.
|
||||
|
||||
Es werden (abhängig davon, ob ein Unbekanntenvektor aus einer Iteration übergeben wurde) die aktuellen
|
||||
Koordinaten und daraus abgeleitete Größen erzeugt und als Substitutionen abgelegt, u. a.:
|
||||
|
||||
- Punktkoordinaten X*, Y*, Z* sowie geodätische Breite B* und Länge L*,
|
||||
- berechnete Größen aus Tachymeterbeziehungen (Azimut, Richtung, Zenitwinkel, Schrägstrecke),
|
||||
- Normalhöhen NH (über Transformationen),
|
||||
- Beobachtungssymbole der Messungen (Tachymeter, GNSS, Nivellement),
|
||||
- Orientierungsunbekannte O.
|
||||
|
||||
:param unbekanntenvektor_aus_iteration: Optionaler numerischer Unbekanntenvektor einer Iteration zur Aktualisierung der Substitutionen.
|
||||
:type unbekanntenvektor_aus_iteration: np.asarray | None
|
||||
:return: Dictionary mit SymPy-Symbolen als Key und numerischen Werten als Value.
|
||||
:rtype: dict[Any, Any]
|
||||
"""
|
||||
if unbekanntenvektor_aus_iteration is None:
|
||||
dict_koordinaten = db_zugriff.get_koordinaten("naeherung_us")
|
||||
dict_koordinaten = self.db_zugriff.get_koordinaten("naeherung_us")
|
||||
else:
|
||||
dict_koordinaten = self.unbekanntenvektor_numerisch_to_dict_unbekanntenvektor(
|
||||
self.liste_unbekanntenvektor_symbolisch,
|
||||
@@ -784,13 +867,15 @@ class FunktionalesModell:
|
||||
for punktnummer, matrix in dict_koordinaten.items():
|
||||
dict_koordinaten[punktnummer] = [float(matrix[0]), float(matrix[1]), float(matrix[2])]
|
||||
|
||||
# Abfragen der Beobachtungen der einzelnen Beobachtungsarten aus der Tabelle Beobachtungen
|
||||
liste_beobachtungen_tachymeter = self.db_zugriff.get_beobachtungen_from_beobachtungenid()
|
||||
liste_beobachtungen_gnssbasislinien = self.db_zugriff.get_beobachtungen_gnssbasislinien()
|
||||
liste_beobachtungen_nivellemente = self.db_zugriff.get_beobachtungen_nivellement()
|
||||
liste_azimut_richtungen, dict_orientierungen = self.berechnungen.berechnung_richtung_azimut_zenitwinkel(self.pfad_datenbank, dict_koordinaten)
|
||||
|
||||
liste_beobachtungen_tachymeter = db_zugriff.get_beobachtungen_from_beobachtungenid()
|
||||
liste_beobachtungen_gnssbasislinien = db_zugriff.get_beobachtungen_gnssbasislinien()
|
||||
liste_beobachtungen_nivellemente = db_zugriff.get_beobachtungen_nivellement()
|
||||
liste_azimut_richtungen, dict_orientierungen = berechnungen.berechnung_richtung_azimut_zenitwinkel(self.pfad_datenbank, dict_koordinaten)
|
||||
# Erstellen von Dictionaries für die weitere Verarbeitung
|
||||
dict_koordinaten_xyz_kopie = {pn: [v[0], v[1], v[2]] for pn, v in dict_koordinaten.items()}
|
||||
dict_koordinaten_B_L = berechnungen.geometrische_breite_laenge(dict_koordinaten_xyz_kopie)
|
||||
dict_koordinaten_B_L = self.berechnungen.geodätische_breite_laenge(dict_koordinaten_xyz_kopie)
|
||||
|
||||
punktnummern_niv = set()
|
||||
for beobachtungenID, pn_sp, pn_zp, niv_dh, niv_strecke, niv_anz_standpkte in liste_beobachtungen_nivellemente:
|
||||
@@ -806,8 +891,8 @@ class FunktionalesModell:
|
||||
dict_koordinaten_niv,
|
||||
self.pfad_tif_quasigeoidundolation)
|
||||
|
||||
# Zuweisen der Symbole zu dem jeweiligen numerischen Wert. Gespeichert wird dies in einem Dictionary.
|
||||
substitutionen = {}
|
||||
|
||||
for punktnummer, vektor in dict_koordinaten_B_L.items():
|
||||
X_sym, Y_sym, Z_sym, B_sym, L_Sym = sp.symbols(
|
||||
f"X{punktnummer} Y{punktnummer} Z{punktnummer} B{punktnummer} L{punktnummer}")
|
||||
@@ -818,10 +903,6 @@ class FunktionalesModell:
|
||||
substitutionen[B_sym] = float(vektor[1])
|
||||
substitutionen[L_Sym] = float(vektor[2])
|
||||
|
||||
#for beobachtungsgruppeID, orientierung in dict_orientierungen.items():
|
||||
# O_sym = sp.symbols(f"O_{beobachtungsgruppeID}")
|
||||
# substitutionen[O_sym] = float(orientierung)
|
||||
|
||||
for beobachtungsgruppeID, standpunkt, zielpunkt, azimut, richtung, zenitwinkel, schraegstrecke, orientierung in liste_azimut_richtungen:
|
||||
richtung_sym = sp.symbols(f"richtung_berechnet_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
substitutionen[richtung_sym] = float(richtung)
|
||||
@@ -839,8 +920,6 @@ class FunktionalesModell:
|
||||
normalhoehe_sym = sp.symbols(f"NH{punktnummer}")
|
||||
substitutionen[normalhoehe_sym] = float(koordinaten_utm[2])
|
||||
|
||||
|
||||
|
||||
for standpunkt, zielpunkt, beobachtungenID, beobachtungsgruppeID, tachymeter_richtung, tachymeter_zenitwinkel, tachymeter_distanz in liste_beobachtungen_tachymeter:
|
||||
alpha = sp.symbols(f"{beobachtungenID}_R_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
zw = sp.symbols(f"{beobachtungenID}_ZW_{beobachtungsgruppeID}_{standpunkt}_{zielpunkt}")
|
||||
@@ -852,7 +931,6 @@ class FunktionalesModell:
|
||||
substitutionen[alpha] = float(tachymeter_richtung)
|
||||
substitutionen[zw] = float(tachymeter_zenitwinkel)
|
||||
substitutionen[s] = float(tachymeter_distanz)
|
||||
#substitutionen[sp.Symbol(f"O{beobachtungsgruppeID}")] = 0.0
|
||||
|
||||
for beobachtungenID, punktnummer_sp, punktnummer_zp, gnss_bx, gnss_by, gnss_bz, gnss_s0, gnss_cxx, gnss_cxy, gnss_cxz, gnss_cyy, gnss_cyz, gnss_czz in liste_beobachtungen_gnssbasislinien:
|
||||
beobachtungenID = str(beobachtungenID).strip()
|
||||
@@ -890,10 +968,6 @@ class FunktionalesModell:
|
||||
for orientierungs_id, wert in dict_O.items():
|
||||
substitutionen[sp.Symbol(f"O{orientierungs_id}")] = float(wert)
|
||||
else:
|
||||
#for standpunkt, zielpunkt, beobachtungenID, beobachtungsgruppeID, *_ in liste_beobachtungen_tachymeter:
|
||||
# O_sym = sp.Symbol(f"O{beobachtungsgruppeID}")
|
||||
# if O_sym not in substitutionen:
|
||||
# substitutionen[O_sym] = 0
|
||||
for beobachtungsgruppeID, standpunkt, zielpunkt, azimut, richtung, zenitwinkel, schraegstrecke, orientierung in liste_azimut_richtungen:
|
||||
O_sym = sp.Symbol(f"O{beobachtungsgruppeID}")
|
||||
if O_sym not in substitutionen:
|
||||
@@ -902,7 +976,18 @@ class FunktionalesModell:
|
||||
return substitutionen
|
||||
|
||||
def unbekanntenvektor_numerisch_to_dict_orientierungen(self, liste_unbekanntenvektor_symbolisch: list,
|
||||
unbekanntenvektor_numerisch: np.Matrix) -> dict[Any, Any]:
|
||||
unbekanntenvektor_numerisch: np.asarray) -> dict[Any, Any]:
|
||||
"""Extrahiert Orientierungsparameter aus einem numerischen Unbekanntenvektor in ein Dictionary.
|
||||
|
||||
Alle Unbekannten, deren Symbolname mit "O" beginnt, werden als als Dictionary in der Form {orientierungs_id: wert} zurückgegeben.
|
||||
|
||||
:param liste_unbekanntenvektor_symbolisch: Liste der Unbekannten (Symbole) in der Reihenfolge des numerischen Vektors.
|
||||
:type liste_unbekanntenvektor_symbolisch: list
|
||||
:param unbekanntenvektor_numerisch: Numerischer Unbekanntenvektor.
|
||||
:type unbekanntenvektor_numerisch: np.asarray
|
||||
:return: Dictionary der Orientierungen je Beobachtungsgruppe.
|
||||
:rtype: dict[Any, Any]
|
||||
"""
|
||||
dict_O = {}
|
||||
unbekanntenvektor_numerisch = np.asarray(unbekanntenvektor_numerisch, dtype=float).reshape(-1, 1)
|
||||
for i, symbol in enumerate(liste_unbekanntenvektor_symbolisch):
|
||||
@@ -911,5 +996,4 @@ class FunktionalesModell:
|
||||
orientierungs_id = name[1:]
|
||||
dict_O[orientierungs_id] = float(unbekanntenvektor_numerisch[i, 0])
|
||||
|
||||
return dict_O
|
||||
|
||||
return dict_O
|
||||
Reference in New Issue
Block a user