# radar_visual **Repository Path**: sunshengliang/radar_visual ## Basic Information - **Project Name**: radar_visual - **Description**: 可视化雷达的相关支持 - **Primary Language**: C - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2022-11-23 - **Last Updated**: 2026-04-16 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 简介 本仓库仅用于可视化雷达的相关支持,主要介绍: - 可视化雷达的固件更新 - 基于雷达和摄像头输出的数据,提供融合方法库. ## 设备介绍 - 可视化雷达内装三个组件<主控><射频组件1><射频组件2> ### 硬件接口 - 供电电源使用12V直流电源. - 通信接口使用485双绞线. ### 软件接口 - 软件通信协议通过技术支持获取.或参考[ *可视化雷达通信协议* ](doc/protocol_intruder.md) - 与可视化设备的推荐交互流程 ``` 一、在断电后上电的情况下 1.主动上报模式中,电流为8mA, 上电18s后电流变化,雷达开始初始化,电流为300mA左右,初始化完毕, 上电23s后雷达回复42报文, 上电26s后雷达进入4mA休眠模式,并在2min后定时发送42报文,主动上报时电流为300mA左右; 发送48报文,27ms后回复本设备版本信息; 发送49报文,27ms后回复49ack报文,之后500ms左右回复00报文,之后500ms左右回复01报文。 2.长休眠模式中,在断电后上电的情况下,电流为7mA, 上电17s后电流发生变化,雷达开始初始化,电流为300mA左右,初始化完毕, 上电23s后雷达发送42报文, 上电27s后雷达进入4mA长休眠模式,此模式下雷达不会主动上报42报文,需要指令触发; 发送59报文触发雷达工作,5s左右回复42报文,等待雷达返回42报文的通知后,1s内发送49报文询问雷达数据,30ms左右回复完整49报文。之后500ms左右回复00报文,之后500ms左右回复01报文。 49报文的查询仅支持3s内交互一次。 二、在不断电情况下 1.输入64 00报文,使雷达为主动上报模式,4s后雷达进入休眠模式,此时电流为4mA。 在此模式下,雷达每隔2分钟主动唤醒一次并主动上报42报文; 发送49报文,27ms后回复49ack报文,之后500ms后回复00报文,500ms后回复01报文; 发送48报文,25ms后回复本设备版本信息。 2.输入64 01报文,使雷达为被动上报模式,4s后雷达进入休眠模式,此时电流为4mA。 在此模式下,雷达每隔2分钟主动唤醒一次,此时雷达不会主动上报42报文; 发送48报文,26ms后回复本设备版本信息; 发送49报文,28ms后回复49ack报文,之后500ms左右回复00报文,之后500ms左右回复01报文。 3.输入64 03报文,使雷达为长休眠模式,4s后雷达进入长休眠模式,此时电流为4mA。 在此模式下,雷达不会主动唤醒,不会主动上报42报文,需要主动发送59指令触发; 发送59报文唤醒雷达扫描,5s后回复42报文表示扫描完成,等待雷达返回42报文的通知后,1s内此时发送49报文询问雷达数据,30ms左右回复完整49报文。之后500ms左右回复00报文,之后500ms左右回复01报文。 49报文的查询仅支持3s内交互一次。 ``` ## 目录介绍 - boot_tool_exe: 上位机刷新程序的可执行文件,目前工具仅更新windows版本。 - boot_tool_hex: 主控代码的hex文件,网关固件存于hw_control_L4,参考[ *网关固件* ](boot_tool_hex/hw_control_L4/hex_L4.md) - boot_tool_lib: 上位机刷新程序的lib库 - camera_radar_merge_lib: 上位机融合输出方法库 - camera_radar_tool: 初始版本配置工具,后续联系技术支持获取最新版本。 - doc: 存放说明文档 # 固件更新 ## 使用工具更新 使用已经编译过的可执行文件进行代码更新,这里介绍windows下使用方法 进入boot_tool_exe目录,选择相应平台的可执行文件,进入相应的目录执行命令 ``` window example: ./p_bootTool_v2.0.0.exe -o comx -f xx/xx.hex comx-------为串口号 xx/xx.hex--为固件 ``` ## 使用库集成更新 boot_tool_lib文件夹下存储不同平台编译的库,调用库中提供的相应的接口函数,进行代码更新. 通用的C接口函数为: ``` typedef enum { boot_sucess = 0, boot_noInputPara = 1, boot_inputParaNotEnough = 2, boot_comOpenError = 3, boot_fileOpenError = 4, boot_TimeOut = 5, }eboot_error_t; /*hal write/read call back function define*/ typedef int (*hal_write_callback_t)(const unsigned char* wbuf, const unsigned short wbuflen); typedef int (*hal_read_callback_t)(unsigned char* rbuf, unsigned short* rbuflen); typedef struct { char* pdev_id; // "" 设置为空,默认刷写主控 "0" 刷写RF0 "1" 刷写RF1 char* pdebug_level; // '0'-'5' char* pcomioctr; //com 485 io control /*hal low level operation*/ hal_write_callback_t hal_write_callback; hal_read_callback_t hal_read_callback; }boot_api_arg_t; extern int bootTool_lib_Api(char* pfilename, char* comx,unsigned char debug_enable, boot_api_arg_t *api_arg); ``` 参数说明 - char* pfilename :固件的文件路径 - char* comx :串口号 - unsigned char debug_enable :是否需要调试开关 - boot_api_arg_t *api_arg :附加参数,见代码中注释 - hal_write_callback/hal_read_callback :当需要外部实现读写时候的回调函数,*注意此时comx不要赋值*。 android平台下会稍有不同,具体可以查看提供的Demo文件。[ *android Boot Demo* ](boot_tool_lib/android/MainActivity.java) # 雷视融合输出方法库 方法库基于雷达的输出数据和摄像头的AI识别结果,对雷达和摄像头检测到的目标进行精确匹配,输出匹配后的隐患目标信息。 这里仅介绍window或linux平台下c接口。 android平台下会有不同,具体可以查看提供的Demo文件。[ *andoroid SDK Demo* ](camera_radar_merge_lib/android/MainActivity.java) ## 函数接口-初始化配置 ``` /*加载json配置文件*/ _LIBCRM_API_ int crm_libinit(const char* config_file); ``` ## 函数接口-库主函数融合库输出距离等信息 输出隐患信息--接口已经不再使用 ``` _LIBCRM_API_ int radar_helplib_zhy( unsigned char *pradar_raw, const unsigned int radar_rawlen, const char*pImage_name, /*path*/ damage_info_t *pdamage_info); /**/ ``` 输出隐患信息 ``` _LIBCRM_API_ int crm_libcompute(int h, unsigned char* pradar_raw, const unsigned int radar_rawlen, const char* pImage_name, damage_info_ext_t* pdamage_infos); ``` 附加输出隐患点到导线线段的位置 ``` _LIBCRM_API_ int crm_libcompute_with_xyz( unsigned char* pradar_raw, const unsigned int radar_rawlen, const char* pImage_name, damage_info_ext_t* pdamage_infos, damage_info_location_t* damge_locs ) ``` ### 返回值定义及说明 ``` typedef enum CA_return_value_t_tag { Warn_image_path_is_not_specified = 1, Success = 0, Failed_image_can_not_opened = -1, Failed_radar_raw_data_too_small = -2, Failed_radar_raw_data_format_error = -3, Failed_radar_config_not_fit_image_input_error = -4, Failed_image_not_exist = -5, Failed_image_not_read_permission = -6, Failed_json_load_failed = -7, Failed_radar_raw_data_is_null = -8, Failed_damage_infos_is_null = -9, Failed_radar_raw_data_input_is_null = -10, Failed_radar_raw_data_header_not_match = -11, Failed_radar_raw_data_tail_not_match = -12, Failed_radar_raw_data_chksum_not_match = -13, Failed_radar_raw_data_not_support_tag = -14, Failed_radar_raw_data_merge_failed = -15, Failed_radar_raw_data_not_completed = -100, Failed_damage_infos_is_empty = -16, Failed_damage_infos_exceed_16 = -17, Failed_damage_roi_exceed_image_range = -18, Failed_damage_roi_is_empty = -19, Failed_lib_not_inited = -20, Failed_env_qiwen_too_low = -21, // -40C Failed_env_qiwen_too_high = -22, // 80C Failed_env_fubing_small_than_zero = -23, Failed_env_fubing_too_thick = -24, // 50mm Failed_env_fengsu_small_than_zero = -25, Failed_env_fengsu_large_than_hurricane = -26, // 40mps Failed_multithread_wrong_handle_id = -27, Failed_multithread_wrong_result = -28, Failed_image_size_not_match_config = -29 }CA_return_value_t; 0 成功 1 失败-图片路径为空 -1 失败-图片路径无法打开-请检查路径是否正确,或者是否有读取权限 -2 失败-雷达原始数据不全 -3 失败-雷达数据类型异常 -4 失败-雷达数据和图片数据不匹配—雷达系统中输入的图像大小和输入图片大小不一致 -5 失败-图片路径不存在 -6 失败-图片不能读取 -7 失败-json文件加载失败 其他说明见代码。 ``` ### 参数说明 - 参数1 ``` /*指针指向雷达原始数据,原始数据通过使用49报文,查看可视化雷达数据获取*/ unsigned char *pradar_raw, ``` - 参数2 ``` /*参数1对应的雷达原始数据的长度*/ const unsigned int radar_rawlen, ``` - 参数3 ``` /*指针指向原始图片的路径*/ const char*pImage_name, ``` - 参数4 ``` /*指针指向隐患的具体信息,damage_info_t 定义及注释如下*/ damage_info_t *pdamage_info ``` ``` //点坐标 typedef struct dl_point_s { int s32X; //像素在X轴值 int s32Y; //像素在Y轴值 } DlPoint_t; typedef struct { /*AI result*//*隐患坐标*/ DlPoint_t d_Point[4]; //像素位置结构体数组,AI框的四个顶点,从左上角开始,依次为,左上、右上、右下、左下,为输入 unsigned int d_class; //AI识别隐患类型(详情参见 _隐患映射表_ ),为输入 float d_confidence;//AI识别置信度(取值范围0-1),为输入 unsigned int ai_res; //预留,为输入 unsigned int ai_res1; //预留,为输入 /*lib out*//*隐患位置*/ float d_dis_d0; //隐患与通道的距离,单位米,为输出 float d_dis_d1; //隐患与导线的距离,单位米,为输出 unsigned int isFlag; //隐患匹配状态,为输出,参考damage_flag_t float lib_res; //预留,为输出--输出速度,单位m/s 目标远离为正,目标接近为负 float lib_res1; //预留,为输出--输出方位,单位为度 通道右侧为正 通道左侧为负 通道下方为0 }damage_t; typedef struct { /*隐患数量*/ unsigned int d_num; /*隐患列表*/ damage_t damage_list[DAMAGE_NUM_MAX]; }damage_info_t; ``` 隐患映射表 ``` 1 吊车 2 塔吊 3 水泥泵车 4 推土机 5 卡车、翻斗车、挂车 6 挖掘机 7 水泥搅拌车 8 打桩机 9 厢车(货车) 99 其他工程车辆(除列出的工程车辆之外的类型) 254 树障 255 其他 ``` 方法库输出的隐患位置标志定义如下 ``` typedef enum damage_flag_t_tag { out_of_intruder_range = 0x00, //定义的外破范围之外 通常定义为+-40m in_intruder_range = 0x01, //定义的外破范围之内 under_wires = 0x02, //两侧导线所对应的通道正下方 out_of_intruder_span = 0x04, unvalid_ai_class = 0xEE, //不在检测的外破物类型之内 unvalid_ai_confidence = 0xEF, //置信度低 radar_not_detected = 0xFF, //雷达未检测到和Ai输出相匹配的框 }damage_flag_t; ``` ## 函数接口-获取隐患点 ``` typedef struct { DlPoint_t m_object; DlPoint_t m_wire; }output_damage_point_t; typedef struct { unsigned int d_num; output_damage_point_t m_ans[DAMAGE_NUM_MAX]; }output_damage_points_info_t; _LIBCRM_API_ void crm_get_damage_points(output_damage_points_info_t* damage_points); ``` ## 调用顺序 ``` crm_libversion() crm_libinit(); crm_libset_env() crm_libcompute() const char* pver = crm_libversion();printf("libversion:%s\r\n",pver); crm_libinit(jsonpath); int ret_set_env = crm_libset_env(15, 0, 0); int ret_libcompute = crm_libcompute( radar_raw, sizeof(radar_raw), imagepath, &damage_info); ``` ## 调用示例 ``` #include "camera_radar_merge_api.hpp" #include #include #include int main() { damage_info_ext_t *p_info = (damage_info_ext_t*)malloc(sizeof(damage_info_ext_t)); if (!p_info) { printf("Memory allocation failed!\n"); return -1; } memset(p_info, 0, sizeof(damage_info_ext_t)); p_info->d_num = 1; // 检测到的目标 p_info->damage_list[0].m_dam.d_Point[0].s32X = 398; // 左上角X(示例值) p_info->damage_list[0].m_dam.d_Point[0].s32Y = 1449; // 左上角Y(示例值) p_info->damage_list[0].m_dam.d_Point[3].s32X = 410; // 右下角X(示例值) p_info->damage_list[0].m_dam.d_Point[3].s32Y = 1495; // 右下角Y(示例值) p_info->damage_list[0].m_dam.d_Point[1].s32X = 0; p_info->damage_list[0].m_dam.d_Point[1].s32Y = 0; p_info->damage_list[0].m_dam.d_Point[2].s32X = 0; p_info->damage_list[0].m_dam.d_Point[2].s32Y = 0; p_info->damage_list[0].m_dam.d_class = 6; // 类别,参考**隐患映射表** p_info->damage_list[0].m_dam.d_confidence = 0.8f; // 置信度 const char* jsonPath = "./config.json"; int ret_init = crm_libinit(jsonPath); printf("Init Result: %d\n", ret_init); const char *version = crm_libversion(); printf("Library Version: %s\n", version); float temp = 15.0f; float ice = 0.0f; float wind = 0.0f; int ret_env = crm_libset_env(temp, ice, wind); unsigned char* radarData = radarRawData; // radar data(funcode is 0x49) unsigned int radarLen = sizeof(radarRawData); std::string imagePath = "./test.jpg"; int ret_cpt = crm_libcompute(radarData, radarLen, imagePath.c_str(), p_info); if (ret_cpt == 0) { float distance_d0 = p_info->damage_list[0].m_dam.d_dis_d0; float distance_d1 = p_info->damage_list[0].m_dam.d_dis_d1; printf("Success!\n"); printf("Distance D0: %.2f\n", distance_d0); printf("Distance D1: %.2f\n", distance_d1); } else { printf("Calculation Failed! Error Code: %d\n", ret_cpt); } free(p_info); return 0; } ``` ## 多线程调用接口 以下新增接口,支持多线程调,说明如下 ``` crm_lib_init_mt 初始化函数(应在线程开启前调用) 输入[1]:json文件路径 输出[1]:返回大于0的话为成功。 小于0参考异常值定义。 crm_lib_deinit_mt 释放函数(应在线程退出时调用, 或者应用推出前调用) 输入[1]:初始化函数 返回值 crm_libcompute_mt 计算主函数 输入[1]:初始化函数 返回值 输入[2]:雷达原始数据 输入[3]:雷达原始数据长度(bytes) 输入[4]:图像文件路径 输入[5]:外破信息 输出[1]:等于0 为成功 crm_get_damage_points_mt 获取外破关键点信息(应在每次调用 计算主函数 成功后 调用) 输入[1]:初始化函数 返回值 输入[2]:外破关键点信息 输出[1]:等于0 为成功 crm_libset_env_mt 设置环境信息(应在每次调用 计算主函数 时调用) 输入[1]:初始化函数 返回值 输入[2]:气温 输入[3]:浮冰厚度 输入[4]:风速 ``` ## 集成调用接口 ``` _LIBCRM_API_ int crm_lib_all_mt( const char* config_file, const float qiwen, const float fubing_mm, const float fengsu_mps, unsigned char* pradar_raw, const unsigned int radar_rawlen, const char* pImage_name, damage_info_ext_t* pdamage_infos, output_damage_points_info_t* damage_points ); ``` # Q&A ## 常见问题 1. 通信波特率是多少? >115200bps 2. 上电的工作时序是什么? - 示意图 >![Alt text](doc/exectric_current_timing.jpg) - 第一次上电的功耗曲线 >![Alt text](doc/current_power_on.png) - 正常工作的功耗曲线 >![Alt text](doc/current_work.png) 3. 加热逻辑如何开启 >目前是1~2分钟发送一次开启加热命令。后续更新为发送一次加热命令开启10分钟左右. 4. 读取到雷达的数据全是0 >雷达上电后,需要等待雷达工作30-40秒,后再去读取雷达数据 5. 算法SDK库报错ROI exceed >ROI边界不能超过图像的大小-1,如2592*1944 则ROI最大边界不能超过2591或1943 ## 头文件相关问题 1. 接口中的初始化值,int h,是什么参数,取什么值? >句柄,是在服务器版本上运行准备的,不需要调用。 2. crm_get_damage_points接口,是什么功能? >crm_get_damage_points是旧版本的接口,不需要调用。 3. crm_libset_env_mt接口,浮冰参数,是指哪里的浮冰,是指导线上的浮冰?还是说雷达外壳上的浮冰厚度? >指的是目标导线上的覆冰。因为在电力场景下,覆冰厚度会影响导线的下垂度(弧垂),算法需要知道当前环境的覆冰情况来修正对导线位置的判断,防止误报。没有覆冰时,该值默认为0。该接口不需要调用。 4. 集成调用接口crm_lib_all_mt,相当于调用初始化、设置环境参数、融合接口、获取隐患目标信息这几个接口的总和,接口内部按业务流程顺序调用是么? >接口正确调用顺序如下,详细调用示例可见 radar_visual: 可视化雷达的相关支持 - Gitee.com 的readme.md文件: >crm_libversion() //询问lib版本 >crm_libinit(); //lib初始化 >crm_libset_env() //环境信息配置 >crm_libcompute() //计算雷视融合,返回值为0时表示成功 5. 集成调用接口,和单独调用有哪些区别?比如我理解单独调用时,crm_libinit只调用一次就可以,集成调用的话内部每次都会调用么?对性能有何影响,比如会增加响应耗时? >crm_lib_all_mt相关的接口都不需要调用。crm_libinit每次都要调用,不消耗时间。 6. crm_libset_env每次做融合都需要调用么? >是的,每次/每帧都需要调用。 ## OpenCV问题 >关于openCV各版本的链接问题,我们可以根据客户的需要编译相应版本。 ## 配置工具相关 > 每一个相机都有自己的内参,客户可以自己测试内参,但我们不保证数据结果的准确性。 ## 固件升级相关 1. gitee资料中有工具升级和集成库升级两种方式,这两种有何差异,对于相机集成的方案选择有什么建议? >没有差异,集成库升级只是为了用户可以调用lib封装自己的可执行程序进行升级。