Files
Masterprojekt_V3/Datumsfestlegung.py

262 lines
12 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import sympy as sp
import numpy as np
from typing import Iterable, List, Sequence, Tuple, Optional
import Stochastisches_Modell
import Export
class Datumsfestlegung:
@staticmethod
def weiches_datum(Q_ll: np.ndarray, Q_AA: np.ndarray, varianzkompontenschaetzung_erfolgt: bool,
dict_indizes_beobachtungsgruppen: dict) -> np.ndarray:
if Stochastisches_Modell.StochastischesModell.berechne_P(Q_ll).ndim != 2 or \
Stochastisches_Modell.StochastischesModell.berechne_P(Q_ll).shape[0] != \
Stochastisches_Modell.StochastischesModell.berechne_P(Q_ll).shape[1]:
raise ValueError("Q_ll muss quadratisch sein.")
if Stochastisches_Modell.StochastischesModell.berechne_P(Q_AA).ndim != 2 or \
Stochastisches_Modell.StochastischesModell.berechne_P(Q_AA).shape[0] != \
Stochastisches_Modell.StochastischesModell.berechne_P(Q_AA).shape[1]:
raise ValueError("Q_AA muss quadratisch sein.")
Q_ext = np.block(
[[Q_ll, np.zeros((Q_ll.shape[0], Q_AA.shape[0]))], [np.zeros((Q_AA.shape[0], Q_ll.shape[0])), Q_AA]])
if varianzkompontenschaetzung_erfolgt == False:
P = np.block([[Stochastisches_Modell.StochastischesModell.berechne_P(Q_ll), np.zeros(
(Stochastisches_Modell.StochastischesModell.berechne_P(Q_ll).shape[0],
Stochastisches_Modell.StochastischesModell.berechne_P(Q_AA).shape[0]))], [np.zeros(
(Stochastisches_Modell.StochastischesModell.berechne_P(Q_AA).shape[0],
Stochastisches_Modell.StochastischesModell.berechne_P(Q_ll).shape[0])),
Stochastisches_Modell.StochastischesModell.berechne_P(
Q_AA)]])
else:
print("Varianzkomponentenschätzung wurde durchgeführt")
for beobachtungsgruppe, indizes in dict_indizes_beobachtungsgruppen.items():
z_start, z_ende = indizes[0], indizes[1] # Zeile 2 bis inklusive 5
s_start, s_ende = indizes[0], indizes[1] # Spalte 1 bis inklusive 4
if beobachtungsgruppe == "SD":
aufgeteilt_SD = Q_ext[z_start: z_ende + 1, s_start: s_ende + 1]
if beobachtungsgruppe == "R":
aufgeteilt_R = Q_ext[z_start: z_ende + 1, s_start: s_ende + 1]
if beobachtungsgruppe == "ZW":
aufgeteilt_ZW = Q_ext[z_start: z_ende + 1, s_start: s_ende + 1]
if beobachtungsgruppe == "gnss":
aufgeteilt_gnss = Q_ext[z_start: z_ende + 1, s_start: s_ende + 1]
if beobachtungsgruppe == "niv":
aufgeteilt_niv = Q_ext[z_start: z_ende + 1, s_start: s_ende + 1]
if beobachtungsgruppe == "lA":
aufgeteilt_lA = Q_ext[z_start: z_ende + 1, s_start: s_ende + 1]
aufgeteilt_SD_invertiert = Stochastisches_Modell.StochastischesModell.berechne_P(aufgeteilt_SD)
aufgeteilt_R_invertiert = Stochastisches_Modell.StochastischesModell.berechne_P(aufgeteilt_R)
aufgeteilt_ZW_invertiert = Stochastisches_Modell.StochastischesModell.berechne_P(aufgeteilt_ZW)
aufgeteilt_gnss_invertiert = Stochastisches_Modell.StochastischesModell.berechne_P(aufgeteilt_gnss)
aufgeteilt_niv_invertiert = Stochastisches_Modell.StochastischesModell.berechne_P(aufgeteilt_niv)
aufgeteilt_lA_invertiert = Stochastisches_Modell.StochastischesModell.berechne_P(aufgeteilt_lA)
def Z(A, B):
return np.zeros((A.shape[0], B.shape[0]))
P = np.block([
[aufgeteilt_SD_invertiert, Z(aufgeteilt_SD_invertiert, aufgeteilt_R_invertiert),
Z(aufgeteilt_SD_invertiert, aufgeteilt_ZW_invertiert),
Z(aufgeteilt_SD_invertiert, aufgeteilt_gnss_invertiert),
Z(aufgeteilt_SD_invertiert, aufgeteilt_niv_invertiert),
Z(aufgeteilt_SD_invertiert, aufgeteilt_lA_invertiert)],
[Z(aufgeteilt_R_invertiert, aufgeteilt_SD_invertiert), aufgeteilt_R_invertiert,
Z(aufgeteilt_R_invertiert, aufgeteilt_ZW_invertiert),
Z(aufgeteilt_R_invertiert, aufgeteilt_gnss_invertiert),
Z(aufgeteilt_R_invertiert, aufgeteilt_niv_invertiert),
Z(aufgeteilt_R_invertiert, aufgeteilt_lA_invertiert)],
[Z(aufgeteilt_ZW_invertiert, aufgeteilt_SD_invertiert),
Z(aufgeteilt_ZW_invertiert, aufgeteilt_R_invertiert), aufgeteilt_ZW_invertiert,
Z(aufgeteilt_ZW_invertiert, aufgeteilt_gnss_invertiert),
Z(aufgeteilt_ZW_invertiert, aufgeteilt_niv_invertiert),
Z(aufgeteilt_ZW_invertiert, aufgeteilt_lA_invertiert)],
[Z(aufgeteilt_gnss_invertiert, aufgeteilt_SD_invertiert),
Z(aufgeteilt_gnss_invertiert, aufgeteilt_R_invertiert),
Z(aufgeteilt_gnss_invertiert, aufgeteilt_ZW_invertiert), aufgeteilt_gnss_invertiert,
Z(aufgeteilt_gnss_invertiert, aufgeteilt_niv_invertiert),
Z(aufgeteilt_gnss_invertiert, aufgeteilt_lA_invertiert)],
[Z(aufgeteilt_niv_invertiert, aufgeteilt_SD_invertiert),
Z(aufgeteilt_niv_invertiert, aufgeteilt_R_invertiert),
Z(aufgeteilt_niv_invertiert, aufgeteilt_ZW_invertiert),
Z(aufgeteilt_niv_invertiert, aufgeteilt_gnss_invertiert), aufgeteilt_niv_invertiert,
Z(aufgeteilt_niv_invertiert, aufgeteilt_lA_invertiert)],
[Z(aufgeteilt_lA_invertiert, aufgeteilt_SD_invertiert),
Z(aufgeteilt_lA_invertiert, aufgeteilt_R_invertiert),
Z(aufgeteilt_lA_invertiert, aufgeteilt_ZW_invertiert),
Z(aufgeteilt_lA_invertiert, aufgeteilt_gnss_invertiert),
Z(aufgeteilt_lA_invertiert, aufgeteilt_niv_invertiert), aufgeteilt_lA_invertiert]
])
# print(aufgeteilt)
# print(beobachtungsgruppe, indizes)
# Export.matrix_to_csv(
# fr"Zwischenergebnisse\_{beobachtungsgruppe}.csv",
# [""],
# labels,
# aufgeteilt,
# f"{beobachtungsgruppe}"
# )
return Q_ext, P
@staticmethod
def indizes_beobachtungsvektor_nach_beobachtungsgruppe(Jacobimatrix_symbolisch_liste_beobachtungsvektor):
liste_strecken_indizes = []
liste_richtungen_indizes = []
liste_zenitwinkel_indizes = []
liste_gnss_indizes = []
liste_nivellement_indizes = []
liste_anschlusspunkte_indizes = []
dict_beobachtungsgruppen_indizes = {}
for beobachtung in Jacobimatrix_symbolisch_liste_beobachtungsvektor:
if beobachtung.split("_")[1] == "SD":
index = Jacobimatrix_symbolisch_liste_beobachtungsvektor.index(beobachtung)
liste_strecken_indizes.append(index)
if beobachtung.split("_")[1] == "R":
index = Jacobimatrix_symbolisch_liste_beobachtungsvektor.index(beobachtung)
liste_richtungen_indizes.append(index)
if beobachtung.split("_")[1] == "ZW":
index = Jacobimatrix_symbolisch_liste_beobachtungsvektor.index(beobachtung)
liste_zenitwinkel_indizes.append(index)
if beobachtung.split("_")[1] == "gnssbx" or beobachtung.split("_")[1] == "gnssby" or beobachtung.split("_")[
1] == "gnssbz":
index = Jacobimatrix_symbolisch_liste_beobachtungsvektor.index(beobachtung)
liste_gnss_indizes.append(index)
if beobachtung.split("_")[1] == "niv":
index = Jacobimatrix_symbolisch_liste_beobachtungsvektor.index(beobachtung)
liste_nivellement_indizes.append(index)
if beobachtung.split("_")[0] == "lA":
index = Jacobimatrix_symbolisch_liste_beobachtungsvektor.index(beobachtung)
liste_anschlusspunkte_indizes.append(index)
dict_beobachtungsgruppen_indizes["SD"] = min(liste_strecken_indizes), max(liste_strecken_indizes)
dict_beobachtungsgruppen_indizes["R"] = min(liste_richtungen_indizes), max(liste_richtungen_indizes)
dict_beobachtungsgruppen_indizes["ZW"] = min(liste_zenitwinkel_indizes), max(liste_zenitwinkel_indizes)
dict_beobachtungsgruppen_indizes["gnss"] = min(liste_gnss_indizes), max(liste_gnss_indizes)
dict_beobachtungsgruppen_indizes["niv"] = min(liste_nivellement_indizes), max(liste_nivellement_indizes)
dict_beobachtungsgruppen_indizes["lA"] = min(liste_anschlusspunkte_indizes), max(liste_anschlusspunkte_indizes)
return dict_beobachtungsgruppen_indizes
@staticmethod
def make_index(unbekannten_liste):
names = [str(s).strip() for s in unbekannten_liste]
return names, {n: i for i, n in enumerate(names)}
@staticmethod
def build_G_from_names(x0, unbekannten_liste, liste_punktnummern=None, mit_massstab=True):
"""
Baut G (u x d) in den vollen Unbekanntenraum.
Wenn liste_punktnummern=None, werden alle Punkt-IDs aus unbekannten_liste
über X*/Y*/Z* automatisch bestimmt.
"""
x0 = np.asarray(x0, float).reshape(-1)
names, idx = Datumsfestlegung.make_index(unbekannten_liste)
u = len(names)
d = 7 if mit_massstab else 6
G = np.zeros((u, d), dtype=float)
# --- Punktliste automatisch, falls nicht gegeben ---
if liste_punktnummern is None:
pids = set()
for n in names:
if len(n) >= 2 and n[0].upper() in ("X", "Y", "Z"):
pids.add(n[1:]) # alles nach X/Y/Z
liste_punktnummern = sorted(pids)
for pid in liste_punktnummern:
sx, sy, sz = f"X{pid}", f"Y{pid}", f"Z{pid}"
if sx not in idx or sy not in idx or sz not in idx:
continue # Punkt nicht vollständig als XYZ-Unbekannte vorhanden
ix, iy, iz = idx[sx], idx[sy], idx[sz]
xi, yi, zi = x0[ix], x0[iy], x0[iz]
# Translationen
G[ix, 0] = 1.0
G[iy, 1] = 1.0
G[iz, 2] = 1.0
# Rotationen (δr = ω × r)
# Rx: δY=-Z, δZ=+Y
G[iy, 3] = -zi
G[iz, 3] = yi
# Ry: δX=+Z, δZ=-X
G[ix, 4] = zi
G[iz, 4] = -xi
# Rz: δX=-Y, δY=+X
G[ix, 5] = -yi
G[iy, 5] = xi
# Maßstab
if mit_massstab:
G[ix, 6] = xi
G[iy, 6] = yi
G[iz, 6] = zi
return G
def aktive_indices_from_selection(auswahl, unbekannten_liste):
names, idx = Datumsfestlegung.make_index(unbekannten_liste)
aktive = []
for pid, comp in auswahl:
key = f"{comp.upper()}{str(pid)}"
if key not in idx:
raise KeyError(f"{key} nicht im Unbekanntenvektor.")
aktive.append(idx[key])
# unique
out = []
seen = set()
for i in aktive:
if i not in seen:
seen.add(i)
out.append(i)
return out
def auswahlmatrix_E(u, aktive_indices):
E = np.zeros((u, u), dtype=float)
for i in aktive_indices:
E[int(i), int(i)] = 1.0
return E
def loese_geraendert_mit_Qxx(N, n, G):
"""
löst [N G; G^T 0] [dx;k] = [n;0]
und liefert zusätzlich Q_xx als oberen linken Block von inv(K).
"""
N = np.asarray(N, float)
n = np.asarray(n, float).reshape(-1, 1)
G = np.asarray(G, float)
u = N.shape[0]
d = G.shape[1]
K = np.block([
[N, G],
[G.T, np.zeros((d, d))]
])
rhs = np.vstack([n, np.zeros((d, 1))])
K_inv = np.linalg.inv(K)
sol = K_inv @ rhs
dx = sol[:u]
k = sol[u:]
Q_xx = K_inv[:u, :u]
return dx, k, Q_xx