|
|
// 全局配置:变量声明 + 配置加载接口
|
|
|
// 运行时配置为"根级 map"结构:
|
|
|
// {
|
|
|
// "server": {...}, "log": {...}, // 全局(进程级)
|
|
|
// "radar1": { "radar":{..}, "scan":{..}, "detect":{..}, "count":{..}, "filter":{..} },
|
|
|
// "radar2": { ... } // 每个雷达一份完整参数
|
|
|
// }
|
|
|
// 除 server/log 外的每个一级键都是一个"雷达标识"(通信时用它指定操作哪台雷达)。
|
|
|
// 业务代码通过 radar_cfg().radar.ip / cfg.log.enable / radar_cfg().count.base_tolerance 访问;
|
|
|
// radar_cfg() 返回"当前线程绑定的雷达配置"(由 RadarScope 绑定,未绑定时为默认雷达)。
|
|
|
#ifndef CONFIG_H
|
|
|
#define CONFIG_H
|
|
|
|
|
|
#include <map>
|
|
|
#include <memory>
|
|
|
#include <string>
|
|
|
#include <vector>
|
|
|
#include <utility>
|
|
|
#include <cstdint>
|
|
|
|
|
|
// ==================== 常量(编译期固定) ====================
|
|
|
const uint32_t OPEN_TIMEOUT_MS = 3000; // 连接超时(ms)
|
|
|
const uint16_t FRAME_TIMEOUT_MS = 2000; // 获取帧数据超时(ms)
|
|
|
const bool FILTER_ENABLE = true; // 多边形过滤开关
|
|
|
const bool SHIFT_Y_POSITIVE = true; // Y值上移使最小Y≥0
|
|
|
const int SLICE_IMG_SIZE = 800; // 截面图片最大像素尺寸
|
|
|
const double ORIGIN_TOL_MM = 0.5; // 原点无效点判定容差(mm)
|
|
|
const int RECONNECT_INTERVAL_MS = 3000; // 雷达断线重连间隔(ms),未连接时后台一直重试
|
|
|
|
|
|
// ==================== 单台雷达的参数(根级 map 的一个条目) ====================
|
|
|
struct RadarConfig
|
|
|
{
|
|
|
std::string id; // 雷达标识(配置里的一级键名)
|
|
|
|
|
|
// ---------- radar: 雷达连接 + 雷达内置滤波 ----------
|
|
|
struct Radar
|
|
|
{
|
|
|
std::string ip = "192.168.0.170"; // 雷达IP
|
|
|
uint16_t port = 2368; // 雷达数据端口
|
|
|
double hz = 50.0; // 雷达帧率(Hz)
|
|
|
int tail_filter = 2; // 拖尾滤波 0关1弱2中3强
|
|
|
int front_filter = 2; // 前冲滤波 0关1弱2中3强
|
|
|
int far_hr_filter = 1; // 远端高反 0关1弱2强
|
|
|
bool near_hr_filter = true; // 近端高反识别
|
|
|
} radar;
|
|
|
|
|
|
// ---------- scan: 扫描采集与走行 ----------
|
|
|
struct Scan
|
|
|
{
|
|
|
int collect_duration_s = 6; // exe模式/默认扫描时长(秒)
|
|
|
double z_speed = 20.0; // Z轴速度(cm/s),0=时间(ms),>0=移动距离(mm)
|
|
|
std::string z_speed_type = "uniformSpeed"; // uniformSpeed=匀速用z_speed / configuration=用config/speed.txt变速
|
|
|
} scan;
|
|
|
|
|
|
// ---------- detect: 截面分析 ----------
|
|
|
struct Detect
|
|
|
{
|
|
|
double z_range_mm = 50.0; // Z截面区间长度(mm)
|
|
|
double y_range_mm = 80.0; // Y截面区间长度(mm)
|
|
|
int rect_width_px = 8; // 截面矩形宽度(px)
|
|
|
double rect_length_ratio = 1.5; // 矩形长倍率
|
|
|
} detect;
|
|
|
|
|
|
// ---------- count: 分层计数 ----------
|
|
|
struct Count
|
|
|
{
|
|
|
double floor_height = 1600.0; // 地板高度(mm): 物品高度=floor_height-Y
|
|
|
double base_tolerance = 50.0; // 分层初始冗余(mm)
|
|
|
double per_level_tolerance = 20.0; // 每层递增冗余(mm)
|
|
|
int point_dilate = 8; // 画layer图每个点膨胀像素
|
|
|
double interp_bucket_deg = 0.08; // 角度插值桶宽(度), 应等于雷达角度分辨率
|
|
|
// (50Hz 常用 0.08; 一圈点数 = 360/桶宽 = 4500)
|
|
|
std::string z_interpolate_mode = "none"; // none/CopyTranslation/AngleBucketInterpolation/AngleBucketInterpolationByDilate
|
|
|
// CopyTranslation : 空隙 > 2×正常圈间隔时, 复制前一圈的点并平移 z
|
|
|
// AngleBucketInterpolation : 同上判定, 按角度分桶对前后圈做线性插值(平滑)
|
|
|
// AngleBucketInterpolationByDilate : 空隙 > point_dilate 时插值; 步长 = point_dilate/2
|
|
|
// (每 point_dilate/2 补一条, 最多 10 条, 平滑过渡)
|
|
|
// 分层容差(三个算法统一): tol(level) = base_tolerance + level×per_level_tolerance
|
|
|
// 层数算法:
|
|
|
// LevelTolerance = 现有: level=round(高度/层高), 判定 |高度-level×层高| <= tol
|
|
|
// HalfMax = 两步判定
|
|
|
// ① 粗筛: 本层中间~下一层中间 = [(level-0.5)×层高, (level+0.5)×层高]
|
|
|
// ② 精筛: 取①内最高点 top(按 floor_height-Y 算), 有效区间 = [top-tol, top]
|
|
|
// KdePeak = 两步判定
|
|
|
// ① 粗筛: 同 HalfMax
|
|
|
// ② 精筛: 对①内高度做 KDE(高斯核密度估计)得密度曲线, 取峰值 peak,
|
|
|
// 有效区间 = [peak-tol, peak+tol]
|
|
|
std::string layer_algorithm = "LevelTolerance";
|
|
|
double kde_bandwidth = 0.0; // KDE高斯核带宽(mm): <=0 按 Silverman 经验法则自动
|
|
|
double kde_step = 1.0; // KDE密度曲线扫描步长(mm)
|
|
|
} count;
|
|
|
|
|
|
// ---------- filter: 软件滤波(多边形 + 拖影) ----------
|
|
|
struct Filter
|
|
|
{
|
|
|
// 连续段尾部减除(图片级, 旧方案, 默认关闭):剪除 count_points 图像左右两侧的胡须状拖影
|
|
|
struct TailCut
|
|
|
{
|
|
|
bool enable = false; // 是否启用尾部减除
|
|
|
int max_tail_length = 15; // 每端最多保留尾部长度(px≈mm)
|
|
|
double y_delta = 30.0; // 尾部Y比核心Y高出多少(mm)更易被剪
|
|
|
int min_run_length = 5; // 连续段长度低于此直接删除
|
|
|
int core_min_len = 5; // 主体核心最小长度,保护小物体
|
|
|
int support_rows = 1; // 上下几行同列有支撑则不剪
|
|
|
} tail_cut;
|
|
|
|
|
|
// 点云级稀疏拖影过滤(计数模式, 默认开启):扫描结束后删除"胡须状拖影"点。
|
|
|
// 稀疏点定义: 同一扫描圈(z相同)内 X±XRadius(mm) 无其它点(不同圈同X不算邻居)。
|
|
|
// 满足任一判据即删该稀疏点:
|
|
|
// 1) 同圈连续: 同一圈内稀疏点数 >= circle_min(如某圈边缘外伸了N个点)
|
|
|
// 2) 跨圈连续: 相近X位置(±x_radius)的稀疏点在z上连续出现圈数 >= run_min
|
|
|
struct SparseCut
|
|
|
{
|
|
|
bool enable = true; // 总开关
|
|
|
double x_radius = 10.0; // 同圈X邻域半径(mm): X±此值内无点=稀疏
|
|
|
int circle_min = 2; // 同圈稀疏点数≥此 即删
|
|
|
int run_min = 2; // 同一X位置跨圈连续出现≥此圈 即删
|
|
|
} sparse_cut;
|
|
|
|
|
|
std::vector<std::pair<double, double>> polygon = { {-650, 0}, {-650, 670}, {650, 670}, {650, 0} }; // 过滤多边形(mm)
|
|
|
int poly_n = (int)polygon.size(); // 多边形顶点数
|
|
|
} filter;
|
|
|
};
|
|
|
|
|
|
// ==================== 全局配置(进程级 + 各雷达参数) ====================
|
|
|
struct AppConfig
|
|
|
{
|
|
|
std::vector<std::string> ids; // 雷达标识列表(配置出现顺序,第一个=默认雷达)
|
|
|
// 用 shared_ptr 持有:load_config 重载时会整体替换,而采集/保存线程可能仍持有旧配置,
|
|
|
// 引用计数保证其生命周期延续到线程作用域结束,避免悬空指针。
|
|
|
std::map<std::string, std::shared_ptr<RadarConfig>> radars; // 雷达标识 -> 该雷达完整参数
|
|
|
|
|
|
// ---------- server: 运行模式(全局) ----------
|
|
|
struct Server
|
|
|
{
|
|
|
std::string mode = "exe"; // exe=直接检测一次 / tcp=TCP服务端 / http=HTTP服务端
|
|
|
uint16_t port = 9601; // TCP/HTTP监听端口
|
|
|
} server;
|
|
|
|
|
|
// ---------- log: 日志(全局) ----------
|
|
|
struct Log
|
|
|
{
|
|
|
bool enable = true; // 是否写日志文件
|
|
|
int retain_days = 15; // 日志(任务目录)保留天数, 超出自动删除
|
|
|
int clean_hour = 1; // 每日日志定时清理时刻 时(0-23),来源: 配置 log.clean_time "HH:MM:SS"
|
|
|
int clean_minute = 0; // 每日日志定时清理时刻 分(0-59)
|
|
|
int clean_sec = 0; // 每日日志定时清理时刻 秒(0-59)
|
|
|
} log;
|
|
|
|
|
|
// 按标识取雷达配置;不存在返回 nullptr。id 为空时返回默认雷达(第一个)
|
|
|
std::shared_ptr<const RadarConfig> find(const std::string& id) const;
|
|
|
// 默认雷达(第一个);无雷达时返回 nullptr
|
|
|
std::shared_ptr<const RadarConfig> first() const;
|
|
|
};
|
|
|
|
|
|
// 全局配置实例(config.cpp 中定义)
|
|
|
extern AppConfig cfg;
|
|
|
|
|
|
// 当前线程生效的雷达配置:
|
|
|
// - 已用 RadarScope 绑定 → 返回该雷达配置;
|
|
|
// - 未绑定 → 返回默认雷达配置(第一个);
|
|
|
// - 无任何雷达 → 返回一份空配置(字段为默认值)。
|
|
|
const RadarConfig& radar_cfg();
|
|
|
|
|
|
// RAII:把当前线程绑定到某个雷达的配置,出作用域自动恢复上一次绑定。
|
|
|
// 采集线程/请求处理线程/异步保存线程都应在入口处绑定。
|
|
|
class RadarScope
|
|
|
{
|
|
|
public:
|
|
|
explicit RadarScope(const std::string& radar_id);
|
|
|
~RadarScope();
|
|
|
private:
|
|
|
std::shared_ptr<const RadarConfig> prev_;
|
|
|
};
|
|
|
|
|
|
// 加载 JSON 格式配置文件(行首(忽略空白)以 // 开头的注释行会被剔除)
|
|
|
// 返回是否成功;失败时保留原有 cfg 不变(绝不退出进程:运行期 config 重载会调用它)。
|
|
|
bool load_config(const std::string& path = "./config/config");
|
|
|
|
|
|
#endif // CONFIG_H
|