299 lines
12 KiB
C++

#ifndef PARKINGSPACEGUIDEPRESENTER_H
#define PARKINGSPACEGUIDEPRESENTER_H
#include <array>
#include <atomic>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <string>
#include <thread>
#include <utility>
#include <vector>
#include <QImage>
#include <QObject>
#include <QRect>
#include <QString>
#include "ConfigManager.h"
#include "IMvsDevice.h"
#include "ILedDisplayDevice.h"
#include "IRsLidarDevice.h"
#include "IYParkingSpaceGuideStatus.h"
class DetectPresenter;
class GpioInput;
class IYUDPClient;
class ParkingStatusHttpServer;
class ParkingSpaceGuideRemoteServer;
struct ParkingGuideAlgorithmState;
struct CameraFrameInfo
{
int width = 0;
int height = 0;
int pixelFormat = 0;
unsigned long long frameId = 0;
unsigned long long timestamp = 0;
};
struct ParkingSpaceGuideSimulationOptions
{
bool enabled = false;
QString dataDirectory;
int frameIntervalMs = 100;
bool loop = false;
};
class ParkingSpaceGuidePresenter : public QObject, public IVrConfigChangeNotify
{
Q_OBJECT
public:
explicit ParkingSpaceGuidePresenter(QObject* parent = nullptr);
ParkingSpaceGuidePresenter(
const ParkingSpaceGuideSimulationOptions& simulationOptions,
QObject* parent = nullptr);
~ParkingSpaceGuidePresenter() override;
int Init();
void RequestShutdown();
void DeinitApp();
bool StartAutomaticDetection(int cameraIndex = -1);
bool StartDetection(const QString& selectedModelType,
int cameraIndex = -1);
bool SelectModel(const QString& selectedModelType);
bool TriggerDetection(int cameraIndex = -1);
int StopDetection();
bool IsDetectionRunning() const;
int LoadAndDetect(const QString& fileName);
int SaveDetectionDataToFile(const std::string& filePath);
int GetDetectionDataCacheSize() const;
void SetDefaultCameraIndex(int cameraIndex);
int GetDetectIndex() const;
QString GetAlgoVersion() const;
ConfigManager* GetConfigManager();
std::vector<std::pair<std::string, void*>> GetCameraList() const;
template<typename StatusCallbackType>
void SetStatusCallback(StatusCallbackType* statusCallback)
{
m_statusCallback = static_cast<void*>(statusCallback);
}
void OnConfigChanged(const ConfigResult& configResult) override;
signals:
void SelectedModelChanged(const QString& modelType);
private:
struct OwnedCloudFrame
{
std::vector<SVzNLPointXYZI> points;
RsCloudData cloud;
RsFrameInfo info;
qint64 timestampMs = 0;
};
struct ModelRecognitionTaskResult
{
int returnCode = -1;
QImage image;
QImage sourceImage;
QRect sourceRoi;
QString modelType;
double confidence = 0.0;
QString message;
bool verified = false;
bool recognitionComplete = false;
bool verificationSupported = true;
bool confidenceAccepted = false;
bool verificationAccepted = false;
};
IYParkingSpaceGuideStatus* StatusCallback() const;
int InitConfig();
int InitMvsCamera(const MvsCameraConfig& config);
int InitRsLidar(const RsLidarConfig& config);
int InitLedDisplay(const LedDisplayConfig& config);
int InitUdpBroadcast(const UdpBroadcastConfig& config);
int InitHttpServer(const HttpServerConfig& config);
int InitRemoteView(const RemoteViewConfig& config);
int InitEmergencyStop(const EmergencyStopConfig& config);
int InitSimulationData();
void CloseEmergencyStop(bool clearLatch = true);
void CloseUdpBroadcast();
void CloseHttpServer();
void CloseRemoteView();
void CloseDevices();
void ClearSimulationData();
void EnrichDetectionResult(DetectionResult& result) const;
void UpdateCurrentStatus(const DetectionResult& result);
std::string CurrentStatusJson() const;
bool BroadcastDetectionResult(const DetectionResult& result);
void NotifyStatus(const std::string& message);
void NotifyWorkStatus(WorkStatus status);
void NotifyCameraStatus(bool connected);
void NotifyLidarStatus(bool connected);
void NotifyLedStatus(bool connected);
LedDisplayResult ConvertLedResult(const DetectionResult& result) const;
std::shared_ptr<OwnedCloudFrame> AcquireCloudFrameBuffer();
static bool CopyCloudFrame(const RsCloudData& cloud,
const RsFrameInfo& info,
OwnedCloudFrame& destination);
bool SubmitCloudFrame(const RsCloudData& cloud, const RsFrameInfo& info);
unsigned long long SubmitOwnedCloudFrame(
const std::shared_ptr<OwnedCloudFrame>& frame);
bool LoadSimulationRadarFrame(size_t frameIndex,
std::shared_ptr<OwnedCloudFrame>& frame,
QString& errorMessage);
bool LoadSimulationCameraFile(size_t imageIndex,
QImage& image,
QString& errorMessage);
void CacheSimulationCameraFrame(size_t frameIndex, const QImage& image);
bool WaitForSimulationFrameProcessed(unsigned long long sequence);
bool WaitForSimulationInterval(int intervalMs);
void SimulationPlaybackLoop();
bool ProcessAirplanePresence(const RsCloudData& cloud);
bool DetectOnce(const RsCloudData& cloud,
qint64 frameTimestampMs,
ParkingGuideAlgorithmState& algorithmState);
bool StartDetectionInternal(const QString& selectedModelType,
int cameraIndex,
bool clearSafetyLatch,
bool automaticMode);
void PublishDetectionResult(DetectionResult& result,
bool safetyResult = false);
void PublishErrorResult(int errorCode, const QString& message);
bool CaptureModelRecognitionImage(QImage& image, QString& errorMessage);
bool StartModelRecognitionTask(const QByteArray& recognitionContext,
const VrModelRecognitionParam& modelParam,
int attempt,
const VrDebugParam& debugParam,
QString& errorMessage);
bool TakeModelRecognitionTaskResult(ModelRecognitionTaskResult& result);
void WaitForModelRecognitionTask(bool discardResult);
void ApplyModelRecognitionTaskResult(
const ModelRecognitionTaskResult& taskResult,
ParkingGuideAlgorithmState& algorithmState,
DetectionResult& result,
const VrModelRecognitionParam& modelParam);
void UpdateDetectionResultModelFields(
DetectionResult& result,
const ParkingGuideAlgorithmState& algorithmState) const;
void DetectionLoop(QString selectedModelType, bool automaticMode);
void HandleEmergencyStopChanged(bool active);
void HandleEmergencyStopStatus(bool available,
const std::string& message);
void RequestDetectionStopForSafety();
DetectionResult CreateGuideStateResult(ParkingGuideState state,
const QString& guideText,
const QString& message,
bool preserveLastMeasurement) const;
void PublishGuideState(ParkingGuideState state,
const QString& guideText,
const QString& message,
bool preserveLastMeasurement);
bool PublishCurrentSafetyState(bool publishWaitingWhenClear,
bool preserveLastMeasurement);
void StartVideoStream(const HttpFlvStreamConfig& config,
const MvsCameraConfig& cameraConfig);
void RequestVideoStreamStop();
void StopVideoStream();
void VideoStreamLoop(HttpFlvStreamConfig config,
MvsCameraConfig cameraConfig);
bool CacheMvsFrame(const MvsImageData& image, QImage& frame);
private:
ConfigManager* m_configManager = nullptr;
DetectPresenter* m_detectPresenter = nullptr;
IMvsDevice* m_mvsDevice = nullptr;
IRsLidarDevice* m_lidarDevice = nullptr;
ILedDisplayDevice* m_ledDisplay = nullptr;
std::unique_ptr<GpioInput> m_emergencyStopInput;
IYUDPClient* m_udpClient = nullptr;
ParkingStatusHttpServer* m_httpServer = nullptr;
ParkingSpaceGuideRemoteServer* m_remoteServer = nullptr;
UdpBroadcastConfig m_udpBroadcastConfig;
EmergencyStopConfig m_emergencyStopConfig;
RemoteViewConfig m_remoteViewConfig;
bool m_hasEmergencyStopConfig = false;
bool m_hasRemoteViewConfig = false;
ParkingSpaceGuideSimulationOptions m_simulationOptions;
void* m_statusCallback = nullptr;
mutable std::mutex m_dataMutex;
mutable std::mutex m_udpMutex;
mutable std::mutex m_statusMutex;
mutable std::mutex m_publishMutex;
mutable std::mutex m_outputMutex;
mutable std::mutex m_safetyMutex;
mutable std::mutex m_safetyPublishMutex;
mutable std::mutex m_workStatusMutex;
mutable std::mutex m_sessionMutex;
mutable std::mutex m_cameraCaptureMutex;
std::string m_currentStatusJson;
DetectionResult m_lastDetectionResult;
std::vector<unsigned char> m_latestFrame;
CameraFrameInfo m_latestFrameInfo;
bool m_hasFrame = false;
std::array<std::shared_ptr<OwnedCloudFrame>, 3> m_cloudFrameSlots;
std::shared_ptr<const OwnedCloudFrame> m_latestCloudFrame;
size_t m_nextCloudFrameSlot = 0;
unsigned long long m_cloudSequence = 0;
unsigned long long m_consumedCloudSequence = 0;
unsigned long long m_processedCloudSequence = 0;
bool m_lidarErrorPending = false;
QString m_lidarErrorMessage;
QString m_selectedModelType;
std::vector<QString> m_simulationRadarFiles;
std::vector<QString> m_simulationCameraFiles;
std::vector<std::shared_ptr<OwnedCloudFrame>> m_simulationRadarFrames;
std::vector<QImage> m_simulationCameraFrames;
QImage m_simulationCameraImage;
std::vector<std::pair<std::string, void*>> m_cameraList;
int m_currentCameraIndex = 1;
int m_detectIndex = 1;
std::atomic<bool> m_initialized{false};
std::atomic<bool> m_reconfiguring{false};
std::atomic<bool> m_shutdownRequested{false};
std::atomic<bool> m_emergencyStopEnabled{false};
std::atomic<bool> m_emergencyStopAvailable{true};
std::atomic<bool> m_emergencyStopActive{false};
std::atomic<bool> m_emergencyStopLatched{false};
std::atomic<bool> m_detectionRunning{false};
std::atomic<bool> m_automaticDetection{false};
std::atomic<bool> m_stopDetectionRequested{false};
std::atomic<bool> m_trackingMode{false};
std::atomic<unsigned long long> m_simulationRound{0};
std::atomic<long long> m_lastProbeAcceptedMs{0};
std::atomic<bool> m_cloudCopyErrorReported{false};
std::mutex m_detectionThreadMutex;
std::mutex m_detectionExecutionMutex;
std::mutex m_reconfigurationMutex;
std::condition_variable m_detectionCondition;
std::thread m_detectionThread;
std::thread m_simulationThread;
std::atomic<bool> m_videoStreamStopRequested{true};
std::atomic<bool> m_videoStreamRunning{false};
std::mutex m_videoStreamMutex;
std::condition_variable m_videoStreamCondition;
std::thread m_videoStreamThread;
std::mutex m_modelRecognitionMutex;
std::thread m_modelRecognitionThread;
ModelRecognitionTaskResult m_modelRecognitionTaskResult;
std::atomic<bool> m_modelRecognitionRunning{false};
std::atomic<bool> m_modelRecognitionResultReady{false};
std::atomic<bool> m_modelRecognitionResultApplying{false};
};
#endif // PARKINGSPACEGUIDEPRESENTER_H