GrabBag/Device/RsLidarDevice/_Inc/RsLidarDevice.h
2026-06-13 13:24:31 +08:00

150 lines
5.3 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#ifndef CRSLIDARDEVICE_H
#define CRSLIDARDEVICE_H
#include "IRsLidarDevice.h"
// SDK 内部以 uint8_t* 调用 recvfrom(),但 C++ 中 char*/unsigned char*/signed char*
// 是三种独立类型MSVC 拒绝 uint8_t*(=unsigned char*) → char* 的隐式转换。
// 此重载在 SDK 头文件之前定义,利用重载决议的精确匹配规则拦截调用并内部转型。
#ifdef _WIN32
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib")
inline int recvfrom(SOCKET s, unsigned char* buf, int len, int flags, sockaddr* from, int* fromlen)
{
return ::recvfrom(s, reinterpret_cast<char*>(buf), len, flags, from, fromlen);
}
#endif
// SDK 依赖 std::array / int16_t / uint16_t但其内部缺少对应的 #include
// 在 Linux 上通过 libstdc++ 间接包含可用MSVC STL 不会间接拉入,需在此处显式引入。
#include <array>
#include <cstdint>
// SDK 头文件全部放在私有层,不污染公共接口
#include <rs_driver/api/lidar_driver.hpp>
#include <rs_driver/msg/point_cloud_msg.hpp>
#include <rs_driver/msg/packet.hpp>
#include <rs_driver/driver/driver_param.hpp>
#include <rs_driver/common/error_code.hpp>
#include <rs_driver/utility/sync_queue.hpp>
#include <thread>
#include <atomic>
#include <mutex>
#include <array>
#include <chrono>
using namespace robosense::lidar;
// 交付帧:封装一次完整扫描的数据 + 行缓冲池p3DPoint 指向此处)
// processCloudThread 填充 → deliveryThread 消费(调用回调)→ 归还 m_frameFreeQueue
struct DeliveryFrame
{
std::vector<std::vector<SVzNLPointXYZI>> linePool;
RsCloudData cloudData;
RsFrameInfo info;
void reserveLines(size_t lines, size_t pointsPerLine)
{
linePool.resize(lines);
for (auto& v : linePool)
v.reserve(pointsPerLine);
}
};
using DeliveryFramePtr = std::shared_ptr<DeliveryFrame>;
class CRsLidarDevice : public IRsLidarDevice
{
public:
CRsLidarDevice();
~CRsLidarDevice();
int InitDevice() override;
int OpenDevice(const RsLidarConfig& config) override;
int CloseDevice() override;
bool IsOpened() const override;
int Start() override;
int Stop() override;
bool IsRunning() const override;
int SetPointCloudCallback(PointCloudCallback callback) override;
int SetPacketCallback(PacketCallback callback) override;
int SetExceptionCallback(ExceptionCallback callback) override;
std::string GetVersion() override;
uint64_t GetDroppedFrameCount() const override;
size_t GetStuffedQueueDepth() const override;
uint64_t GetExceptionCount(int errCode) const override;
RsCallbackStats GetCallbackLatencyStats() const override;
size_t GetStuffedQueuePeak() const override;
private:
// SDK 内部类型别名
using SdkCloudMsg = PointCloudT<PointXYZI>;
using SdkCloudPtr = std::shared_ptr<SdkCloudMsg>;
/// 解析线程pop SDK帧 → NaN→0+变换+拆线 → 推入交付队列 → 归还SDK缓冲
void processCloudThread();
/// 交付线程:从交付队列取帧 → 调用用户回调PushFrame memcpy在此发生→ 归还交付帧
void deliveryThread();
/// 输出 5s 窗口诊断日志并重置窗口字段;仅当距 lastLogTime ≥5s 时实际输出
void emitDiagnosticLogIfDue(std::chrono::steady_clock::time_point& lastLogTime);
SdkCloudPtr getFreeCloud();
void putStuffedCloud(SdkCloudPtr msg);
/// 将 SDK Packet 转为 RsPacketInfo 后转发给用户
void onPacket(const Packet& pkt);
/// 将 SDK Error 转为 RsExceptionInfo 后转发给用户
void onException(const Error& code);
/// RsLidarConfig → RSDriverParam
static RSDriverParam toDriverParam(const RsLidarConfig& config);
bool m_bOpened = false;
std::atomic<bool> m_bRunning{false};
std::atomic<bool> m_bStopProcess{false};
std::atomic<bool> m_bStopDelivery{false};
PointCloudCallback m_pointCloudCallback;
PacketCallback m_packetCallback;
ExceptionCallback m_exceptionCallback;
std::mutex m_callbackMutex;
std::unique_ptr<LidarDriver<SdkCloudMsg>> m_pDriver;
std::thread m_processThread;
std::thread m_deliveryThread;
SyncQueue<SdkCloudPtr, 4096> m_freeQueue;
SyncQueue<SdkCloudPtr, 4096> m_stuffedQueue;
// 交付帧流水线深度2=解耦一帧processCloud 推入 → deliveryThread 消费
SyncQueue<DeliveryFramePtr, 2> m_deliveryQueue;
SyncQueue<DeliveryFramePtr, 4> m_frameFreeQueue; // 空闲帧池3帧预分配 + 1余量
RSDriverParam m_param;
// 丢帧监控
std::atomic<uint64_t> m_droppedFrameCount{0};
std::atomic<uint64_t> m_totalPushCount{0};
// 诊断统计(每 5s 滚动窗口)
// bucket: 0=MSOPTIMEOUT(0x40) 1=PKTBUFOVERFLOW(0x48) 2=CLOUDOVERFLOW(0x49) 3=WRONGMSOPLEN(0x42) 4=other
static constexpr size_t EXC_BUCKET_COUNT = 5;
std::array<std::atomic<uint64_t>, EXC_BUCKET_COUNT> m_exceptionCounts{};
std::atomic<uint64_t> m_cbMaxUs{0};
std::atomic<uint64_t> m_cbAccumUs{0};
std::atomic<uint64_t> m_cbCount{0};
std::atomic<size_t> m_qPeak{0};
/// 将 SDK ErrCode 映射到统计桶下标,未知返回 4 (other)
static size_t errCodeToBucket(int errCode);
};
#endif // CRSLIDARDEVICE_H