#include "handler_nasat_impact.h" #include "initialization.h" #include "dds_handler.h" #include "handler_participant.h" #include #include #include #include #include #ifdef TRIGGER_DUMMY_IMPACT # include #endif namespace GuezNasat { HandlerNasatImpact::HandlerNasatImpact(Initialization *mainHandler) : AreaEffectSimulation::Interface::Ftc::AirSupportImpactModifyReplyHandler() , m_logger(getLogger("HandlerNasatImpact")) , m_mainHandler(mainHandler) { TRACE_LOG(m_logger) << Q_FUNC_INFO << " START"; auto pdmDtc = m_mainHandler->dds()->pdmDtc(); connect(pdmDtc.get(), &ProjectDataManagement::Interface::Dtc::chargeTypeChanged, this, &HandlerNasatImpact::onChargeTypeChanged); pdmDtc->chargeTypes([this](const ProjectDataManagement::ChargeType &ct) { onChargeTypeChanged(ct);}); #ifdef TRIGGER_DUMMY_IMPACT FATAL_LOG(m_logger) << Q_FUNC_INFO << " prepare singleShot..."; QTimer *timer = new QTimer; timer->setInterval(30000); connect(timer, &QTimer::timeout, [this] () { FATAL_LOG(m_logger) << Q_FUNC_INFO << " singleShot..."; NasatWeaponRelease wr; wr.aircraftId = 1; GeoPosition2D geoPos; geoPos.lon = 11.56; geoPos.lat = 52.46; wr.impactPosition = geoPos; wr.flightTime = 5; wr.munition = Munition::MSL_AGM_114K; wr.fuseType = FuseType::Instant; wr.releaseMode = ReleaseMode::Undefined; this->nasatWeaponRelease(wr); FATAL_LOG(m_logger) << Q_FUNC_INFO << " singleShot...DONE"; }); timer->start(); #endif TRACE_LOG(m_logger) << Q_FUNC_INFO << " END"; } void HandlerNasatImpact::onAirSupportImpactModifyReply(const Core::FunctionReplyObject &reply) { if (reply.error()) WARNING_LOG(m_logger) << "Could not create single explosion for nasat impact: " << reply(); #ifdef NLDEVCTRL_844 testing.replyCounter++; INFO_LOG(m_logger) << "Got create reply: " << reply() << "(id=" << reply.id() << ")" << ", this=" << this << " - replyCounter=" << testing.replyCounter; #else INFO_LOG(m_logger) << "Got create reply: " << reply() << "(id=" << reply.id() << ")" << ", this=" << this; #endif } void HandlerNasatImpact::onExplosionClusterModifyReply(const Core::FunctionReplyObject &reply) { INFO_LOG(m_logger) << "Got create reply: " << reply() << "(id=" << reply.id() << ")" << ", this=" << this << ", reply.error()=" << reply.error(); if (reply.error()) ERROR_LOG(m_logger) << "onExplosionClusterModifyReply: Got reply: " << reply() << "(id=" << reply.id() << ")" << " '" << reply.translated() << "'"; } void HandlerNasatImpact::nasatWeaponRelease(const GuezNasat::NasatWeaponRelease &weaponRelease) { const Core::GeoPosition geoPos(weaponRelease.impactPosition.lon * LtsCoordTrans::deg2rad(), weaponRelease.impactPosition.lat * LtsCoordTrans::deg2rad(), 0); double tsWeaponRelease = weaponRelease.timestamp < 0 ? QDateTime::currentSecsSinceEpoch() : weaponRelease.timestamp; tsWeaponRelease += 5; qint64 impactTimeMsec = qRound64((tsWeaponRelease + weaponRelease.flightTime) * 1000); qint64 weaponReleaseMsec = qRound64(weaponRelease.flightTime * 1000); nasatImpact(weaponRelease.aircraftId, geoPos, weaponReleaseMsec, impactTimeMsec, static_cast(weaponRelease.munition), weaponRelease.fuseType); } void HandlerNasatImpact::nasatImpact(int nasatId, const Core::GeoPosition &pos, qint64 flightTimeMsec, qint64 impactTimeMsec, int munitionCode, FuseType fuseType) { #ifdef NLDEVCTRL_844 static bool bEnable = true; if (!bEnable) return; #endif DEBUG_LOG(m_logger) << Q_FUNC_INFO << " START, nasatId=" << nasatId << ", pos=" << pos << ", flightTimeMsec = " << flightTimeMsec << ", impactTimeMsec = " << impactTimeMsec; const auto participants = m_mainHandler->handlerParticipant()->participantsForNasatId(nasatId); if (participants.isEmpty()) { WARNING_LOG(m_logger) << "Can not find a valid participant for nasat aircraft with id " << nasatId; return; } const int chargeTypeIdVal = chargeTypeFromMunitionCode(munitionCode); if (chargeTypeIdVal < 0) return; const QDateTime dtNow = QDateTime::currentDateTime(); const qint64 tNow = dtNow.toMSecsSinceEpoch() + 5000; AreaEffectSimulation::ExplosionClusterSingleEffectOnlyRequest ecReq; ecReq.id = 0; ecReq.effectStart = impactTimeMsec > tNow ? impactTimeMsec : tNow; ecReq.name = QStringLiteral("NASAT_%1_%2_%3").arg(nasatId).arg(munitionCode).arg(dtNow.toString(QStringLiteral("dd hh:mm:ss"))).toStdString(); ecReq.element = ecReq.name; ecReq.impactPosition = Core::GeoPosition2D(pos.lon, pos.lat); ecReq.chargeTypeId = chargeTypeIdVal; if (m_logger.isDebugEnabled()) { const Core::GeoPosition &nasatPos = m_mainHandler->handlerParticipant()->nasatPosition(nasatId); DEBUG_LOG(m_logger) << Q_FUNC_INFO << " START, nasatId=" << nasatId << ", pos=" << nasatPos << ", flightTimeMsec = " << flightTimeMsec << ", impactTimeMsec=" << impactTimeMsec; } AreaEffectSimulation::ExplosionClusterModifyRequest ecCommonModifyRequest; ecCommonModifyRequest.id = 0; ecCommonModifyRequest.effectStart = impactTimeMsec > tNow ? impactTimeMsec : tNow; ecCommonModifyRequest.effectDuration = 1000; ecCommonModifyRequest.effectSourceId = ProjectDataManagement::EffectSource::ES_Internal; ecCommonModifyRequest.explosionGeometry = AreaEffectSimulation::AesExplosionGeometry::EgPoint; ecCommonModifyRequest.chargeStruct.chargeTypeId = chargeTypeIdVal; ecCommonModifyRequest.chargeStruct.igniterTypeId = fuseTypeToPdmIgniterType(fuseType); ecCommonModifyRequest.area.cornerBottomLeft = Core::GeoPosition2D(pos.lon, pos.lat); ecCommonModifyRequest.name = QStringLiteral("NASAT_%1_%2_%3").arg(nasatId).arg(munitionCode).arg(dtNow.toString(QStringLiteral("dd hh:mm:ss"))).toStdString(); ecCommonModifyRequest.element = ecReq.name; ecCommonModifyRequest.mhpCount = 1; ecCommonModifyRequest.impactCount = 1; ecCommonModifyRequest.flightDuration = flightTimeMsec; DEBUG_LOG(m_logger) << " Sending air support impact: number of participant= " << participants.size(); for (const NasatAircraftParticipantEx *nap : participants) { ecReq.partyId = nap->partyId(); ecCommonModifyRequest.partyId = nap->partyId(); ecCommonModifyRequest.participantId = nap->participantId(); int success = nap->publisher()->publish(ecCommonModifyRequest, this); if (success) DEBUG_LOG(m_logger) << "Sending air support impact create request: " << ecReq << " to exercise " << nap->exerciseId() << ", nap=" << nap->participant() << " -> success = " << success; else ERROR_LOG(m_logger) << "Error on Sending air support impact create request: " << ecReq << " to exercise " << nap->exerciseId() << ", nap=" << nap->participant() << " -> success = " << success; #ifdef NLDEVCTRL_844 testing.requestCounter++; INFO_LOG(m_logger) << " requestCounter = " << testing.requestCounter; #endif } #ifdef NLDEVCTRL_844 bool bOk = (testing.requestCounter - testing.replyCounter) < 23; FATAL_LOG(m_logger) << " bOk= " << bOk << ", requestCounter = " << testing.requestCounter << ", replyCounter = " << testing.replyCounter; if (!bOk) { FATAL_LOG(m_logger) << " bOk= " << bOk << ", requestCounter = " << testing.requestCounter << " -> DISABLE"; bEnable = false; abort(); } if (testing.requestCounter > 70) { FATAL_LOG(m_logger) << " bOk= " << bOk << ", requestCounter = " << testing.requestCounter << " -> RESTART"; exit(42); } #endif } void HandlerNasatImpact::onChargeTypeChanged(const ProjectDataManagement::ChargeType &ct) { const QJsonDocument doc(QJsonDocument::fromJson(QByteArray::fromRawData(ct.properties.c_str(), ct.properties.size()))); const QJsonObject obj(doc.object()); if (!obj.contains(QLatin1String("nasatId"))) return; int nasatId = obj.value(QLatin1String("nasatId")).toInt(); if (nasatId == 0) { WARNING_LOG(m_logger) << "Found charge with an invalid property 'nasatId', id: " << ct.id; return; } m_chargeMapping.insert(nasatId, ct.id); } int HandlerNasatImpact::chargeTypeFromMunitionCode(int nasatChargeCode) const { auto it = m_chargeMapping.find(nasatChargeCode); if (it != m_chargeMapping.end()) return it.value(); WARNING_LOG(m_logger) << "Got unmapped nasat charge code " << nasatChargeCode; Q_ASSERT(false); return -1; } int HandlerNasatImpact::fuseTypeToPdmIgniterType(FuseType fusetype) const { switch (fusetype) { case FuseType::Instant: return 102; case FuseType::Delay: return 103; case GuezNasat::FuseType::AirBurst: return 101; default: return 102; } } }