- Merged 292 changed files from dlbo snapshot - Fixed IDL enum collisions (PortType, PdmEventType) - Fixed Grantlee template for C++11 scoped enums - Fixed CMake VERSION_GREATER syntax - Added missing directories (THP, LtsRestClient, etc.) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
260 lines
10 KiB
C++
Executable File
260 lines
10 KiB
C++
Executable File
/**
|
|
* @RDE_HEADER@
|
|
* Namespace for rocket related functions
|
|
* $Id$
|
|
* $HeadURL$
|
|
* $Author$
|
|
* Created by Hannes Fritsche, ESZS, 2026-06-03
|
|
*/
|
|
|
|
#include "aes_rocket_utility.h"
|
|
|
|
#include <QComboBox>
|
|
#include <QJsonDocument>
|
|
#include <QJsonObject>
|
|
#include <QStandardItemModel>
|
|
|
|
#include <AreaEffectSimulation/aes.hpp>
|
|
#include <AreaEffectSimulation/Trajectory/trajectory_generator.h>
|
|
#include <LtsCoordTrans/lts_coord_trans.h>
|
|
#include <LtsUtils/LtsUtilsCore/qpoint3d.h>
|
|
#include <ParticipantManagement/ppm_dtc.h>
|
|
#include <ProjectDataManagement/pdm_enums.hpp>
|
|
#include <Proxies/TrainingAreaBase/Plugins/AdlerJson/telegrams.h>
|
|
|
|
namespace AreaEffectSimulation
|
|
{
|
|
namespace RocketUtility
|
|
{
|
|
|
|
void enaDisaWirkmittel(QComboBox *wirkmittelCombobox, AesExplosionGeometry::type geometry)
|
|
{
|
|
if (wirkmittelCombobox == nullptr)
|
|
return;
|
|
|
|
const QStandardItemModel *cboModel = qobject_cast<QStandardItemModel *>(wirkmittelCombobox->model());
|
|
|
|
if (cboModel == nullptr)
|
|
return;
|
|
|
|
switch (geometry)
|
|
{
|
|
case AesExplosionGeometry::type::EgAimPoint:
|
|
case AesExplosionGeometry::type::EgPoint:
|
|
case AesExplosionGeometry::type::EgLine:
|
|
for (int indexCounter = 0; indexCounter < wirkmittelCombobox->count(); ++indexCounter)
|
|
{
|
|
const QVariant currentData = wirkmittelCombobox->itemData(indexCounter);
|
|
const ProjectDataManagement::GearClass::type currentGearClass = static_cast<ProjectDataManagement::GearClass::type>(currentData.toInt());
|
|
|
|
if (currentGearClass == ProjectDataManagement::GearClass::Rocket)
|
|
{
|
|
QStandardItem *item = cboModel->item(indexCounter);
|
|
|
|
if (item == nullptr)
|
|
continue;
|
|
|
|
item->setFlags(item->flags() | Qt::ItemIsEnabled | Qt::ItemIsSelectable);
|
|
|
|
// we do not break the loop here because there may be more rocket wirkmittel in the future
|
|
}
|
|
}
|
|
return;
|
|
case AesExplosionGeometry::type::EgRadial:
|
|
case AesExplosionGeometry::type::EgArea:
|
|
{
|
|
const int currentIndex = wirkmittelCombobox->currentIndex();
|
|
|
|
for (int indexCounter = 0; indexCounter < wirkmittelCombobox->count(); ++indexCounter)
|
|
{
|
|
const QVariant currentData = wirkmittelCombobox->itemData(indexCounter);
|
|
const ProjectDataManagement::GearClass::type currentGearClass = static_cast<ProjectDataManagement::GearClass::type>(currentData.toInt());
|
|
|
|
if (currentGearClass == ProjectDataManagement::GearClass::Rocket)
|
|
{
|
|
QStandardItem *item = cboModel->item(indexCounter);
|
|
|
|
if (item == nullptr)
|
|
continue;
|
|
|
|
item->setFlags(item->flags() & ~Qt::ItemIsEnabled & ~Qt::ItemIsSelectable);
|
|
|
|
// if rocket ist currently selected, we have to set another index
|
|
if (indexCounter == currentIndex && wirkmittelCombobox->count() > 1)
|
|
{
|
|
const int newIndex = currentIndex == 0 ? 1 : 0;
|
|
|
|
wirkmittelCombobox->setCurrentIndex(newIndex);
|
|
}
|
|
// we do not break the loop here because there may be more rocket wirkmittel in the future
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
void addRocketPropertiesToRequest(EffectClusterModifyRequest &request, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
|
|
{
|
|
switch (request.explosionGeometry().underlying())
|
|
{
|
|
case AesExplosionGeometry::type::EgAimPoint:
|
|
case AesExplosionGeometry::type::EgPoint:
|
|
addRocketPropertiesForPointGeometry(request, ppmDtc);
|
|
return;
|
|
case AesExplosionGeometry::type::EgLine:
|
|
addRocketPropertiesForLinearGeometry(request, ppmDtc);
|
|
return;
|
|
case AesExplosionGeometry::type::EgRadial:
|
|
case AesExplosionGeometry::type::EgArea:
|
|
default:
|
|
return;
|
|
}
|
|
}
|
|
|
|
void addRocketPropertiesForLinearGeometry(EffectClusterModifyRequest &request, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
|
|
{
|
|
using namespace LtsCoordTrans;
|
|
|
|
AdlerJson::WirkmittelFeuerkommandoRakete wirkmittel;
|
|
AdlerJson::Treffpunkt treffpunkt;
|
|
|
|
wirkmittel.wirkzeit = 6;
|
|
|
|
const UtmCoordinate areaBottomLeftUtm = UtmCoordinate::fromGeographic(request.area().cornerBottomLeft().lon(), request.area().cornerBottomLeft().lat());
|
|
|
|
QTransform transform;
|
|
transform.translate(areaBottomLeftUtm.x, areaBottomLeftUtm.y);
|
|
transform.rotate(-request.area().rotation());
|
|
|
|
const double yLocal = request.area().height() / 2;
|
|
|
|
int mhpSliceCounter = 1;
|
|
|
|
for (EffectorData ¤tEffector : request.effectors())
|
|
{
|
|
wirkmittel.geschoss.anzahl = currentEffector.chargeAmount();
|
|
treffpunkt.anzahl = wirkmittel.geschoss.anzahl;
|
|
|
|
// calculate local x
|
|
double xLocal = request.area().width() * (static_cast<double>(mhpSliceCounter++) / (request.effectors().size() + 1));
|
|
|
|
// transform local point to UTM
|
|
const QPointF localPoint(xLocal, yLocal);
|
|
const QPointF utmPoint = transform.map(localPoint);
|
|
|
|
// tranform utm point to geographic WGS84 coordinate
|
|
const UtmCoordinate currentUtm(areaBottomLeftUtm.zone, utmPoint.x(), utmPoint.y());
|
|
const QPointF mhpGeo = currentUtm.geographic();
|
|
|
|
// treffpunkt
|
|
currentEffector.mhpPosition().lon(mhpGeo.x());
|
|
currentEffector.mhpPosition().lat(mhpGeo.y());
|
|
treffpunkt.koordinate.koordinate.longitude = currentEffector.mhpPosition().lon() * LtsCoordTrans::rad2deg();
|
|
treffpunkt.koordinate.koordinate.latitude = currentEffector.mhpPosition().lat() * LtsCoordTrans::rad2deg();
|
|
|
|
wirkmittel.treffpunkte.clear();
|
|
wirkmittel.treffpunkte.append(treffpunkt);
|
|
|
|
QJsonObject wirkmittelObj;
|
|
AdlerJson::wirkmittelFeuerkommandoRaketeToJson(wirkmittelObj, wirkmittel);
|
|
|
|
currentEffector.properties(QJsonDocument(wirkmittelObj).toJson().toStdString());
|
|
|
|
// trajectory
|
|
const ParticipantManagement::ParticipantPosition &participantPosition = ppmDtc->participantPosition(currentEffector.participantId());
|
|
const LtsUtils::QPoint3D trajectoryStart(participantPosition.pos().lon(),
|
|
participantPosition.pos().lat(),
|
|
participantPosition.pos().z());
|
|
const LtsUtils::QPoint3D trajectoryEnd(currentEffector.mhpPosition().lon(),
|
|
currentEffector.mhpPosition().lat(),
|
|
currentEffector.mhpPosition().z()); // TODO
|
|
TrajectoryGeoPosition trajectoryWithoutTime;
|
|
|
|
TrajectoryGenerator::getInstance()->generateTrajectoryBiedziak(trajectoryStart, trajectoryEnd, 45.0, trajectoryWithoutTime);
|
|
|
|
currentEffector.flightTime(60000.0);
|
|
const double flightTimeStep = currentEffector.flightTime() / static_cast<double>(trajectoryWithoutTime.size());
|
|
double currentFlightTime = 0.0;
|
|
|
|
currentEffector.trajectoryRelative().clear(); // LS_711_akkumulierende_flugkurven_bei_rakete
|
|
const LtsCoordTrans::UtmCoordinate utmStartPos = LtsCoordTrans::UtmCoordinate::fromGeographic(participantPosition.pos().lon(), participantPosition.pos().lat());
|
|
for (const Core::GeoPosition &pos : trajectoryWithoutTime)
|
|
{
|
|
const LtsCoordTrans::UtmCoordinate utmCurrentPos = LtsCoordTrans::UtmCoordinate::fromGeographic(pos.lon(), pos.lat());
|
|
|
|
currentEffector.trajectoryRelative().emplace_back(utmCurrentPos.x - utmStartPos.x,
|
|
utmCurrentPos.y - utmStartPos.y, pos.z(), currentFlightTime);
|
|
|
|
currentFlightTime += flightTimeStep;
|
|
}
|
|
}
|
|
}
|
|
|
|
void addRocketPropertiesForPointGeometry(EffectClusterModifyRequest &request, const std::shared_ptr<ParticipantManagement::Interface::Dtc> &ppmDtc)
|
|
{
|
|
using namespace LtsCoordTrans;
|
|
|
|
AdlerJson::WirkmittelFeuerkommandoRakete wirkmittel;
|
|
AdlerJson::Treffpunkt treffpunkt;
|
|
|
|
wirkmittel.wirkzeit = 6;
|
|
treffpunkt.anzahl = 1;
|
|
|
|
const UtmCoordinate areaBottomLeftUtm = UtmCoordinate::fromGeographic(request.area().cornerBottomLeft().lon(), request.area().cornerBottomLeft().lat());
|
|
const QPointF areaCenterGeo = areaBottomLeftUtm.geographic(request.area().width() / 2, request.area().height() / 2);
|
|
|
|
for (EffectorData ¤tEffector : request.effectors())
|
|
{
|
|
wirkmittel.geschoss.anzahl = currentEffector.chargeAmount();
|
|
treffpunkt.anzahl = wirkmittel.geschoss.anzahl;
|
|
|
|
// treffpunkt
|
|
currentEffector.mhpPosition().lon(areaCenterGeo.x());
|
|
currentEffector.mhpPosition().lat(areaCenterGeo.y());
|
|
treffpunkt.koordinate.koordinate.longitude = currentEffector.mhpPosition().lon() * LtsCoordTrans::rad2deg();
|
|
treffpunkt.koordinate.koordinate.latitude = currentEffector.mhpPosition().lat() * LtsCoordTrans::rad2deg();
|
|
|
|
wirkmittel.treffpunkte.clear();
|
|
wirkmittel.treffpunkte.append(treffpunkt);
|
|
|
|
QJsonObject wirkmittelObj;
|
|
AdlerJson::wirkmittelFeuerkommandoRaketeToJson(wirkmittelObj, wirkmittel);
|
|
|
|
currentEffector.properties(QJsonDocument(wirkmittelObj).toJson().toStdString());
|
|
|
|
// trajectory
|
|
const ParticipantManagement::ParticipantPosition &participantPosition = ppmDtc->participantPosition(currentEffector.participantId());
|
|
const LtsUtils::QPoint3D trajectoryStart(participantPosition.pos().lon(),
|
|
participantPosition.pos().lat(),
|
|
participantPosition.pos().z());
|
|
const LtsUtils::QPoint3D trajectoryEnd(currentEffector.mhpPosition().lon(),
|
|
currentEffector.mhpPosition().lat(),
|
|
currentEffector.mhpPosition().z());
|
|
TrajectoryGeoPosition trajectoryWithoutTime;
|
|
|
|
TrajectoryGenerator::getInstance()->generateTrajectoryBiedziak(trajectoryStart, trajectoryEnd, 45.0, trajectoryWithoutTime);
|
|
|
|
currentEffector.flightTime(60000.0);
|
|
const double flightTimeStep = currentEffector.flightTime() / static_cast<double>(trajectoryWithoutTime.size());
|
|
double currentFlightTime = 0.0;
|
|
|
|
currentEffector.trajectoryRelative().clear(); // LS_711_akkumulierende_flugkurven_bei_rakete
|
|
const LtsCoordTrans::UtmCoordinate utmStartPos = LtsCoordTrans::UtmCoordinate::fromGeographic(participantPosition.pos().lon(), participantPosition.pos().lat());
|
|
for (const Core::GeoPosition &pos : trajectoryWithoutTime)
|
|
{
|
|
const LtsCoordTrans::UtmCoordinate utmCurrentPos = LtsCoordTrans::UtmCoordinate::fromGeographic(pos.lon(), pos.lat());
|
|
|
|
currentEffector.trajectoryRelative().emplace_back(utmCurrentPos.x - utmStartPos.x,
|
|
utmCurrentPos.y - utmStartPos.y, pos.z(), currentFlightTime);
|
|
|
|
currentFlightTime += flightTimeStep;
|
|
}
|
|
} // for (EffectorData ¤tEffector : request.effectors())
|
|
}
|
|
|
|
} // namespace RocketUtility
|
|
} // namespace AreaEffectSimulation
|