Initial commit
This commit is contained in:
commit
b7d90b9afe
16245 files changed
+3396666
No files matched your search
+190
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
* Effector Firing Strategy for DM72
|
||||
* $Id$
|
||||
* $HeadURL$
|
||||
* $Author$
|
||||
* Created by Hannes Fritsche, ESZS, 2026-05-21
|
||||
*/
|
||||
|
||||
#include "dm72_firing_strategy.h"
|
||||
|
||||
#include "main_handler.h"
|
||||
#include "object_effector.h"
|
||||
|
||||
#include <LtsCoordTrans/lts_coord_trans.h>
|
||||
#include <TrainingAreaBase/Plugins/AdlerJson/telegrams.h>
|
||||
#include <Trajectory/trajectory_transform.h>
|
||||
|
||||
#include <QJsonArray>
|
||||
#include <QJsonDocument>
|
||||
#include <QJsonObject>
|
||||
#include <QJsonValue>
|
||||
#include <QTransform>
|
||||
|
||||
namespace AreaEffectSimulation
|
||||
{
|
||||
|
||||
Dm72FiringStrategy::Dm72FiringStrategy(ObjectEffector *effector)
|
||||
: AbstractFiringStrategy(effector)
|
||||
{
|
||||
init();
|
||||
|
||||
DEBUG_LOG(m_logger) << "using Dm72FiringStrategy";
|
||||
}
|
||||
|
||||
void Dm72FiringStrategy::doFiring()
|
||||
{
|
||||
m_transformedTrajectory = TrajectoryTransform::transformToNewTarget(m_effector->intendendTrajectory(), m_impactPoints.at(m_impactPointIndex++));
|
||||
|
||||
if (m_impactPointIndex >= m_impactPoints.size())
|
||||
m_impactPointIndex = 0;
|
||||
|
||||
const qint64 trajectoryStartTime = getStartTime();
|
||||
|
||||
const auto &geometry = buildTrajectoryGeometry(m_transformedTrajectory);
|
||||
const auto &trajTimeAware = buildTrajectoryTimeAware(geometry, trajectoryStartTime);
|
||||
|
||||
QJsonObject props{{QStringLiteral("effectDurationMsec"), m_effectDurationMsec}};
|
||||
const int chargeEffectId = sendChargeEffect(trajTimeAware, props);
|
||||
|
||||
emit signalFired(m_effector->participantId(), m_effector->aesItemId(), {chargeEffectId});
|
||||
}
|
||||
|
||||
void Dm72FiringStrategy::init()
|
||||
{
|
||||
using namespace AdlerJson;
|
||||
using namespace LtsCoordTrans;
|
||||
|
||||
m_impactPointIndex = 0;
|
||||
m_impactPoints.clear();
|
||||
|
||||
bool bOk;
|
||||
WirkmittelFeuerkommandoRakete wirkmittel;
|
||||
const QJsonObject properties = QJsonDocument::fromJson(QByteArray::fromStdString(m_effector->effectorData().properties())).object();
|
||||
const Core::GeoPosition geoStartPos = participantPosition(m_effector->participantId());
|
||||
const UtmCoordinate utmStartPos = UtmCoordinate::fromGeographic(geoStartPos.lon(), geoStartPos.lat());
|
||||
|
||||
wirkmittelFeuerkommandoRaketeFromJson(properties, wirkmittel, bOk);
|
||||
|
||||
using UtmWithHeight = std::pair<UtmCoordinate, int>;
|
||||
|
||||
m_effectDurationMsec = getFeuerkommandoRaketeEffectDurationMsec(properties);
|
||||
QVector<UtmWithHeight> tempUtmTreffpunkte;
|
||||
tempUtmTreffpunkte.reserve(wirkmittel.geschoss.anzahl);
|
||||
|
||||
for (const Treffpunkt &treffpunkt : qAsConst(wirkmittel.treffpunkte))
|
||||
{
|
||||
const UtmCoordinate utmTreffpunkt = UtmCoordinate::fromGeographic(treffpunkt.koordinate.koordinate.longitude * deg2rad(),
|
||||
treffpunkt.koordinate.koordinate.latitude * deg2rad(),
|
||||
utmStartPos.zone);
|
||||
|
||||
for (int anzahlCounter = 1; anzahlCounter <= treffpunkt.anzahl; ++anzahlCounter)
|
||||
tempUtmTreffpunkte.append({utmTreffpunkt, treffpunkt.koordinate.hoehe});
|
||||
}
|
||||
|
||||
const QVector<QPointF> mineLayingCentroidDeviations = mineLayingCentroids();
|
||||
int deviationIndex = 0;
|
||||
|
||||
for (const UtmWithHeight &tempUtmTreffpunkt : tempUtmTreffpunkte)
|
||||
{
|
||||
const QPointF &deviation = mineLayingCentroidDeviations.at(deviationIndex++);
|
||||
const LtsUtils::QPoint3D impactPoint(tempUtmTreffpunkt.first.x - utmStartPos.x + deviation.x(),
|
||||
tempUtmTreffpunkt.first.y - utmStartPos.y + deviation.y(),
|
||||
tempUtmTreffpunkt.second);
|
||||
|
||||
m_impactPoints.append(impactPoint);
|
||||
|
||||
if (deviationIndex >= mineLayingCentroidDeviations.size())
|
||||
deviationIndex = 0;
|
||||
}
|
||||
|
||||
DEBUG_LOG(m_logger) << "Got " << m_impactPoints.size() << " impact points";
|
||||
}
|
||||
|
||||
QVector<QPointF> Dm72FiringStrategy::mineLayingCentroids() const
|
||||
{
|
||||
using namespace LtsCoordTrans;
|
||||
|
||||
const int chargeTypeId = m_effector->effectorData().chargeStruct().chargeTypeId();
|
||||
const ProjectDataManagement::ChargeType &chargeType = m_effector->mainHandler()->dds()->pdmDtc()->chargeType(chargeTypeId);
|
||||
const QJsonObject chargeTypeProperties = QJsonDocument::fromJson(QByteArray::fromStdString(chargeType.properties())).object();
|
||||
const QJsonObject mineLaying = chargeTypeProperties.value(QStringLiteral("mineLaying")).toObject();
|
||||
const QJsonArray mineLayingPattern = mineLaying.value(QStringLiteral("pattern")).toArray();
|
||||
/* QMap is used here because it sort its entries by key.
|
||||
* Since each pattern has an id and we want the pattern sorted by id, adding them to a QMap
|
||||
* automatically sorts the pattern.
|
||||
*/
|
||||
QMap<int, QPointF> centroidsMap;
|
||||
const UtmCoordinate mhpUtm = UtmCoordinate::fromGeographic(m_effector->effectorData().mhpPosition().lon(),
|
||||
m_effector->effectorData().mhpPosition().lat());
|
||||
const double rotationAngle = angleToMhpUtm(mhpUtm.toPoint());
|
||||
QTransform rotation;
|
||||
|
||||
rotation.rotate(rotationAngle);
|
||||
|
||||
for (const QJsonValue &patternValue: mineLayingPattern)
|
||||
{
|
||||
const QJsonObject patternObject = patternValue.toObject();
|
||||
const int patternId = patternObject.value(QStringLiteral("id")).toInt();
|
||||
const QJsonArray patternPositionArray = patternObject.value(QStringLiteral("positions")).toArray();
|
||||
int sumNorthing = 0;
|
||||
int sumEasting = 0;
|
||||
|
||||
for (const QJsonValue &positionValue : patternPositionArray)
|
||||
{
|
||||
const QJsonObject positionObject = positionValue.toObject();
|
||||
|
||||
const int northing = positionObject.value(QStringLiteral("northing")).toInt();
|
||||
const int easting = positionObject.value(QStringLiteral("easting")).toInt();
|
||||
|
||||
sumNorthing += northing;
|
||||
sumEasting += easting;
|
||||
}
|
||||
|
||||
QPointF centroid(static_cast<double>(sumEasting) / patternPositionArray.size(), static_cast<double>(sumNorthing) / patternPositionArray.size());
|
||||
|
||||
centroid = rotation.map(centroid);
|
||||
|
||||
centroidsMap.insert(patternId, centroid);
|
||||
}
|
||||
|
||||
if (centroidsMap.isEmpty())
|
||||
{
|
||||
WARNING_LOG(m_logger) << "Could not read mine laying patterns from DM72 ammunition properties for creation of DM72 trajectories.";
|
||||
|
||||
return { QPointF(0.0, 0.0) }; // We have to return at least one QPointF(0.0, 0.0) to ensure later DM72 functionality
|
||||
}
|
||||
|
||||
int vectorIndex = 0;
|
||||
QVector<QPointF> mineLayingCentroids;
|
||||
|
||||
mineLayingCentroids.reserve(centroidsMap.size());
|
||||
|
||||
for (auto it = centroidsMap.constBegin(); it != centroidsMap.constEnd(); ++it)
|
||||
mineLayingCentroids.insert(vectorIndex++, it.value()); // insert with index ensures sorting
|
||||
|
||||
return mineLayingCentroids;
|
||||
}
|
||||
|
||||
double Dm72FiringStrategy::angleToMhpUtm(const QPointF &mhpUtm) const
|
||||
{
|
||||
const ParticipantManagement::ParticipantPosition &ownPosition = m_effector->mainHandler()->dds()->ppmDtc()->participantPosition(m_effector->participantId());
|
||||
const LtsCoordTrans::UtmCoordinate ownPositionUtm = LtsCoordTrans::UtmCoordinate::fromGeographic(ownPosition.pos().lon(), ownPosition.pos().lat());
|
||||
const double angle = QLineF(mhpUtm, ownPositionUtm.toPoint()).angle();
|
||||
double northAngle = 90 - angle;
|
||||
|
||||
northAngle = std::fmod(northAngle, 360.0);
|
||||
|
||||
if (northAngle < 0.0)
|
||||
northAngle += 360.0;
|
||||
|
||||
DEBUG_LOG(m_logger) << "angleToMhpUtm:"
|
||||
<< "mhpUtm=" << mhpUtm
|
||||
<< ", ownPositionUtm=" << ownPositionUtm.toPoint()
|
||||
<< ", angle=" << angle
|
||||
<< ", northAngle=" << northAngle;
|
||||
|
||||
return northAngle;
|
||||
}
|
||||
|
||||
} // namespace AreaEffectSimulation
|
||||
Reference in new issue
Block a user