125 lines
4.3 KiB
C++
125 lines
4.3 KiB
C++
#ifndef CCLOUDSHOW_H
|
||
#define CCLOUDSHOW_H
|
||
|
||
#include <pcl/point_types.h>
|
||
#include <pcl/point_cloud.h>
|
||
#include <pcl/visualization/pcl_visualizer.h>
|
||
#include <vtkTextActor.h>
|
||
|
||
#include <atomic>
|
||
#include <condition_variable>
|
||
#include <deque>
|
||
#include <mutex>
|
||
#include <string>
|
||
#include <thread>
|
||
#include <vector>
|
||
|
||
#include "ICloudShow.h"
|
||
|
||
class vtkOrientationMarkerWidget;
|
||
|
||
class CCloudShow : public ICloudShow
|
||
{
|
||
public:
|
||
CCloudShow();
|
||
~CCloudShow() override;
|
||
|
||
int Show(const CloudData& cloudData,
|
||
const CloudFrameInfo& info,
|
||
const std::string& windowName = "PointCloud") override;
|
||
int Start(const std::string& windowName = "PointCloud", void* hwnd = nullptr) override;
|
||
int Stop() override;
|
||
int SpinOnce(int ms = 1) override;
|
||
bool IsRunning() const override;
|
||
|
||
void PushFrame(const CloudData& cloudData,
|
||
const CloudFrameInfo& info) override;
|
||
|
||
void SetSaveBaseDir(const std::string& dir) override;
|
||
void SetSaveFrameInterval(int interval) override;
|
||
bool IsSaveActive() const override;
|
||
|
||
bool IsQuitRequested() const override;
|
||
bool IsSaveRequested() const override;
|
||
void ClearSaveRequest() override;
|
||
|
||
private:
|
||
static void keyboardCallback(const pcl::visualization::KeyboardEvent& event, void* cookie);
|
||
|
||
// UI
|
||
void handleStartStopToggle();
|
||
void updateStartStopButton();
|
||
void updateProgressText();
|
||
|
||
// 保存线程
|
||
void saveLoop();
|
||
|
||
// ── 显示相关 ──
|
||
std::shared_ptr<pcl::visualization::PCLVisualizer> m_viewer;
|
||
std::atomic<bool> m_bRunning{false};
|
||
std::mutex m_cloudMutex;
|
||
bool m_bUpdated = false;
|
||
bool m_bFirstCloud = true;
|
||
std::string m_windowName;
|
||
vtkOrientationMarkerWidget* m_axesWidget = nullptr;
|
||
|
||
// 当前待显示的 PCL 云 + 最近一帧 CloudData(供单帧保存)
|
||
// 注意:m_lastCloudData / m_lastCloudBuffers / m_lastFrameInfo 被 PushFrame(回调线程)
|
||
// 和 SpinOnce(主线程)同时访问,需 m_lastCloudMutex 保护
|
||
pcl::PointCloud<pcl::PointXYZI>::Ptr m_displayCloud;
|
||
pcl::PointCloud<pcl::PointXYZI>::Ptr m_renderPool; // 复用,避免每帧 make_shared
|
||
std::mutex m_lastCloudMutex;
|
||
CloudData m_lastCloudData;
|
||
CloudFrameInfo m_lastFrameInfo;
|
||
std::vector<std::vector<uint8_t>> m_lastCloudBuffers;
|
||
|
||
// UI 状态
|
||
std::atomic<bool> m_bQuitRequested{false};
|
||
std::atomic<bool> m_bSaveRequested{false};
|
||
std::atomic<bool> m_bStartStopRequested{false};
|
||
vtkTextActor* m_pStartStopBtnActor = nullptr;
|
||
vtkTextActor* m_pProgressActor = nullptr;
|
||
std::mutex m_textMutex;
|
||
|
||
// ── 保存相关 ──
|
||
struct SaveTask
|
||
{
|
||
CloudData cloudData; // 深拷贝的标准格式
|
||
std::vector<std::vector<uint8_t>> buffers; // p3DPoint 指向的实际内存(预分配复用)
|
||
CloudFrameInfo info;
|
||
};
|
||
std::string m_saveBaseDir = ".";
|
||
std::atomic<bool> m_bSaveActive{false};
|
||
std::string m_currentSessionDir;
|
||
|
||
// SaveTask 缓冲池:PushFrame(回调线程)从池取预分配好的 task,
|
||
// 零堆分配完成数据拷贝,saveLoop 用完后归还。消除回调线程的 malloc 延迟抖动。
|
||
std::mutex m_taskPoolMutex;
|
||
std::vector<SaveTask> m_taskPool; // 空闲 task 栈
|
||
|
||
SaveTask acquireTask();
|
||
void releaseTask(SaveTask& task);
|
||
void packIntoTask(SaveTask& task,
|
||
const ICloudShow::CloudData& cloudData,
|
||
const CloudFrameInfo& info);
|
||
|
||
std::mutex m_saveMutex;
|
||
std::condition_variable m_saveCv;
|
||
std::deque<SaveTask> m_saveQueue;
|
||
std::atomic<bool> m_bFlushAndSave{false}; // true=STOP已点击,保存线程开始写盘
|
||
static constexpr int SAVE_THREAD_COUNT = 1;
|
||
std::atomic<bool> m_saveExit{false};
|
||
std::vector<std::thread> m_saveThreads;
|
||
|
||
std::atomic<int> m_nSaveSeq{0};
|
||
std::atomic<int> m_nSingleSaveSeq{0};
|
||
std::atomic<int> m_nSaveDropped{0};
|
||
std::atomic<int> m_saveCompleted{0};
|
||
std::atomic<int> m_saveTotal{0};
|
||
|
||
int m_nSaveFrameInterval = 10; // 保存帧间隔,默认每10帧存1帧
|
||
int m_nPushFrameCount = 0; // PushFrame 调用计数(回调线程独占)
|
||
};
|
||
|
||
#endif // CCLOUDSHOW_H
|