Files
qt5-legatus-legacy/Lts/Proxies/TrainingAreaBase/Plugins/UAS/from_tab.cpp
T
2026-08-13 18:33:10 +02:00

248 lines
6.9 KiB
C++
Executable File

/**
* "SendToTab" implementation to receive requests from TAB (which originate from the OpApp)
* $Id$
* $HeadURL$
* $Author$
* Created by Mike Wille, ESZS, 2025-04-17
*/
#include "from_tab.h"
#include "uav_ia_manager.h"
#include <NGLLogger/NGLLoggerBootstrap.h>
#include <ProjectDataManagement/pdm_dtc.h>
#include <TrainingAreaBase/recv_from_tab.h>
#include <QJsonDocument>
#include <QJsonObject>
namespace UAS
{
FromTab::FromTab(const std::shared_ptr<TrainingAreaBase::DdsHandler> &ddsHandler,
const std::shared_ptr<TrainingAreaBase::RecvFromTab> &sendToDds,
UAVInterfaceAdapterManager *uavIAManager, int exerciseId)
: m_isConnected(false)
, m_dtcPdm(ProjectDataManagement::Interface::Dtc::create(ddsHandler->ddsConnector()))
, m_dtcPpm(ParticipantManagement::Interface::Dtc::create(ddsHandler->ddsConnector()))
, m_sendToDds(sendToDds)
, m_uavIAManager(uavIAManager)
, m_exerciseId(exerciseId)
, m_logger(NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger("FromTab"))
{
m_dtcPpm->enableUAS();
m_dtcPpm->enableParticipant();
}
TrainingAreaBase::SendToTab::HandleState FromTab::canHandleTelegram(int equipmentNumber, int telegramId) const
{
bool found = false;
const auto &uasList = m_dtcPpm->uASs();
for (const auto &uas : uasList)
{
if (uas.exerciseId() != m_exerciseId)
{
continue;
}
const auto &part = m_dtcPpm->participant(uas.participantId());
if (!part.equipmentNumber().is_set())
{
continue;
}
if (part.equipmentNumber().get() == equipmentNumber)
{
found = true;
break;
}
}
using namespace TrainingAreaBase::TetraIcd;
if (!found)
{
return HandleState::No;
}
if (telegramId == Constraints<UAVPerformMission>::id())
{
return HandleState::YesConsume; // we're the only plugin able to fly drones ;)
}
if (telegramId == Constraints<UAVChangeState>::id())
{
return HandleState::YesConsume; // we're the only plugin able to fly drones ;)
}
if (telegramId == Constraints<CesHitRequest>::id())
{
return HandleState::YesShare; // participants hit (jam) the drone, we need this info to tell the drone to e.g. return to home after a hit
}
if (telegramId == Constraints<DemandVulnerabilityStateChange>::id())
{
return HandleState::YesConsume;
}
if (telegramId == Constraints<Init>::id())
{
return HandleState::YesConsume;
}
return HandleState::No; // we handle drone telegrams ONLY
}
bool FromTab::txData(const TrainingAreaBase::TetraIcd::Init &data)
{
if (!data.resetVulnerabilityState)
{
return false;
}
//send statechange init
TrainingAreaBase::TetraIcd::StateChange msg;
msg.header.equipmentNumber = data.header.equipmentNumber;
msg.header.timeStamp = QDateTime::currentMSecsSinceEpoch(); //data.timestamp * 1000;
msg.originatorId = data.workstationId;
msg.originatorType = TrainingAreaBase::TetraIcd::OriginatorType::ExerciseControl;
msg.tasVitality = 100;
msg.vulnerabilityBits = 0;
msg.vulnerabilityState = TrainingAreaBase::TetraIcd::VulnerabilityState::CombatReady;
m_sendToDds->rxData(msg);
return true;
}
bool FromTab::txData(const TrainingAreaBase::TetraIcd::UAVPerformMission &data)
{
const int eqId = data.header.equipmentNumber;
DEBUG_LOG(m_logger) << "eqId: " << eqId;
const ParticipantManagement::Participant p = m_dtcPpm->participant(m_dtcPpm->participantIdByEquipmentNumber(eqId));
if (p.id() <= 0)
{
WARNING_LOG(m_logger) << "participant not found - stop";
return false;
}
// NOTE: only first action is performed ...
const auto &action = data.actions.front();
if (!m_uavIAManager->waypoint(p.id(), action.absPosition, QStringLiteral("%1_%2").arg(data.missionId).arg(data.missionName))) // send waypoint to uav
{
WARNING_LOG(m_logger) << "sending waypoint failed!";
return false;
}
return true;
}
bool FromTab::txData(const TrainingAreaBase::TetraIcd::UAVChangeState &data)
{
const int eqId = data.header.equipmentNumber;
const ParticipantManagement::Participant p = m_dtcPpm->participant(m_dtcPpm->participantIdByEquipmentNumber(eqId));
if (p.id() <= 0)
{
WARNING_LOG(m_logger) << "participant not found - stop";
return false;
}
// NOTE: only first action is performed ...
switch (data.requestedState)
{
case TrainingAreaBase::TetraIcd::UAVState::Auto:
return m_uavIAManager->tryChangeModeToAuto(p.id());
default:
return true;
}
return true;
}
bool FromTab::txData(const TrainingAreaBase::TetraIcd::CesHitRequest &data)
{
// drone was hit by jamming
DEBUG_LOG(m_logger) << "data.chargeTasCodeDirect = " << data.chargeTasCodeDirect;
// NOTE: igniterType/IgniterFunciton = 0 as long as CesHitRequest does not contain values
if (!m_dtcPdm->isJamming(data.chargeTasCodeDirect,0,0))
{
WARNING_LOG(m_logger) << "not jamming";
return false;
}
DEBUG_LOG(m_logger) << "participantEventChanged: JAMMING! chargetasCodeDirect = " << data.chargeTasCodeDirect;
const int eqId = data.header.equipmentNumber;
const ParticipantManagement::Participant p = m_dtcPpm->participant(m_dtcPpm->participantIdByEquipmentNumber(eqId));
if (p.id() <= 0)
{
WARNING_LOG(m_logger) << "participant not found - stop";
return false;
}
m_uavIAManager->kill(p.id()); // kill UAV in EXCON and return UAV home
TrainingAreaBase::TetraIcd::StateChangeDirect msg;
msg.chargeTypeId = data.chargeTasCodeDirect; // = jamming
msg.header.equipmentNumber = eqId;
msg.header.timeStamp = data.header.timeStamp;
msg.vulnerabilityState = TrainingAreaBase::TetraIcd::VulnerabilityState::CatastrophicKill;
msg.originatorId = data.originatorEquipmentNumber;
DEBUG_LOG(m_logger) << "sending state change direct (kill) with jamming for eqId " << msg.header.equipmentNumber;
m_sendToDds->rxData(msg);
return true;
}
bool FromTab::txData(const TrainingAreaBase::TetraIcd::DemandVulnerabilityStateChange &data)
{
const auto p = m_dtcPpm->participantIdByEquipmentNumber(data.header.equipmentNumber);
// we could trigger RTH if needed with:
// if (p > 0 && m_uavIAManager)
// m_uavIAManager->kill(p); // kill UAV in EXCON and return UAV home
const auto &pData = m_dtcPpm->dynamicParticipantData(p);
for (const auto &dyn : pData.stateHistory())
{
if (dyn.vulnerabilityState() == ProjectDataManagement::VulnerabilityState::CatastrophicKill)
{
return false;
}
}
//send statechange init
TrainingAreaBase::TetraIcd::StateChange msg;
msg.header.equipmentNumber = data.header.equipmentNumber;
msg.header.timeStamp = QDateTime::currentMSecsSinceEpoch(); //data.timestamp * 1000;
msg.originatorId = data.workstationId;
msg.originatorType = TrainingAreaBase::TetraIcd::OriginatorType::ExerciseControl;
msg.tasVitality = 0;
msg.vulnerabilityBits = 0;
msg.vulnerabilityState = data.reqestedState;
m_sendToDds->rxData(msg);
return true;
}
bool FromTab::txData(const TrainingAreaBase::TetraIcd::OcCommand &data)
{
Q_UNUSED(data)
return false;
}
} // namespace UAS