Initial commit

This commit is contained in:
torsten committed 2026-08-13 18:33:10 +02:00
commit b7d90b9afe
16245 files changed
+3396666

No files matched your search

+56
View File
@@ -0,0 +1,56 @@
#
# $Id$
# $HeadURL$
# $Author$
#
INCLUDE(MacroCodeGenIdl)
SET(xml_FILE gmp_service.xml)
#
# --- Library svcGmpServer -------------------------------------------------
#
SET(SRCS
initialization.cpp
initialization.h
handler_minelayer_data.cpp
handler_minelayer_data.h
GFS_map_cont.h
zssi_wi_Minenfeld_Interpreter.cpp
zssi_wi_Minenfeld_Interpreter.h
zssi_wi_Minenfeld_Generator.cpp
zssi_wi_Minenfeld_Generator.h
dds_handler.cpp
dds_handler.h
settings.cpp
settings.h
logger.cpp
logger.h
${xml_FILE}
)
# make sure xml file is properly installed
CODEGEN_HANDLE_SVC_XML(SRCS ${xml_FILE})
NGL_ADD_LIBRARY(AAR SV svcGmpServer SHARED ${SRCS})
NGL_TARGET_LINK_LIBRARIES(svcGmpServer
Qt5::Core
svcAesClient
svcCoreClient
svcPdmClient
svcPpmClient
svcTabClient
LtsCoordTrans
ddsconnector
NGLLogger
nglsettings
ngldb
ngltools
)
NGL_INSTALL_TARGET(svcGmpServer)
# Uncomment if necessary
ADD_SUBDIRECTORY(UnitTests)
#ADD_SUBDIRECTORY(ModuleTests)
+383
View File
@@ -0,0 +1,383 @@
/* --------------------------------------------------------------------
// $HeadURL$
// --------------------------------------------------------------------
//!
// --------------------------------------------------------------------
// COPYRIGHT (C) 1999: STN ATLAS ELEKTRONIK GMBH, D-28305 BREMEN
// --------------------------------------------------------------------
//
// HIER/ITEM : CSU: RP 5182 R 100 SRC 51103
// BRIEF DESC: Generische Container-Klasse auf Basis der STL
// AUTHOR : Norbert Thoden
// RELEASE :
// MODIF/STAT: 28.06.99
// ORIGIN REF:
//
// Revision INFO:
// --------------
// $Revision$
// $Date$
// $Id$
//
// LANGUAGE: C++ (Compiler: MIPSPro Version: 7.2.1)
// LANGUAGE: C++ (Compiler: MSVC Version: 5.0)
//
// PURPOSE:
// --------
// Verschiedene assoziative Datentypen (Key <--> Date,
// wie z.B. Positionsmeldungen)
// werden in einem Container gesammelt.
//
// ERROR HANDLING:
// ---------------
// (keine / Beschreibung)
//
// IMPLEMENTATION DETAILS:
// -----------------------
// Benutzt wird eine Container vom Typ map aus der STL.
// Wegen der Template-Eigenschaft mu? unter MS VC5.0 das entsprechende
// cpp-File am Ende des Header-Files eingebunden werden.
//
//!
*/
#pragma once
//------------------ includes ------------------------------
#include <map>
#include <vector>
//------------------ externals (procs + vars) --------------
//------------------ constants/ defines --------------------
//------------------ types ---------------------------------
typedef int32_t ausstattungs_id_t;
typedef int32_t wirkfeldkennung_t;
struct header_rt
{
ausstattungs_id_t identitaet = 0;
};
struct gps_zeit_rt
{
uint32_t gps_zeit = 0;
};
struct gps_position_rt
{
int32_t utm_nordwert = 0;
int32_t utm_ostwert = 0;
};
enum ausstossart_et
{
mitte = 0,
rechts = 1,
links = 2,
rechts_und_links = 3,
reserve = 4,
rechts_einzel = 5,
links_einzel = 6,
rechts_links_einzel = 7,
};
struct beschr_wmiv_verlegedaten_rt
{
int16_t sperren_id = 0;
int16_t verlegedichte = 0;
gps_zeit_rt wirkbeginn;
uint16_t wirkzeit = 0;
uint16_t minentyp = 0;
ausstossart_et ausstossart = mitte;
int16_t anzahl_verlegter_minen = 0;
};
struct sondersensorik_wmiv_verlegedaten_rt
{
header_rt header;
gps_zeit_rt gps_zeit;
gps_position_rt gps_position;
beschr_wmiv_verlegedaten_rt verlegedaten;
};
struct sondersensorik_fahrspur_rt
{
header_rt header;
gps_zeit_rt gps_zeit;
gps_position_rt gps_position;
int16_t ss_betriebszustand = 0;
};
struct Segment_rt {
gps_position_rt startpunkt;
int16_t anzahl = 0;
uint16_t drehwinkel = 0;
};
struct bes_wirkfeld_minensperre_rt
{
wirkfeldkennung_t kennung;
gps_zeit_rt wirkbeginn;
uint32_t wirkdauer = 0;
gps_position_rt eckpunkt;
uint16_t wirkfeldbreite = 0;
uint16_t wirkfeldtiefe = 0;
uint32_t verlegetiefe = 0;
int32_t verlegedichte = 0;
uint16_t minentyp = 0;
int16_t minenanzahl = 0;
std::vector<Segment_rt> segmente;
};
struct wirkfeld_minensperre_rt
{
header_rt header;
bes_wirkfeld_minensperre_rt beschreibung;
};
struct VERLEGEDATEN_INTERN
{
int32_t status = -1;
sondersensorik_wmiv_verlegedaten_rt daten;
}; //auch mivanh werden dort hinein geschrieben
struct VERLEGEDATEN_KEY
{
ausstattungs_id_t fz_id = -1;
gps_zeit_rt zeitpunkt;
bool operator==(const VERLEGEDATEN_KEY &o) const
{
return ((fz_id == o.fz_id) &&
(zeitpunkt.gps_zeit == o.zeitpunkt.gps_zeit));
}
bool operator!=(const VERLEGEDATEN_KEY &o) const
{
return !operator==(o);
}
bool operator<(const VERLEGEDATEN_KEY &o) const
{
if (fz_id != o.fz_id)
return (fz_id < o.fz_id);
return (zeitpunkt.gps_zeit < o.zeitpunkt.gps_zeit);
}
};
struct FAHRSPUR_INTERN
{
int32_t intstat = -1;
sondersensorik_fahrspur_rt daten;
};
static inline VERLEGEDATEN_KEY keyFromFahrspur(const FAHRSPUR_INTERN &fs)
{
VERLEGEDATEN_KEY ret;
ret.fz_id = fs.daten.header.identitaet;
ret.zeitpunkt = fs.daten.gps_zeit;
return ret;
}
//-------------------function prototypes -------------------
//-------------------Class declarations --------------------
//c+########################################################################*/
template <class TKEY, class TDATA>
class GFS_Map_Container
//----------------------------------------------------------------------------
// DESCRIPTION:
//
//----------------------------------------------------------------------------
{
public:
//--------------------------------------------------------------------
// Default constructor:
GFS_Map_Container()
{
//Iterator auf Begin legen:
it = container.begin();
}
//## EINTRAG HINZUFUEGEN ###################################################
bool eintrag_container(const TKEY &key, const TDATA &data)
{
// Uwe Gahre von Astrid Mueller
std::pair<typename std::map<const TKEY, TDATA>::iterator, bool>
P = container.insert(std::make_pair(key, data));
return P.second;
}
// Ueberpruefen ob Eintrag vorhanden *ohne* iterator zu veraendern
bool contains(const TKEY &key) const
{
return (container.find(key) != container.end());
}
//## EINTRAG FINDEN #########################################################
TDATA *finden_eintrag_container(const TKEY &key)
{
it = container.find(key);
if (it == container.end())
return nullptr;
TDATA *ptr = &((*it).second);
return ptr;
}
//## EINTRAG LOESCHEN #########################################################
bool loeschen_eintrag_container(const TKEY &key)
{
it = container.find(key);
if (it == container.end())
return false;
container.erase(it++);
return true;
}
//## ALLE EINTRAEGE ABSCANNEN ################################################
void scan_container(void (*fkt_ptr)(const TKEY *, TDATA *))
{
typedef typename std::map<const TKEY, TDATA>::iterator ITERATOR;
for (ITERATOR it = container.begin(); it != container.end(); ++it)
{
const TKEY *key_p = &(*it).first; //Mu? const sein,
TDATA *data_p = &(*it).second; //wg, map<const TKEY...
(fkt_ptr)(key_p, data_p); //Zeiger auf Funktion
}
}
//## iter_reset #################################################
void iter_reset(void) { it = container.begin(); }
//## iter_modify #################################################
bool iter_modify(int relativ)
{
// Wenn ueberhaupt Eintraege vorhanden sind...
if (!container.empty())
{
bool ret = true;
// bei positive Werten:
if (relativ >= 0)
{
for (int i = 0; i < relativ; i++)
{
// Wenn moeglich, it incrementieren:
if (it != container.end()) ++it;
// Ende nun erreicht?
if (it == container.end())
{
--it; // Weil end() nicht gueltig ist, dekrementieren
ret = false;
}
}
}
else
{
relativ = -1 * relativ;
for (int i = 0; i < relativ; i++)
{
// Anfang erreicht? Hier v o r dem dekrementieren,
// um auch alle Eintraege z.B. per do while bearbeiten zu k?nnen.
// Damit ist das Verhalten wie beim Incrementieren.
if (it == container.begin())
ret = false;
if (it != container.begin()) --it;
}
}
return ret;
}
else
{
// keine Eintraege vorhanden:
return false;
}
}
//## iter_erase #############################################
bool iter_erase(void)
{
if (container.empty())
return false;
size_t size = container.size();
// aktuelles Element l?schen:
container.erase(it++);
// Wenn letztes Element geloescht wurde, diesen decrementieren,
// damit it auf ein gueltiges Paar zeigt. Jedoch nur wenn noch Daten
// enthalten sind. (Decrementieren von .end auf .begin => Core-Dump
if (!container.empty())
{
if (it == container.end()) --it;
}
else
it = container.begin();
// Wenn nun kleiner als vorher:
if (container.size() < size)
return true;
else
return false;
}
//## getKey #################################################
const TKEY &getKey() const
{
return ((*it).first);
}
//## getData #################################################
TDATA *getData()
{
return &((*it).second);
}
//## LOESCHEN DES CONTAINERS ##################################################
void clear()
{
container.clear();
// Iterator auf Beginn setzen:
it = container.begin();
}
bool empty() const { return container.empty(); }
//## AKTUELLE CONTAINERGROESSE ################################################
size_t size() const { return container.size(); }
std::map<const TKEY, TDATA> &c() { return container; }
const std::map<const TKEY, TDATA> &c() const { return container; }
//----------------------------------------------------------------------------
protected:
//
//-----------------------------------------------------------------------------
// der Container vom Typ map:
std::map<const TKEY, TDATA> container;
// ein Iterator dazu:
typename std::map<const TKEY, TDATA>::iterator it;
};
//c-##########################################################################
@@ -0,0 +1,32 @@
#
# $Id$
# $HeadURL$
# $Author$
#
SET (SRCS_TEST
../logger.cpp
../logger.h
../GFS_map_cont.h
../zssi_wi_Minenfeld_Generator.cpp
../zssi_wi_Minenfeld_Generator.h
../zssi_wi_Minenfeld_Interpreter.cpp
../zssi_wi_Minenfeld_Interpreter.h
gmp_minefieldInterpreter_test.cpp
gmp_minefieldInterpreter_test.h
)
IF(BUILD_TESTING AND TARGET svcGmpServer)
ADD_EXECUTABLE(gmpTests ${SRCS_TEST})
TARGET_LINK_LIBRARIES(gmpTests
NGLLogger
ProjectConfig
Qt5::Core
Qt5::Test
)
IF(NOT BUILD_RPM)
NGL_INSTALL(AAR SV TARGETS gmpTests DESTINATION bin/test)
NGL_INSTALL(AAR SV FILES log4cxx_gmp_tests.props DESTINATION bin/test)
ENDIF()
ENDIF()
@@ -0,0 +1,391 @@
/**
* @RDE_HEADER@
* UnitTests for ExerciseManagement (EXM)
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLEA, 2017-05-29
*/
#include "gmp_minefieldInterpreter_test.h"
#include <QCoreApplication>
#include <QDateTime>
#include <QtTest/QTest>
#include <NGLLogger/NGLLoggerBootstrap.h>
Q_DECLARE_METATYPE(wirkfeld_minensperre_rt)
Q_DECLARE_METATYPE(ausstossart_et)
Q_DECLARE_METATYPE(Segment_rt)
typedef QPair<int, int> Coordinate;
Q_DECLARE_METATYPE(Coordinate)
//-------------------------------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
QCoreApplication app(argc, argv);
// Init the logger
NGL::NGLLoggerBootstrap::createNGLRootLogger("log4cxx_gmp_tests.props", true);
GmpMinefieldInterpreterTestsMain *tc = new GmpMinefieldInterpreterTestsMain;
int retCode = QTest::qExec(tc, argc, argv);
delete tc;
return retCode;
}
//-------------------------------------------------------------------------------------------------------
GmpMinefieldInterpreterTestsMain::GmpMinefieldInterpreterTestsMain()
: m_minefieldInterpreter(nullptr)
, m_receivedMinefield()
, m_receivedVeType(0)
, m_minefieldInterpreterTimer(nullptr)
, m_minefieldSpy(nullptr)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("Tests.GmpMinefieldInterpreterTest"))
{
}
//-------------------------------------------------------------------------------------------------------
void GmpMinefieldInterpreterTestsMain::initTestCase()
{
DEBUG_LOG(m_logger) << "GmpMinefieldInterpreterTestsMain: initTestCase";
m_minefieldInterpreter = new GuezMinelayerProcessing::ZSSI_WI_Minenfeld_Interpreter();
QVERIFY2(m_minefieldInterpreter, "Initialisation of GuezMinelayerProcessing::ZSSI_WI_Minenfeld_Interpreter failed");
// connect to minefield generator
connect(m_minefieldInterpreter, &GuezMinelayerProcessing::ZSSI_WI_Minenfeld_Interpreter::sendeWirkfeld, this, &GmpMinefieldInterpreterTestsMain::onSendMinefield);
// set up signal spy
qRegisterMetaType<wirkfeld_minensperre_rt>();
m_minefieldSpy = new QSignalSpy(m_minefieldInterpreter, &GuezMinelayerProcessing::ZSSI_WI_Minenfeld_Interpreter::sendeWirkfeld);
// start interpreter
m_minefieldInterpreterTimer = new QTimer();
connect(m_minefieldInterpreterTimer, &QTimer::timeout, m_minefieldInterpreter, &GuezMinelayerProcessing::ZSSI_WI_Minenfeld_Interpreter::processData);
m_minefieldInterpreterTimer->start(m_minefieldInterpreter->triggerIntervall * 1000);
}
//-------------------------------------------------------------------------------------------------------
void GmpMinefieldInterpreterTestsMain::minefieldTestCase_data()
{
// define set of data needed
QTest::addColumn<QVector<int>>("identities");
QTest::addColumn<uint32_t>("effectDuration");
QTest::addColumn<int>("operationalState");
QTest::addColumn<int>("barrierId");
QTest::addColumn<unsigned short>("mineType");
QTest::addColumn<short>("mineCount");
QTest::addColumn<int>("mineLayingDensity");
QTest::addColumn<QVector<ausstossart_et>>("throwingTypes");
QTest::addColumn<QVector <QVector<Coordinate>>>("coordinates"); // (Coordinate == QPair) is interpreted as utm_north, utm_east
QTest::addColumn<int>("identityResult");
QTest::addColumn<short>("mineCountResult");
QTest::addColumn<int>("mineDensityResult");
QTest::addColumn<uint32_t>("layingDepth");
QTest::addColumn<QVector<Segment_rt>>("segmentsResult");
// data set: minefield with mutltiple laying vehicles
// identities
QVector <int> identities({4000, 4010, 4020});
uint32_t effectDuration = 10;
int operationalState = 98;
int barrierId = 43;
unsigned short mineType = 214;
short mineCount = 12;
int mineLayingDensity = 1;
QVector<ausstossart_et> throwingTypes({rechts_und_links, links, rechts});
// List of coordinates for the lane data
// QPair is utm_north, utm_east
QVector<Coordinate> coordinates1, coordinates2, coordinates3;
coordinates1 << QPair<int, int>(79500, 94200);
coordinates2 << QPair<int, int>(79540, 94200);
coordinates3 << QPair<int, int>(79460, 94200);
coordinates1 << QPair<int, int>(79500, 94220);
coordinates2 << QPair<int, int>(79540, 94220);
coordinates3 << QPair<int, int>(79460, 94220);
coordinates1 << QPair<int, int>(79500, 94240);
coordinates2 << QPair<int, int>(79540, 94240);
coordinates3 << QPair<int, int>(79460, 94240);
coordinates1 << QPair<int, int>(79500, 94260);
coordinates2 << QPair<int, int>(79540, 94260);
coordinates3 << QPair<int, int>(79460, 94260);
QVector <QVector<Coordinate>> coordinates;
coordinates << coordinates1 << coordinates2 << coordinates3;
// result data
int identityResult = 4010;
short mineCountResult = mineCount * 3;
int mineDensityResult = 60;
uint32_t layingDepth = 128;
QVector<Segment_rt> segmentsResult;
Segment_rt segment;
segment.anzahl = mineCountResult;
segment.drehwinkel = 0;
segment.startpunkt.utm_nordwert = 79500;
segment.startpunkt.utm_ostwert = 94200;
segmentsResult << segment;
QTest::newRow("minefield from multiple vehicles")
<< identities
<< effectDuration
<< operationalState
<< barrierId
<< mineType
<< mineCount
<< mineLayingDensity
<< throwingTypes
<< coordinates
<< identityResult
<< mineCountResult
<< mineDensityResult
<< layingDepth
<< segmentsResult;
// clear lists
identities.clear();
throwingTypes.clear();
coordinates1.clear();
coordinates2.clear();
coordinates3.clear();
coordinates.clear();
segmentsResult.clear();
// data set: minefield with 1 laying vehicle and 5 segments
identities << 4000;
effectDuration = 6;
operationalState = 98;
barrierId = 42;
mineType = 215;
mineCount = 111;
mineLayingDensity = 4;
throwingTypes << mitte;
//coordinates
coordinates1 << QPair<int, int>(79100, 94100);
coordinates1 << QPair<int, int>(79120, 94110);
coordinates1 << QPair<int, int>(79140, 94120);
coordinates1 << QPair<int, int>(79140, 94140);
coordinates1 << QPair<int, int>(79130, 94160);
coordinates1 << QPair<int, int>(79110, 94170);
coordinates1 << QPair<int, int>(79090, 94160);
coordinates1 << QPair<int, int>(79080, 94140);
coordinates1 << QPair<int, int>(79080, 94120);
coordinates1 << QPair<int, int>(79070, 94100);
coordinates1 << QPair<int, int>(79080, 94080);
coordinates1 << QPair<int, int>(79100, 94070);
coordinates1 << QPair<int, int>(79120, 94060);
coordinates1 << QPair<int, int>(79130, 94040);
coordinates << coordinates1;
// result data
identityResult = 4000;
mineCountResult = mineCount;
mineDensityResult = 41;
layingDepth = 12;
// segment 0
segment.anzahl = 18;
segment.drehwinkel = 6343;
segment.startpunkt.utm_nordwert = 79100;
segment.startpunkt.utm_ostwert = 94100;
segmentsResult << segment;
// segment 1
segment.anzahl = 17;
segment.drehwinkel = 34596;
segment.startpunkt.utm_nordwert = 79140;
segment.startpunkt.utm_ostwert = 94120;
segmentsResult << segment;
// segment 2
segment.anzahl = 16;
segment.drehwinkel = 27000;
segment.startpunkt.utm_nordwert = 79130;
segment.startpunkt.utm_ostwert = 94160;
segmentsResult << segment;
// segment 3
segment.anzahl = 26;
segment.drehwinkel = 19843;
segment.startpunkt.utm_nordwert = 79090;
segment.startpunkt.utm_ostwert = 94160;
segmentsResult << segment;
// segment 4
segment.anzahl = 34;
segment.drehwinkel = 13500;
segment.startpunkt.utm_nordwert = 79070;
segment.startpunkt.utm_ostwert = 94100;
segmentsResult << segment;
QTest::newRow("minefield from 1 vehicle with 5 segments")
<< identities
<< effectDuration
<< operationalState
<< barrierId
<< mineType
<< mineCount
<< mineLayingDensity
<< throwingTypes
<< coordinates
<< identityResult
<< mineCountResult
<< mineDensityResult
<< layingDepth
<< segmentsResult;
}
//-------------------------------------------------------------------------------------------------------
void GmpMinefieldInterpreterTestsMain::minefieldTestCase()
{
DEBUG_LOG(m_logger) << "GmpMinefieldInterpreterTestsMain: multiLaneMinefieldTestCase";
NOTICE_LOG(m_logger) << "this may take a while.. don't worry";
uint64_t timeStamp = QDateTime::currentSecsSinceEpoch();
uint32_t effectStart = timeStamp + 100;
QFETCH(int, barrierId);
QFETCH(unsigned short, mineType);
// inserting start minelayer data
VERLEGEDATEN_INTERN verlegedaten_intern;
VERLEGEDATEN_KEY verlegekey_intern;
verlegedaten_intern.daten.gps_zeit.gps_zeit = timeStamp;
verlegedaten_intern.daten.verlegedaten.sperren_id = barrierId;
verlegedaten_intern.daten.verlegedaten.verlegedichte = 0;
verlegedaten_intern.daten.verlegedaten.wirkbeginn.gps_zeit = effectStart;
verlegedaten_intern.daten.verlegedaten.wirkzeit = 0;
verlegedaten_intern.daten.verlegedaten.minentyp = mineType;
verlegedaten_intern.daten.verlegedaten.anzahl_verlegter_minen = 0;
verlegekey_intern.zeitpunkt.gps_zeit = timeStamp;
QFETCH(QVector<int>, identities);
QFETCH(QVector<QVector<Coordinate>>, coordinates);
QFETCH(QVector<ausstossart_et>, throwingTypes);
for (int i = 0; i < identities.size(); ++i)
{
verlegekey_intern.fz_id = identities.at(i);
verlegedaten_intern.daten.header.identitaet = identities.at(i);
verlegedaten_intern.daten.gps_position.utm_nordwert = coordinates.at(i).first().first;
verlegedaten_intern.daten.gps_position.utm_ostwert = coordinates.at(i).first().second;
verlegedaten_intern.daten.verlegedaten.ausstossart = throwingTypes.at(i);
interne_datenbasis_Verlegedaten.eintrag_container(
verlegekey_intern, verlegedaten_intern);
}
QFETCH(int, operationalState);
// inserting lane data timed
FAHRSPUR_INTERN daten_intern;
VERLEGEDATEN_KEY key_intern;
//Interpretationsstatus auf 0 setzen
daten_intern.intstat = 0;
daten_intern.daten.ss_betriebszustand = operationalState;
// for each coordinate
for (int i = 0; i < coordinates.first().size(); ++i)
{
key_intern.zeitpunkt.gps_zeit = timeStamp;
daten_intern.daten.gps_zeit.gps_zeit = timeStamp;
// for each identity
for (int j = 0; j < identities.size(); ++j)
{
daten_intern.daten.header.identitaet = identities.at(j);
daten_intern.daten.gps_position.utm_nordwert = coordinates.at(j).at(i).first;
daten_intern.daten.gps_position.utm_ostwert = coordinates.at(j).at(i).second;
key_intern.fz_id = identities.at(j);
interne_datenbasis_Fahrspur.eintrag_container(
key_intern, daten_intern);
}
NOTICE_LOG(m_logger) << "... waiting for next coordinate input";
QTest::qWait(5000);
timeStamp += 5;
}
NOTICE_LOG(m_logger) << "finished!";
QFETCH(short, mineCount);
QFETCH(uint32_t, effectDuration);
QFETCH(int, mineLayingDensity);
// inserting end minelayer data
timeStamp -= 5;
verlegedaten_intern.daten.gps_zeit.gps_zeit = timeStamp;
verlegedaten_intern.daten.verlegedaten.sperren_id = barrierId;
verlegedaten_intern.daten.verlegedaten.verlegedichte = mineLayingDensity;
verlegedaten_intern.daten.verlegedaten.wirkbeginn.gps_zeit = effectStart;
verlegedaten_intern.daten.verlegedaten.wirkzeit = effectDuration;
verlegedaten_intern.daten.verlegedaten.anzahl_verlegter_minen = mineCount;
verlegekey_intern.zeitpunkt.gps_zeit = timeStamp;
for (int i = 0; i < identities.size(); ++i)
{
verlegekey_intern.fz_id = identities.at(i);
verlegedaten_intern.daten.header.identitaet = identities.at(i);
verlegedaten_intern.daten.gps_position.utm_nordwert = coordinates.at(i).last().first;
verlegedaten_intern.daten.gps_position.utm_ostwert = coordinates.at(i).last().second;
verlegedaten_intern.daten.verlegedaten.ausstossart = throwingTypes.at(i);
interne_datenbasis_Verlegedaten.eintrag_container(
verlegekey_intern, verlegedaten_intern);
}
// the interpreter/generator waits for 240 seconds before processing the data
NOTICE_LOG(m_logger) << "Now we have to wait for minefield generation timeout (270s) ...";
QVERIFY2(m_minefieldSpy->wait(270 * 1000), "Generation of minefield timed out");
QFETCH(int, identityResult);
QFETCH(short, mineCountResult);
QFETCH(int, mineDensityResult);
QFETCH(uint32_t, layingDepth);
QFETCH(QVector<Segment_rt>, segmentsResult);
// check for correct minefield data
QCOMPARE(m_receivedMinefield.header.identitaet, identityResult);
QCOMPARE(m_receivedMinefield.beschreibung.kennung, barrierId);
QCOMPARE(m_receivedMinefield.beschreibung.wirkbeginn.gps_zeit, effectStart);
QCOMPARE(m_receivedMinefield.beschreibung.wirkdauer, effectDuration);
QCOMPARE(m_receivedMinefield.beschreibung.minentyp, mineType);
QCOMPARE(m_receivedMinefield.beschreibung.minenanzahl, mineCountResult);
QCOMPARE(m_receivedMinefield.beschreibung.verlegedichte, mineDensityResult);
QCOMPARE(m_receivedMinefield.beschreibung.verlegetiefe, layingDepth);
QCOMPARE(m_receivedMinefield.beschreibung.segmente.size(), static_cast<size_t>(segmentsResult.size()));
// Segments
for (size_t i = 0; i < m_receivedMinefield.beschreibung.segmente.size(); ++i)
{
QCOMPARE(m_receivedMinefield.beschreibung.segmente.at(i).anzahl, segmentsResult.at(i).anzahl);
QCOMPARE(m_receivedMinefield.beschreibung.segmente.at(i).drehwinkel, segmentsResult.at(i).drehwinkel);
QCOMPARE(m_receivedMinefield.beschreibung.segmente.at(i).startpunkt.utm_nordwert, segmentsResult.at(i).startpunkt.utm_nordwert);
QCOMPARE(m_receivedMinefield.beschreibung.segmente.at(i).startpunkt.utm_ostwert, segmentsResult.at(i).startpunkt.utm_ostwert);
}
}
//-------------------------------------------------------------------------------------------------------
void GmpMinefieldInterpreterTestsMain::cleanupTestCase()
{
DEBUG_LOG(m_logger) << "GmpMinefieldInterpreterTestsMain: cleanupTestCase";
m_minefieldInterpreterTimer->stop();
m_minefieldInterpreterTimer->deleteLater();
delete m_minefieldInterpreter;
delete m_minefieldSpy;
}
//-------------------------------------------------------------------------------------------------------
void GmpMinefieldInterpreterTestsMain::onSendMinefield(const wirkfeld_minensperre_rt &minefield, int veType)
{
m_receivedMinefield = minefield;
m_receivedVeType = veType;
}
//-------------------------------------------------------------------------------------------------------
@@ -0,0 +1,48 @@
/**
* @RDE_HEADER@
* UnitTests for GuezMinelayerProcessing (GMP)
* $Id$
* $HeadURL$
* $Author$
* Created by Philipp Dassow, SLEA, 2017-05-29
*/
#pragma once
#include <QObject>
#include <QTimer>
#include <QSignalSpy>
#include <QPair>
#include "../zssi_wi_Minenfeld_Interpreter.h"
namespace NGL
{
class INGLLogger;
}
class GmpMinefieldInterpreterTestsMain : public QObject
{
Q_OBJECT
public:
GmpMinefieldInterpreterTestsMain();
private slots:
void initTestCase();
// void singleLaneMinefieldTestCase();
void minefieldTestCase_data();
void minefieldTestCase();
void cleanupTestCase();
void onSendMinefield(const wirkfeld_minensperre_rt &minefield, int veType);
private:
GuezMinelayerProcessing::ZSSI_WI_Minenfeld_Interpreter *m_minefieldInterpreter;
wirkfeld_minensperre_rt m_receivedMinefield;
int m_receivedVeType;
QTimer *m_minefieldInterpreterTimer;
QSignalSpy *m_minefieldSpy;
NGL::INGLLogger &m_logger;
};
@@ -0,0 +1,79 @@
log4j.reset=true
log4j.rootLogger=WARN, file
# Test: GuezMinelayerProcessing
###########################################################
log4j.logger.Tests.GmpMinefieldInterpreterTest=DEBUG
log4j.logger.GMP.zssi_wi_Minenfeld_Interpreter=INFO
log4j.logger.GMP.zssi_wi_Minenfeld_Generator=INFO
log4j.appender.file=Lts::RollingFileAppender
log4j.appender.file.MaxFileSize=1MB
log4j.appender.file.MaxBackupIndex=9
# will be filled by NGLLogger
log4j.appender.file.file=${LOG4QT_LOGDIR}/${LOG4QT_USER}_gmp_test.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
log4j.appender.file.layout.ConversionPattern=%d %-5p %c |#| %m (%.50F:%L) %n
# Appnd_Console
###########################################################
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern= %d %p %c %c{1} - %m (%-.30F:%L) %n
# Appnd_Syslog
###########################################################
log4j.appender.syslog=org.apache.log4j.SyslogAppender
log4j.appender.syslog.Threshold=ERROR
log4j.appender.syslog.SysLogHost=localhost
log4j.appender.syslog.Facility=LOCAL7
log4j.appender.syslog.layout=org.apache.log4j.PatternLayout
log4j.appender.syslog.layout.ConversionPattern= %-4r %-5p %c %x - %m
log4j.appender.syslog.LevelRangeFilter.AcceptOnMatch=true
log4j.appender.syslog.LevelRangeFilter.LevelMin=INFO
log4j.appender.syslog.LevelRangeFilter.LevelMax=FATAL
###########################################################
###########################################################
###########################################################
# 1) Available Levels in LOG4CXX Version 0.10.0:
# TRACE,
# DEBUG,
# INFO,
# WARN,
# ERROR
# FATAL
#
# d = date/time
# p = priority (Level)
# c = category/channel
# m = message
# F = file
# L = line
# n = platform dependent line separator character or characters.
# ....
#
# Examples for console:
# a)
# %d %p %c #%m# (%.50F:%L)%n
# date/time
# priority
# category/channel
# #message#
# (Maximal 50Character des Filename von rechts:Line)
# line separator
#
# b)
# %d (%.15F:%L) %-5p %c |#| %m%n
# date/time
# (Maximal 15Character des Filename von rechts:Line)
# priority, Right pad with spaces if the priority name is less than 5 characters long.
# category/channel
# message
# line separator
#
# Examples for files:
+37
View File
@@ -0,0 +1,37 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-02
*/
#include "dds_handler.h"
#include <DDS/Core/pacemaker.h>
namespace GuezMinelayerProcessing
{
DdsHandler::DdsHandler(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector)
: m_ddsConnector(ddsConnector)
, m_logger(getLogger("DdsHandler"))
{
DEBUG_LOG(m_logger) << "DdsHandler(" << ddsConnector->getDomainId() << ") for partition: " << m_ddsConnector->getDefaultPartition();
}
bool DdsHandler::init(const QStringList &qosFileList)
{
if (!m_ddsConnector->init(qosFileList))
{
ERROR_LOG(m_logger) << "Error initializing dds connections - aborting";
return false;
}
// default initialize Publisher and Subscriber
m_ddsConnector->initPublisherSubscriber();
return true;
}
} // Namespace GPM
+33
View File
@@ -0,0 +1,33 @@
/**
* DdsHandler for DDS
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-09-02
*/
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include <DDS/Core/topic_lock_master.h>
#include "logger.h"
namespace GuezMinelayerProcessing
{
class DdsHandler final
{
public:
explicit DdsHandler(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector);
~DdsHandler() = default;
bool init(const QStringList &qosFileList = QStringList());
std::shared_ptr<DDSConnector::DdsConnector> ddsConnector() const { return m_ddsConnector; }
std::shared_ptr<Core::TopicLockMaster> topicLockMaster() const { return m_topicLockMaster; }
private:
std::shared_ptr<DDSConnector::DdsConnector> m_ddsConnector;
std::shared_ptr<Core::TopicLockMaster> m_topicLockMaster;
NGL::INGLLogger &m_logger;
};
}
+52
View File
@@ -0,0 +1,52 @@
/**
* Export definitions
* $Id$
* $HeadURL$
* $Author$
* Created by Hanna E. Rathje, SLSE, 2015-08-04
*/
#pragma once
#include <QtCore/qglobal.h>
#ifndef GMP_COMMON_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define GMP_COMMON_EXPORT
# else
# if defined(MAKE_SVCGMPCOMMON_LIB)
# define GMP_COMMON_EXPORT Q_DECL_EXPORT
# ifndef WIN32
# ifdef NDDSUSERDllExport
# undef NDDSUSERDllExport
# endif
# define NDDSUSERDllExport Q_DECL_EXPORT
# endif
# else
# define GMP_COMMON_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef GMP_CLIENT_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define GMP_CLIENT_EXPORT
# else
# if defined(MAKE_SVCGMPCLIENT_LIB)
# define GMP_CLIENT_EXPORT Q_DECL_EXPORT
# else
# define GMP_CLIENT_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
#ifndef GMP_SERVER_EXPORT
# ifdef BUILD_STATIC_LIBRARIES
# define GMP_SERVER_EXPORT
# else
# if defined(MAKE_SVCGMPSERVER_LIB)
# define GMP_SERVER_EXPORT Q_DECL_EXPORT
# else
# define GMP_SERVER_EXPORT Q_DECL_IMPORT
# endif
# endif
#endif
+15
View File
@@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<service namespace="GuezMinelayerProcessing" abbreviation="GMP" procNames="GuezMinelayerProcessing" exerciseDependency="Exercise">
<rcs>
<Id Id="$Id$"/>
<HeadURL HeadURL="$HeadURL$"/>
<Author Author="$Author$"/>
</rcs>
<operatorRights offset="17"/>
<topicTypes/>
<functionTopics/>
<tables/>
<views/>
<dbServiceStructs/>
<enumerations/>
</service>
@@ -0,0 +1,353 @@
/**
* @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))
, m_logger(getLogger("HandlerMinelayerData"))
{}
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(m_logger) << "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(m_logger) << "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(m_logger) << "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(m_logger) << 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(m_logger) << 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(m_logger) << "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(m_logger) << log_tr("Telegramm 'SONDERSENSORIK_MIVANH_VERLEGEDATEN' empfangen");
if ( checkeTelegrammZeit(telegramm_rt.gps_zeit.gps_zeit) ) {
ERROR_LOG(m_logger) << 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(m_logger) << 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(m_logger) << 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(m_logger) << "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(m_logger) << 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(m_logger) << 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(m_logger) << 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(m_logger) << "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(m_logger) << "Sending new minefield from generator to AES: " << outData;
// request create mine area from aes
m_aesFtc->mineAreaModifyFromCtaDataRequest(outData, this);
}
void HandlerMinelayerData::onStartMinefieldInterpreter()
{
INFO_LOG(m_logger) << "Starting minefield interpreter ...";
m_minefieldInterpreter->processData();
}
void HandlerMinelayerData::onMineAreaModifyFromCtaDataReply(const Core::FunctionReplyObject &replyObject)
{
if (replyObject.error())
ERROR_LOG(m_logger) << "Error inserting minefield via AES->FTC";
else
INFO_LOG(m_logger) << "Got onMineAreaCreateFromCtaDataReply reply with id " << replyObject.id();
}
}
@@ -0,0 +1,67 @@
/**
* @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
*/
#pragma once
#include <QObject>
#include <QPointF>
#include <QTimer>
#include <AreaEffectSimulation/aes_ftc.h>
#include <LtsCoordTrans/lts_coord_trans.h>
#include <ParticipantManagement/ppm_dtc.h>
#include <Proxies/TrainingAreaBase/tab_dtc.h>
#include "GFS_map_cont.h"
#include "logger.h"
namespace GuezMinelayerProcessing
{
class DdsHandler;
class ZSSI_WI_Minenfeld_Interpreter;
class HandlerMinelayerData : public QObject
, protected AreaEffectSimulation::Interface::Ftc::MineAreaModifyFromCtaDataReplyHandler
{
Q_OBJECT
public:
explicit HandlerMinelayerData(const std::shared_ptr<DdsHandler> &ddsHandler,
QObject *parent = nullptr);
~HandlerMinelayerData();
bool init();
void onMineAreaModifyFromCtaDataReply(const Core::FunctionReplyObject &replyObject) override final;
private slots:
void onSpecialSensorDataChanged(const TrainingAreaBase::SpecialSensorData &data, DataModification modType);
void onMinelayerTrailerData(const TrainingAreaBase::MinelayerTrailerData &data, DataModification modType);
void onMinelayerThrowerData(const TrainingAreaBase::MinelayerThrowerData &data, DataModification modType);
void onSendMinefield(const wirkfeld_minensperre_rt &minefield, int fzArt);
void onStartMinefieldInterpreter ();
private:
template<typename T>
void convertMinelayerDataToXdrData(const TrainingAreaBase::MinelayerTrailerData &inData, T &outData);
Core::GeoPosition2D geographicFromRelative(const gps_position_rt &position) const;
gps_position_rt relativeFromGeographic(double lon, double lat);
int partyIdFromEquipmentNumber(int eqNumber) const;
std::shared_ptr<DdsHandler> m_ddsHandler;
std::shared_ptr<TrainingAreaBase::Interface::Dtc> m_tabDtc;
std::shared_ptr<ParticipantManagement::Interface::Dtc> m_ppmDtc;
std::shared_ptr<AreaEffectSimulation::Interface::Ftc> m_aesFtc;
LtsCoordTrans::UtmCoordinate m_baseCoord;
ZSSI_WI_Minenfeld_Interpreter *m_minefieldInterpreter;
QTimer *m_minefieldInterpreterTimer;
NGL::INGLLogger &m_logger;
};
} // namespace GuezMinelayerProcessing
+55
View File
@@ -0,0 +1,55 @@
/**
* Initialization for GuezMinelayerProcessing
* $Id$
* $HeadURL$
* $Author$
*/
#include "initialization.h"
#include "dds_handler.h"
#include "handler_minelayer_data.h"
#include <DDS/DDSConnector/dds_connector.h>
using namespace GuezMinelayerProcessing;
Initialization::Initialization()
: m_ddsHandler(nullptr)
, m_handlerMinelayerData(nullptr)
, m_logger(getLogger("Initialization"))
{}
Initialization::~Initialization()
{
m_handlerMinelayerData = nullptr;
m_ddsHandler = nullptr;
}
bool Initialization::initialize(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector)
{
if (m_handlerMinelayerData)
return true;
// initialize DDS
m_ddsHandler.reset(new DdsHandler(ddsConnector));
if (!m_ddsHandler->init())
{
ERROR_LOG(m_logger) << "Initialisation ddsHandler failed.";
return false;
}
// initialize handler minelayer data
m_handlerMinelayerData.reset(new HandlerMinelayerData(m_ddsHandler));
if (!m_handlerMinelayerData->init())
{
ERROR_LOG(m_logger) << "Initialisation m_handlerMinelayerData failed.";
return false;
}
return true;
}
bool Initialization::loadFromDatabase()
{
return true;
}
+35
View File
@@ -0,0 +1,35 @@
/**
* @RDE_HEADER@
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <DDS/DDSConnector/dds_connector.h>
#include <ngldb/db_service_handler.h>
#include <GuezMinelayerProcessing/gmp_export.h>
#include "logger.h"
namespace GuezMinelayerProcessing
{
class DdsHandler;
class HandlerMinelayerData;
class GMP_SERVER_EXPORT Initialization final
{
public:
Initialization();
~Initialization();
bool initialize(const std::shared_ptr<DDSConnector::DdsConnector> &ddsConnector);
bool loadFromDatabase();
private:
std::shared_ptr<DdsHandler> m_ddsHandler;
std::shared_ptr<HandlerMinelayerData> m_handlerMinelayerData;
NGL::INGLLogger &m_logger;
};
} // namespace GuezMinelayerProcessing
+37
View File
@@ -0,0 +1,37 @@
/**
* @RDE_HEADER@
* Building Config - logging facility
* $Id$
* $HeadURL$
* $Author$
*/
#include "logger.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
namespace GuezMinelayerProcessing
{
LOGGER_T getLogger(const char *name)
{
static const char ns[] = "GMP.";
std::string loggerName;
const size_t len = strlen(name);
loggerName.reserve(sizeof(ns) + len);
loggerName.append(ns, sizeof(ns) - 1);
loggerName.append(name, len);
try
{
return NGL::NGLLoggerBootstrap::getNGLRootLogger().
getNGLLogger(loggerName);
}
catch (const std::exception &ex)
{
fprintf(stderr, "Error retrieving logger: %s", ex.what());
abort();
}
}
} // namespace GuezMinelayerProcessing
+23
View File
@@ -0,0 +1,23 @@
/**
* @RDE_HEADER@
* Logging for GuezMinelayerProcessing
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <NGLLogger/INGLLogger.h>
#include "gmp_export.h"
namespace GuezMinelayerProcessing
{
using LOGGER_T = NGL::INGLLogger &;
LOGGER_T getLogger(const char *name);
inline LOGGER_T getLogger(const QString &loggerName)
{
return getLogger(loggerName.toUtf8().constData());
}
} // namespace GuezMinelayerProcessing
+42
View File
@@ -0,0 +1,42 @@
/**
* Settings for GuezMinelayerProcessing
* $Id$
* $HeadURL$
* $Author$
*/
#include "settings.h"
#include <QtCore/QSettings>
#include <nglsettings/nglsettings_settings.h>
#include <ngltools/ngltools_filesystem.h>
namespace GuezMinelayerProcessing
{
class NGLSettingsClass : public NGL::Settings
{
public:
NGLSettingsClass()
: NGL::Settings(s_iniFile.isEmpty() ? NGL::findProjectConfigFile() : s_iniFile)
{}
static void setIniFile(const QString &fn)
{
s_iniFile = fn;
}
static QString s_iniFile;
};
QString NGLSettingsClass::s_iniFile;
Q_GLOBAL_STATIC(NGLSettingsClass, s)
//-----------------------------------------------------------------------------
NGL::Settings *Settings::settings()
{
return s();
}
//-----------------------------------------------------------------------------
void Settings::setIniFile(const QString &ini)
{
NGLSettingsClass::setIniFile(ini);
}
} // namespace GuezMinelayerProcessing
+25
View File
@@ -0,0 +1,25 @@
/**
* Settings for GuezMinelayerProcessing
* $Id$
* $HeadURL$
* $Author$
*/
#pragma once
#include <QString>
#include <GuezMinelayerProcessing/gmp_export.h>
namespace NGL
{
class Settings;
}
namespace GuezMinelayerProcessing
{
namespace Settings
{
NGL::Settings *settings();
GMP_SERVER_EXPORT void setIniFile(const QString &ini);
}
} // namespace GuezMinelayerProcessing
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,148 @@
/* --------------------------------------------------------------------
// $HeadURL$
// --------------------------------------------------------------------
//!
// --------------------------------------------------------------------
// COPYRIGHT (C) 1996: STN ATLAS ELEKTRONIK GMBH, D-28305 BREMEN
// --------------------------------------------------------------------
//
// HIER/ITEM : CSU: RP 5182 P 005 SRC 01102
// BRIEF DESC: Funktionalitaet Minengenerator
// AUTHOR : Ingo Kannetzky
// RELEASE :
// MODIF/STAT: 29.02.00
// ORIGIN REF:
//
// Revision INFO:
// --------------
// $Revision$
// $Date$
// $Id$
// $Author$
//
// LANGUAGE: C++ (Compiler: CC Version: XXX)
// LANGUAGE: C++ (Compiler: MSVC Version: 5.0)
//
// PURPOSE:
// --------
//
// Aufgabe dieser Funktion ist es, aus den Daten der Minenstreifen Modellparameter fr ein Minensperre zu errechnen. Zus�zlich wird
// eine eindeutige Kennung berechnet und s�tliche Daten als Gefechtsfeldtelegramm "Wirkfeld Minensperre" aufbereitet und mittels
// "ZSSI_WI_Telegramme_versenden" in das Empfangs- und in das Sende-verzeichnis der SWKE Kommunikationssystem kopiert.
//
//
//
// ERROR HANDLING:
// ---------------
// (keine / Beschreibung)
//
// IMPLEMENTATION DETAILS:
// -----------------------
//
//
//
//!
*/
#ifndef ZSSI_WI_MINENFELD_GENERATOR_H
#define ZSSI_WI_MINENFELD_GENERATOR_H
/*------------------ includes ----------------------------*/
#include <QObject>
#include "GFS_map_cont.h"
/*------------------ imports/exports ---------------------*/
/*------------------ externals (procs + vars) ------------*/
/*------------------ types -------------------------------*/
/*------------------ globals -----------------------------*/
/*------------------ revision id-code --------------------*/
/*------------------ statics -----------------------------*/
/*------------------ constants ---------------------------*/
/*-------------------function prototypes -----------------*/
extern GFS_Map_Container<VERLEGEDATEN_KEY, VERLEGEDATEN_INTERN> interne_datenbasis_Verlegedaten;
extern GFS_Map_Container<VERLEGEDATEN_KEY, FAHRSPUR_INTERN> interne_datenbasis_Fahrspur;
float Punktabstand(const gps_position_rt &p1, const gps_position_rt &p2);
// copied from zssi_wi_Minen_math.cpp
float Punktabstand(float x1, float y1, float x2, float y2);
namespace GuezMinelayerProcessing {
class ZSSI_WI_Minenfeld_Generator : public QObject
{
Q_OBJECT
public:
explicit ZSSI_WI_Minenfeld_Generator(QObject *parent = nullptr);
~ZSSI_WI_Minenfeld_Generator();
void processData();
signals:
void sendeWirkfeld(const wirkfeld_minensperre_rt &minensperre, int fzArt);
};
}
#endif /* ifndef ZSSI_WI_MINENFELD_GENERATOR_H */
/*--------------------------------------------------------------------
// END $HeadURL$
//--------------------------------------------------------------------
// *** PCO - DOMAIN ***
//
// n/ Michael Arendt:SGE3,3936 / 07.04.99
// zz / no.
//
//
// E:
//
// $Log: zssi_wi_Minenfeld_Generator.h,v $
// Revision 1.1.1.1 2005/02/11 14:10:42 guez
// CTC MOUT Zentrale
//
// Revision 1.1.2.7 2002/10/31 13:31:57 e_entw
// Fkt check_anz_minen behoben
//
// Revision 1.1.2.6 2002/04/24 07:57:50 e_entw
// Funktion check_anz_minen hinzugefuegt
//
// Revision 1.1.2.5 2000/03/01 13:15:57 e_entw
// Kommentare eingefuegt bearbeitet !!
//
// Revision 1.1.2.4 2000/02/17 13:45:37 e_entw
// Programmsachnummern !!
//
// Revision 1.1.2.3 1999/10/18 13:13:59 e_entw
// Neuer Stand mit Minen !!
//
// Revision 1.1.2.2 1999/10/06 13:10:48 e_entw
// Einspurige Minensperre/Generator/Interpreter hinzugefuegt , Minensperre kann ueber MMI eingefuegt werden
//
// Revision 1.1.2.1 1999/10/01 08:30:50 e_entw
// Neuer Stand Minen !!!
//
// Revision 1.1.2.2 1999/09/21 08:10:31 e_entw
// Neues X-File
//
// Revision 1.1.2.1 1999/09/15 07:55:53 e_entw
// Neuer Stand mit DMF und Mineninterpreter
//
//
// B:
//
// D:
//
*/
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,160 @@
/* --------------------------------------------------------------------
// $HeadURL$
// --------------------------------------------------------------------
//!
// --------------------------------------------------------------------
// COPYRIGHT (C) 1996: STN ATLAS ELEKTRONIK GMBH, D-28305 BREMEN
// --------------------------------------------------------------------
//
// HIER/ITEM : CSU: RP 5182 P 005 SRC 01105
// BRIEF DESC: Funktionalitaet Mineninterpreter
// AUTHOR : Ingo Kannetzky
// RELEASE :
// MODIF/STAT: 22.02.00
// ORIGIN REF:
//
// Revision INFO:
// --------------
// $Revision$
// $Date$
// $Id$
// $Author$
//
// LANGUAGE: C++ (Compiler: CC Version: XXX)
// LANGUAGE: C++ (Compiler: MSVC Version: 5.0)
//
// PURPOSE:
// --------
// Funktionalitaet Mineninterpreter
//
//
//
// ERROR HANDLING:
// ---------------
// (keine / Beschreibung)
//
// IMPLEMENTATION DETAILS:
// -----------------------
//
//
//
//!
*/
#pragma once
/*------------------ includes ----------------------------*/
#include <QObject>
#include "GFS_map_cont.h"
#include "zssi_wi_Minenfeld_Generator.h"
/*------------------ imports/exports ---------------------*/
/*------------------ externals (procs + vars) ------------*/
/*------------------ types -------------------------------*/
/*------------------ globals -----------------------------*/
/*------------------ revision id-code --------------------*/
/*------------------ statics -----------------------------*/
/*------------------ constants ---------------------------*/
// copied from zssi_wi_Types.h
constexpr int MV_VERLEGEN = 98;
constexpr int WMV_VERLEGEN = 119;
// copied from zsksmal_wirksimulation.h
constexpr double FAKTOR_VERLEGEDICHTE = 100;
/*-------------------function prototypes -----------------*/
VERLEGEDATEN_KEY Key_des_zugehoerigen_Verlegebeginns(const VERLEGEDATEN_KEY &);
VERLEGEDATEN_KEY Key_des_zugehoerigen_Verlegeendes(const VERLEGEDATEN_KEY &);
int Eintrag_vor_zugehoerigem_Verlegebeginn(const VERLEGEDATEN_KEY &);
namespace GuezMinelayerProcessing
{
class ZSSI_WI_Minenfeld_Interpreter : public QObject
{
Q_OBJECT
public:
const int triggerIntervall = 10; // Intervall in Sekunden in dem der Interpreter in der alten SW aufgerufen wurde
explicit ZSSI_WI_Minenfeld_Interpreter(QObject *parent = nullptr);
~ZSSI_WI_Minenfeld_Interpreter();
void processData();
void ZSSI_WI_modifiziere_Verlegedaten(const VERLEGEDATEN_KEY &,
const VERLEGEDATEN_INTERN &);
signals:
void sendeWirkfeld(const wirkfeld_minensperre_rt &minensperre, int fzArt);
private:
void ZSSI_WI_Erstelle_einzel_minensperre(const VERLEGEDATEN_KEY &key,
const VERLEGEDATEN_INTERN &daten);
ZSSI_WI_Minenfeld_Generator *m_minenfeldGenerator;
};
}
/*--------------------------------------------------------------------
// END $HeadURL$
//--------------------------------------------------------------------
// *** PCO - DOMAIN ***
//
// n/ Michael Arendt:SGE3,3936 / 07.04.99
// zz / no.
//
//
// E:
//
// $Log: zssi_wi_Minenfeld_Interpreter.h,v $
// Revision 1.1.1.1 2005/02/11 14:10:42 guez
// CTC MOUT Zentrale
//
// Revision 1.1.2.9 2002/04/24 05:16:14 e_entw
// Ueberabeitung des Kopfes
//
// Revision 1.1.2.8 2001/03/21 09:12:31 e_entw
// Hinzufuegen von Funktionen zur Erstellung von Verlege-Minensperren,
// da 3 neue Verlegearten hinzugekommen sind. (RP 1249)
//
// Revision 1.1.2.7 2000/02/22 16:08:06 e_entw
// Realisierung Raeumen von Minensperren !!
//
// Revision 1.1.2.6 2000/02/17 13:45:39 e_entw
// Programmsachnummern !!
//
// Revision 1.1.2.5 1999/11/17 14:06:44 e_entw
// Umstellung auf Status 119 und 98 in Fahrspurtelegrammauswertung
//
// Revision 1.1.2.4 1999/10/06 13:10:50 e_entw
// Einspurige Minensperre/Generator/Interpreter hinzugefuegt , Minensperre kann ueber MMI eingefuegt werden
//
// Revision 1.1.2.3 1999/09/24 09:34:05 e_entw
// Stand abgeglichen (Arendt/Kannetzky)
//
// Revision 1.1.2.2 1999/09/21 08:10:31 e_entw
// Neues X-File
//
// Revision 1.1.2.1 1999/09/15 07:55:53 e_entw
// Neuer Stand mit DMF und Mineninterpreter
//
//
// B:
//
// D:
//
*/