Erdkoordinaten weiterverarbeiten/berechnen (Flugzeug)
-
Hallo,
ich verwende für meinen Cockpitsimulator Koordinaten innerhalb Europas bisher nach den Orthodromen-Berechnung. Dazu verwende ich folgenden Code mit C++:DistAndGrad FMC::GetDistAndGrad(double von_lat, double von_lon, double nach_lat, double nach_lon) { int winkelInt; //Orthodrome double cos_von_lat = cos(von_lat * PI / 180.0); double sin_von_lat = sin(von_lat * PI / 180.0); double cos_nach_lat = cos(nach_lat * PI / 180.0); double sin_nach_lat = sin(nach_lat * PI / 180.0); double diff_lon = nach_lon - von_lon; double diff_lon_cos = cos(diff_lon * PI / 180.0); double sin1 = sin_von_lat * sin_nach_lat; double cos1 = cos_von_lat * cos_nach_lat * diff_lon_cos; double winkel1 = sin1 + cos1; double winkel2 = acos(winkel1); double winkel3 = winkel2 * 180.0 / PI; double coswinkel = cos(winkel3 * PI / 180.0); double sinwinkel = sin(winkel3 * PI / 180.0); double alpha_oben1 = sin_von_lat * coswinkel; double alpha_oben2 = sin_nach_lat - alpha_oben1; double alpha_unten = cos_von_lat * sinwinkel; double alpha_gesamt = acos(alpha_oben2 / alpha_unten); double alpha = alpha_gesamt * 180.0 / PI; int winkelInt1 = (int)round(alpha); if (von_lon > nach_lon) { winkelInt = 360 - winkelInt1; } else { winkelInt = winkelInt1; } double distance_km = winkel3 * 6371.0 * PI; distance_km /= 180.0; double distance_nm = distance_km / 1.852; return DistAndGrad(winkelInt, distance_nm); }
Die Klasse DistAndGrad dient lediglich dazu, den berechneten Winkel in Grad und die Entfernung in NM quasi gleichzeitig zu speichern und um einzeln weiterverarbeit werden zu können. So weit so gut. Dann gibt es eine Liste mit sogenannten Wegpunkten, die besagen wo das Flugzeug später entlangfliegen soll. Ein Beispiel sind folgende Wegpunkte, die von oben nach unten durchlaufen werden sollen:
NORKU,52.215556,6.976389,ED SONSA,52.330895,6.745586,EH ROBIS,52.468611,6.467222,EH OSKUR,52.490456,6.024022,EH
Diese werden aus einer Datei als double ausgelesen. NORKU wäre also der Name, 52... die Latitude und 6..... die Longitude und ED ist ein Kürzel welches aber hier nicht von belang ist. Wenn ich in meinem Cockpit das Navigation Display auf PLN schalte (ok, das ist jetzt fachchinesisch ), soll der ausgewählte Wegpunkt (im Problemfall ROBIS) in der Mitte zu sehen sein und zum vorhergehenden (SONSA) als auch nachfolgenden Wegpunkt (OSKUR) per Linie verbunden werden.
Kurz gesagt: eine Linie von SONSA nach ROBIS und eine Linie von ROBIS nach OSKUR. Stattdessen verbindet das Programm aber ROBIS mit einer zusäztlichen Linie abweichend in Richtung von OSKUR.
Wenn ich ROBIS testweise ausfallen lasse, stimmt alles, bis auf die fehlende Koordinate ROBIS. Wenn ich die Koordinaten von ROBIS bspw. auf 52.4 und 6.4 setze, wird alles richtig angezeigt, allerdings ist die Koordinate nicht so genau wie gewollt.Das Auslesen der Daten habe ich mit zwei Varianten getestet, bringt aber das gleiche Verhalten. Warum funktioniert das nicht so wie ich will? Es gibt andere Beispiele, die teilweise noch wildere Linien erzeugen (geschätzt 5 Linien vom Mittelpunkt). Die Zahl ist aber m.E. das Problem (double).
Fast vergessen:
C++, VisualStudio und Qt mit Widgets (letzteres zeigt das Navigation Display an).
-
Das ist eine Menge Text, nur um zu sagen, dass der Fehler an völlig anderer Stelle liegt. Was soll deine Abstandsrechnung damit zu tun haben, welche Linien irgendwoanders verbunden werden?
-
Die Frage ist, wie zeichnest du die Linien?
Ich nehme mal an, daß die Koordinaten in der Liste stimmen, d.h. korrekt eingelesen werden. Wie berechnest du aus denDistAndGrad
-Werten dann die 2D-Punkte für die Projektion?Vllt. kannst du auch mal einen Screenshot davon machen (und z.B. auf imgur.com hochladen)?
Auf der Wiki-Seite Orthodrome ist ja auch ein Beispiel: berechnet deine Funktion dieselben Werte für "Berlin – Tokio"?
-
@SeppJ sagte in Erdkoordinaten weiterverarbeiten/berechnen (Flugzeug):
Hast du schon einmal von der Haversineformel gehört?
Nein
@Th69
Code zu den Linien:auto itplnbegin = std::next(itbegin, fmc->GetInactiveWptLength()); for (itpln = itplnbegin; itpln != fmc->route.end(); ++itpln) { if (fmc->GetStepLast() >= 1) { if (itpln->name == itplnbegin->name) //==act Wpt ==1 { if (itpln->lat == lat_center && itpln->lon == lon_center) { newX = 200; newY = 200; } else { dagpln = fmc->GetDistAndGrad(lat_center, lon_center, itpln->lat, itpln->lon); int diffX = GetNewX(dagpln.GetWinkel(), dagpln.GetDistance(), drawfactorcopy); int diffY = GetNewY(dagpln.GetWinkel(), dagpln.GetDistance(), drawfactorcopy); newX = 200 + diffX; newY = 200 - diffY; } if (fmc->GetRouteExec()) { painter.setPen(MyColor::magenta); } else { painter.setPen(MyColor::white); } WptStar(newX, newY); painter.drawPolygon(poly); painter.setFont(arial12); int tx = newX + 10; painter.drawText(QRectF(tx, newY, 50, 15), itpln->name, QTextOption(Qt::AlignLeft)); lastX = newX; lastY = newY; } else if (itpln->lat == lat_center && itpln->lon == lon_center) //==stepactual wpt, aber nicht act wpt { newX = 200; newY = 200; painter.setPen(MyColor::white); WptStar(newX, newY); painter.drawPolygon(poly); painter.setFont(arial12); int tx = newX + 10; painter.drawText(QRectF(tx, newY, 50, 15), itpln->name, QTextOption(Qt::AlignLeft)); auto itprev = std::prev(itpln); if (itprev->typ != "Disc") { if (fmc->GetRouteExec()) { painter.setPen(MyColor::magenta); } else { painter.setPen(MyColor::cyan); } painter.drawLine(lastX, lastY, newX, newY); } lastX = newX; lastY = newY; } else if (itpln->typ != "Disc") //normaler wpt { dagpln = fmc->GetDistAndGrad(lat_center, lon_center, itpln->lat, itpln->lon); int diffX = GetNewX(dagpln.GetWinkel(), dagpln.GetDistance(), drawfactorcopy); int diffY = GetNewY(dagpln.GetWinkel(), dagpln.GetDistance(), drawfactorcopy); newX = 200 + diffX; newY = 200 - diffY; painter.setPen(MyColor::white); WptStar(newX, newY); painter.drawPolygon(poly); painter.setFont(arial12); int tx = newX + 10; painter.drawText(QRectF(tx, newY, 50, 15), itpln->name, QTextOption(Qt::AlignLeft)); auto itprev = std::prev(itpln); if (itprev->typ != "Disc") { if (fmc->GetRouteExec()) { painter.setPen(MyColor::magenta); } else { painter.setPen(MyColor::cyan); } painter.drawLine(lastX, lastY, newX, newY); } lastX = newX; lastY = newY; } } }
Der Iterator itpln ist in der Header-Datei deklariert:
private: std::vector<Routemember>::iterator itpln;
X=200, Y=200 ist der Mittelpunkt im Widget.
latcenter, loncenter ist der zuvor festgelegte Mittelpunkt in double.
Der WptStar(newX, newY) erzeugt ein Polygon für den Wegpunkt. Das funktioniert tadellos.
-
@stefanpc81 sagte in Erdkoordinaten weiterverarbeiten/berechnen (Flugzeug):
Kurz gesagt: eine Linie von SONSA nach ROBIS und eine Linie von ROBIS nach OSKUR. Stattdessen verbindet das Programm aber ROBIS mit einer zusäztlichen Linie abweichend in Richtung von OSKUR.
WIe verhält sich dein Programm wenn du z.B. die folgenden Wegpunkte hast?
NORKU,52.215556,6.976389,ED SONSA,52.330895,6.745586,EH ROBIS,52.468611,6.467222,EH OSKUR,52.490456,6.024022,EH DEBUG,52.5123,5.580822,EH
PS:
Warum steht bei dem ersten Punkt ein ED und bei den anderen Punkten EH?
-
Ich habe das Problem zum Glück selbst gefunden. In meiner Funktion zur Errechnung des X-Wertes war ein Fehler. Wen es interessiert:
Alter Codeint ND::GetNewX(int winkel1, double distance1, int factor1) { double coswinkel = cos(winkel1 * PI / 180); double tanwinkel = tan(winkel1 * PI / 180); double get_yX = coswinkel * distance1 * 300; // [px] get_yX /= factor1; int draw_max_y = (int)round(get_yX); double get_x = tanwinkel * draw_max_y; // [px] int draw_x = (int)round(get_x); return draw_x; }
Neuer Code:
int ND::GetNewX(int winkel1, double distance1, int factor1) { double coswinkel = cos(winkel1 * PI / 180); double tanwinkel = tan(winkel1 * PI / 180); double get_yX = coswinkel * distance1 * 300; // [px] get_yX /= factor1; double get_x = tanwinkel * get_yX; // [px] int draw_x = (int)round(get_x); return draw_x; }
Außerdem habe ich vom ersten Code den unteren Abschnitt geändert, damit Koordinaten im negativen Bereich (westliche Halbkugel de Erde) auch richtig dargestellt werden.
double distance_km = winkel3 * 6371.0 * PI; distance_km /= 333.36; //== /(geteilt durch) 180.0 und 1.852 if (distance_km < 0) { distance_km *= -1; } double distance_nm = distance_km; return DistAndGrad(winkelInt, distance_nm);
Vielen Dank für eure Bemühungen!
-
PS:
Warum steht bei dem ersten Punkt ein ED und bei den anderen Punkten EH?Das ist ein Länderkürzel in der Luftfahrt. ED ist Deutschland, EH Holland, LO Österreich etc.
-
@stefanpc81 sagte in Erdkoordinaten weiterverarbeiten/berechnen (Flugzeug):
Das ist ein Länderkürzel in der Luftfahrt. ED ist Deutschland, EH Holland, LO Österreich etc.
Danke für die Info.
Ich hatte schon die Befürchtung es könne sich um eine spezielle Winkelangabe handeln.
Viele GNSS / GPS Systeme liefern nämlich den Breitengrad / Längengrad bezogen auf Nord / Süd bzw. West Ost. Da steht da z.B.
...,52.468611,N,6.467222,E,...