소스 검색

夹持干雷达

LiuZe 1 년 전
부모
커밋
482f2ab1c5

+ 6 - 0
.gitignore

@@ -70,3 +70,9 @@ Makefile
 cmake_install.cmake
 install_manifest.txt
 
+# ---> Clion
+cmake-build-debug
+cmake-build-release
+.idea
+
+

+ 61 - 0
CMakeLists.txt

@@ -0,0 +1,61 @@
+cmake_minimum_required(VERSION 3.5)
+
+project(AllProject)
+
+if (NOT DEFINED CMAKE_BUILD_TYPE OR ${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+    add_definitions(-DETC_PATH="${CMAKE_SOURCE_DIR}/etc/")
+else ()
+    add_definitions(-DETC_PATH="${CMAKE_INSTALL_PREFIX}/etc/")
+endif ()
+
+# 第三方库
+find_package(PkgConfig REQUIRED)
+pkg_check_modules(nanomsg REQUIRED nanomsg)
+pkg_check_modules(YAML_CPP REQUIRED yaml-cpp)
+find_path(YAML_CPP_INCLUDE_DIR
+        NAMES yaml_cpp.h
+        PATHS ${YAML_CPP_INCLUDE_DIRS})
+find_library(YAML_CPP_LIBRARY
+        NAMES YAML_CPP
+        PATHS ${YAML_CPP_LIBRARY_DIRS})
+if (NOT ${YAML_CPP_VERSION} VERSION_LESS "0.5")
+    add_definitions(-DHAVE_NEW_YAMLCPP)
+endif (NOT ${YAML_CPP_VERSION} VERSION_LESS "0.5")
+#add_subdirectory(thirdpart/rs_driver)
+
+# Don't search with REQUIRED as we can continue without gflags.
+find_package(gflags 2.2.0)
+if (gflags_FOUND)
+    if (TARGET gflags)
+        message("-- Found Google Flags (gflags) version ${gflags_VERSION}: ${gflags_DIR}")
+        message("-- Found Google Flags (gflags) version ${gflags_VERSION}: ${GFLAGS_LIBRARIES}")
+    else()
+        message("-- Detected version of gflags: ${gflags_VERSION} does not define "
+                "expected gflags CMake target which should be exported by gflags 2.2+. "
+                "Building without gflags.")
+        update_cache_variable(GFLAGS OFF)
+    endif()
+else (gflags_FOUND)
+    message("-- Did not find Google Flags (gflags), Building without gflags.")
+    update_cache_variable(GFLAGS OFF)
+endif (gflags_FOUND)
+
+find_package(PCL REQUIRED)
+find_package(Eigen3 REQUIRED)
+find_package(Ceres REQUIRED)
+find_package(OpenCV REQUIRED)
+#find_package(rs_driver REQUIRED)
+find_package(Protobuf REQUIRED)
+
+if (EXISTS "${CMAKE_SOURCE_DIR}/include/CMakeLists.txt")
+    include_directories(${CMAKE_SOURCE_DIR}/include)
+    add_subdirectory(${CMAKE_SOURCE_DIR}/include)
+else ()
+    message("Can't find dir: " "${CMAKE_SOURCE_DIR}/include/CMakeLists.txt")
+endif ()
+
+if (EXISTS "${CMAKE_SOURCE_DIR}/project/CMakeLists.txt")
+    add_subdirectory(${CMAKE_SOURCE_DIR}/project)
+else ()
+    message("Can't find dir: " "${CMAKE_SOURCE_DIR}/project/CMakeLists.txt")
+endif ()

+ 1 - 1
etc

@@ -1 +1 @@
-Subproject commit 2d42ff75fa8285c0feb3cf46c55b8acee1ebe22c
+Subproject commit 597b4cbc89eff1f0390e35b812b62c978a7b35b3

+ 1 - 1
include/CMakeLists.txt

@@ -2,7 +2,7 @@
 message("===== compile library =====")
 OPTION(ENABLE_LIBRARY_ERROR_CODE "" ON)
 OPTION(ENABLE_LIBRARY_GOOGLE_LOG "" ON)
-OPTION(ENABLE_LIBRARY_PCL "" OFF)
+OPTION(ENABLE_LIBRARY_PCL "" ON)
 OPTION(ENABLE_LIBRARY_RABBITMQ "" OFF)
 OPTION(ENABLE_LIBRARY_THREAD "" ON)
 OPTION(ENABLE_LIBRARY_PLC "" ON)

+ 1 - 20
include/error_code/CMakeLists.txt

@@ -3,32 +3,13 @@ set(LIBRARY_NAME error_code)
 unset(OPTION_ENABLE_TEST_CODE CACHE)
 option(OPTION_ENABLE_TEST_CODE "Whether enable test code." OFF)
 message("<=${LIBRARY_NAME}=> OPTION_ENABLE_TEST_CODE: " ${OPTION_ENABLE_TEST_CODE})
-unset(OPTION_ERROR_CODE_DESCRIPTE CACHE)
-option(OPTION_ERROR_CODE_DESCRIPTE "Whether enable error code description." OFF)
-message("<=${LIBRARY_NAME}=> OPTION_ERROR_CODE_DESCRIPTE: " ${OPTION_ERROR_CODE_DESCRIPTE})
-
-if (OPTION_ERROR_CODE_DESCRIPTE)
-    add_definitions(-DOPTION_ERROR_CODE_DESCRIPTE=1)
-else ()
-    add_definitions(-DOPTION_ERROR_CODE_DESCRIPTE=0)
-endif ()
-
-
-set(LIBRARY_SOURCE_LIST
-        ${CMAKE_CURRENT_LIST_DIR}/error_code.hpp
-        ${CMAKE_CURRENT_LIST_DIR}/error_code.cpp
-)
-
-set(LIBRARY_DEPEND_LIST)
-
-add_library(${LIBRARY_NAME} ${LIBRARY_SOURCE_LIST})
-target_link_libraries(${LIBRARY_NAME} PUBLIC ${LIBRARY_DEPEND_LIST})
 
 if (OPTION_ENABLE_TEST_CODE)
     set(LIBRARY_TEST_NAME "${LIBRARY_NAME}_test")
     set(LIBRARY_TEST_SOURCE_LIST
             ${CMAKE_CURRENT_LIST_DIR}/test.h
             ${CMAKE_CURRENT_LIST_DIR}/test.cpp
+            ${CMAKE_CURRENT_LIST_DIR}/error_code.cpp
     )
     add_executable(${LIBRARY_TEST_NAME} ${LIBRARY_TEST_SOURCE_LIST})
     target_link_libraries(${LIBRARY_TEST_NAME} ${LIBRARY_NAME} )

+ 0 - 5
include/error_code/error_code.cpp

@@ -1,5 +0,0 @@
-//
-// Created by zx on 2023/10/26.
-//
-
-#include "error_code.hpp"

+ 41 - 22
include/error_code/error_code.hpp

@@ -8,6 +8,8 @@
 #include <string>
 #include <string.h>
 #include<iostream>
+#include <stdio.h>	/* vsnprintf与vsprintf */
+#include <stdarg.h>	/* va... */
 
 #define MAIN_TEST 1
 //#define PROCESS_TEST 1
@@ -20,7 +22,7 @@
 //错误管理类转化为字符串 的前缀,固定长度为58
 //这个是由显示格式来确定的,如果要修改格式或者 Error_code长度超过8位,Error_level长度超过2位,折需要重新计算
 #define ERROR_NAMAGER_TO_STRING_FRONT_LENGTH   58
-
+#define DESCRIPTION_BUF_SIZE 1024
 //进程加锁的状态,
 enum Lock_status {
     UNLOCK = 0,
@@ -496,7 +498,6 @@ enum Error_code {
 
 
 
-
     //parkspace allocator,车位分配模块
     PARKSPACE_ALLOCATOR_ERROR_BASE = 0x20010000,
     PARKSPACE_ALLOCATOR_MSG_REQUEST_TYPE_ERROR,    //反馈车位消息类型错误 
@@ -641,12 +642,16 @@ public://外部接口函数
 
     //赋值构造
     Error_manager(Error_code error_code, Error_level error_level = NORMAL,
-                  const char *p_error_description = nullptr) {
+                  const char *f = nullptr, ...) {
+        va_list arg_ptr;
+        char buf[DESCRIPTION_BUF_SIZE];
+        va_start(arg_ptr, f);
+        vsnprintf(buf, DESCRIPTION_BUF_SIZE, f, arg_ptr);
+        va_end(arg_ptr);
+
         m_error_code = error_code;
         m_error_level = error_level;
-        if (p_error_description != nullptr) {
-            m_error_description = std::string(p_error_description);
-        }
+        m_error_description = std::string(buf);
     }
 
     //赋值构造
@@ -666,12 +671,16 @@ public://外部接口函数
 
     //初始化
     void error_manager_init(Error_code error_code, Error_level error_level = NORMAL,
-                            const char *p_error_description = nullptr) {
+                            const char *f = nullptr, ...) {
+        va_list arg_ptr;
+        char buf[DESCRIPTION_BUF_SIZE];
+        va_start(arg_ptr, f);
+        vsnprintf(buf, DESCRIPTION_BUF_SIZE, f, arg_ptr);
+        va_end(arg_ptr);
+
         m_error_code = error_code;
         m_error_level = error_level;
-        if (p_error_description != nullptr) {
-            m_error_description = std::string(p_error_description);
-        }
+        m_error_description = std::string(buf);
     }
 
     //初始化
@@ -683,12 +692,16 @@ public://外部接口函数
 
     //重置
     void error_manager_reset(Error_code error_code, Error_level error_level = NORMAL,
-                             const char *p_error_description = nullptr) {
+                             const char *f = nullptr, ...) {
+        va_list arg_ptr;
+        char buf[DESCRIPTION_BUF_SIZE];
+        va_start(arg_ptr, f);
+        vsnprintf(buf, DESCRIPTION_BUF_SIZE, f, arg_ptr);
+        va_end(arg_ptr);
+
         m_error_code = error_code;
         m_error_level = error_level;
-        if (p_error_description != nullptr) {
-            m_error_description = std::string(p_error_description);
-        }
+        m_error_description = std::string(buf);
     }
 
     //重置
@@ -815,10 +828,13 @@ public://外部接口函数
     }
 
     //设置错误描述
-    void set_error_description(const char *p_error_description) {
-        if (p_error_description != nullptr) {
-            m_error_description = std::string(p_error_description);
-        }
+    void set_error_description(const char *f, ...) {
+        va_list arg_ptr;
+        char buf[DESCRIPTION_BUF_SIZE];
+        va_start(arg_ptr, f);
+        vsnprintf(buf, DESCRIPTION_BUF_SIZE, f, arg_ptr);
+        va_end(arg_ptr);
+        m_error_description = std::string(buf);
     }
 
     //设置错误描述
@@ -827,10 +843,13 @@ public://外部接口函数
     }
 
     //尾部追加错误描述
-    void add_error_description(const char *p_error_description) {
-        if (p_error_description != nullptr) {
-            m_error_description += std::string(p_error_description);
-        }
+    void add_error_description(const char *f, ...) {
+        va_list arg_ptr;
+        char buf[DESCRIPTION_BUF_SIZE];
+        va_start(arg_ptr, f);
+        vsnprintf(buf, DESCRIPTION_BUF_SIZE, f, arg_ptr);
+        va_end(arg_ptr);
+        m_error_description += std::string(buf);
     }
 
     //尾部追加错误描述

+ 1 - 0
include/log/CMakeLists.txt

@@ -13,6 +13,7 @@ set(LIBRARY_SOURCE_LIST
 )
 
 set(LIBRARY_DEPEND_LIST
+        libfile
         -lgflags
         glog::glog
 )

+ 6 - 5
include/log/log.h

@@ -23,20 +23,21 @@ namespace ZX{
         fclose(tp_file);
     }
 
-// 例子: ZX::InitGlog("MeasureNode", ETC_PATH"MeasureNode/MeasureNodeLog/");
-    static void InitGlog(const char * project_name, const char *logPath) {
+// 例子: ZX::InitGlog(PROJECT_NAME, ETC_PATH PROJECT_NAME "/LogInfo/");
+    static bool InitGlog(const char * project_name, const char *logPath) {
         PathCreator pc;
-        pc.Mkdir(logPath);
+        if (!pc.Mkdir(logPath)) {return false;}
         google::InitGoogleLogging(project_name);
         google::SetStderrLogging(google::INFO);
         google::SetLogDestination(google::INFO, logPath);
-        google::SetLogFilenameExtension(".txt");
+        google::SetLogFilenameExtension(".log");
         google::InstallFailureSignalHandler();
         google::InstallFailureWriter(&ZX::shut_down_logging);
         FLAGS_colorlogtostderr = true;        // Set log color
         FLAGS_logbufsecs = 0;                // Set log output speed(s)
-        FLAGS_max_log_size = 24;            // Set max log file size(GB)
+        FLAGS_max_log_size = 32;            // Set max log file size(MB)
         FLAGS_stop_logging_if_full_disk = true;
+        return true;
     }
 }
 

+ 12 - 2
include/pcl/CMakeLists.txt

@@ -4,9 +4,19 @@ unset(OPTION_ENABLE_TEST_CODE CACHE)
 option(OPTION_ENABLE_TEST_CODE "Whether enable test code." ON)
 message("<=${LIBRARY_NAME}=> OPTION_ENABLE_TEST_CODE: " ${OPTION_ENABLE_TEST_CODE})
 
-set(LIBRARY_SOURCE_LIST)
+if (NOT ENABLE_LIBRARY_GOOGLE_LOG)
+    message(FATAL_ERROR "Not enable ENABLE_LIBRARY_GOOGLE_LOG")
+endif ()
+
+include_directories(${PCL_INCLUDE_DIRS} ${OpenCV_INCLUDE_DIRS})
+set(LIBRARY_SOURCE_LIST
+        ${CMAKE_CURRENT_LIST_DIR}/point2D_tool.h
+        ${CMAKE_CURRENT_LIST_DIR}/point2D_tool.cpp
+        ${CMAKE_CURRENT_LIST_DIR}/point3D_tool.h
+        ${CMAKE_CURRENT_LIST_DIR}/point3D_tool.cpp
+)
 
-set(LIBRARY_DEPEND_LIST)
+set(LIBRARY_DEPEND_LIST liblog ${PCL_LIBRARIES} ${OpenCV_LIBRARIES})
 
 add_library(${LIBRARY_NAME} ${LIBRARY_SOURCE_LIST})
 target_link_libraries(${LIBRARY_NAME} PUBLIC ${LIBRARY_DEPEND_LIST})

+ 140 - 0
include/pcl/point2D_tool.cpp

@@ -0,0 +1,140 @@
+//
+// Created by huli on 2020/9/1.
+//
+
+#include "point2D_tool.h"
+
+//极坐标 -> 平面坐标
+bool Point2D_tool::Polar_coordinates_to_point2D(Point2D_tool::Polar_coordinates* p_polar_coordinates, Point2D_tool::Point2D* p_point2D)
+{
+	if ( p_polar_coordinates == NULL || p_point2D == NULL)
+	{
+		return false;
+	}
+	else
+	{
+		p_point2D->x = p_polar_coordinates->distance * cos(p_polar_coordinates->angle);
+		p_point2D->y = p_polar_coordinates->distance * sin(p_polar_coordinates->angle);
+		return true;
+	}
+	return true;
+}
+//平面坐标 -> 极坐标
+bool Point2D_tool::Point2D_to_polar_coordinates(Point2D_tool::Point2D* p_point2D, Point2D_tool::Polar_coordinates* p_polar_coordinates)
+{
+	if ( p_polar_coordinates == NULL || p_point2D == NULL)
+	{
+		return false;
+	}
+	else
+	{
+		p_polar_coordinates->distance = sqrt(p_point2D->x * p_point2D->x + p_point2D->y * p_point2D->y);
+		p_polar_coordinates->angle = atan(p_point2D->y / p_point2D->x);
+		return true;
+	}
+	return true;
+}
+
+//判断极坐标点是否在限制范围
+bool Point2D_tool::limit_with_polar_coordinates_box(float distance, float angle, Point2D_tool::Polar_coordinates_box* p_polar_coordinates_box)
+{
+	if ( p_polar_coordinates_box == NULL )
+	{
+		return false;
+	}
+	else
+	{
+		if ( angle >= p_polar_coordinates_box->angle_min &&
+			 angle <= p_polar_coordinates_box->angle_max &&
+			 distance >= p_polar_coordinates_box->distance_min &&
+			 distance <= p_polar_coordinates_box->distance_max )
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+	return true;
+}
+
+//判断平面坐标点是否在限制范围
+bool Point2D_tool::limit_with_point2D_box(float x, float y, Point2D_tool::Point2D_box* p_point2D_box)
+{
+	if ( p_point2D_box == NULL )
+	{
+		return false;
+	}
+	else
+	{
+		if ( x >= p_point2D_box->x_min &&
+			 x <= p_point2D_box->x_max &&
+			 y >= p_point2D_box->y_min &&
+			 y <= p_point2D_box->y_max )
+		{
+			return true;
+		}
+		else
+		{
+			return false;
+		}
+	}
+	return true;
+}
+#ifdef OPEN_PCL_FLAG
+//平面坐标的转换, 可以进行旋转和平移, 不能缩放
+bool Point2D_tool::transform_with_translation_rotation(float* p_x_in, float* p_y_in, float* p_x_out, float* p_y_out,
+										 Point2D_tool::Point2D_transform* p_point2D_transform)
+{
+	if ( p_x_in == NULL || p_x_in == NULL || p_x_out == NULL || p_y_out == NULL || p_point2D_transform == NULL)
+	{
+		return false;
+	}
+	else
+	{
+		*p_x_out = *p_x_in * p_point2D_transform->m00 + *p_y_in * p_point2D_transform->m01 + p_point2D_transform->m02;
+		*p_y_out = *p_x_in * p_point2D_transform->m10 + *p_y_in * p_point2D_transform->m11 + p_point2D_transform->m12;
+		return true;
+	}
+	return true;
+}
+bool Point2D_tool::transform_with_translation_rotation(pcl::PointXYZ* p_point3D_in, pcl::PointXYZ* p_point3D_out,
+												Point2D_tool::Point2D_transform* p_point2D_transform)
+{
+	if (p_point3D_in == NULL || p_point3D_out == NULL || p_point2D_transform == NULL)
+	{
+		return false;
+	}
+	else
+	{
+		p_point3D_out->x = p_point3D_in->x * p_point2D_transform->m00 + p_point3D_in->y * p_point2D_transform->m01 +
+						   p_point2D_transform->m02;
+		p_point3D_out->y = p_point3D_in->x * p_point2D_transform->m10 + p_point3D_in->y * p_point2D_transform->m11 +
+						   p_point2D_transform->m12;
+		return true;
+	}
+	return true;
+}
+bool Point2D_tool::transform_with_translation_rotation(pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_in,
+												pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_out,
+												Point2D_tool::Point2D_transform* p_point2D_transform)
+{
+	if ( p_cloud_in.get() == NULL || p_cloud_out.get() == NULL || p_point2D_transform == NULL)
+	{
+	    return false;
+	}
+	else
+	{
+		pcl::PointXYZ point;
+		for (int i = 0; i < p_cloud_in->size(); ++i)
+		{
+			point.x = p_cloud_in->points[i].x * p_point2D_transform->m00 + p_cloud_in->points[i].y * p_point2D_transform->m01 + p_point2D_transform->m02;
+			point.y = p_cloud_in->points[i].x * p_point2D_transform->m10 + p_cloud_in->points[i].y * p_point2D_transform->m11 + p_point2D_transform->m12;
+			p_cloud_out->push_back(point);
+		}
+		return true;
+	}
+	return true;
+}
+#endif

+ 92 - 0
include/pcl/point2D_tool.h

@@ -0,0 +1,92 @@
+//
+// Created by huli on 2020/9/1.
+//
+
+#ifndef POINT2D_TOOL_H
+#define POINT2D_TOOL_H
+
+
+
+//#define OPEN_PCL_FLAG
+#ifdef OPEN_PCL_FLAG
+#include <pcl/point_types.h>
+#include <pcl/PCLPointCloud2.h>
+#include <pcl/conversions.h>
+#include <pcl/common/common.h>
+#endif
+
+#include <stddef.h>
+#include <math.h>
+
+class Point2D_tool
+{
+public:
+	//极坐标
+	struct Polar_coordinates
+	{
+		float angle=0;				//弧度
+		float distance=0;				//距离
+	};
+
+	//极坐标的限定范围
+	struct Polar_coordinates_box
+	{
+		float angle_min=0;			//角度最小值
+		float angle_max=0;			//角度最大值
+		float distance_min=0;			//距离最小值
+		float distance_max=0;			//距离最大值
+	};
+
+	//平面坐标
+	struct Point2D
+	{
+		float x=0;				//x轴
+		float y=0;				//y轴
+	};
+
+	//平面坐标的限定范围
+	struct Point2D_box
+	{
+		float x_min=0;				//x轴最小值
+		float x_max=0;				//x轴最大值
+		float y_min=0;				//y轴最小值
+		float y_max=0;				//y轴最大值
+	};
+
+	//平面坐标的转换矩阵, 可以进行旋转和平移, 不能缩放
+	struct Point2D_transform
+	{
+		float m00=1;
+		float m01=0;
+		float m02=0;
+		float m10=0;
+		float m11=1;
+		float m12=0;
+	};
+
+	//极坐标 -> 平面坐标
+	static bool Polar_coordinates_to_point2D(Point2D_tool::Polar_coordinates* p_polar_coordinates, Point2D_tool::Point2D* p_point2D);
+	//平面坐标 -> 极坐标
+	static bool Point2D_to_polar_coordinates(Point2D_tool::Point2D* p_point2D, Point2D_tool::Polar_coordinates* p_polar_coordinates);
+
+
+	//判断极坐标点是否在限制范围
+	static bool limit_with_polar_coordinates_box(float distance, float angle, Point2D_tool::Polar_coordinates_box* p_polar_coordinates_box);
+	//判断平面坐标点是否在限制范围
+	static bool limit_with_point2D_box(float x, float y, Point2D_tool::Point2D_box* p_point2D_box);
+
+#ifdef OPEN_PCL_FLAG
+	//平面坐标的转换, 可以进行旋转和平移, 不能缩放
+	static bool transform_with_translation_rotation(float* p_x_in, float* p_y_in, float* p_x_out, float* p_y_out,
+													Point2D_tool::Point2D_transform* p_point2D_transform);
+	static bool transform_with_translation_rotation(pcl::PointXYZ* p_point3D_in, pcl::PointXYZ* p_point3D_out,
+													Point2D_tool::Point2D_transform* p_point2D_transform);
+	static bool transform_with_translation_rotation(pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_in,
+													pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_out,
+													Point2D_tool::Point2D_transform* p_point2D_transform);
+
+#endif
+};
+
+
+#endif //POINT2D_TOOL_H

+ 5 - 0
include/pcl/point3D_tool.cpp

@@ -0,0 +1,5 @@
+//
+// Created by huli on 2021/3/24.
+//
+
+#include "point3D_tool.h"

+ 121 - 0
include/pcl/point3D_tool.h

@@ -0,0 +1,121 @@
+//
+// Created by huli on 2021/3/24.
+//
+
+#ifndef NNXX_TESTS_POINT3D_TOOL_H
+#define NNXX_TESTS_POINT3D_TOOL_H
+
+#include <pcl/point_cloud.h>
+#include <pcl/point_types.h>
+#include <vector>
+#include <opencv4/opencv2/opencv.hpp>
+#include "log/log.h"
+
+class Point3D_tool
+{
+public:
+	//坐标
+	struct Point3D
+	{
+		float x=0;				//x轴
+		float y=0;				//y轴
+		float z=0;				//z轴
+	};
+
+	//平面坐标的限定范围
+	struct Point3D_box
+	{
+		float x_min=0;				//x轴最小值
+		float x_max=0;				//x轴最大值
+		float y_min=0;				//y轴最小值
+		float y_max=0;				//y轴最大值
+		float z_min=0;				//z轴最小值
+		float z_max=0;				//z轴最大值
+	};
+
+	template <typename PclPoint>
+	static int getMinRect(cv::RotatedRect &rect, pcl::shared_ptr<pcl::PointCloud<PclPoint>> &clouds) {
+		if (clouds->points.size() < 4) {
+			DLOG(ERROR) << "points to little.";
+			return false;
+		}
+		std::vector<cv::Point2f> cv_clouds;
+		for (auto &point: clouds->points) {
+			cv_clouds.emplace_back(point.x, point.y);
+		}
+		rect = cv::minAreaRect(cv_clouds);
+		return true;
+	}
+
+	// template <typename PclPoint>
+	// static int getMinRect(cv::RotatedRect &rect, pcl::shared_ptr<pcl::PointCloud<PclPoint>> &points) {
+	static int getRectCloud(cv::RotatedRect &rect, pcl::shared_ptr<pcl::PointCloud<pcl::PointXYZ>> &points, float z_value = 0, int numbers = 100) {
+		cv::Point2f cv_points[4];
+		rect.points(cv_points);
+		// PclPoint point;
+		pcl::PointXYZ point;
+		// 左侧点
+		double step_x = (cv_points[1].x - cv_points[0].x) / numbers;
+		double step_y = (cv_points[1].y - cv_points[0].y) / numbers;
+		for (int i = 0; i < numbers; i++) {
+			point.x = cv_points[0].x + i * step_x;
+			point.y = cv_points[0].y + i * step_y;
+			point.z = z_value;
+			points->points.emplace_back(point);
+		}
+
+		// 上侧点
+		step_x = (cv_points[2].x - cv_points[1].x) / numbers;
+		step_y = (cv_points[2].y - cv_points[1].y) / numbers;
+		for (int i = 0; i < numbers; i++) {
+			point.x = cv_points[1].x + i * step_x;
+			point.y = cv_points[1].y + i * step_y;
+			point.z = z_value;
+			points->points.emplace_back(point);
+		}
+
+		// 右侧点
+		step_x = (cv_points[3].x - cv_points[2].x) / numbers;
+		step_y = (cv_points[3].y - cv_points[2].y) / numbers;
+		for (int i = 0; i < numbers; i++) {
+			point.x = cv_points[2].x + i * step_x;
+			point.y = cv_points[2].y + i * step_y;
+			point.z = z_value;
+			points->points.emplace_back(point);
+		}
+
+
+		// 下侧点
+		step_x = (cv_points[0].x - cv_points[3].x) / numbers;
+		step_y = (cv_points[0].y - cv_points[3].y) / numbers;
+		for (int i = 0; i < numbers; i++) {
+			point.x = cv_points[3].x + i * step_x;
+			point.y = cv_points[3].y + i * step_y;
+			point.z = z_value;
+			points->points.emplace_back(point);
+		}
+
+		return points->size();
+	}
+
+	template <typename PclPoint>
+	static int getRectCloud(pcl::shared_ptr<pcl::PointCloud<PclPoint>> &clouds, pcl::shared_ptr<pcl::PointCloud<pcl::PointXYZ>> &points, float z_value = 0, int numbers = 100) {
+		cv::RotatedRect rect = getMinRect(clouds);
+        getRectCloud(rect, points, z_value, numbers);
+		return points->size();
+	}
+
+	static void getRectWidthlength(cv::RotatedRect &rect, double &width, double &length) {
+		cv::Point2f points[4];
+		rect.points(points);
+
+		double a = sqrt((points[1].x - points[0].x) * (points[1].x - points[0].x) + (points[1].y - points[0].y) * (points[1].y - points[0].y));
+		double b = sqrt((points[2].x - points[1].x) * (points[2].x - points[1].x) + (points[2].y - points[1].y) * (points[2].y - points[1].y));
+
+		width = MIN(a, b);
+		length = MAX(a, b);
+	}
+};
+
+
+#endif //NNXX_TESTS_POINT3D_TOOL_H

+ 79 - 0
include/protobuf/load_protobuf.hpp

@@ -0,0 +1,79 @@
+#pragma once
+
+#include <fcntl.h>
+#include <unistd.h>
+#include <iostream>
+#include <fstream>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/text_format.h>
+#include "google/protobuf/util/json_util.h"
+
+#include "error_code/error_code.hpp"
+
+using google::protobuf::io::FileInputStream;
+using google::protobuf::io::FileOutputStream;
+using google::protobuf::io::ZeroCopyInputStream;
+using google::protobuf::io::CodedInputStream;
+using google::protobuf::io::ZeroCopyOutputStream;
+using google::protobuf::io::CodedOutputStream;
+using google::protobuf::Message;
+
+
+static std::string getFileExtension(const std::string& file_path) {
+    size_t dot_pos = file_path.find_last_of('.');
+    if (dot_pos != std::string::npos && dot_pos < file_path.length() - 1) {
+        return file_path.substr(dot_pos + 1);
+    }
+    return "";
+}
+
+static bool readTxtProtobufFile(const std::string &file_path, ::google::protobuf::Message& message)
+{
+    int fd = open(file_path.c_str(), O_RDONLY);
+    if (fd == -1) return false;
+    auto* input = new FileInputStream(fd);
+    bool success = google::protobuf::TextFormat::Parse(input, &message);
+    delete input;
+    close(fd);
+    return success;
+}
+
+static bool readJsonProtobufFile(const std::string& file_path, ::google::protobuf::Message& message) {
+    std::ifstream file(file_path);
+    std::string json_data;
+
+    if (file.is_open()) {
+        // 将文件内容读取到字符串
+        std::string line;
+        while (std::getline(file, line)) {
+            json_data += line;
+        }
+        file.close();
+    } else {
+        return false;
+    }
+
+    return google::protobuf::util::JsonStringToMessage(json_data, &message) == google::protobuf::util::Status::OK;
+}
+
+static Error_manager loadProtobufFile(const std::string &file, ::google::protobuf::Message &message) {
+    std::string ext = getFileExtension(file);
+    if (ext.empty()) {
+        return {PARSE_FAILED, MINOR_ERROR, "prase protobuf file %s ext failed.", file.c_str()};
+    }
+
+    bool ret = false;
+    if (ext == "prototxt") {
+        ret = readTxtProtobufFile(file, message);
+    } else if (ext == "json") {
+        ret = readJsonProtobufFile(file, message);
+    } else {
+        return {PARSE_FAILED, MINOR_ERROR, "protobuf file %s type error.", file.c_str()};
+    }
+
+    if (ret) {
+        return {SUCCESS, NORMAL, "prase protobuf file %s success.", file.c_str()};
+    } else {
+        return {PARSE_FAILED, MINOR_ERROR, "prase protobuf file %s failed.", file.c_str()};
+    }
+}

+ 2 - 0
include/thread/CMakeLists.txt

@@ -13,6 +13,8 @@ set(LIBRARY_SOURCE_LIST
         ${CMAKE_CURRENT_LIST_DIR}/time_tool.cpp
         ${CMAKE_CURRENT_LIST_DIR}/singleton.h
         ${CMAKE_CURRENT_LIST_DIR}/singleton.cpp
+        ${CMAKE_CURRENT_LIST_DIR}/binary_buf.h
+        ${CMAKE_CURRENT_LIST_DIR}/binary_buf.cpp
 )
 
 set(LIBRARY_DEPEND_LIST

+ 264 - 0
include/thread/binary_buf.cpp

@@ -0,0 +1,264 @@
+
+/*
+ * binary_buf是二进制缓存
+ * 这里用字符串,来存储雷达的通信消息的原始数据
+ * Binary_buf 的内容格式:消息类型 + 消息数据
+ *
+ * 例如思科的雷达的消息类型
+ * ready->ready->start->data->data->data->stop->ready->ready
+ *
+ * 提供了 is_equal 系列的函数,来进行判断前面的消息类型
+ * 
+ * 注意了:m_buf是中间可以允许有‘\0’的,不是单纯的字符串格式
+ * 			末尾也不一定是‘\0’
+ */
+
+#include "binary_buf.h"
+
+#include <string>
+#include <string.h>
+
+Binary_buf::Binary_buf() {
+    mp_buf = NULL;
+    m_length = 0;
+}
+
+Binary_buf::Binary_buf(const Binary_buf &other) {
+    mp_buf = NULL;
+    m_length = 0;
+
+    if (other.m_length > 0 && other.mp_buf != NULL) {
+        mp_buf = (char *) malloc(other.m_length);
+        memcpy(mp_buf, other.mp_buf, other.m_length);
+        m_length = other.m_length;
+    }
+}
+
+Binary_buf::~Binary_buf() {
+    if (mp_buf) {
+        free(mp_buf);
+        mp_buf = NULL;
+    }
+    m_length = 0;
+
+//	std::cout << "Binary_buf::~Binary_buf()" << std::endl;
+}
+
+
+//使用参数构造,深拷贝,len为0时,使用strlen(buf),不存储结束符'\0'
+Binary_buf::Binary_buf(const char *p_buf, int len) {
+    mp_buf = NULL;
+    m_length = 0;
+
+    if (p_buf != NULL) {
+        if (len <= 0) {
+            len = strlen(p_buf);
+        }
+
+        mp_buf = (char *) malloc(len);
+        memcpy(mp_buf, p_buf, len);
+        m_length = len;
+    }
+}
+
+
+//使用参数构造,深拷贝,len为0时,使用strlen(buf),不存储结束符'\0'
+Binary_buf::Binary_buf(char *p_buf, int len) {
+    mp_buf = NULL;
+    m_length = 0;
+
+    if (p_buf != NULL) {
+        if (len <= 0) {
+            len = strlen(p_buf);
+        }
+
+        mp_buf = (char *) malloc(len);
+        memcpy(mp_buf, p_buf, len);
+        m_length = len;
+    }
+}
+
+//重载=,深拷贝,
+Binary_buf &Binary_buf::operator=(const Binary_buf &other) {
+    clear();
+
+    if (other.m_length > 0 && other.mp_buf != NULL) {
+        mp_buf = (char *) malloc(other.m_length);
+        memcpy(mp_buf, other.mp_buf, other.m_length);
+        m_length = other.m_length;
+    }
+    return *this;
+}
+
+//重载=,深拷贝,使用strlen(buf),不存储结束符'\0'
+Binary_buf &Binary_buf::operator=(const char *p_buf) {
+    clear();
+
+    if (p_buf != NULL) {
+        int len = strlen(p_buf);
+        mp_buf = (char *) malloc(len);
+        memcpy(mp_buf, p_buf, len);
+        m_length = len;
+    }
+    return *this;
+}
+
+//重载+,other追加在this的后面,
+Binary_buf &Binary_buf::operator+(Binary_buf &other) {
+    if (other.mp_buf != NULL && other.m_length > 0) {
+        int t_length_total = m_length + other.m_length;
+        char *tp_buf_total = (char *) malloc(t_length_total);
+        memcpy(tp_buf_total, mp_buf, m_length);
+        memcpy(tp_buf_total + m_length, other.mp_buf, other.m_length);
+        free(mp_buf);
+        mp_buf = tp_buf_total;
+        m_length = t_length_total;
+    }
+    return *this;
+}
+
+//重载+,追加在this的后面,使用strlen(buf),不存储结束符'\0'
+Binary_buf &Binary_buf::operator+(const char *p_buf) {
+    if (p_buf != NULL) {
+        int t_length_back = strlen(p_buf);
+        int t_length_total = m_length + t_length_back;
+        char *tp_buf_total = (char *) malloc(t_length_total);
+        memcpy(tp_buf_total, mp_buf, m_length);
+        memcpy(tp_buf_total + m_length, p_buf, t_length_back);
+        free(mp_buf);
+        mp_buf = tp_buf_total;
+        m_length = t_length_total;
+    }
+    return *this;
+}
+
+//重载[],允许直接使用数组的形式,直接访问buf的内存。注意,n值必须在0~m_length之间,
+char &Binary_buf::operator[](int n) {
+    if (n >= 0 && n < m_length) {
+        return mp_buf[n];
+    } else {
+        throw (n);
+    }
+}
+
+
+//判空
+bool Binary_buf::is_empty() {
+    if (mp_buf != NULL && m_length > 0) {
+        return false;
+    } else {
+        return true;
+    }
+}
+
+//清空
+void Binary_buf::clear() {
+    if (mp_buf) {
+        free(mp_buf);
+        mp_buf = NULL;
+    }
+    m_length = 0;
+}
+
+
+//比较前面部分的buf是否相等,使用 other.m_length 为标准
+bool Binary_buf::is_equal_front(const Binary_buf &other) {
+    if (other.mp_buf == NULL || other.m_length <= 0) {
+        if (mp_buf == NULL || m_length <= 0) {
+            return true;
+        } else {
+            return false;
+        }
+    } else {
+        if (mp_buf != NULL && m_length > 0) {
+            if (other.m_length > m_length) {
+                return false;
+            }
+            return (strncmp((const char *) mp_buf, other.mp_buf, other.m_length) == 0);
+        } else {
+            return false;
+        }
+
+    }
+}
+
+//比较前面部分的buf是否相等,len为0时,使用strlen(buf)为标准,不比较结束符'\0'
+bool Binary_buf::is_equal_front(const char *p_buf, int len) {
+    if (p_buf == NULL) {
+        if (mp_buf == NULL || m_length <= 0) {
+            return true;
+        } else {
+            return false;
+        }
+    } else {
+        if (mp_buf != NULL && m_length > 0) {
+            if (len == 0) {
+                len = strlen(p_buf);
+            }
+            if (len > m_length) {
+                return false;
+            }
+            return (strncmp((const char *) mp_buf, p_buf, len) == 0);
+        } else {
+            return false;
+        }
+
+    }
+}
+
+//比较的buf是否全部相等,
+bool Binary_buf::is_equal_all(const Binary_buf &other) {
+    if (other.mp_buf == NULL || other.m_length <= 0) {
+        if (mp_buf == NULL || m_length <= 0) {
+            return true;
+        } else {
+            return false;
+        }
+    } else {
+        if (mp_buf != NULL && m_length > 0) {
+            if (other.m_length != m_length) {
+                return false;
+            }
+            return (strncmp((const char *) mp_buf, other.mp_buf, other.m_length) == 0);
+        } else {
+            return false;
+        }
+
+    }
+}
+
+//比较的buf是否全部相等,不比较结束符'\0'
+bool Binary_buf::is_equal_all(const char *p_buf) {
+    if (p_buf == NULL) {
+        if (mp_buf == NULL || m_length <= 0) {
+            return true;
+        } else {
+            return false;
+        }
+    } else {
+        if (mp_buf != NULL && m_length > 0) {
+            int len = strlen(p_buf);
+            if (len != m_length) {
+                return false;
+            }
+            return (strncmp((const char *) mp_buf, p_buf, len) == 0);
+        } else {
+            return false;
+        }
+
+    }
+}
+
+
+char *Binary_buf::get_buf() const {
+    return mp_buf;
+}
+
+int Binary_buf::get_length() const {
+    return m_length;
+}
+
+
+
+
+

+ 99 - 0
include/thread/binary_buf.h

@@ -0,0 +1,99 @@
+
+/*
+ * binary_buf是二进制缓存
+ * 这里用字符串,来存储雷达的通信消息的原始数据
+ * Binary_buf 的内容格式:消息类型 + 消息数据
+ *
+ * 例如思科的雷达的消息类型
+ * ready->ready->start->data->data->data->stop->ready->ready
+ *
+ * 提供了 is_equal 系列的函数,来进行判断前面的消息类型
+ *
+ * 注意了:m_buf是中间可以允许有‘\0’的,不是单纯的字符串格式
+ * 			末尾也不一定是‘\0’
+ */
+
+#ifndef LIDARMEASURE_BINARY_BUF_H
+#define LIDARMEASURE_BINARY_BUF_H
+
+#include <iostream>
+
+
+//雷达消息的类型
+//在通信消息的前面一部分字符串,表示这条消息的类型。
+//在解析消息的时候,先解析前面的消息类型,来判断这条消息的功用
+enum Buf_type {
+    //默认值 BUF_UNKNOW = 0
+    BUF_UNKNOW = 0,    //未知消息
+    BUF_READY = 1,    //待机消息
+    BUF_START = 2,    //开始消息
+    BUF_DATA = 3,    //数据消息
+    BUF_STOP = 4,    //结束消息
+    BUF_ERROR = 5,    //错误消息
+};
+
+
+//二进制缓存,
+class Binary_buf {
+public:
+    Binary_buf();
+
+    Binary_buf(const Binary_buf &other);
+
+    ~Binary_buf();
+
+    //使用参数构造,深拷贝,len为0时,使用strlen(buf),不存储结束符'\0'
+    Binary_buf(const char *p_buf, int len = 0);
+
+    //使用参数构造,深拷贝,len为0时,使用strlen(buf),不存储结束符'\0'
+    Binary_buf(char *p_buf, int len = 0);
+
+    //重载=,深拷贝,
+    Binary_buf &operator=(const Binary_buf &other);
+
+    //重载=,深拷贝,使用strlen(buf),不存储结束符'\0'
+    Binary_buf &operator=(const char *p_buf);
+
+    //重载+,other追加在this的后面,
+    Binary_buf &operator+(Binary_buf &other);
+
+    //重载+,追加在this的后面,使用strlen(buf),不存储结束符'\0'
+    Binary_buf &operator+(const char *p_buf);
+
+    //重载[],允许直接使用数组的形式,直接访问buf的内存。注意,n值必须在0~m_length之间,
+    char &operator[](int n);
+
+    //判空
+    bool is_empty();
+
+    //清空
+    void clear();
+
+    //比较前面部分的buf是否相等,使用 other.m_length 为标准
+    bool is_equal_front(const Binary_buf &other);
+
+    //比较前面部分的buf是否相等,len为0时,使用strlen(buf)为标准,不比较结束符'\0'
+    bool is_equal_front(const char *p_buf, int len = 0);
+
+    //比较的buf是否全部相等,
+    bool is_equal_all(const Binary_buf &other);
+
+    //比较的buf是否全部相等,不比较结束符'\0'
+    bool is_equal_all(const char *p_buf);
+
+
+public:
+    char *get_buf() const;
+
+    int get_length() const;
+
+protected:
+    char *mp_buf;                //二进制缓存指针
+    int m_length;            //二进制缓存长度
+
+private:
+
+};
+
+
+#endif //LIDARMEASURE_BINARY_BUF_H

+ 1 - 1
project/clamp_lidar

@@ -1 +1 @@
-Subproject commit b2cacc22c5120a40a8477196c6a7b05352485185
+Subproject commit 0241dd4089c65097bd31f31360db108035565015