FERS 1.0.0
The Flexible Extensible Radar Simulator
Loading...
Searching...
No Matches
serial::KmlGenerator Class Reference

Generates KML files from FERS simulation scenarios for geographical visualization. More...

#include "kml_generator.h"

Static Public Member Functions

static bool generateKml (const core::World &world, const std::string &outputKmlPath)
 Generates a KML file from a pre-built simulation world.
 

Detailed Description

Generates KML files from FERS simulation scenarios for geographical visualization.

This class generates KML files for geographical visualization of FERS scenarios. It interprets the simulation coordinates based on the user-specified coordinate system in the XML file, which can be one of:

  • ENU (East-North-Up): Default. Local Cartesian coordinates (x, y, z) are treated as meters in an ENU tangent plane centered at a geodetic <origin>.
  • UTM (Universal Transverse Mercator): Coordinates (x, y, z) are treated as easting (m), northing (m), and altitude (m) within a specified UTM zone and hemisphere.
  • ECEF (Earth-Centered, Earth-Fixed): Coordinates (x, y, z) are treated as geocentric X, Y, Z values in meters.

All input coordinates are converted to WGS84 geodetic coordinates (latitude, longitude, altitude) for the final KML output. The KML is written with <altitudeMode>absolute</altitudeMode>, where altitude is relative to Mean Sea Level (MSL).

Definition at line 46 of file kml_generator.h.

Member Function Documentation

◆ generateKml()

bool serial::KmlGenerator::generateKml ( const core::World world,
const std::string &  outputKmlPath 
)
static

Generates a KML file from a pre-built simulation world.

Parameters
worldThe simulation world containing all objects and paths.
outputKmlPathThe path for the output KML file.
Returns
True on success, false on failure.

Definition at line 654 of file kml_generator.cpp.

655 {
656 try
657 {
658 // Setup coordinate conversion based on global parameters
659 ConverterFunc converter;
660 double reference_latitude, reference_longitude, reference_altitude;
661
662 switch (params::coordinateFrame())
663 {
665 {
666 reference_latitude = params::originLatitude();
667 reference_longitude = params::originLongitude();
668 reference_altitude = params::originAltitude();
669 auto proj = std::make_shared<GeographicLib::LocalCartesian>(reference_latitude, reference_longitude,
670 reference_altitude);
671 converter = [proj](const math::Vec3& pos, double& lat, double& lon, double& alt)
672 { proj->Reverse(pos.x, pos.y, pos.z, lat, lon, alt); };
673 break;
674 }
676 {
677 const int zone = params::utmZone();
678 const bool northp = params::utmNorthHemisphere();
679 converter = [zone, northp](const math::Vec3& pos, double& lat, double& lon, double& alt)
680 {
681 double gamma, k;
682 GeographicLib::UTMUPS::Reverse(zone, northp, pos.x, pos.y, lat, lon, gamma, k);
683 alt = pos.z; // Altitude is given directly in the z-coordinate
684 };
685 break;
686 }
688 {
689 const auto& earth = GeographicLib::Geocentric::WGS84();
690 converter = [&earth](const math::Vec3& pos, double& lat, double& lon, double& alt)
691 { earth.Reverse(pos.x, pos.y, pos.z, lat, lon, alt); };
692 break;
693 }
694 }
695
696 map<const radar::Platform*, vector<const radar::Object*>> platform_to_objects;
697 const auto group_objects = [&](const auto& objectCollection)
698 {
699 for (const auto& obj_ptr : objectCollection)
700 {
701 platform_to_objects[obj_ptr->getPlatform()].push_back(obj_ptr.get());
702 }
703 };
704
705 group_objects(world.getReceivers());
706 group_objects(world.getTransmitters());
707 group_objects(world.getTargets());
708
710 {
711 bool ref_set = false;
712 for (const auto& platform : platform_to_objects | views::keys)
713 {
714 if (!platform->getMotionPath()->getCoords().empty())
715 {
716 const math::Vec3& first_pos = platform->getMotionPath()->getCoords().front().pos;
717 converter(first_pos, reference_latitude, reference_longitude, reference_altitude);
718 ref_set = true;
719 break;
720 }
721 }
722 if (!ref_set) // Fallback if no platforms or no waypoints
723 {
724 reference_latitude = params::originLatitude(); // UCT default
725 reference_longitude = params::originLongitude();
726 reference_altitude = params::originAltitude();
727 }
728 }
729
730 std::ofstream kml_file(outputKmlPath.c_str());
731 if (!kml_file.is_open())
732 {
733 LOG(logging::Level::ERROR, "Error opening output KML file {}", outputKmlPath);
734 return false;
735 }
736
737 writeKmlHeaderAndStyles(kml_file);
738
739 kml_file << " <Folder>\n";
740 kml_file << " <name>Reference Coordinate</name>\n";
741 kml_file << " <description>Placemarks for various elements in the FERSXML file. All Placemarks are "
742 "situated relative to this reference point.</description>\n";
743 kml_file << " <LookAt>\n";
744 kml_file << " <longitude>" << reference_longitude << "</longitude>\n";
745 kml_file << " <latitude>" << reference_latitude << "</latitude>\n";
746 kml_file << " <altitude>" << reference_altitude << "</altitude>\n";
747 kml_file << " <heading>-148.41</heading><tilt>40.55</tilt><range>10000</range>\n";
748 kml_file << " </LookAt>\n";
749
750 const std::string platform_indent = " ";
751 for (const auto& [platform, objects] : platform_to_objects)
752 {
753 processPlatform(platform, objects, kml_file, converter, reference_altitude, platform_indent);
754 }
755
756 kml_file << " </Folder>\n";
757 kml_file << "</Document>\n";
758 kml_file << "</kml>\n";
759 kml_file.close();
760 }
761 catch (const std::exception& e)
762 {
763 LOG(logging::Level::ERROR, "Error generating KML file: {}", e.what());
764 return false;
765 }
766 catch (...)
767 {
768 LOG(logging::Level::ERROR, "Unknown error occurred while generating KML file.");
769 return false;
770 }
771 return true;
772 }
const std::vector< std::unique_ptr< radar::Target > > & getTargets() const noexcept
Retrieves the list of radar targets.
Definition world.h:143
const std::vector< std::unique_ptr< radar::Transmitter > > & getTransmitters() const noexcept
Retrieves the list of radar transmitters.
Definition world.h:163
const std::vector< std::unique_ptr< radar::Receiver > > & getReceivers() const noexcept
Retrieves the list of radar receivers.
Definition world.h:153
A class representing a vector in rectangular coordinates.
RealType x
The x component of the vector.
RealType z
The z component of the vector.
RealType y
The y component of the vector.
#define LOG(level,...)
Definition logging.h:19
@ ERROR
Error level for error events.
double originLongitude() noexcept
Definition parameters.h:238
int utmZone() noexcept
Definition parameters.h:274
@ UTM
Universal Transverse Mercator.
@ ENU
East-North-Up local tangent plane (default)
@ ECEF
Earth-Centered, Earth-Fixed.
CoordinateFrame coordinateFrame() noexcept
Definition parameters.h:272
double originLatitude() noexcept
Definition parameters.h:236
bool utmNorthHemisphere() noexcept
Definition parameters.h:276
double originAltitude() noexcept
Definition parameters.h:240

References params::coordinateFrame(), params::ECEF, params::ENU, logging::ERROR, math::Path::getCoords(), radar::Platform::getMotionPath(), core::World::getReceivers(), core::World::getTargets(), core::World::getTransmitters(), LOG, params::originAltitude(), params::originLatitude(), params::originLongitude(), params::UTM, params::utmNorthHemisphere(), params::utmZone(), math::Vec3::x, math::Vec3::y, and math::Vec3::z.

Referenced by fers_generate_kml().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

The documentation for this class was generated from the following files: