Migrate to radians instead of degrees to lessen conversion errors

This commit is contained in:
Kilian Hofmann 2022-09-23 00:16:52 +02:00
parent 07487e9e51
commit 115e4d9265
8 changed files with 94 additions and 53 deletions

View File

@ -6,6 +6,17 @@ namespace file
{ {
namespace simdata namespace simdata
{ {
Gate::Gate(std::string designator,
double latitude,
double longitude,
std::uint8_t radius)
{
this->designator = designator;
this->center = {geodata::toRadians(latitude),
geodata::toRadians(longitude)};
this->radius = radius;
}
Gate::Gate(std::string designator, Gate::Gate(std::string designator,
struct geodata::point center, struct geodata::point center,
std::uint8_t radius) std::uint8_t radius)

View File

@ -21,11 +21,9 @@ namespace file
{ {
/* /*
* Representation of gate * Representation of gate
* Heading in degrees (0...360) * Center in lat/lon radians
* Radius in metres * Radius in metres
* *
* Designator must be null terminated
*
* UINT8 | CHAR[] | POINT | UINT8 * UINT8 | CHAR[] | POINT | UINT8
* -------+------------+--------+------- * -------+------------+--------+-------
* STRLEN | DESIGNATOR | CENTER | RADIUS * STRLEN | DESIGNATOR | CENTER | RADIUS
@ -38,6 +36,12 @@ namespace file
std::uint8_t radius; std::uint8_t radius;
public: public:
// From X-Plane or MakeRwys
Gate(std::string designator,
double latitude,
double longitude,
std::uint8_t radius);
// From Database
Gate(std::string designator, Gate(std::string designator,
struct geodata::point center, struct geodata::point center,
std::uint8_t radius); std::uint8_t radius);
@ -48,8 +52,9 @@ namespace file
inline const std::string to_string() const inline const std::string to_string() const
{ {
std::ostringstream str; std::ostringstream str;
str << "Gate " << this->designator << " at " << this->center.latitude str << "Gate " << this->designator << " at "
<< "N " << this->center.longitude << "E, Radius " << geodata::toDegrees(this->center.latitude) << "N "
<< geodata::toDegrees(this->center.longitude) << "E, Radius "
<< (int)this->radius; << (int)this->radius;
return str.str(); return str.str();
} }

View File

@ -21,24 +21,22 @@ namespace file
{ {
/* /*
* Representation of one runway with supplementary information * Representation of one runway with supplementary information
* Heading in degrees (0...360) true * Heading in radians true
* Threshold center in lat/lon radians
* Width and length in meters * Width and length in meters
* *
* Designator must be null terminated * UINT8 | CHAR[] | POINT | UINT8 | UINT16 | DOUBLE
*
* UINT8 | CHAR[] | BOX | UINT8 | UINT16 | UINT16
* -------+------------+--------+-------+--------+------- * -------+------------+--------+-------+--------+-------
* STRLEN | DESIGNATOR | BOUNDS | WIDTH | LENGTH | TRUHDG * STRLEN | DESIGNATOR | CENTER | WIDTH | LENGTH | TRUHDG
*/ */
class Runway class Runway
{ {
private: private:
std::string designator; std::string designator;
struct geodata::box bounds; struct geodata::point center;
std::uint8_t width; std::uint8_t width;
std::uint16_t length; std::uint16_t length;
std::uint16_t trueHeading; double trueHeading;
std::vector<std::uint8_t> file;
public: public:
// From X-Plane or MakeRwys // From X-Plane or MakeRwys
@ -50,27 +48,22 @@ namespace file
double width); double width);
// From database // From database
Runway(std::string designator, Runway(std::string designator,
struct geodata::box bounds, struct geodata::point center,
std::uint8_t width, std::uint8_t width,
std::uint16_t length, std::uint16_t length,
std::uint16_t trueHeading); double trueHeading);
void toFile(std::ofstream &out) const; void toFile(std::ofstream &out) const;
inline const std::string to_string() const inline const std::string to_string() const
{ {
std::ostringstream str; std::ostringstream str;
str << "Runway " << this->designator << " with bounds " str << "Runway " << this->designator << " with threshold center "
<< this->bounds.topLeft.latitude << "N " << geodata::toDegrees(this->center.latitude) << "N "
<< this->bounds.topLeft.longitude << "E, " << geodata::toDegrees(this->center.longitude) << "E, Width "
<< this->bounds.topRight.latitude << "N " << (int)this->width << "m, Length " << this->length
<< this->bounds.topRight.longitude << "E, " << "m, True Heading " << geodata::toDegrees(this->trueHeading)
<< this->bounds.bottomRight.latitude << "N " << "°";
<< this->bounds.bottomRight.longitude << "E, "
<< this->bounds.bottomLeft.latitude << "N "
<< this->bounds.bottomLeft.longitude << "E, "
<< "Width " << (int)this->width << "m, Length " << this->length
<< "m, True Heading " << this->trueHeading << "°";
return str.str(); return str.str();
} }

View File

@ -19,25 +19,22 @@ namespace file
longitudeStart, longitudeStart,
latitudeEnd, latitudeEnd,
longitudeEnd); longitudeEnd);
this->trueHeading = this->trueHeading = geodata::bearingDR(latitudeStart,
(std::uint16_t)std::round(geodata::bearingDD(latitudeStart,
longitudeStart, longitudeStart,
latitudeEnd, latitudeEnd,
longitudeEnd)); longitudeEnd);
this->bounds = geodata::calculateBoxDD({latitudeStart, longitudeStart}, this->center = {geodata::toRadians(latitudeStart),
{latitudeEnd, longitudeEnd}, geodata::toRadians(longitudeStart)};
this->trueHeading,
this->width);
} }
Runway::Runway(std::string designator, Runway::Runway(std::string designator,
geodata::box bounds, geodata::point center,
std::uint8_t width, std::uint8_t width,
std::uint16_t length, std::uint16_t length,
std::uint16_t trueHeading) double trueHeading)
{ {
this->designator = designator; this->designator = designator;
this->bounds = bounds; this->center = center;
this->width = width; this->width = width;
this->length = length; this->length = length;
this->trueHeading = trueHeading; this->trueHeading = trueHeading;
@ -46,7 +43,7 @@ namespace file
void Runway::toFile(std::ofstream &out) const void Runway::toFile(std::ofstream &out) const
{ {
writeString(out, this->designator); writeString(out, this->designator);
write<decltype(this->bounds)>(out, this->bounds); write<decltype(this->center)>(out, this->center);
write<decltype(this->width)>(out, this->width); write<decltype(this->width)>(out, this->width);
write<decltype(this->length)>(out, this->length); write<decltype(this->length)>(out, this->length);
write<decltype(this->trueHeading)>(out, this->trueHeading); write<decltype(this->trueHeading)>(out, this->trueHeading);

View File

@ -25,6 +25,8 @@ namespace file
toLog("Sim Database updated"); toLog("Sim Database updated");
} else { } else {
this->fromFile(); this->fromFile();
toLog("Sim Database loaded");
} }
} }
@ -65,14 +67,14 @@ namespace file
std::uint8_t numRunways = read<std::uint8_t>(in); std::uint8_t numRunways = read<std::uint8_t>(in);
for (int j = 0; j < numRunways; j++) { for (int j = 0; j < numRunways; j++) {
std::string designator = readString(in); std::string designator = readString(in);
// Bounds // Center
struct geodata::box bounds = read<struct geodata::box>(in); struct geodata::point center = read<struct geodata::point>(in);
std::uint8_t width = read<std::uint8_t>(in); std::uint8_t width = read<std::uint8_t>(in);
std::uint16_t length = read<std::uint16_t>(in); std::uint16_t length = read<std::uint16_t>(in);
std::uint16_t trueHeading = read<std::uint16_t>(in); double trueHeading = read<double>(in);
this->airports[icao].second.emplace_back(designator, this->airports[icao].second.emplace_back(designator,
bounds, center,
width, width,
length, length,
trueHeading); trueHeading);

View File

@ -153,10 +153,10 @@ namespace file
} }
gateName += fields.back(); gateName += fields.back();
gateName = std::regex_replace(gateName, std::regex{","}, "0"); gateName = std::regex_replace(gateName, std::regex{","}, "0");
struct geodata::point pt { gates.emplace_back(gateName,
std::stod(fields[1]), std::stod(fields[2]) std::stod(fields[1]),
}; std::stod(fields[2]),
gates.emplace_back(gateName, pt, 40); 40);
} }
void makeRunway(std::vector<Runway> &runways, void makeRunway(std::vector<Runway> &runways,
@ -186,10 +186,10 @@ namespace file
gateName += fields.back(); gateName += fields.back();
gateName = std::regex_replace(gateName, std::regex{","}, "0"); gateName = std::regex_replace(gateName, std::regex{","}, "0");
struct geodata::point pt { gates.emplace_back(gateName,
std::stod(fields[1]), std::stod(fields[2]) std::stod(fields[1]),
}; std::stod(fields[2]),
gates.emplace_back(gateName, pt, 40); 40);
} }
} // namespace simdata } // namespace simdata
} // namespace file } // namespace file

View File

@ -41,11 +41,16 @@ namespace geodata
static inline double toRadians(double value) { return value * M_PI / 180; } static inline double toRadians(double value) { return value * M_PI / 180; }
static inline double normalize(double value) static inline double normalizeD(double value)
{ {
return fmod(value + 360, 360); return fmod(value + 360, 360);
} }
static inline double normalizeR(double value)
{
return value < 0 ? 2 * M_PI + value : value;
}
// Input and Output in degrees // Input and Output in degrees
static inline double bearingDD(double fromLatitude, static inline double bearingDD(double fromLatitude,
double fromLongitude, double fromLongitude,
@ -58,7 +63,22 @@ namespace geodata
sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) * sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) *
cos(toRadians(toLongitude) - toRadians(fromLongitude)); cos(toRadians(toLongitude) - toRadians(fromLongitude));
return normalize(toDegrees(atan2(y, x))); return normalizeD(toDegrees(atan2(y, x)));
}
// Input in degrees, Output in radians
static inline double bearingDR(double fromLatitude,
double fromLongitude,
double toLatitude,
double toLongitude)
{
double y = sin(toRadians(toLongitude) - toRadians(fromLongitude)) *
cos(toRadians(toLatitude));
double x = cos(toRadians(fromLatitude)) * sin(toRadians(toLatitude)) -
sin(toRadians(fromLatitude)) * cos(toRadians(toLatitude)) *
cos(toRadians(toLongitude) - toRadians(fromLongitude));
return normalizeR(atan2(y, x));
} }
// Input in degrees, Output in metres // Input in degrees, Output in metres

View File

@ -130,6 +130,19 @@ PLUGIN_API int XPluginStart(char *outName, char *outSig, char *outDesc)
toLog); toLog);
} }
toLog("Readback test of sim database using EDDF");
auto ap = (*database)["EDDF"];
for (const auto &it : ap.first) {
toLog(" " + it.to_string());
}
for (const auto &it : ap.second) {
toLog(" " + it.to_string());
}
toLog("Readback test of sim database using XXXX");
auto ap2 = (*database)["XXXX"];
ap2.first.size() == 0 ? toLog(" SUCCESS") : toLog(" ERROR");
// Thread for sending data to websocket // Thread for sending data to websocket
serverThread = std::thread(&serverWorker); serverThread = std::thread(&serverWorker);
recordingThread = std::thread(&recordingWorker); recordingThread = std::thread(&recordingWorker);