Getestet auf Ubuntu 22.04 mit dem System-Python 3.10 und einem Grafiktreiber mit OpenGL ≥ 3.2 (die 3D-Ansicht ist VTK). Was davon da ist, prüft ein Skript und sagt zu jedem fehlenden Teil den Befehl:
python3 scripts/pruefe_installation.pyWas man braucht, hängt davon ab, was man machen will:
| Teil | wofür | Pflicht? |
|---|---|---|
| PyQt5, VTK (apt) + Python-Pakete (pip) | App starten, Projekte öffnen, ansehen, messen, exportieren | ja |
| PointCloudMerger (Nachbar-Repo) | Mäander-Einfärbung aus dem DJI-Flug | für Mäander |
Interpreter mit pycolmap |
neue COLMAP-Rekonstruktion eines Mäanderfluges | nur ohne fertiges Modell |
| ROS 2 Humble + Livox-Treiber + FAST_LIO_ROS2 | Karte berechnen aus einem Rosbag | nur dafür |
| EPIC_ros2 | RViz-Wiedergabe (traj_utils/quadrotor_msgs) |
nur dafür |
Ein fertiges Projekt (z. B. ein exportierter Ordner) lässt sich also mit den Pflichtteilen allein öffnen, ansehen, messen, einfärben aus der Mäander-Ebene und exportieren — ROS braucht es nur zum Berechnen der Karte.
sudo apt install python3-pip python3-pyqt5 python3-pyqt5.qtopengl python3-vtk9
pip install --user -r requirements.txtPyQt5 und VTK bewusst aus apt (getestet: PyQt5 5.15.6, VTK 9.1.0) — die
pip-Wheels von VTK bringen eigene Qt-Bindungen mit und vertragen sich damit
nicht zuverlässig. requirements.txt enthält den Rest (numpy, scipy,
opencv-python, open3d, rosbags 0.10, Pillow, laspy, pyproj, pyqtdarktheme)
mit den getesteten Versionen als Kommentar. Fehlt pyqtdarktheme, startet die
App im Standard-Look.
git clone git@github.com:LenaKremer98/PointCloudMerger.git ~/PointCloudMerger
sudo apt install libimage-exiftool-perl # optional: Geotags schnellerGesucht wird unter ~/PointCloudMerger und neben diesem Repo. Temperaturen aus
den Thermalbildern brauchen kein DJI-SDK (s. „Temperaturen“).
Liegt im Projekt noch kein COLMAP-Modell des Fluges, rechnet die App eins — dafür
braucht es einen Interpreter mit pycolmap, getrennt vom System-Python:
python3 -m venv ~/.venvs/colmap
~/.venvs/colmap/bin/pip install pycolmap # getestet: 4.0.4Nur dafür braucht es ROS 2 Humble. Die App erwartet die Workspaces unter
~/ws_livox und ~/fastlio2_ws und sourct sie selbst — vor dem Start der App
muss nichts gesourct werden. Kurzfassung (Details in den READMEs der Repos):
# ROS 2 Humble (https://docs.ros.org/en/humble/Installation/Ubuntu-Install-Debs.html)
sudo apt install ros-humble-desktop ros-humble-pcl-ros libpcl-dev libeigen3-dev \
python3-colcon-common-extensions
# Livox-SDK2
git clone https://github.com/Livox-SDK/Livox-SDK2.git ~/Livox-SDK2
cd ~/Livox-SDK2 && mkdir -p build && cd build && cmake .. && make -j && sudo make install
# livox_ros_driver2 (liefert den Nachrichtentyp CustomMsg der Mid-360)
mkdir -p ~/ws_livox/src
git clone https://github.com/Livox-SDK/livox_ros_driver2.git ~/ws_livox/src/livox_ros_driver2
cd ~/ws_livox/src/livox_ros_driver2 && source /opt/ros/humble/setup.bash && ./build.sh humble
# FAST_LIO_ROS2 mit der Konfiguration aus diesem Repo
mkdir -p ~/fastlio2_ws/src
git clone --recursive https://github.com/Ericsii/FAST_LIO_ROS2.git ~/fastlio2_ws/src/FAST_LIO_ROS2
cp config/fastlio/whs_dense.yaml ~/fastlio2_ws/src/FAST_LIO_ROS2/config/
cd ~/fastlio2_ws && source /opt/ros/humble/setup.bash \
&& source ~/ws_livox/install/setup.bash && colcon buildwhs_dense.yaml gehört nicht zu FAST_LIO_ROS2 — es ist die eigene
Konfiguration für die Super-Drohne (jeder Rohpunkt, volle Scans, Lidar-IMU-
Extrinsik der Mid-360) und liegt deshalb unter config/fastlio/ in diesem Repo.
Ohne sie schlägt „Karte berechnen“ fehl. Nach einer Änderung neu bauen, der
Workspace ist ohne --symlink-install gebaut.
Optional für die RViz-Wiedergabe: EPIC
als ~/EPIC_ros2 bauen — ohne dessen Nachrichtentypen bricht ros2 bag play
bei den Drohnen-Bags ab.
sudo apt install xvfb
xvfb-run -a python3 scripts/test_cloud_view_steuerung.py
python3 -m core.meander # jedes Modul in core/ und ui/ hat einen Selbsttest./run_gui.sh # oder: python3 app.pyKein ROS-Sourcing nötig — die GUI liest Bags über die rosbags-Bibliothek;
nur der FAST-LIO-Schritt startet intern Subprozesse mit ROS-Umgebung
(/opt/ros/humble, ~/ws_livox, ~/fastlio2_ws).
Projekte liegen im Cache unter ~/RosBagSuper_Gui/rosbag_suite/cache, umzuhängen
mit der Umgebungsvariable SUPER360_CACHE_ROOT.
- Bag öffnen… — Bag-Ordner wählen (z. B.
rosbag_2026-07-11_15-37-07_seg0). Vorhandene Cache-Artefakte (Karte/Farben/Panoramen) werden automatisch geladen. - Karte berechnen — FAST-LIO2-Lauf (Dauer ≈ Bag-Länge / Abspielrate). Es darf nur eine Instanz laufen (Instanz-Sperre); alte FAST-LIO-Prozesse werden vorher beendet.
- Einfärben — erst ggf. „Auto-Kalibrierung (grob)", Overlay-Vorschau prüfen, dann „Einfärben".
- Zusammenführen — zweiten Flug dazuladen und beide Karten zu einer machen.
- GPS-Tab — Ampel + Gründe; Georeferenzierung nur bei grün/gelb möglich.
- Export — berücksichtigt „Nur eingefärbte Punkte".
Die Maus steuert die Wolke genau wie der VS-Code-Punktwolken-Viewer
(PointCloudMerger/vscode-pointcloud-viewer):
| Eingabe | Wirkung |
|---|---|
| links ziehen | um den Zielpunkt drehen (Z oben, 0,006 rad je Pixel) |
| rechts ziehen, oder Umschalt/Strg und ziehen | in der Bildebene verschieben |
| Mausrad | zoomen (Abstand × exp(0,0012 · Δ), eine Raste ≈ 12 %) |
R oder „Ansicht zurücksetzen“ |
auf den Schwerpunkt, schräg von oben |
M oder „Messen“ |
Messen ein/aus; ein Klick ist ein Klick, solange die Maus unter 5 px bleibt — gedreht wird auch beim Messen |
Esc |
Messung verwerfen |
Oben liegt die Leiste wie dort:
- Farbe — Einheitsfarbe, Intensität, Höhe, RGB Onboard, RGB Mäander, Thermal Mäander. Farbmodus und Farbquelle in einem; was das Projekt nicht hat, ist ausgegraut. Seitenleiste und Menü ziehen mit.
- Punkte — 0,5 bis 10 px in Viertelschritten. Gebrochene Größen wirken wirklich (bei 1 / 1,5 / 2 px gemessen 18,6 / 22,2 / 23,4 % bedeckte Pixel).
- Messen und Ansicht zurücksetzen.
- Temperatur anzeigen (Standard an) — über einem Punkt zeigt die Maus seine Temperatur, in jedem Farbmodus, sobald es eine Thermal-Mäander-Ebene mit Temperaturen gibt.
Die Thermalbilder der M30T sind radiometrische JPEGs: neben dem Palettenbild
tragen sie die Rohwerte des Sensors (APP3, 640 × 512 × 16 Bit) und die
kameraeigene Umrechnungstabelle Rohwert → Zehntelgrad (APP5). core/temperatur.py
liest beides, ohne DJI-SDK. Beim Einfärben bekommt jeder Punkt die Temperatur aus
demselben Bild und Pixel wie seine Farbe; sie liegt als
colors_meander_thermal/temperatur.bin neben der Ebene. Am DRZ-Flug: 64 % der
Punkte, 21,9 bis 37,3 °C (1.–99. Perzentil). Es ist die Temperatur, die auch
die DJI-App zeigt — mit dem Emissionsgrad, der in der Kamera eingestellt war.
Ältere Thermal-Ebenen haben noch keine Temperaturen; einmal neu einfärben.
M, Werkzeuge → Messen oder Messen in der Leiste schaltet um. Zwei Klicks in die Wolke setzen die
Marken, dazwischen liegt eine Linie mit dem Abstand in Metern. Unter der
3D-Ansicht stehen beide Punkte in Originalkoordinaten, dazu Abstand, waagerechter
Anteil, Höhenunterschied und die Differenz je Achse. Ein dritter Klick fängt neu
an.
Genommen wird der Punkt, welcher dem Klick am nächsten liegt und dabei der Kamera am nächsten steht — sonst greift man durch eine Wand hindurch. Gesucht wird nur unter den sichtbaren Punkten: ein aktiver Höhenschnitt schließt alles Weggeschnittene aus.
Rechts am Viewer liegt eine Leiste mit zwei Griffen, die die sichtbare Höhenschicht aufspannen — damit lässt sich das Dach abnehmen und in ein Gebäude hineinschauen. Die Höhen stehen in Metern an den Griffen.
| Eingabe | Wirkung |
|---|---|
| Griff ziehen | obere oder untere Schnittebene setzen |
| auf die Leiste klicken | den näher liegenden Griff dorthin holen |
| Mausrad über der Leiste | die ganze Schicht nach oben oder unten schieben |
| Doppelklick oder „alles" | Schnitt aufheben |
Geschnitten wird über Clipping-Ebenen auf der Grafikkarte, die Geometrie bleibt also unberührt und das Ziehen ist auch bei Millionen Punkten flüssig. Die Trajektorie hängt an einem eigenen Mapper und bleibt sichtbar.
Zweite Art, die Wolke einzufärben: mit den Nadirbildern eines DJI-Kartierungs- fluges statt aus der 360°-Kamera an Bord. Der Weg dahinter kommt aus dem Repo PointCloudMerger und läuft hier ohne Eingriff durch:
Bilder ──► COLMAP ──► Kameraposen im willkürlichen Rahmen
│
RTK-Geotags ───────────┤ Umeyama → metrisch in ENU
▼
LiDAR-Karte ───────────┤ Drehung um die Hochachse + Verschiebung
▼
jeder Punkt ──► in das nadirnächste Bild ──► RGB
Zwischen ENU und der Karte bleibt nur eine Drehung um die Hochachse, weil beide Rahmen lotrecht sind — das ENU per Definition, die Karte seit der Kippkorrektur über die IMU. Vier Freiheitsgrade statt sieben, und die lassen sich suchen: grob per Kreuzkorrelation über den Gierwinkel, fein über den Höhenunterschied zum Rastermodell. Kein ICP über sechs Freiheitsgrade — das verkippt an Gebäudekanten und zerstört die Lotrechte, die man geschenkt bekommt.
Ablauf: Mäanderflug wählen (Ordner mit den _V.JPG), Ausrichten,
Ergebnis im Viewer prüfen, dann Einfärben. Ist noch kein COLMAP-Modell da,
wird vorher gefragt — bei 255 Bildern dauert die Rekonstruktion etwa eine halbe
Stunde und liegt danach im Arbeitsordner des Projekts.
Auf die Gütezahl achten, nicht auf die Trefferquote. Nach dem Ausrichten steht im Protokoll, wie viele Fotopunkte auf der Oberfläche der Wolke liegen. Bei einer Nadirbefliegung gehören sie dorthin, stimmt der Winkel sind es 70 % und mehr. Liegt der Wert unter 40 %, sitzt die Ausrichtung falsch und das Einfärben bricht mit einer Meldung ab, statt Minuten in eine verdrehte Lage zu stecken. Die Trefferquote beim Einfärben taugt dafür nicht: sie liegt auch bei einer um 60° verdrehten Lage bei 99,8 %, weil fast jeder Punkt in irgendein Bild fällt.
Die Bewertung der Kandidaten liegt eng beieinander — in einem gemessenen Fall gewann 154,53° mit 0,291 gegen die richtigen 92,35° mit 0,289. Wenn das passiert: den Gierwinkel von Hand auf den Wert der Grobsuche ziehen (der steht mit im Protokoll) und erneut ausrichten.
Thermal braucht keine zweite Rekonstruktion: beide Optiken sitzen auf derselben Gimbal und lösen zusammen aus, nur die Brennweite ist eine andere.
Die Handjustage wirkt erst nach dem Ausrichten. Die Regler sind ein Zuschlag auf die gefundene Lage — solange es keine gibt, sind sie ausgegraut, und unter ihnen steht, was fehlt. Reihenfolge also: Flug wählen → Ausrichten → justieren → Einfärben.
Die Handjustage wirkt live. Nach dem Ausrichten lädt das Programm die Bilder einmal stark verkleinert in den Speicher (255 Stück in gut drei Sekunden, rund 40 MB) und färbt damit eine Stichprobe von 50.000 Punkten. Jeder Zug an Gier, X oder Y färbt diese Stichprobe neu ein und legt sie über die Karte — ein Durchlauf dauert etwa 90 ms, die Wolke folgt dem Regler also ohne Verzögerung. In der Statuszeile stehen dabei Winkel, Versatz und wie viel Prozent der Stichprobe getroffen wurde. Beim Einfärben wird die eingestellte Lage übernommen und die Vorschau geräumt.
Während der Justage ist die volle Karte ausgeblendet und nur die Stichprobe zu sehen. Das ist Absicht: 50.000 Punkte sind bei einer Karte aus 24 Millionen zwei Promille — als Staub darüber gestreut wäre von einer Farbänderung nichts zu erkennen. Allein gezeigt ist die Stichprobe die ganze Ansicht, und jeder Reglerzug ist sofort sichtbar.
Der Haken „Während der Justage nur die Vorschau zeigen" schaltet das ab; dann liegen beide übereinander.
„Überlagern und justieren …" öffnet ein eigenes Fenster, in dem beide Wolken übereinander liegen — so wie in der Pipeline. Das Hauptfenster bleibt dabei unberührt.
| Ansicht | was zu sehen ist |
|---|---|
| Überlagerung | Karte in Grau (hell = hoch), die Fotopunkte des Fluges in Magenta, mit eigener Thermallage zusätzlich in Orange |
| Farbvorschau RGB | die Karte, eingefärbt aus den RGB-Bildern mit der aktuellen Lage |
| Farbvorschau Thermal | dasselbe aus den Thermalbildern, mit der Thermallage |
Navigation mit der Maus: Mausrad zoomt zum Mauszeiger hin, links ziehen dreht, rechts oder mittel ziehen (oder Umschalt + links) verschiebt, Doppelklick passt die ganze Karte ein. Dazu Blickrichtungen (oben, vorn, Seite, schräg), eine Punktgröße und oben links ein Maßstabsbalken in Metern. Beim Justieren bleibt die Ansicht stehen — wo man hingezoomt hat, sieht man die Wirkung des Reglers.
Gier, X und Y gibt es zweimal: eine Zeile für RGB, eine für Thermal. Alle wirken sofort. Unter dem Bild stehen Winkel, Versatz und — je nach Ansicht — der Abstand der Schwerpunkte oder die Trefferquote. Wer an einem Thermalregler dreht, bekommt die Thermal-Farbvorschau. Lage übernehmen schreibt beide Lagen zurück ins Hauptfenster, zurücksetzen stellt die Lage beim Öffnen wieder her. Ein Handzuschlag aus dem Hauptfenster wird beim Öffnen verrechnet, das Fenster setzt auf der Lage auf, die man gerade sieht.
Gezeichnet wird als Bild, nicht mit einem zweiten 3D-Fenster. Zwei OpenGL-Kontexte in einer Anwendung sind je nach Grafiktreiber und Sitzung eine Quelle schwarzer Fenster. Das Bild rechnet numpy mit Tiefenpuffer, ein Bild aus 400.000 Punkten kostet einige zehn Millisekunden — genug, damit Drehen und Zoomen der Maus folgen, und zuverlässig, geprüft sogar ganz ohne X-Server.
Die Bilder eines Mäanderfluges passen erst zueinander, wenn die Optik stimmt. Am DRZ-Flug (DJI M30T, 57 m) stimmte sie nicht:
- RGB-Brennweite ~11 % zu kurz. COLMAP hält die Optik bewusst fest (sonst wölbt sich die Rekonstruktion zur Kuppel) — aber mit dem Nennwert aus dem EXIF. Jedes Bild landet dadurch zu klein auf der Karte, am Rand um Meter und in jedem Bild in eine andere Richtung: die Bilder wirken zueinander verzerrt. Die Fotopunkte schweben aus demselben Grund knapp 4 m über der Lidar-Oberfläche.
- Thermal schielt, ist verzeichnet und hat eine andere Brennweite. Die Thermalkamera ist gegen die RGB-Kamera um rund 2° verdreht (2 m am Boden), ihr Objektiv hat eine kräftige Tonnenverzeichnung, und die Brennweite weicht vom EXIF ab. Bisher wurde mit der RGB-Pose, EXIF-Brennweite und ohne Verzeichnung gerechnet.
„Optik einmessen“ (läuft nach dem ersten Ausrichten von selbst, rund eine
Minute) misst das nacheinander ein, siehe core/optik.py:
- Höhe über den Laser-Entfernungsmesser der Drohne — jedes Bild trägt im XMP den Abstand zum Boden. Die Höhe muss zuerst feststehen: auf ebenem Boden lassen sich Brennweite und Flughöhe gegeneinander tauschen.
- RGB-Brennweite über die Farbkonsistenz: jeder Kartenpunkt wird in alle Bilder projiziert, die ihn sehen; stimmt die Brennweite, widersprechen sich die Bilder am wenigsten.
- Thermaloptik gegen das RGB-Bild desselben Auslösers — Brennweite, Hauptpunkt, Verzeichnung und Schielwinkel, über die Transinformation der Grauwerte. Geprüft an Bildpaaren, die nicht zum Einmessen dienten.
Das Ergebnis liegt in meander/optik_kalibrierung.json, die Maßstab-Regler
zeigen es, Einfärben und Vorschau benutzen es. ODM/WebODM wurde erwogen und
verworfen: die M30T ist dort nicht unterstützt, eine gekoppelte Verarbeitung von
Weitwinkel und Thermal gibt es nicht, und SfM auf reinen Thermalbildern scheitert
an texturarmen Dächern.
„Automatisch: ausrichten bis zur Farbe“ macht alles hintereinander, rund sechs Minuten: Ausrichten → Optik einmessen → Feinausrichten → Einfärben mit Sichtprüfung. Jeder Schritt gibt es auch als eigenen Knopf.
Feinausrichten (core/optik.py, feinausrichten) legt das Fotomodell auf
die Karte — mit den Maßen, die den jeweiligen Freiheitsgrad wirklich festlegen:
| Freiheitsgrad | woran gemessen | DRZ-Flug |
|---|---|---|
| Neigung, Höhe | Fotopunkte auf der Lidar-Oberfläche (Punkt-zu-Ebene, robust) | −0,04°/−0,18° |
| Versatz in der Ebene | Kantenmaß (Farbkanten gegen Höhenkanten), zwei Stichproben gemittelt | +0,25/+0,45 m |
| Maßstab | Brennweite aus „Optik einmessen“ | 1,086 |
| Gier | bleibt aus dem Ausrichten | — |
Gier und Blockmaßstab werden bewusst nicht automatisch gesucht: gemessen ist das Kantenmaß über ±0,5° Gier flach (zwei Stichproben fanden +0,15° und +0,45°), und ein Blockmaßstab tauscht gegen Brennweite und Höhe — er zog die Fotopunkte von der Oberfläche (50 % → 34 %). Übernommen wird eine Korrektur nur, wenn die Farbkonsistenz der Bilder dabei nicht schlechter wird. Eine neue Ausrichtung verwirft Feinausrichtung und Höhe und misst sie neu; Brennweite und Thermaloptik bleiben, die gehören zur Kamera.
Bisher bekam jeder Punkt die Farbe aus dem Bild, in dem er am nächsten zur Bildmitte lag. Von einer Wand sieht dieses Bild aber nichts — davor liegt das Dach. Das Dachmuster lief die Wände hinunter.
Mit „Beim Einfärben Sichtbarkeit prüfen“ (Standard, core/sichtbar.py):
- Je Kamera wird aus der Karte eine Tiefenkarte gerechnet; ein Punkt bekommt nur Farbe aus Bildern, in denen er nicht verdeckt ist.
- Unter diesen gewinnt das Bild, das am frontalsten auf seine Fläche blickt (Normale aus der Karte) — für Dächer die Kamera darüber, für Wände eine von der Seite.
Was keine Kamera sieht, bleibt ungefärbt: Unterholz, das Innere einer Halle, das der Lidar durch Tor und Oberlichter gescannt hat, eine zweite Dachschicht. Am DRZ-Flug rund 30 % der Punkte; von oben fehlt dadurch nichts (0,2 %). Mit „Nur eingefärbte Punkte“ sind sie ausgeblendet. Ein Auffüllen vom Nachbarn wurde ausprobiert und verworfen — es verteilte die Farbe weniger zufällig sichtbarer Punkte zu Klecksen. Die Einfärbung dauert etwa dreimal so lang; Live-Vorschau und Ausrichtfenster rechnen weiter ohne Sichtprüfung.
Jeder Versatz — Lage des Mäanderfluges (RGB und Thermal), Maßstab, Hauptpunkt der Optiken, Zusammenführen, Extrinsik — hat zwei Schieber: einen groben für den Weg und einen feinen für das letzte Stück (Meter bis auf den Zentimeter, Winkel bis 0,005°, Maßstab bis 0,01 %). Der Wert ist die Summe; das Feld daneben zeigt sie und nimmt einen getippten Wert an, „0“ setzt zurück.
Die Thermalbilder haben eigene Regler für Gier, X und Y — im Hauptfenster unter
Lage von Hand in der Zeile Thermal, im Ausrichtfenster ebenso. Sie sind
ein Zuschlag auf die RGB-Lage, keine zweite Lage daneben: beide Optiken
hängen an derselben Gimbal. Wird RGB neu ausgerichtet oder nachgezogen, zieht
Thermal mit, und in den Thermalreglern steht nur, was zwischen den Optiken
nicht passt. Der Wert bleibt im Projekt (meander/thermal_lage.json) und wird
beim Einfärben für die Thermalebene verwendet; ihre meta.json hält ihn fest.
Das ist der Weg, wenn die automatische Ausrichtung danebenliegt: erst in der Überlagerung grob schieben, bis Magenta auf Grau liegt, dann in der Farbvorschau feinjustieren.
In der Vorschau bedeutet Grau: von keinem Bild getroffen, und Magenta sind die Kamerastandorte des Fluges. Sieht man nur Grau, beantwortet ein Blick auf die magentafarbenen Punkte die erste Frage sofort — liegen sie weit neben der Wolke, deckt der Mäanderflug dieses Gebiet nicht ab; liegen sie darüber, stimmt die Ausrichtung nicht. Unter 5 % Trefferquote schreibt das Protokoll beides mit Zahlen hin: Abstand der Kameras zur Wolkenmitte gegen die Ausdehnung der Wolke.
Die Vorschau erscheint erst beim ersten Zug an einem Regler, nicht schon nach dem Ausrichten — wer nichts justiert, soll seine Karte sehen. Und sie verschwindet wieder bei jedem Fehlschlag, jedem Abbruch, jedem Wechsel der Farbquelle und nach dem Einfärben. Eine ausgeblendete Karte bleibt nie zurück.
Die Regler sind ein Zuschlag auf die gefundene Lage, nicht die Lage selbst — sonst würde jeder Zug auf dem vorigen aufbauen und man käme nie zurück. X, Y und Z sind Meter; der grobe Schieber geht in Dezimetern, der feine in Zentimetern. Beim DRZ-Datensatz deckt ein RGB-Pixel rund 5 cm Boden ab — der feine Schieber bewegt also um Bruchteile eines Pixels. Die Maßstab-Regler sind kein Zuschlag, sondern der Wert selbst; sie bleiben im Projekt gespeichert.
Die beiden Kästen RGB-Optik und Thermal-Optik verschieben den Bildhauptpunkt in Pixeln. Das wirkt wie eine Verkippung der Kamera gegen die Achse, die COLMAP angenommen hat, und die Verschiebung am Boden wächst mit dem Abstand — anders als die Regler für Gier, X und Y darüber, die starr schieben. Getrennt je Optik, weil es zwei Objektive sind. Bewusst ohne Automatik: eine Kennzahl dafür ist nicht zu finden, ein sonnenwarmes Dach ist thermisch gleichmäßig und optisch strukturiert, ein Schatten umgekehrt.
Drei Einfärbungen liegen nebeneinander im Projekt und lassen sich unter Ansicht → Farbquelle oder in der Seitenleiste sofort umschalten:
| Quelle | woher |
|---|---|
| Onboard RGB | 360°-Kamera an der Super-Drohne, colors/ |
| Mäander RGB | _V.JPG des DJI-Fluges, colors_meander_rgb/ |
| Mäander Thermal | _T.JPG desselben Fluges, colors_meander_thermal/ |
Nach dem Einfärben einer zusammengeführten Karte steht im Protokoll die Quote je Abschnitt, nicht nur eine Gesamtzahl — sonst merkt man nicht, wenn ein ganzer Flug leer geblieben ist. Bleibt alles leer, löst das Programm „Nur eingefärbte Punkte" von selbst, weil die Ansicht sonst komplett verschwindet.
Angeboten wird nur, was berechnet ist. Der Export schreibt die angezeigte Ebene.
Jeder Flug bekommt von FAST-LIO ein eigenes Weltsystem, verankert im ersten Scan. Zwei Karten liegen darum beliebig zueinander, auch wenn sie dasselbe Gebäude zeigen. Der Ablauf in der Sidebar:
- Zweiten Flug wählen — dessen Karte muss berechnet sein; ist sie es nicht, wird mit der zu erwartenden Dauer gefragt und FAST-LIO läuft direkt hier. Die zweite Wolke erscheint orange im Viewer.
- Auto-Ausrichten — globale Suche (FGR über FPFH) plus ICP von grob nach fein. Dauert Sekunden bis Minuten. Nur ICP verfeinert stattdessen die aktuelle Lage, was nach einer Handjustage reicht.
- X/Y/Z/Gier schieben und drehen die zweite Wolke von Hand, mit sofortiger Vorschau. Gedreht wird um ihren eigenen Schwerpunkt.
Die zweite Wolke ist orange und halbdurchsichtig dargestellt. Orange heißt: Vorschau, noch nicht übernommen. Sie gehört erst nach Übernehmen zur Karte, und bis dahin ändert kein anderer Schritt etwas an ihr — färbst du in diesem Zustand ein, wird nur der offene Flug eingefärbt, und das Programm fragt vorher nach. Über Ansicht → Zweiten Flug anzeigen lässt sie sich ausblenden, ohne sie zu verwerfen. 4. Übernehmen schreibt eine gemeinsame Aufzeichnung und öffnet sie als Arbeitswolke. Sie lässt sich danach als Ganzes einfärben und exportieren; jeder Abschnitt wird mit der Kamera seines eigenen Bags eingefärbt.
Nach dem Ausrichten stehen Trefferquote und Restfehler im Protokoll. Unter 0,3 Trefferquote überlappen die Wolken zu wenig — dann von Hand grob zusammenschieben und „Nur ICP" nachlaufen lassen. Ein Restfehler über 0,3 m heißt: die Lage stimmt grob, sitzt aber nicht sauber.
Ein zusammengeführtes Projekt hat keinen einzelnen Bagpfad, unter dem man es
wiederfände — sein Schlüssel ist ein erfundenes „A+B". Es lässt sich deshalb nur
über Datei → Berechnetes Projekt öffnen … (Strg+Umschalt+P) wieder öffnen;
die Liste zeigt alle Projekte des Caches und markiert die zusammengeführten.
Beim Laden liest das Programm die Abschnitte aus der meta.json der
Aufzeichnung, nicht aus dem Sitzungsgedächtnis. Nur so färbt jeder Abschnitt aus
der Kamera seines eigenen Bags — sonst bliebe der zweite Flug ungefärbt, weil es
in den Bildern des ersten keine Frames in seinem Zeitfenster gibt.
Grenzen: das 360°-Video und die GPS-Prüfung zeigen weiter den zeitlich ersten Flug. Zeitlich überlappende Aufnahmen werden abgelehnt, weil die Scan-Reihenfolge dann nicht mehr eindeutig wäre.
FAST-LIO richtet sein Weltsystem an der Sensorlage des ersten Scans aus, nicht an der Schwerkraft. Steht der Livox schräg auf der Drohne, kippt die ganze Karte mit. Seit dem 08.09.2026 ist er rund 40° gekippt montiert (gemessen 40,1° / 39,7° / 41,5°; davor durchgehend 0,3°–5,6°).
Die GUI misst die Lotrechte deshalb aus dem IMU-Ruhefenster am Bag-Anfang und dreht die Karte beim Laden gerade — aber erst ab 10° Schräglage, damit die sauber montierten Flüge unverändert bleiben. Im Protokoll steht dann eine Zeile wie „Karte lotrecht gedreht: Livox war 40.1° schräg montiert". Gedreht wird nur das Weltsystem, Einfärbung und Farb-Cache sind davon nicht betroffen.
Die Double-Sphere-Kalibrierungen liegen als Kopie in calib/
(calib_result_new2.json, calib_new_vign.json, calib_new_refined.json),
damit das Repo ohne das Stitcher-Projekt lauffähig ist. Gefunden wird die
erste existierende Datei der Kandidatenliste; danach folgen die Originale in
Super360_Stitcher_rosbag/work/ als Fallback.
Vor jeder Einfärbung wird die gespeicherte Kamera-Extrinsik geprüft (3–6 s): ein kurzer Hillclimb startet dort und schaut, ob sie auf einem Gipfel der Foto-Konsistenz sitzt. Die Güte steht danach im Protokoll, zusammen mit dem besten erreichbaren Wert und dem Abstand dorthin.
Das ist nötig, weil der absolute Wert zwischen Flügen nicht vergleichbar ist: bei
rosbag_2026-07-17_13-16-18_Flug0 stand 0,71 gespeichert und sah unauffällig aus,
während 0,84 möglich waren — die Extrinsik war 15,7° verdreht und kostete 26 %
Farbqualität. Erst ab 5° Abstand und 0,08 Vorsprung wird gewarnt; darunter lohnt
der Abbruch nicht (bei 2,5° sind es 3 %).
Genauer als das braucht die Kalibrierung nicht zu sein. Unterhalb von etwa 0,5° ändert eine Verschiebung die Farbqualität nur noch um Bruchteile eines Prozents, und der Hebelarm zwischen Kamera und Lidar ist bei diesem Aufbau messbar null.
Je Scan werden bis zu K zeitnächste Kamera-Frames plus zwei Konsens-Frames aus
±0,8 s gesampelt; je Punkt gewinnt der Farb-Median. Dazu kommen zwei Filter gegen
den Himmel, denn der Himmel liefert keine Lidar-Punkte — jede Farbe von dort ist
ein Fehlgriff:
- Himmelssaum (Standard 4 px) sperrt den Rand um ausgebrannte Flächen. Reines Weiß fängt „Helligkeit max" schon ab; was Baumkronen weiß überzieht, ist der Saum daneben, wo Unschärfe und Farbsaum Himmel und Blattwerk zu Grauweiß mischen. Der Wert steht in der Sidebar, 0 schaltet die Sperre ab.
- Vorrang für echte Oberflächen: hat ein Punkt neben hellen, flauen Proben auch eine normale, bestimmen nur die normalen den Median. Punkte, für die es nur helle flaue Proben gibt (weiße Wand), bleiben unberührt.
Was das nicht repariert: die 360°-Kamera belichtet im Gegenlicht die ganze Szene über, nicht nur den Himmel. Kronen bleiben dadurch blasser als in Wirklichkeit.
Datei → Projekt exportieren … (Strg+Umschalt+E) kopiert alles Berechnete in
einen Ordner, den du weiterreichen kannst. Der Dialog zeigt je Teil die Größe,
weil der Unterschied zwischen mit und ohne Rosbag schnell 24 GB ausmacht:
<ziel>/
super360.json Manifest: was drin ist, woher es kommt, Kennzahlen
projekt/ recording/, colors*/, pano_*/, meander/, gps/extrinsic/settings
bags/ nur wenn angehakt
kalibrierung/ die verwendete calibration.json
Die Punktwolke ist immer dabei, ohne sie gibt es kein Projekt. Das Rosbag ist per Vorgabe nicht dabei — es ist der Eingang, nicht das Ergebnis. Ohne Bag bleiben Karte, Farben, Messen, Höhenschnitt und Export erhalten; das 360°-Video und ein erneutes Einfärben brauchen es.
Datei → Projektordner öffnen … (Strg+I) öffnet so einen Ordner an Ort
und Stelle — ohne Kopie in den Cache und ohne Rückfrage. Gearbeitet wird im
Ordner selbst, jede Änderung landet sofort dort: Einstellungen, Ausrichtung,
Handzuschlag, Optik, Einfärbungen. Mitgenommene Bags werden aus dem Ordner
benutzt, die Bagpfade in der meta.json darauf gezogen (auch auf einem anderen
Rechner, gesucht wird über den Ordnernamen). Fehlt ein Bag, sagt das Protokoll
welches, und das Projekt öffnet trotzdem — nur eben ohne die Schritte, die es
braucht.
Ein Zielordner, der nicht leer ist und kein Projekt enthält, wird abgelehnt statt zugeschüttet.
Der Cache liegt außerhalb des Repos, per Default unter
/home/lena/RosBagSuper_Gui/rosbag_suite/cache. Ein anderer Ort geht über
die Umgebungsvariable SUPER360_CACHE_ROOT.
<cache_root>/<bagname>-<pfad-hash>/ enthält recording/ (Punkte/Posen),
colors/, pano_<Breite>/ (gestitchte JPEGs), extrinsic.json,
settings.json. Löschen ist jederzeit erlaubt (wird neu berechnet).
Ein fehlgeschlagener/abgebrochener FAST-LIO-Lauf lässt eine vorhandene
Aufzeichnung unangetastet (Schreiben in recording.tmp, Promotion nur bei
Erfolg).
- GPS in den Juli-Bags ist tot (fix_type=0, 0 Satelliten) — die GUI zeigt das als „GPS unbrauchbar" mit Gründen; Georeferenzierung ist dann deaktiviert.
- Kamera↔Lidar-Extrinsik ist nicht werksseitig kalibriert; die Auto-Kalibrierung ist grob (Rotation, ±wenige Grad) — Feinjustage über die Spinboxen, Ergebnis wird pro Bag gespeichert.
- Colorization hat keine Occlusion-Behandlung; bewegte Objekte können Farbschlieren bekommen.
- Der obere Polbereich (~5 %) des Panos ist physikalisch von keiner Linse abgedeckt (Sensor beschneidet die Fisheye-Kreise).
- Beim Zusammenführen wird nur eine starre Transformation gesucht. Driftet eine der beiden LIO-Karten in sich, lässt sich das damit nicht geradebiegen.
Siehe ARCHITECTURE.md (Module, Datenformate, Konventionen). Kern Qt-frei
(core/), UI in ui/, FAST-LIO-Recorder in scripts/record_fastlio.py.
