/** * Simulation for Movement * $Id$ * $HeadURL$ * $Author$ * Created by gr, SLSE, 2017-12-13 */ #include "simulation_movement.h" #include #include namespace CentralEffectSimulationBasic { SimulationMovement::SimulationMovement(const std::shared_ptr &ddsHandler, const std::shared_ptr &db, const std::shared_ptr &participantHandler, const CentralEffectSimulation::SimulatedMovement &sml, QObject *parent) : QObject(parent) , m_ddsHandler(ddsHandler) , m_db(db) , m_handlerParticipant(participantHandler) , m_moveTime(1) , m_actSegment() , m_newPos() , m_simStart(true) , m_zone(-1) , m_segTimer(new QTimer(this)) , m_moveTimer(new QTimer(this)) , m_simMovement(sml) , m_logger(CentralEffectSimulation::getLogger("Plugin.Basic.SimulationMovement")) { m_segTimer->setSingleShot(true); connect(m_segTimer, &QTimer::timeout, this, &SimulationMovement::startNewSegment); m_moveTimer->setSingleShot(true); connect(m_moveTimer, &QTimer::timeout, this, &SimulationMovement::move); setSimulatedMovementRequest(sml); } SimulationMovement::~SimulationMovement() { DEBUG_LOG(m_logger) << "Delete SimulatedMovement " << " id=" << m_simMovement.id() << " participantId= " << m_simMovement.participantId(); m_ddsHandler->dtsCes()->removeSimulatedMovementByKey(m_simMovement.id()); m_segTimer->stop(); m_moveTimer->stop(); } void SimulationMovement::setSimulatedMovementRequest(const CentralEffectSimulation::SimulatedMovement &sml) { int nextPoint = m_simMovement.nextPoint(); m_simMovement = sml; m_simMovement.nextPoint(nextPoint); m_moveTime = 1; m_segTimer->stop(); m_moveTimer->stop(); m_points.clear(); m_segSpeed.clear(); m_segDelay.clear(); m_points.reserve(sml.segments().size()); m_segSpeed.reserve(sml.segments().size()); m_segDelay.reserve(sml.segments().size()); for (const CentralEffectSimulation::SimulatedMovementSegment &point : sml.segments()) { const Core::GeoPosition2D &pointGeo = point.position(); m_points.push_back(m_zone == -1 ? CentralEffectSimulation::geographic2Utm(pointGeo, &m_zone) : CentralEffectSimulation::geographic2Utm(pointGeo, m_zone)); DEBUG_LOG(m_logger) << "pointGeo lat=" << pointGeo.lat() << " lon=" << pointGeo.lon() << " point lat=" << point.position().lat() << " lon=" << point.position().lon() << " utmPoint=" << CentralEffectSimulation::debug(m_points.last()); m_segSpeed.append(point.speed()); m_segDelay.append(point.delay()); } // Only start simulation in future DEBUG_LOG(m_logger) << "m_startTime - QDateTime::currentMSecsSinceEpoch()=" << m_simMovement.startTime() - QDateTime::currentMSecsSinceEpoch() << " m_startTime=" << m_simMovement.startTime() << " currentTime=" << QDateTime::currentMSecsSinceEpoch() << " m_nextPoint=" << m_simMovement.nextPoint(); if (m_simMovement.nextPoint() > 0 && m_points.size() > m_simMovement.nextPoint()) m_newPos = m_points[m_simMovement.nextPoint()].toPoint(); if (m_simMovement.startTime() - QDateTime::currentMSecsSinceEpoch() > 0) m_moveTimer->start(m_simMovement.startTime() - QDateTime::currentMSecsSinceEpoch()); else { DEBUG_LOG(m_logger) << "Service-Start"; m_moveTimer->start(10); // Service-Start } } void SimulationMovement::updateNextPointInDb() { if (m_simMovement.id() <= 0) { WARNING_LOG(m_logger) << "Internal error - id not set!"; return; } CentralEffectSimulation::Database::CesSimulatedMovement dbSim = toDb(m_simMovement); m_db->update(dbSim); } void SimulationMovement::startNewSegment() { DEBUG_LOG(m_logger) << "simulate participantId = " << m_simMovement.participantId() << " m_nextPoint = " << m_simMovement.nextPoint(); m_moveTime = 1; if (m_simMovement.nextPoint() < m_points.size()) { QPointF p1; // Next segment const CentralEffectSimulation::HandlerParticipant::CesParticipantData pos = m_handlerParticipant->position(m_simMovement.participantId()); if (pos.participantId() == m_simMovement.participantId()) { p1 = CentralEffectSimulation::geographic2Utm(pos.pos(), m_zone); DEBUG_LOG(m_logger) << "Next segment ParticipantPosition =" << CentralEffectSimulation::debug(p1); } else { if (m_simStart) // Wait for participantPosition { INFO_LOG(m_logger) << "Wait for participant position participantId =" << m_simMovement.participantId(); m_segTimer->start(1000); return; } if (m_simMovement.nextPoint() > 0) { p1 = m_points.at(m_simMovement.participantId() - 1); DEBUG_LOG(m_logger) << "nextPoint>0 (" << m_simMovement.nextPoint() << ") ParticipantPosition =" << CentralEffectSimulation::debug(p1); } else { p1 = m_points.at(m_points.size() - 1); DEBUG_LOG(m_logger) << "nextPoint=" << m_simMovement.nextPoint() << " ParticipantPosition =" << CentralEffectSimulation::debug(p1); } } const QPointF &p2 = m_points.at(m_simMovement.nextPoint()); m_actSegment.setPoints(p1, p2); int curDelay = m_segDelay.at(m_simMovement.nextPoint()); DEBUG_LOG(m_logger) << "New Segment: p1 = " << CentralEffectSimulation::debug(p1) << " p2=" << CentralEffectSimulation::debug(p2) << " delay =" << curDelay; m_moveTimer->start(curDelay); } else { if (m_simMovement.repeat()) { m_simMovement.nextPoint(0); m_moveTimer->start(m_segDelay.at(m_simMovement.nextPoint())); } else m_simMovement.nextPoint(-1); // Invalid value } } void SimulationMovement::setJump(bool jump) { DEBUG_LOG(m_logger) << "Jump"; if (jump) { m_simMovement.nextPoint(1); m_newPos = m_points.at(0); m_actSegment.setPoints(m_newPos, m_points.at(m_simMovement.nextPoint())); m_moveTime = 1; m_simStart = false; publishNewPos(); DEBUG_LOG(m_logger) << "Jump done"; } } void SimulationMovement::publishSimulatedMovement() { DEBUG_LOG(m_logger) << " m_nextPoint= " << m_simMovement.nextPoint(); m_ddsHandler->dtsCes()->publish(m_simMovement); } void SimulationMovement::publishNewPos() { TrainingAreaBase::EquipmentPosition participantPos; LtsCoordTrans::UtmCoordinate utmPos; utmPos.zone = m_zone; utmPos.northp = true; utmPos.x = m_newPos.x(); utmPos.y = m_newPos.y(); const QPointF posGeo = utmPos.geographic(); DEBUG_LOG(m_logger) << "participantPos zone=" << utmPos.zone << " northp=" << utmPos.northp << " x=" << utmPos.x << " y=" << utmPos.y; const Core::GeoPosition pos(Core::GeoPosition(posGeo.x(), posGeo.y(), 0)); participantPos.equipmentNumber(-m_simMovement.participantId()); // negative - treat as participantId participantPos.sampleTime(m_ddsHandler->currentPartitionTime()); participantPos.position().position(pos); participantPos.position().reportingSource(Core::PositionReportingSource::MovementSimulation); m_ddsHandler->dtsTab()->publish(participantPos); } void SimulationMovement::move() { DEBUG_LOG(m_logger) << "move"; if (m_simMovement.nextPoint() < 0) { DEBUG_LOG(m_logger) << "move next point < 0"; return; } const CentralEffectSimulation::HandlerParticipant::CesParticipantData partPos = m_handlerParticipant->position(m_simMovement.participantId()); const QPointF participantPosUtm = CentralEffectSimulation::geographic2Utm(partPos.pos(), m_zone); if (partPos.participantId() != m_simMovement.participantId()) { DEBUG_LOG(m_logger) << "move no ParticipantId=" << m_simMovement.participantId(); m_moveTimer->start(1000); return; } if (!partPos.positionValid) { DEBUG_LOG(m_logger) << "move no ParticipantId=" << m_simMovement.participantId(); m_moveTimer->start(1000); return; } DEBUG_LOG(m_logger) << " pos=" << CentralEffectSimulation::debug(participantPosUtm); QLineF step = m_actSegment; if (m_simStart) { m_actSegment.setPoints(participantPosUtm, m_points.at(m_simMovement.nextPoint())); step = m_actSegment; DEBUG_LOG(m_logger) << "m_simStart set m_actSegment" << " p1: " << CentralEffectSimulation::debug(m_actSegment.p1()) << " p2: " << CentralEffectSimulation::debug(m_actSegment.p2()); m_simStart = false; } if (m_segSpeed[m_simMovement.nextPoint()] <= 0.0) { DEBUG_LOG(m_logger) << "move next point < 0"; return; } m_newPos = m_points[m_simMovement.nextPoint()]; step.setLength(m_segSpeed[m_simMovement.nextPoint()] * m_moveTime); m_moveTime++; // ready criterion if (step.length() >= m_actSegment.length() + 0.1 || step.length() < 0.1) // 0.1 Magic Number but 10 cm distance to Point is arrived { DEBUG_LOG(m_logger) << "move ready step.length()=" << step.length() << " m_actSegment.length()=" << m_actSegment.length(); m_simMovement.nextPoint(m_simMovement.nextPoint() + 1); if (m_simMovement.nextPoint() >= m_points.size()) { if (m_simMovement.repeat()) m_simMovement.nextPoint(0); else { m_simMovement.nextPoint(-1); // Invalid value return; } } updateNextPointInDb(); DEBUG_LOG(m_logger) << "ready move participantId = " << m_simMovement.participantId() << " m_nextPoint =" << m_simMovement.nextPoint() << " newPos =" << m_newPos.x() << "/" << m_newPos.y() << " m_moveTime=" << m_moveTime << " length=" << m_segSpeed[m_simMovement.nextPoint()] * m_moveTime << " step.length=" << step.length() << " m_segSpeed[m_nextPoint]=" << m_segSpeed[m_simMovement.nextPoint()] << " m_moveTime=" << m_moveTime << " m_actSegment.length=" << m_actSegment.length() << " m_zone=" << m_zone; publishNewPos(); startNewSegment(); publishSimulatedMovement(); return; } m_newPos = step.p2(); DEBUG_LOG(m_logger) << "move participantId = " << m_simMovement.participantId() << " m_nextPoint =" << m_simMovement.nextPoint() << " newPos =" << m_newPos.x() << "/" << m_newPos.y() << " m_moveTime=" << m_moveTime << " length=" << m_segSpeed[m_simMovement.nextPoint()] * m_moveTime << " step.length=" << step.length() << " m_speed=" << m_segSpeed[m_simMovement.nextPoint()] << " m_moveTime=" << m_moveTime << " m_actSegment.length=" << m_actSegment.length() << " m_zone=" << m_zone; publishNewPos(); m_moveTimer->start(1000); // Calculate new position each second } CentralEffectSimulation::Database::CesSimulatedMovement SimulationMovement::toDb(const CentralEffectSimulation::SimulatedMovement &ddsSimMovement) { CentralEffectSimulation::Database::CesSimulatedMovement ret; ret.id = ddsSimMovement.id(); ret.name = QString::fromStdString(ddsSimMovement.name()); ret.startTime = ddsSimMovement.startTime(); ret.participantId = ddsSimMovement.participantId(); ret.repeat = ddsSimMovement.repeat(); ret.nextpoint = ddsSimMovement.nextPoint(); return ret; } }