9#include <GeographicLib/Geodesic.hpp>
67 const double max_gain_db = 10.0 * std::log10(max_gain);
71 { return std::abs(a - target_gain) < std::abs(b - target_gain); });
82 "Gaussian antenna '{}' has a non-positive azimuth scale ({}). 3dB beamwidth is undefined. KML will "
83 "only show boresight.",
96 "Parabolic antenna '{}' has a non-positive diameter ({}). This is physically impossible. KML will only "
105 "Parabolic antenna '{}': The operating wavelength ({:.4f}m) is very large compared to its diameter "
106 "({:.4f}m), resulting in a nearly omnidirectional pattern. KML visualization will cap the 3dB "
107 "half-angle at 90 degrees.",
120 "SquareHorn antenna '{}' has a non-positive dimension ({}). This is physically impossible. KML will "
121 "only show boresight.",
129 "SquareHorn antenna '{}': The operating wavelength ({:.4f}m) is very large compared to its dimension "
130 "({:.4f}m), resulting in a nearly omnidirectional pattern. KML visualization will cap the 3dB "
131 "half-angle at 90 degrees.",
141 std::stringstream
ss;
142 ss << std::fixed << std::setprecision(6) <<
lon <<
"," <<
lat <<
"," <<
alt;
149 const GeographicLib::Geodesic&
geod = GeographicLib::Geodesic::WGS84();
170 out <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
171 out <<
"<kml xmlns=\"http://www.opengis.net/kml/2.2\" xmlns:gx=\"http://www.google.com/kml/ext/2.2\">\n";
172 out <<
"<Document>\n";
174 if (
ctx.parameters.simulation_name.empty())
176 out <<
"FERS Simulation Visualization";
180 out <<
ctx.parameters.simulation_name;
184 "id=\"receiver\"><IconStyle><Icon><href>https://cdn-icons-png.flaticon.com/512/645/645436.png</href></"
185 "Icon></IconStyle></Style>\n";
187 "id=\"transmitter\"><IconStyle><Icon><href>https://cdn-icons-png.flaticon.com/128/224/224666.png</"
188 "href></Icon></IconStyle></Style>\n";
190 "id=\"target\"><IconStyle><Icon><href>https://upload.wikimedia.org/wikipedia/commons/thumb/a/ad/"
191 "Target_red_dot1.svg/1200px-Target_red_dot1.svg.png</href></Icon></IconStyle><LineStyle><width>2</"
192 "width></LineStyle></Style>\n";
194 "id=\"translucentPolygon\"><LineStyle><color>ff0000ff</color><width>2</width></"
195 "LineStyle><PolyStyle><color>00ffffff</color></PolyStyle></Style>\n";
197 "id=\"arrowStyle\"><IconStyle><Icon><href>http://maps.google.com/mapfiles/kml/shapes/arrow.png</href></"
198 "Icon><scale>0.5</scale></IconStyle></Style>\n";
199 out <<
" <Style id=\"lineStyle\"><LineStyle><color>ff0000ff</color><width>2</width></LineStyle></Style>\n";
200 out <<
" <Style id=\"lineStyleBlue\"><LineStyle><color>ffff0000</color><width>2</width></LineStyle></Style>\n";
207 out <<
indent <<
" <name>" << name <<
"</name>\n";
211 out <<
indent <<
" <altitudeMode>absolute</altitudeMode>\n";
214 out <<
indent <<
" <extrude>1</extrude>\n";
224 out <<
indent <<
" <name>" << name <<
"</name>\n";
227 out <<
indent <<
" <altitudeMode>absolute</altitudeMode>\n";
228 out <<
indent <<
" <tessellate>1</tessellate>\n";
256 return "#transmitter";
274 const std::string&
indent)
284 out <<
indent <<
" <name>Isotropic pattern range</name>\n";
285 out <<
indent <<
" <styleUrl>#translucentPolygon</styleUrl>\n";
287 out <<
indent <<
" <extrude>1</extrude>\n";
288 out <<
indent <<
" <altitudeMode>absolute</altitudeMode>\n";
289 out <<
indent <<
" <outerBoundaryIs><LinearRing><coordinates>\n";
296 out <<
indent <<
" </coordinates></LinearRing></outerBoundaryIs>\n";
335 out <<
indent <<
" <name>Antenna Boresight</name>\n";
337 out <<
indent <<
" <Data name=\"rotationangleunit\"><value>"
342 out <<
indent <<
" <styleUrl>#lineStyle</styleUrl>\n";
344 out <<
indent <<
" <altitudeMode>absolute</altitudeMode>\n";
345 out <<
indent <<
" <tessellate>1</tessellate>\n";
371 out <<
indent <<
" <name>Antenna Arrow</name>\n";
372 out <<
indent <<
" <styleUrl>#arrowStyle</styleUrl>\n";
374 <<
"</coordinates><altitudeMode>absolute</altitudeMode></Point>\n";
385 if (
tx->getSignal() !=
nullptr)
387 return ctx.parameters.c /
tx->getSignal()->getCarrier();
441 "KML visualization for antenna '{}' ('{}') is symbolic. "
442 "Only the boresight direction is shown, as a 3dB beamwidth is not calculated from file-based "
451 if ((
ant ==
nullptr) ||
platform->getMotionPath()->getCoords().empty())
487 out <<
indent <<
" <altitudeMode>absolute</altitudeMode>\n";
490 out <<
indent <<
" <extrude>1</extrude>\n";
493 const double start_time =
waypoints.front().t;
494 const double end_time =
waypoints.back().t;
503 out <<
indent <<
" <when>" << start_time <<
"</when>\n";
568 out <<
indent <<
" <longitude>" <<
lon <<
"</longitude>\n";
569 out <<
indent <<
" <latitude>" <<
lat <<
"</latitude>\n";
571 out <<
indent <<
" <heading>-148.41</heading><tilt>40.55</tilt><range>500.65</range>\n";
575 out <<
indent <<
" <altitudeMode>absolute</altitudeMode>\n";
578 out <<
indent <<
" <extrude>1</extrude>\n";
606 if (
platform->getMotionPath()->getCoords().empty())
651 if (!
platform->getMotionPath()->getCoords().empty())
669 out <<
" <Folder>\n";
670 out <<
" <name>Reference Coordinate</name>\n";
671 out <<
" <description>Placemarks for various elements in the FERSXML file. All Placemarks are "
672 "situated relative to this reference point.</description>\n";
673 out <<
" <LookAt>\n";
677 out <<
" <heading>-148.41</heading><tilt>40.55</tilt><range>10000</range>\n";
678 out <<
" </LookAt>\n";
686 out <<
" </Folder>\n";
687 out <<
"</Document>\n";
Header file defining various types of antennas and their gain patterns.
Abstract base class representing an antenna.
Represents a Gaussian-shaped antenna gain pattern.
Represents an antenna whose gain pattern is loaded from a HDF5 file.
Represents an isotropic antenna with uniform gain in all directions.
Represents a parabolic reflector antenna.
Represents a sinc function-based antenna gain pattern.
Represents a square horn antenna.
Represents an antenna whose gain pattern is defined by an XML file.
The World class manages the simulator environment.
const std::vector< std::unique_ptr< radar::Target > > & getTargets() const noexcept
Retrieves the list of radar targets.
const std::vector< std::unique_ptr< radar::Transmitter > > & getTransmitters() const noexcept
Retrieves the list of radar transmitters.
const std::vector< std::unique_ptr< radar::Receiver > > & getReceivers() const noexcept
Retrieves the list of radar receivers.
Represents a path with coordinates and allows for various interpolation methods.
Vec3 getPosition(RealType t) const
Retrieves the position at a given time along the path.
const std::vector< Coord > & getCoords() const noexcept
Gets the list of coordinates in the path.
@ INTERP_LINEAR
Linearly interpolate between neighboring coordinates.
@ INTERP_CUBIC
Cubically interpolate between neighboring coordinates.
A class representing a vector in spherical coordinates.
A class representing a vector in rectangular coordinates.
Represents a radar system on a platform.
Manages radar signal reception and response processing.
Represents a radar transmitter system.
constexpr RealType EPSILON
Machine epsilon for real numbers.
constexpr RealType PI
Mathematical constant π (pi).
Coordinate and rotation structure operations.
Utility definitions and functions for generating KML files from simulation scenarios.
Header file for the logging system.
@ WARNING
Warning level for potentially harmful situations.
@ INFO
Info level for informational messages.
@ ENU
East-North-Up local tangent plane (default)
constexpr std::string_view rotationAngleUnitToken(const RotationAngleUnit unit) noexcept
Converts a rotation angle unit to its XML token.
void generateTrackEndpointsKml(std::ostream &out, const radar::Platform *platform, const double refAlt, const KmlContext &ctx, const std::string &indent)
Generates KML rendering start and end pushpins for a moving platform's track.
void writePoint(std::ostream &out, const std::string &indent, const std::string &name, const std::string &styleUrl, const std::string &coordinates, const double objectAltitude, const double referenceAltitude)
Writes a KML <Point> placemark to the output stream.
std::string formatCoordinates(const double lon, const double lat, const double alt)
Formats coordinates into a comma-separated string suitable for KML <coordinates>.
std::vector< std::pair< double, double > > generateCircleCoordinates(const double lat, const double lon, const double radius_km)
Generates a collection of points tracing a circle around a center coordinate.
constexpr double ISOTROPIC_PATTERN_RADIUS_KM
double findSquareHorn3DbDropAngle(const antenna::SquareHorn *squarehornAnt, const double wavelength)
Calculates the 3dB drop angle for a Square Horn antenna.
void generateDirectionalAntennaKml(std::ostream &out, const radar::Platform *platform, const KmlContext &ctx, const std::optional< double > &angle3DbDropDeg, const std::string &indent)
Renders the visual pointing representation for a directional (beam) antenna.
double findParabolic3DbDropAngle(const antenna::Parabolic *parabolicAnt, const double wavelength)
Calculates the 3dB drop angle for a Parabolic antenna.
std::string getPlacemarkStyleForPlatform(const std::vector< const radar::Object * > &objects)
Determines the proper KML style definition ID to use based on the platform's attached objects.
double sincAntennaGain(const double theta, const double alpha, const double beta, const double gamma)
Calculates a normalized sinc-based antenna gain mapping.
double findGaussian3DbDropAngle(const antenna::Gaussian *gaussianAnt)
Calculates the 3dB drop angle for a Gaussian antenna.
std::optional< double > antenna3DbDropAngle(const antenna::Antenna *ant, const std::optional< double > wavelength)
void generateKmlToStream(std::ostream &out, const core::World &world, const KmlContext &ctx)
Master entry point designed to convert the comprehensive simulation world state into a valid KML docu...
double find3DbDropAngle(const double alpha, const double beta, const double gamma)
Numerically determines the 3dB drop angle for a parameterized generic antenna.
constexpr int TRACK_NUM_DIVISIONS
void generateDynamicPathKml(std::ostream &out, const radar::Platform *platform, const std::string &styleUrl, const double refAlt, const KmlContext &ctx, const std::string &indent)
Generates KML for a continuously moving dynamic platform path.
void generateAntennaKml(std::ostream &out, const radar::Platform *platform, const radar::Radar *radar, const KmlContext &ctx, const std::string &indent)
Dispatch function that selects and generates the appropriate KML for a given radar's antenna.
const radar::Radar * getPrimaryRadar(const std::vector< const radar::Object * > &objects)
Identifies the primary radar object within a platform for styling and direction tracking.
std::optional< double > antennaCarrierWavelength(const radar::Radar *radar, const KmlContext &ctx)
void processPlatform(std::ostream &out, const radar::Platform *platform, const std::vector< const radar::Object * > &objects, const KmlContext &ctx, const double referenceAltitude, const std::string &indent)
Orchestrates full processing and rendering of an individual platform into the KML stream.
void calculateDestinationCoordinate(const double startLatitude, const double startLongitude, const double angle, const double distance, double &destLatitude, double &destLongitude)
Calculates a destination coordinate given a starting position, bearing, and distance.
constexpr int ISOTROPIC_PATTERN_POINTS
void writeKmlHeaderAndStyles(std::ostream &out, const KmlContext &ctx)
Writes the standard KML preamble and style definitions to the output stream.
void generateStaticPlacemarkKml(std::ostream &out, const radar::Platform *platform, const std::string &styleUrl, const double refAlt, const KmlContext &ctx, const std::string &indent)
Generates a simple static placemark KML for a non-moving platform.
void logSymbolicAntennaKml(const antenna::Antenna *ant)
void generatePlatformPathKml(std::ostream &out, const radar::Platform *platform, const std::string &style, const double refAlt, const KmlContext &ctx, const std::string &indent)
Dispatches the generation of a platform's path representation (static vs dynamic).
void writeAntennaBeamLine(std::ostream &out, const std::string &indent, const std::string &name, const std::string &style, const std::string &startCoords, const std::string &endCoords)
Writes a visual cone/beam line representing the antenna look direction.
constexpr double DIRECTIONAL_ANTENNA_ARROW_LENGTH_M
void generateIsotropicAntennaKml(std::ostream &out, const math::Vec3 &position, const KmlContext &ctx, const std::string &indent)
Renders the visual representation for an isotropic antenna into the output stream.
RealType internal_elevation_to_external(const RealType elevation, const params::RotationAngleUnit unit) noexcept
Converts an internal elevation angle to the external unit.
RealType internal_azimuth_to_external(const RealType azimuth, const params::RotationAngleUnit unit) noexcept
Converts an internal azimuth angle to the external compass convention.
Provides the definition and functionality of the Path class for handling coordinate-based paths with ...
Defines the Radar class and associated functionality.
Classes for handling radar waveforms and signals.
Radar Receiver class for managing signal reception and response handling.
Context data required during KML generation.
Defines classes for radar targets and their Radar Cross-Section (RCS) models.
Header file for the Transmitter class in the radar namespace.
Header file for the World class in the simulator.