zx 4 роки тому
батько
коміт
f91370ca52

+ 7 - 18
CMakeLists.txt

@@ -20,6 +20,7 @@ set(CMAKE_BUILD_TYPE "RELEASE")
 #find_package(Eigen3 REQUIRED)
 
 include_directories(
+        tool
         laser
         plc
         src
@@ -46,23 +47,11 @@ aux_source_directory(${CMAKE_CURRENT_LIST_DIR}/wj_lidar WJLIDAR_SRC )
 
 
 
-add_executable(locate_sample  test/locate_sample.cpp ${LOCATE_SRC}  ${TASK_MANAGER_SRC} ${ERROR_SRC}
-        ${TOOL_SRC})
-target_link_libraries(locate_sample ${OpenCV_LIBS}
-        ${GLOG_LIBRARIES} ${PCL_LIBRARIES} ${PROTOBUF_LIBRARIES} libtensorflow_cc.so
-        tf_3dcnn_api.so pointSIFT_API.so dark.so /usr/local/lib/libglog.a
-        /usr/local/lib/libgflags.a snap7 nnxx nanomsg)
-
-add_executable(fence_debug  test/plc_s7.cpp wj_lidar/wj_lidar_msg.pb.cc)
-target_link_libraries(fence_debug ${GLOG_LIBRARIES} ${PROTOBUF_LIBRARIES} /usr/local/lib/libglog.a
-        /usr/local/lib/libgflags.a nnxx nanomsg)
-
-
-add_executable(locate  main.cpp ${LOCATE_SRC} ${PLC_SRC} ${TERMINOR_SRC} ${TASK_MANAGER_SRC} ${LASER_SRC} ${ERROR_SRC}
-        ${TOOL_SRC} ${SYS_SRC} ${VERIFY_SRC} ${WJLIDAR_SRC})
-target_link_libraries(locate ${OpenCV_LIBS} ${CERES_LIBRARIES}
-        ${GLOG_LIBRARIES} ${PCL_LIBRARIES} ${PROTOBUF_LIBRARIES} ipopt libtensorflow_cc.so
-        tf_3dcnn_api.so pointSIFT_API.so dark.so /usr/local/lib/libmodbus.so /usr/local/lib/libglog.a
-        /usr/local/lib/libgflags.a /usr/local/lib/liblivox_sdk_static.a /usr/local/apr/lib/libapr-1.a snap7 nnxx nanomsg)
+add_executable(test_laser  ./test/test_laser.cpp ${LASER_SRC} ${ERROR_SRC}
+        ${TOOL_SRC} ${TASK_MANAGER_SRC})
+target_link_libraries(test_laser ${OpenCV_LIBS}
+        ${GLOG_LIBRARIES} ${PCL_LIBRARIES} ${PROTOBUF_LIBRARIES}
+        /usr/local/lib/libglog.a snap7 nnxx nanomsg
+        /usr/local/lib/libgflags.a /usr/local/lib/liblivox_sdk_static.a /usr/lib/x86_64-linux-gnu/libapr-1.a)
 
 

+ 23 - 2
error_code/error_code.cpp

@@ -108,23 +108,26 @@ void Error_manager::error_manager_clear_all()
     m_error_code = SUCCESS;
     m_error_level = NORMAL;
     free_description();
+	return;
 }
 
 //重载=
 Error_manager& Error_manager::operator=(const Error_manager & error_manager)
 {
     error_manager_reset(error_manager);
+	return *this;
 }
 //重载=,支持Error_manager和Error_code的直接转化,会清空错误等级和描述
 Error_manager& Error_manager::operator=(Error_code error_code)
 {
     error_manager_clear_all();
     set_error_code(error_code);
+	return *this;
 }
 //重载==
 bool Error_manager::operator==(const Error_manager & error_manager)
 {
-    is_equal_error_manager(error_manager);
+	return is_equal_error_manager(error_manager);
 }
 //重载==,支持Error_manager和Error_code的直接比较
 bool Error_manager::operator==(Error_code error_code)
@@ -142,7 +145,7 @@ bool Error_manager::operator==(Error_code error_code)
 //重载!=
 bool Error_manager::operator!=(const Error_manager & error_manager)
 {
-    ! is_equal_error_manager(error_manager);
+	return (! is_equal_error_manager(error_manager));
 }
 //重载!=,支持Error_manager和Error_code的直接比较
 bool Error_manager::operator!=(Error_code error_code)
@@ -156,6 +159,12 @@ bool Error_manager::operator!=(Error_code error_code)
         return false;
     }
 }
+//重载<<,支持cout<<
+std::ostream & operator<<(std::ostream &out, Error_manager &error_manager)
+{
+	out << error_manager.to_string();
+	return out;
+}
 
 //获取错误码
 Error_code Error_manager::get_error_code()
@@ -173,6 +182,11 @@ char* Error_manager::get_error_description()
     return pm_error_description;
 }
 
+int Error_manager::get_description_length()
+{
+	return m_description_length;
+}
+
 //复制错误描述,(深拷贝)
 //output:p_error_description     错误描述的字符串指针,不可以为NULL,必须要有实际的内存
 //output:description_length      错误描述的字符串长度,不可以为0,长度最好足够大,一般256即可。
@@ -299,6 +313,7 @@ void Error_manager::add_error_description(std::string & error_description_string
 
         reallocate_memory_and_copy_string(t_description_string);
     }
+	return;
 }
 
 //比较错误是否相同,
@@ -350,6 +365,7 @@ void Error_manager::compare_and_cover_error(const Error_manager & error_manager)
             add_error_description(pt_string_inside,t_string_inside_length);
         }
     }
+	return;
 }
 //比较并覆盖错误,讲低级错误转为字符串存放于描述中,
 //如果错误相同,则保留this的,将输入参数转入描述。
@@ -386,6 +402,7 @@ void Error_manager::compare_and_cover_error( Error_manager * p_error_manager)
 			add_error_description(pt_string_inside,t_string_inside_length);
 		}
 	}
+	return;
 }
 
 //将所有的错误信息,格式化为字符串,用作日志打印。
@@ -421,6 +438,7 @@ void Error_manager::translate_error_to_string(char* p_error_aggregate, int aggre
             pt_index_back++;
         }
     }
+	return;
 }
 //output:error_description_string     错误汇总的string
 void Error_manager::translate_error_to_string(std::string & error_aggregate_string)
@@ -437,6 +455,7 @@ void Error_manager::translate_error_to_string(std::string & error_aggregate_stri
     {
         //error_aggregate_string += "NULL";
     }
+	return;
 }
 //错误码转字符串的简易版,可支持cout<<
 //return     错误汇总的string
@@ -459,6 +478,7 @@ void Error_manager::free_description()
         pm_error_description = NULL;
     }
     m_description_length = 0;
+	return;
 }
 
 //重新分配错误描述的内存,并从外部拷贝新的(深拷贝)
@@ -518,6 +538,7 @@ void Error_manager::reallocate_memory_and_copy_string(std::string & error_aggreg
 
         strcpy(pm_error_description ,   error_aggregate_string.c_str()  );
     }
+	return;
 }
 
 

+ 14 - 4
error_code/error_code.h

@@ -12,6 +12,7 @@
 
 #include <string>
 #include <string.h>
+#include<iostream>
 
 //错误管理类转化为字符串 的前缀,固定长度为58
 //这个是由显示格式来确定的,如果要修改格式或者 Error_code长度超过8位,Error_level长度超过2位,折需要重新计算
@@ -60,6 +61,10 @@ enum Error_code
 
     CLASS_BASE_FUNCTION_CANNOT_USE  = 0x00000201,//基类函数不允许使用,必须使用子类的
 
+	CONTAINER_IS_TERMINATE			= 0x00000301,//容器被终止
+
+
+
 
 //    错误码的规范,
 //    错误码是int型,32位,十六进制。
@@ -213,7 +218,8 @@ enum Error_code
     WJ_LIDAR_TASK_INVALID_TASK,
     WJ_LIDAR_TASK_MEASURE_FAILED,
 
-
+    WJ_FILTER_LACK_OF_RESULT,
+    WJ_FILTER_FLUCTUATING,
 
 };
 
@@ -224,9 +230,9 @@ enum Error_level
     NORMAL                = 0,
 
 
-//    可忽略的故障,NEGLIGIBLE_ERROR
+//    轻微故障,可忽略的故障,NEGLIGIBLE_ERROR
 //    提示作用,不做任何处理,不影响代码的流程,
-//    用作一些不重要的事件,一半出错也不会影响到系统功能,
+//    用作一些不重要的事件,即使出错也不会影响到系统功能,
 //    例如:文件保存错误,等
     NEGLIGIBLE_ERROR      = 1,
 
@@ -234,7 +240,7 @@ enum Error_level
 //    一般故障,MINOR_ERROR
 //    用作底层功能函数的错误返回,表示该功能函数执行失败,
 //    返回给应用层之后,需要做故障分析和处理,
-//    例如:雷达数据传输失败,应用层进行重新扫描,或者重连,或者重置参数等。
+//    例如:雷达数据传输失败,应用层就需要进行重新扫描,或者重连,或者重置参数等。
     MINOR_ERROR           = 2,
 
 
@@ -301,6 +307,8 @@ public://外部接口函数
     bool operator!=(const Error_manager & error_manager);
     //重载!=,支持Error_manager和Error_code的直接比较
     bool operator!=(Error_code error_code);
+	//重载<<,支持cout<<
+	friend std::ostream & operator<<(std::ostream &out, Error_manager &error_manager);
 
 
     //获取错误码
@@ -310,6 +318,8 @@ public://外部接口函数
     //获取错误描述的指针,(浅拷贝)
     char* get_error_description();
 
+	int get_description_length();
+
     //复制错误描述,(深拷贝)
     //output:p_error_description     错误描述的字符串指针,不可以为NULL,必须要有实际的内存
     //output:description_length      错误描述的字符串长度,不可以为0,长度最好足够大,一般256即可。

+ 7 - 2
laser/Laser.cpp

@@ -160,6 +160,7 @@ Error_manager Laser_base::start_scan()
 	LOG(INFO) << " Laser_base::start_scan "<< this;
 	if ( is_ready() )
 	{
+
 		//启动雷达扫描
 		m_laser_scan_flag=true;				//启动雷达扫描
 		m_laser_statu = LASER_BUSY;			//雷达状态 繁忙
@@ -227,24 +228,27 @@ Error_manager Laser_base::end_task()
 
 
 //设置保存文件的路径,并打开文件,
-Error_manager Laser_base::set_open_save_path(std::string save_path,bool is_save)
+Error_manager Laser_base::set_open_save_path(const std::string& save_path,bool is_save)
 {
+    LOG(ERROR)<<" save :"<<is_save<<"   path"<<save_path;
+
 	m_save_flag = is_save;
 	m_points_log_tool.close();
 	m_binary_log_tool.close();
-
 	if (is_save == false)
 	{
 		return Error_code::SUCCESS;
 	}
 	else
 	{
+
 		m_save_path = save_path;
 		char pts_file[255] = { 0 };
 		sprintf(pts_file, "%s/pts%d.txt", save_path.c_str(), m_laser_id+1);
 		m_points_log_tool.open(pts_file);
 		//std::cout << "huli m_points_log_tool path "<< pts_file << std::endl;
 
+
 		char bin_file[255] = { 0 };
 		sprintf(bin_file, "%s/laser%d.data", save_path.c_str(), m_laser_id+1);
 		m_binary_log_tool.open(bin_file,true);
@@ -454,6 +458,7 @@ void Laser_base::thread_transform()
 #include "../tool/MeasureTopicPublisher.h"
 Error_manager Laser_base::publish_laser_to_message()
 {
+    return SUCCESS;
     //usleep(5*1000*1000);
 	laser_message::laserMsg msg;
 	laser_message::laserStatus status;

+ 1 - 1
laser/Laser.h

@@ -73,7 +73,7 @@ public:
 
 public:
 	//设置保存文件的路径,并打开文件,
-	Error_manager set_open_save_path(std::string save_path,bool is_save=true);
+	Error_manager set_open_save_path(const std::string& save_path,bool is_save=true);
 	//关闭保存文件,推出前一定要执行
 	Error_manager close_save_path();
 	//判断雷达状态是否为待机,如果已经准备好,则可以执行任务。

+ 72 - 0
laser/LivoxHorizon.cpp

@@ -0,0 +1,72 @@
+
+
+#include "LivoxHorizon.h"
+
+RegisterLaser(Horizon)
+
+
+
+CHorizonLaser::CHorizonLaser(int id, Laser_proto::laser_parameter laser_param)
+:CLivoxLaser(id, laser_param)
+{
+
+        //设备livox扫描最大帧数
+        m_frame_maxnum = laser_param.frame_num();
+        //判断参数类型,
+        if(laser_param.type()=="Horizon")
+        {
+            //填充雷达设备的广播码
+            g_sn_laser.insert(std::make_pair(laser_param.sn(), this));
+            //初始化livox
+            InitLivox();
+        }
+
+
+}
+
+CHorizonLaser::~CHorizonLaser()
+{
+
+}
+
+//将二进制消息转化为三维点云的功能函数,每次只转化一个CBinaryData,
+// 纯虚函数,必须由子类重载,
+Buf_type CHorizonLaser::transform_buf_to_points(Binary_buf* p_binary_buf, std::vector<CPoint3D>& point3D_cloud)
+{
+
+
+    if ( p_binary_buf ==NULL )
+    {
+        return BUF_UNKNOW;
+    }
+    else
+    {
+        //livox的二进制数据格式就是三维点坐标。直接强行转化指针类型即可
+        LivoxExtendRawPoint *tp_Livox_data = (LivoxExtendRawPoint *)p_binary_buf->get_buf();
+        //计算这一帧数据有多少个三维点。
+        int t_count = p_binary_buf->get_length() / (sizeof(LivoxExtendRawPoint));
+
+        if (t_count <= 0)
+        {
+            return BUF_UNKNOW;
+        }
+        else
+        {
+            //转变三维点格式,并存入vector。
+            for (int i = 0; i < t_count; ++i)
+            {
+                //LivoxExtendRawPoint 转为 CPoint3D
+                //int32_t 转 double。不要信号强度
+                LivoxExtendRawPoint t_livox_point = tp_Livox_data[i];
+                CPoint3D t_point3D;
+                t_point3D.x = t_livox_point.x;
+                t_point3D.y = t_livox_point.y;
+                t_point3D.z = t_livox_point.z;
+                point3D_cloud.push_back(t_point3D);
+//				std::cout << "huli points:" << t_point3D.x << " : " << t_point3D.y << " : " << t_point3D.z<< std::endl;
+            }
+            return BUF_DATA;
+        }
+    }
+
+}

+ 40 - 0
laser/LivoxHorizon.h

@@ -0,0 +1,40 @@
+#ifndef __LIVOX_HORIZON__H
+#define __LIVOX_HORIZON__H
+
+#include "Laser.h"
+#include "livox_def.h"
+#include "livox_sdk.h"
+#include <map>
+#include "LivoxLaser.h"
+
+
+
+
+//大疆livox雷达,从Laser_base继承。
+class CHorizonLaser :public CLivoxLaser
+{
+
+public:
+	CHorizonLaser() = delete;
+	CHorizonLaser(const CHorizonLaser& other) = delete;
+	//唯一的构造函数,按照设备名称和雷达参数来创建实例。
+	//input:id: 雷达设备的id,(唯一索引)
+	//input:laser_param:雷达的参数,
+	//注:利用protobuf创建 laser_parameter 类,然后从文件读取参数
+	CHorizonLaser(int id, Laser_proto::laser_parameter laser_param);
+	~CHorizonLaser();
+
+
+	//将二进制消息转化为三维点云的功能函数,并将其存入 任务单 , 每次只转化一个CBinaryData,
+	// 纯虚函数,必须由子类重载,
+	virtual Buf_type transform_buf_to_points(Binary_buf* p_binary_buf, std::vector<CPoint3D>& point3D_cloud);
+};
+
+
+
+
+
+
+
+
+#endif

+ 35 - 15
laser/LivoxLaser.cpp

@@ -60,6 +60,7 @@ Error_manager CLivoxLaser::execute_task(Task_Base* p_laser_task)
 							 "Laser_base::porform_task failed, POINTER_IS_NULL");
 	}
 	//检查任务类型,
+
 	if (p_laser_task->get_task_type() != LASER_TASK)
 	{
 		return Error_manager(Error_code::LIVOX_TASK_TYPE_ERROR, Error_level::MINOR_ERROR,
@@ -68,6 +69,7 @@ Error_manager CLivoxLaser::execute_task(Task_Base* p_laser_task)
 
 	//接受任务,并将任务的状态改为TASK_SIGNED已签收
 	mp_laser_task = (Laser_task *) p_laser_task;
+    LOG(WARNING)<<mp_laser_task->get_save_path();
 	mp_laser_task->set_task_statu(TASK_SIGNED);
 
 	//检查消息内容是否正确,
@@ -87,10 +89,12 @@ Error_manager CLivoxLaser::execute_task(Task_Base* p_laser_task)
 	{
 		m_frame_maxnum=mp_laser_task->get_task_frame_maxnum();
 
-
 		//设置保存文件的路径
-		std::string save_path = mp_laser_task->get_task_save_path();
-		t_error = set_open_save_path(save_path);
+        LOG(WARNING)<<mp_laser_task->get_save_path();
+		std::string save_points_path(mp_laser_task->get_task_save_path());
+        LOG(WARNING)<<mp_laser_task->get_save_path();
+		t_error = set_open_save_path(mp_laser_task->get_task_save_path());
+
 		if ( t_error != Error_code::SUCCESS )
 		{
 			//文件保存文件的路径的设置 允许失败。继续后面的动作
@@ -113,6 +117,7 @@ Error_manager CLivoxLaser::execute_task(Task_Base* p_laser_task)
 			//将任务的状态改为 TASK_WORKING 处理中
 			mp_laser_task->set_task_statu(TASK_WORKING);
 		}
+        std::cout<<"11111"<<std::endl;
 	}
 	//返回错误码
 	if (t_result != Error_code::SUCCESS)
@@ -151,15 +156,16 @@ Error_manager CLivoxLaser::end_task()
 //子类重载 is_ready(),里面增加livox sdk后台线程状态的判断。
 bool CLivoxLaser::is_ready()
 {
+
 	//livox雷达设备的状态,livox sdk后台线程的状态
 	if ( m_laser_statu == LASER_READY &&
 		 g_devices[m_handle].device_state != kDeviceStateDisconnect  )
 	{
-		true;
+		return true;
 	}
 	else
 	{
-	    false;
+	    return false;
 	}
 }
 
@@ -354,10 +360,10 @@ void CLivoxLaser::OnDeviceBroadcast(const BroadcastDeviceInfo *info)
 
 void CLivoxLaser::LidarDataCallback(uint8_t handle, LivoxEthPacket *data, uint32_t data_num, void *client_data)
 {
-//	std::cout << "huli LidarDataCallback" << std::endl;
+	//std::cout << "huli LidarDataCallback" << std::endl;
 
 	CLivoxLaser* livox = g_all_laser[handle];
-	if (livox == NULL)
+	if (livox == 0)
 	{
 		if (g_handle_sn.find(handle) != g_handle_sn.end())
 		{
@@ -374,13 +380,16 @@ void CLivoxLaser::LidarDataCallback(uint8_t handle, LivoxEthPacket *data, uint32
 //	std::cout << "huli LidarDataCallback " << std::endl;
 
 
-	if (data && livox)
+	if (data!= nullptr && livox!= nullptr)
 	{
-//		std::cout << "huli m_laser_scan_flag = " << livox->m_laser_scan_flag << std::endl;
+
+		//std::cout << "huli m_laser_scan_flag = " << livox->m_laser_scan_flag <<"datatype:"<<int(data->data_type)<< std::endl;
+
 
 		//判断雷达扫描标志位
 		if (livox->m_laser_scan_flag)
 		{
+
 			if (livox->IsScanComplete())
 			{
 				//std::cout << "huli qwe point count = " << livox->g_count[livox->m_handle] << std::endl;
@@ -392,16 +401,27 @@ void CLivoxLaser::LidarDataCallback(uint8_t handle, LivoxEthPacket *data, uint32
 				//std::cout << "huli asd point count = " << livox->g_count[livox->m_handle] << std::endl;
 
 			}*/
-//			std::cout << "huli LidarDataCallback " << std::endl;
+
 
 			if (g_count[handle] >= livox->m_frame_maxnum)
 				return;
 			uint64_t cur_timestamp = *((uint64_t *)(data->timestamp));
-			LivoxRawPoint *p_point_data = (LivoxRawPoint *)data->data;
-
-			Binary_buf* data_bin = new Binary_buf((char*)p_point_data, data_num * sizeof(LivoxRawPoint));
-			livox->m_queue_livox_data.push(data_bin);
-			//std::cout << "huli m_queue_livox_data.push " << std::endl;
+            if(data ->data_type == kCartesian)
+            {
+                LivoxRawPoint *p_point_data = (LivoxRawPoint *)data->data;
+                Binary_buf* data_bin = new Binary_buf((char*)p_point_data, data_num * sizeof(LivoxRawPoint));
+                livox->m_queue_livox_data.push(data_bin);
+            }
+            else if(data ->data_type == kExtendCartesian)
+            {
+                LivoxExtendRawPoint *p_point_data = (LivoxExtendRawPoint *)data->data;
+                Binary_buf* data_bin = new Binary_buf((char*)p_point_data, data_num * sizeof(LivoxExtendRawPoint));
+                livox->m_queue_livox_data.push(data_bin);
+            }
+            else
+            {
+                return;
+            }
 
 			g_count[handle]++;
 

+ 1 - 2
main.cpp

@@ -93,8 +93,7 @@ void test_classify()
 
 int main(int argc,char* argv[])
 {
-    test_classify();
-    return 0;
+
     Error_manager code;
     //初始化日志
     init_glog();

+ 6 - 4
system_manager/System_Manager.cpp

@@ -161,12 +161,12 @@ Error_manager System_Manager::init()
     mp_verify_result_tool=new Verify_result(hardware_parameter);
     LOG(WARNING)<<"0 verify addr : "<<mp_verify_result_tool;
     //创建万集雷达
-    mp_wj_controller=new Fence_controller(mp_verify_result_tool);
+    /*mp_wj_controller=new Fence_controller(mp_verify_result_tool);
     code=mp_wj_controller->initialize(wj_parameter);
     if(code!=SUCCESS)
     {
         return code;
-    }
+    }*/
 
     //创建测量模块
     mp_locater=new Locater();
@@ -188,14 +188,16 @@ Error_manager System_Manager::init()
         m_terminal_vector[i]->set_save_root_path(terminor_parameter_all.save_root_path());
     }
     //最后创建plc,连接,设置回调
-    mp_plc=new Plc_Communicator(plc_parameter);
+    /*mp_plc=new Plc_Communicator(plc_parameter);
     code=mp_plc->get_error();
     if(code!=SUCCESS)
     {
         code.set_error_description("plc create error");
         return code;
     }
-    code=mp_plc->set_plc_callback(plc_command_callback,this);
+    code=mp_plc->set_plc_callback(plc_command_callback,this);*/
+
+    plc_command_callback(1,this);
     return code;
 
 }

+ 251 - 0
test/test_laser.cpp

@@ -0,0 +1,251 @@
+//
+// Created by zx on 2021/5/10.
+//
+
+#include "LivoxLaser.h"
+
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/text_format.h>
+#include <fcntl.h>
+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;
+
+#include "pathcreator.h"
+//读取protobuf 配置文件
+//file:文件
+//parameter:要读取的配置
+bool read_proto_param(std::string file, ::google::protobuf::Message& parameter)
+{
+    int fd = open(file.c_str(), O_RDONLY);
+    if (fd == -1) return false;
+    FileInputStream* input = new FileInputStream(fd);
+    bool success = google::protobuf::TextFormat::Parse(input, &parameter);
+    delete input;
+    close(fd);
+    return success;
+}
+
+GOOGLE_GLOG_DLL_DECL void shut_down_logging(const char* data, int size)
+{
+    time_t tt;
+    time( &tt );
+    tt = tt + 8*3600;  // transform the time zone
+    tm* t= gmtime( &tt );
+    char buf[255]={0};
+    sprintf(buf,"./%d%02d%02d-%02d%02d%02d-dump.txt",
+            t->tm_year + 1900,
+            t->tm_mon + 1,
+            t->tm_mday,
+            t->tm_hour,
+            t->tm_min,
+            t->tm_sec);
+
+    FILE* tp_file=fopen(buf,"w");
+    fprintf(tp_file,data,strlen(data));
+    fclose(tp_file);
+
+}
+
+void init_glog()
+{
+    time_t tt = time(0);//时间cuo
+    struct tm* t = localtime(&tt);
+
+    char strYear[255]={0};
+    char strMonth[255]={0};
+    char strDay[255]={0};
+
+    sprintf(strYear,"%04d", t->tm_year+1900);
+    sprintf(strMonth,"%02d", t->tm_mon+1);
+    sprintf(strDay,"%02d", t->tm_mday);
+
+    char buf[255]={0};
+    getcwd(buf,255);
+    char strdir[255]={0};
+    sprintf(strdir,"%s/testlog/%s/%s/%s", buf,strYear,strMonth,strDay);
+    PathCreator creator;
+    creator.Mkdir(strdir);
+
+    char logPath[255] = { 0 };
+    sprintf(logPath, "%s/", strdir);
+    FLAGS_max_log_size = 100;
+    FLAGS_logbufsecs = 0;
+    google::InitGoogleLogging("test_lidar");
+    google::SetStderrLogging(google::INFO);
+    google::SetLogDestination(0, logPath);
+    google::SetLogFilenameExtension("zxlog");
+    google::InstallFailureSignalHandler();
+    google::InstallFailureWriter(&shut_down_logging);
+    FLAGS_colorlogtostderr = true;        // Set log color
+    FLAGS_logbufsecs = 0;                // Set log output speed(s)
+    FLAGS_max_log_size = 1024;            // Set max log file size(GB)
+    FLAGS_stop_logging_if_full_disk = true;
+}
+
+Error_manager scan(std::vector<Laser_base*> tp_lasers)
+{
+
+    //准备目录
+    time_t tt;
+    time(&tt);
+    tt = tt + 8 * 3600;  // transform the time zone
+    tm *t = gmtime(&tt);
+    char path[255] = {0};
+    sprintf(path, "/home/zx/data/livoxhorizon_test/%4d/%02d/%02d",
+            t->tm_year + 1900,
+            t->tm_mon + 1,
+            t->tm_mday);
+    PathCreator path_creator;
+    path_creator.CreateDatePath(path);
+    std::string project_path = path_creator.GetCurPath();
+
+
+    //第一步,启动雷达扫描点云,切换当前状态为扫描中
+    //根据配置筛选雷达
+    pcl::PointCloud<pcl::PointXYZ> scan_cloud;
+    std::mutex cloud_lock;
+    std::vector<Laser_task *> laser_task_vector;
+    Error_manager code;
+
+    for (int i = 0; i < tp_lasers.size(); ++i) {
+
+        //创建扫描任务,
+        Laser_task *laser_task = new Laser_task();
+        //
+        laser_task->task_init(TASK_CREATED, &scan_cloud, &cloud_lock);
+        laser_task->set_task_frame_maxnum(1000);
+        laser_task->set_save_path(project_path);
+        laser_task_vector.push_back(laser_task);
+        //发送任务单给雷达
+        code = tp_lasers[i]->execute_task(laser_task);
+
+        if (code != SUCCESS) {
+            return code;
+        }
+
+    }
+
+    if (tp_lasers.size() == 0) {
+        return TERMINOR_NOT_CONTAINS_LASER;
+    }
+   double timeout=3.0;
+    auto t_start_point = std::chrono::system_clock::now();
+    //等待雷达完成任务单
+    while (1) {
+        //判断是否强制退出
+
+        //判断雷达任务单是否全部完成
+        bool tb_laser_complete = true;
+        for (int i = 0; i < laser_task_vector.size(); ++i) {
+            tb_laser_complete &= (TASK_OVER == laser_task_vector[i]->get_statu());
+        }
+        if (tb_laser_complete) {
+            break;
+        }
+        //计算扫描时间,若超时,并且没有点,则返回错误.
+        auto t_end_point = std::chrono::system_clock::now();
+        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(t_end_point - t_start_point);
+        double second = double(duration.count()) *
+                std::chrono::milliseconds::period::num / std::chrono::milliseconds::period::den;
+        if (second > timeout) {
+            //扫描超时,点云中没有点,则返回错误
+            if (scan_cloud.size() == 0) {
+                return TERMINOR_LASER_TIMEOUT;
+            }
+
+
+        }
+        usleep(1000 * 100);
+    }
+    //检查雷达任务完成情况,是否是正常完成
+    LOG(INFO) << " laser scanning over cloud size:" << scan_cloud.size();
+    //释放扫描任务单
+    for (int i = 0; i < laser_task_vector.size(); ++i) {
+        if (laser_task_vector[i] != 0) {
+            delete laser_task_vector[i];
+            laser_task_vector[i] = NULL;
+        }
+    }
+
+    return SUCCESS;
+}
+
+int main(int argc,char* argv[])
+{
+    init_glog();
+    Error_manager code;
+    //读laser配置
+    Laser_proto::Laser_parameter_all laser_parameters;
+    if(!read_proto_param("./setting/laser.prototxt",laser_parameters))
+    {
+        code= Error_manager(SYSTEM_READ_PARAMETER_ERROR,NORMAL,"read laser parameter failed");
+    }
+    if(code!=SUCCESS)
+    {
+        std::cout<<code.get_error_description()<<std::endl;
+        return -1;
+    }
+
+    //创建大疆雷达
+    int laser_cout=laser_parameters.laser_parameters_size();
+    std::vector<Laser_base*>  laser_vector;
+    laser_vector.resize(laser_cout);
+    for(int i=0;i<laser_parameters.laser_parameters_size();++i)
+    {
+        LOG(INFO)<<"创建雷达:"<<laser_parameters.laser_parameters(i).sn();
+        laser_vector[i]=LaserRegistory::CreateLaser(laser_parameters.laser_parameters(i).type(),i,
+                                                      laser_parameters.laser_parameters(i));
+        if(laser_vector[i]!=NULL)
+        {
+            if(laser_vector[i]->connect_laser()!=SUCCESS)
+            {
+                char description[255]={0};
+                sprintf(description,"Laser %d connect failed...",i);
+                code= Error_manager(LASER_CONNECT_FAILED,NORMAL,description);
+            }
+        }
+    }
+    if(code!=SUCCESS)
+    {
+        std::cout<<code.get_error_description()<<std::endl;
+        return -1;
+    }
+    //查询是否有livox雷达,初始化库
+    for (int i = 0; i < laser_parameters.laser_parameters_size(); ++i)
+    {
+        std::string type = laser_parameters.laser_parameters(i).type();
+        if ( (type.find("Livox") != type.npos) || (type.find("Horizon") != type.npos) )
+        {
+            if (Start() == false)
+            {
+                Uninit();
+                code= Error_manager(LASER_LIVOX_SKD_INIT_FAILED,NORMAL,"Livox laser init failed...");
+            }
+            break;
+        }
+    }
+
+    if(code!=SUCCESS)
+    {
+        std::cout<<code.get_error_description()<<std::endl;
+        return -1;
+    }
+
+    //扫描
+
+    char c=getchar();
+    code =scan(laser_vector);
+    if(code!=SUCCESS)
+    {
+        std::cout<<code.get_error_description()<<std::endl;
+        return -1;
+    }
+    std::cout<<"   scan over"<<std::endl;
+
+    return 0;
+}