Files
qt-migration-legatus/qt6-after/qt6-migrated-legatus/Lts/Services/GuezMinelayerProcessing/handler_minelayer_data.cpp
T
torstenandCopilot b774f4035c Qt6 Migration: DDS-Stubs, Logger-Fixes, Export-Header Korrekturen
- NGL_ADD_LIBRARY2: 87 CMakeLists.txt konvertiert für Export-Header Generierung
- 44 Export-Header Include-Pfade korrigiert (_export.h)
- 81 DDS-Stub-Header generiert (*_dtc.h, *_fts.h, *_dts.h, *_ftc.h)
- INGLLogger: Duplikat gelöscht, m_logger Member entfernt, variadische Makros
- Q_FUNC_INFO Redefinition behoben (Qt6 definiert bereits)
- FATAL_LOG Makro hinzugefügt
- InfrastructureManagement DDS-Stubs (ism.hpp, ism_enums.hpp, ism_ftc.h)
- FilterManagement DDS-Stubs (flt_ftc.h, flt_dts.h)
- AreaEffectSimulation DDS-Stubs (aes.hpp, aes_enums.hpp)
- SymbolAppearance Klasse vollständig definiert mit content() Methode
- BuildingComponentFilter Klasse definiert mit Copy-Konstruktor
- Ftc Factory: nullptr Return (abstract class)
- AesFilter Klasse in aes.hpp hinzugefügt
- Dtc Klasse in ppm.hpp mit participantChanged Signal
- AesType Enum: alle 15 At* Werte definiert
- AesEffectState_def: EsReceived hinzugefügt
- DataModification Enum: eAdded/eModified/eRemoved
- function_reply_object.h → core_types.h Include-Pfad (72 Dateien)
- Enum-Class-Streaming Template-Operator in INGLLogger.h
- ism_mounting_point.h: QImage → QtGui/QImage, QGuiApplication/QScreen
- ism_data_plugin_interface.h: QSet Include, Include-Reihenfolge
- QRegExp → QRegularExpression in tpm_js_parser.cpp
- .underlying() Aufrufe zu direktem Enum-Vergleich korrigiert
- Include-Pfade: aes.hpp in symbol_appearance_settings_impl.h und aes_display_filter_impl.h

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-08-19 06:06:24 +02:00

353 lines
13 KiB
C++
Executable File

/**
* @RDE_HEADER@
* Handler for incoming data from minelayer trialer/thrower and thier lane data
* $Id$
* $HeadURL$
* $Author$
* created by Philipp Dassow, SLEA, 2017-04-06
*/
#include "handler_minelayer_data.h"
#include <AreaEffectSimulation/aes_ftc.h>
#include <AssetManagement/asm_dtc.h>
#include <ExerciseManagement/exm_dtc.h>
#include "dds_handler.h"
#include "zssi_wi_Minenfeld_Interpreter.h"
#include <QLineF>
namespace GuezMinelayerProcessing
{
HandlerMinelayerData::HandlerMinelayerData(const std::shared_ptr<DdsHandler> &ddsHandler,
QObject *parent)
: QObject(parent)
, m_ddsHandler(ddsHandler)
, m_tabDtc(nullptr)
, m_ppmDtc(nullptr)
, m_aesFtc(nullptr)
, m_minefieldInterpreter(new ZSSI_WI_Minenfeld_Interpreter(this))
, m_minefieldInterpreterTimer(new QTimer(this))
{}
HandlerMinelayerData::~HandlerMinelayerData()
{}
bool HandlerMinelayerData::init()
{
// AES-Ftc
m_aesFtc = AreaEffectSimulation::Interface::Ftc::create(m_ddsHandler->ddsConnector());
bool ret = m_aesFtc->enableMineAreaModifyFromCtaData();
if (!ret)
{
ERROR_LOG() << "AesFtc Can not enable MineAreaCreateFromCtaData()";
return false;
}
// Data from training area base
m_tabDtc = TrainingAreaBase::Interface::Dtc::create(m_ddsHandler->ddsConnector());
ret &= m_tabDtc->enableSpecialSensorData();
ret &= m_tabDtc->enableMinelayerTrailerData();
ret &= m_tabDtc->enableMinelayerThrowerData();
if (!ret)
{
ERROR_LOG() << "TabDtc Can not ebale Data";
return false;
}
connect(m_tabDtc.get(), &TrainingAreaBase::Interface::Dtc::specialSensorDataChanged, this, &HandlerMinelayerData::onSpecialSensorDataChanged);
connect(m_tabDtc.get(), &TrainingAreaBase::Interface::Dtc::minelayerTrailerDataChanged, this, &HandlerMinelayerData::onMinelayerTrailerData);
connect(m_tabDtc.get(), &TrainingAreaBase::Interface::Dtc::minelayerThrowerDataChanged, this, &HandlerMinelayerData::onMinelayerThrowerData);
// PPM for partyId Mapping
m_ppmDtc = ParticipantManagement::Interface::Dtc::create(m_ddsHandler->ddsConnector());
ret &= m_ppmDtc->enableParticipant();
if (!ret)
{
ERROR_LOG() << "PpmDtc Can not enable Participant Data";
return false;
}
// connect to minefield generator
connect(m_minefieldInterpreter, &ZSSI_WI_Minenfeld_Interpreter::sendeWirkfeld, this, &HandlerMinelayerData::onSendMinefield);
// start Interpreter
connect(m_minefieldInterpreterTimer, &QTimer::timeout, this, &HandlerMinelayerData::onStartMinefieldInterpreter);
m_minefieldInterpreterTimer->start(m_minefieldInterpreter->triggerIntervall * 1000);
return ret;
}
void HandlerMinelayerData::onSpecialSensorDataChanged(const TrainingAreaBase::SpecialSensorData &data, DataModification modType)
{
if (modType != DataModification::eAdded &&
modType != DataModification::eModified)
return;
if (data.operationalState() != MV_VERLEGEN &&
data.operationalState() != WMV_VERLEGEN)
return;
if (!data.position().is_set())
return;
{
// convert TrainingAreaBase::LaneData back to sondersensorik_fahrspur_rt
FAHRSPUR_INTERN daten_intern;
//Interpretationsstatus auf 0 setzen
daten_intern.intstat = 0;
daten_intern.daten.header.identitaet = data.equipmentNumber();
daten_intern.daten.gps_zeit.gps_zeit = data.sampleTime() / 1000;
daten_intern.daten.gps_position = relativeFromGeographic(data.position().get().lon(), data.position().get().lat());
daten_intern.daten.ss_betriebszustand = data.operationalState();
// old code copied from zssi_wi_Empfaenger.cpp
/*
if ( checkeTelegrammZeit(telegramm_rt.gps_zeit.gps_zeit) ) {
ERROR_LOG() << QStringLiteral("Keine plausible gps_zeit !! gps_zeit=%1").arg(telegramm_rt.gps_zeit.gps_zeit);
return;
}
if ( checkeKoordinaten(telegramm_rt.gps_pos)!=0 ) {
ERROR_LOG() << QStringLiteral("Keine plausible gps_pos !! pos_x=%1 Keine plausible gps_pos !! pos_y=%2").arg(telegramm_rt.gps_pos.utm_ostwert).arg(telegramm_rt.gps_pos.utm_nordwert);
return;
}
*/
VERLEGEDATEN_KEY key_intern;
key_intern.fz_id = daten_intern.daten.header.identitaet;
key_intern.zeitpunkt.gps_zeit = daten_intern.daten.gps_zeit.gps_zeit;
interne_datenbasis_Fahrspur.eintrag_container(key_intern, daten_intern);
INFO_LOG() << "Inserted new lane data into old interne_datenbasis_Fahrspur succesfully! Lane data:" << data;
// end old code
}
}
template<typename T>
void HandlerMinelayerData::convertMinelayerDataToXdrData(const TrainingAreaBase::MinelayerTrailerData &inData, T &outData)
{
outData.header.identitaet = inData.equipmentNumber();
outData.gps_zeit.gps_zeit = inData.sampleTime() / 1000; // derived from Tetra telegram
outData.gps_position = relativeFromGeographic(inData.position().lon(), inData.position().lat());
outData.verlegedaten.sperren_id = inData.barrierId();
outData.verlegedaten.verlegedichte = inData.layingDensity();
outData.verlegedaten.wirkbeginn.gps_zeit = inData.effectStart() / 1000; // derived from Tetra telegram
outData.verlegedaten.wirkzeit = inData.effectDuration();
outData.verlegedaten.minentyp = inData.chargeTypeId();
outData.verlegedaten.anzahl_verlegter_minen = inData.mineCount();
}
void HandlerMinelayerData::onMinelayerTrailerData(const TrainingAreaBase::MinelayerTrailerData &data, DataModification modType)
{
if ((modType == DataModification::eAdded) ||
(modType == DataModification::eModified))
{
VERLEGEDATEN_INTERN daten_intern;
convertMinelayerDataToXdrData(data, daten_intern.daten);
// old code copied from zssi_wi_Empfaenger.cpp
/*
INFO_LOG() << log_tr("Telegramm 'SONDERSENSORIK_MIVANH_VERLEGEDATEN' empfangen");
if ( checkeTelegrammZeit(telegramm_rt.gps_zeit.gps_zeit) ) {
ERROR_LOG() << log_tr("Keine plausible gps_zeit !! gps_zeit=%1").arg(telegramm_rt.gps_zeit.gps_zeit);
return;
}
if ( checkeKoordinaten(telegramm_rt.gps_pos)!=0 ) {
ERROR_LOG() << log_tr("Keine plausible gps_pos !! pos_x=%1 Keine plausible gps_pos !! pos_y=%2").arg(telegramm_rt.gps_pos.utm_ostwert).arg(telegramm_rt.gps_pos.utm_nordwert);
return;
}
*/
daten_intern.daten.verlegedaten.ausstossart = ausstossart_et(0);
//Diese Null gilt als Unterscheidung zwischen Scorpion und
//Minenverlegeangaenger, da der Scorpion nur ausstossart 1..3 hat
if (daten_intern.daten.verlegedaten.anzahl_verlegter_minen > 1200)
{
WARNING_LOG() << QStringLiteral("Anzahl_verlegter_minen = %1, wird auf 1200 zurueckgesetzt").arg(daten_intern.daten.verlegedaten.anzahl_verlegter_minen);
daten_intern.daten.verlegedaten.anzahl_verlegter_minen = 1200;
}
VERLEGEDATEN_KEY key_intern;
key_intern.fz_id = daten_intern.daten.header.identitaet;
key_intern.zeitpunkt.gps_zeit = daten_intern.daten.gps_zeit.gps_zeit;
interne_datenbasis_Verlegedaten.eintrag_container(
key_intern, daten_intern);
INFO_LOG() << "Inserted new minelayertrailer data into old interne_datenbasis_Verlegedaten succesfully! Minelayerthrower data:" << data;
}
}
void HandlerMinelayerData::onMinelayerThrowerData(const TrainingAreaBase::MinelayerThrowerData &data, DataModification modType)
{
if ((modType == DataModification::eAdded) ||
(modType == DataModification::eModified))
{
VERLEGEDATEN_INTERN daten_intern;
convertMinelayerDataToXdrData(data, daten_intern.daten);
daten_intern.daten.verlegedaten.ausstossart = static_cast<ausstossart_et>(data.throwingType().underlying());
/*
if ( checkeTelegrammZeit(telegramm_rt.gps_zeit.gps_zeit) ) {
ERROR_LOG() << log_tr("Keine plausible gps_zeit !! gps_zeit=%1").arg(telegramm_rt.gps_zeit.gps_zeit);
return;
}
if ( checkeKoordinaten(telegramm_rt.gps_pos) !=0 ) {
ERROR_LOG() << log_tr("Keine plausible gps_pos !! pos_x=%1 Keine plausible gps_pos !! pos_y=%2").arg(telegramm_rt.gps_pos.utm_ostwert).arg(telegramm_rt.gps_pos.utm_nordwert);
return;
}
*/
if (daten_intern.daten.verlegedaten.anzahl_verlegter_minen > 1200)
{
WARNING_LOG() << QStringLiteral("Anzahl_verlegter_minen = %1, wird auf 1200 zurueckgesetzt").arg(daten_intern.daten.verlegedaten.anzahl_verlegter_minen);
daten_intern.daten.verlegedaten.anzahl_verlegter_minen = 1200;
}
VERLEGEDATEN_KEY key_intern;
key_intern.fz_id = daten_intern.daten.header.identitaet;
key_intern.zeitpunkt.gps_zeit = daten_intern.daten.gps_zeit.gps_zeit;
if (daten_intern.daten.verlegedaten.ausstossart >= 5 && daten_intern.daten.verlegedaten.ausstossart <= 7)
{
daten_intern.daten.verlegedaten.anzahl_verlegter_minen = 5;
m_minefieldInterpreter->ZSSI_WI_modifiziere_Verlegedaten(key_intern, daten_intern);
}
else
{
interne_datenbasis_Verlegedaten.eintrag_container(
key_intern, daten_intern);
}
INFO_LOG() << "Inserted new minelayerthrower data into old interne_datenbasis_Verlegedaten succesfully! Minelayerthrower data:" << data;
}
}
Core::GeoPosition2D HandlerMinelayerData::geographicFromRelative(const gps_position_rt &position) const
{
// this function is called after m_baseCoord is set within relativeFromGeographic()
// since we do a mgrs->geographic conversion only when a mine area is created
const QPointF point(m_baseCoord.geographic(position.utm_ostwert - m_baseCoord.x, position.utm_nordwert - m_baseCoord.y));
Core::GeoPosition2D ret;
ret.lon(point.x());
ret.lat(point.y());
return ret;
}
gps_position_rt HandlerMinelayerData::relativeFromGeographic(double lon, double lat)
{
const LtsCoordTrans::UtmCoordinate coord(LtsCoordTrans::UtmCoordinate::fromGeographic(lon, lat, m_baseCoord.zone));
if (m_baseCoord.zone == -1)
{
const QString mgrs = coord.mgrs(0) + QStringLiteral("00000000000000");
// our mgrs base point (taken from the first coordinate we get from Tetra)
m_baseCoord = LtsCoordTrans::UtmCoordinate::fromMgrs(mgrs);
}
gps_position_rt ret;
ret.utm_ostwert = qRound(coord.x);
ret.utm_nordwert = qRound(coord.y);
return ret;
}
int HandlerMinelayerData::partyIdFromEquipmentNumber(int eqNumber) const
{
int partyId = 0;
std::function<bool(const ParticipantManagement::Participant &data)> cb =
[eqNumber, &partyId](const ParticipantManagement::Participant & participant) -> bool
{
if (participant.equipmentNumber() == eqNumber)
{
partyId = participant.partyId();
return true;
}
return false;
};
m_ppmDtc->participants(cb);
return partyId;
}
// mathmatisch positiv nordbezogen <- mathematisch negativ, ost = 0°, 0,01degree in 1/100° -> Faktor 100
static inline double compassFromMathAngleForSfm(int mathAngle)
{
double ret = (9000.0 - mathAngle) / 100;
while (ret < 0.0)
ret += 360.0;
while (ret > 360.0)
ret -= 360.0;
return ret;
}
void HandlerMinelayerData::onSendMinefield(const wirkfeld_minensperre_rt &minefield, int fzArt)
{
AreaEffectSimulation::MineArea outData;
outData.participantId(minefield.header.identitaet);
outData.partyId(partyIdFromEquipmentNumber(minefield.header.identitaet)); // Get from PPM;
outData.name(QString::fromUtf8(tr_lts("dds", "_%1")).arg(minefield.beschreibung.kennung).toStdString());
outData.effectStart(minefield.beschreibung.wirkbeginn.gps_zeit * 1000LL); // derived from Tetra telegram
outData.effectDuration(minefield.beschreibung.wirkdauer * (1000 * 60 * 60)); // orig resolution is 1h based
outData.density(minefield.beschreibung.verlegedichte / 100.0); // derived from Tetra telegram
outData.chargeStruct().chargeTypeId(minefield.beschreibung.minentyp); // is already in TAB converted to chargeTypeId
outData.layingProcedureType(static_cast<AreaEffectSimulation::AesMaLayingProcedureType::inner_enum>(fzArt));
outData.width(minefield.beschreibung.verlegetiefe);
outData.isLaidHidden(false);
outData.layingProcedureType(AreaEffectSimulation::AesMaLayingProcedureType::LptPioneer);
outData.isCenterLine(true);
// segments
std::vector<AreaEffectSimulation::MineSegment> segVec;
segVec.reserve(minefield.beschreibung.segmente.size());
for (const auto &seg : minefield.beschreibung.segmente)
{
AreaEffectSimulation::MineSegment segment;
segment.positionStart(geographicFromRelative(seg.startpunkt));
const LtsCoordTrans::UtmCoordinate startPositionUtm = LtsCoordTrans::UtmCoordinate::fromGeographic({segment.positionStart().lon(), segment.positionStart().lat()});
QLineF line;
line.setP1({startPositionUtm.x, startPositionUtm.y});
line.setAngle(seg.drehwinkel);
line.setLength(double(seg.anzahl / outData.density()));
LtsCoordTrans::UtmCoordinate endPositionUtm = startPositionUtm;
endPositionUtm.x = line.p2().x();
endPositionUtm.y = line.p2().y();
QPointF endPos = endPositionUtm.geographic();
segment.positionEnd({endPos.x(), endPos.y()});
segVec.emplace_back(segment);
}
outData.segments(segVec);
INFO_LOG() << "Sending new minefield from generator to AES: " << outData;
// request create mine area from aes
m_aesFtc->mineAreaModifyFromCtaDataRequest(outData, this);
}
void HandlerMinelayerData::onStartMinefieldInterpreter()
{
INFO_LOG() << "Starting minefield interpreter ...";
m_minefieldInterpreter->processData();
}
void HandlerMinelayerData::onMineAreaModifyFromCtaDataReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
ERROR_LOG() << "Error inserting minefield via AES->FTC";
else
INFO_LOG() << "Got onMineAreaCreateFromCtaDataReply reply with id " << replyObject.id();
}
}