#include "LivoxLaser.h" RegisterLaser(Livox) CLivoxLaser::DeviceItem CLivoxLaser::g_devices[kMaxLidarCount] = { 0 }; std::map CLivoxLaser::g_handle_sn= std::map(); std::map CLivoxLaser::g_sn_handle = std::map(); std::map CLivoxLaser::g_sn_laser= std::map(); CLivoxLaser* CLivoxLaser::g_all_laser[kMaxLidarCount] = { 0 }; unsigned int CLivoxLaser::g_count[kMaxLidarCount] = { 0 }; CLivoxLaser::CLivoxLaser(int id, Laser_proto::laser_parameter laser_param) :Laser_base(id, laser_param) { //设备livox扫描最大帧数 m_frame_maxnum = laser_param.frame_num(); //判断参数类型, if(laser_param.type()=="Livox") { //填充雷达设备的广播码 g_sn_laser.insert(std::make_pair(laser_param.sn(), this)); //初始化livox InitLivox(); } } CLivoxLaser::~CLivoxLaser() { } //雷达链接设备,为3个线程添加线程执行函数。 Error_manager CLivoxLaser::connect_laser() { return Laser_base::connect_laser(); } //雷达断开链接,释放3个线程 Error_manager CLivoxLaser::disconnect_laser() { return Laser_base::disconnect_laser(); } //对外的接口函数,负责接受并处理任务单, //input:p_laser_task 雷达任务单,基类的指针,指向子类的实例,(多态) //注:这个函数为虚函数,实际的处理任务的代码由子类重载并实现。 Error_manager CLivoxLaser::execute_task(Task_Base* p_laser_task) { LOG(INFO) << " CLivoxLaser::execute_task start "<< this; Error_manager t_error; Error_manager t_result; //检查指针 if (p_laser_task == NULL) { return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR, "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, "laser task type error != LASER_TASK"); } //检查雷达状态 t_error = check_laser(); if ( t_error != SUCCESS ) { t_result.compare_and_cover_error(t_error); return t_result; } else { //接受任务,并将任务的状态改为TASK_SIGNED已签收 mp_laser_task = (Laser_task *) p_laser_task; mp_laser_task->set_task_statu(TASK_SIGNED); //检查消息内容是否正确, //检查三维点云指针 if (mp_laser_task->get_task_point_cloud().get() == NULL) { t_result.error_manager_reset(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR, "execute_task mp_task_point_cloud is null"); t_result.compare_and_cover_error(t_error); } else if (mp_laser_task->get_task_cloud_lock() == NULL) { t_error.error_manager_reset(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR, "execute_task mp_task_cloud_lock is null"); t_result.compare_and_cover_error(t_error); } else { 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,m_laser_param.is_save_txt()); if ( t_error != Error_code::SUCCESS ) { //文件保存文件的路径的设置 允许失败。继续后面的动作 t_result.compare_and_cover_error(t_error); } //启动雷达扫描 t_error = start_scan(); if ( t_error != Error_code::SUCCESS ) { t_result.compare_and_cover_error(t_error); } else { //将任务的状态改为 TASK_WORKING 处理中 mp_laser_task->set_task_statu(TASK_WORKING); } } } //返回错误码 if (t_result != Error_code::SUCCESS) { //将任务的状态改为 TASK_OVER 结束任务 mp_laser_task->set_task_statu(TASK_OVER); //返回错误码 mp_laser_task->set_task_error_manager(t_result); return t_result; } return t_result; } //检查雷达状态,是否正常运行 Error_manager CLivoxLaser::check_laser() { if ( is_ready() ) { return Error_code::SUCCESS; } else { return Error_manager(Error_code::lIVOX_STATUS_ERROR, Error_level::MINOR_ERROR, " CLivoxLaser::check_status error "); } return Error_code::SUCCESS; } //雷达的启动接口函数, 让雷达进行扫描,一般需要子类重载,不同的雷达开始方式不同。 Error_manager CLivoxLaser::start_scan() { LOG(INFO) << " livox start :"<& point3D_cloud) { if ( p_binary_buf ==NULL ) { return BUF_UNKNOW; } else { //livox的二进制数据格式就是三维点坐标。直接强行转化指针类型即可 LivoxRawPoint *tp_Livox_data = (LivoxRawPoint *)p_binary_buf->get_buf(); //计算这一帧数据有多少个三维点。 int t_count = p_binary_buf->get_length() / (sizeof(LivoxRawPoint)); if (t_count <= 0) { return BUF_UNKNOW; } else { //转变三维点格式,并存入vector。 for (int i = 0; i < t_count; ++i) { //LivoxRawPoint 转为 CPoint3D //int32_t 转 double。不要信号强度 LivoxRawPoint 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; } } } void CLivoxLaser::InitLivox() { static bool g_init = false; if (g_init == false) { if (!Init()) { LOG(INFO) << "livox sdk init failed..."; } else { LivoxSdkVersion _sdkversion; GetLivoxSdkVersion(&_sdkversion); char buf[255] = { 0 }; sprintf(buf, "Livox SDK version %d.%d.%d .\n", _sdkversion.major, _sdkversion.minor, _sdkversion.patch); LOG(INFO) << buf; SetBroadcastCallback(OnDeviceBroadcast); SetDeviceStateUpdateCallback(OnDeviceChange); g_init = true; } } } bool CLivoxLaser::IsScanComplete() { //雷达的采集帧数判断,直接比较任务单里面的帧数最大值 if(mp_laser_task!=NULL) return g_count[m_handle] >= mp_laser_task->get_task_frame_maxnum(); else return false; } void CLivoxLaser::UpdataHandle() { std::string sn = m_laser_param.sn(); if (g_sn_handle.find(sn) != g_sn_handle.end()) { m_handle = g_sn_handle[sn]; } } void CLivoxLaser::OnSampleCallback(uint8_t status, uint8_t handle, uint8_t response, void *data) { CLivoxLaser* laser = (CLivoxLaser*)data; if (status == kStatusSuccess) { if (response != 0) { g_devices[handle].device_state = kDeviceStateConnect; } } else if (status == kStatusTimeout) { g_devices[handle].device_state = kDeviceStateConnect; } } void CLivoxLaser::OnDeviceChange(const DeviceInfo *info, DeviceEvent type) { if (info == NULL) { return; } uint8_t handle = info->handle; if (handle >= kMaxLidarCount) { return; } /*std::cout<<"-----------------------------------------------------------------"<broadcast_code<<" type : "<broadcast_code); LOG(INFO) << " broadcast sn : " << info->broadcast_code; bool result = false; uint8_t handle = 0; result = AddLidarToConnect(info->broadcast_code, &handle); if (result == kStatusSuccess) { /** Set the point cloud data for a specific Livox LiDAR. */ SetDataCallback(handle, LidarDataCallback, NULL); g_devices[handle].handle = handle; g_devices[handle].device_state = kDeviceStateDisconnect; std::string sn = info->broadcast_code; if (g_handle_sn.find(handle) != g_handle_sn.end()) g_handle_sn[handle] = sn; else g_handle_sn.insert(std::make_pair(handle,sn)); if (g_sn_handle.find(sn) != g_sn_handle.end()) g_sn_handle[sn] = handle; else g_sn_handle.insert(std::make_pair(sn,handle)); } } void CLivoxLaser::LidarDataCallback(uint8_t handle, LivoxEthPacket *data, uint32_t data_num, void *client_data) { // std::cout << "huli LidarDataCallback" << std::endl; CLivoxLaser* livox = g_all_laser[handle]; if (livox == NULL) { if (g_handle_sn.find(handle) != g_handle_sn.end()) { std::string sn = g_handle_sn[handle]; if (g_sn_laser.find(sn) != g_sn_laser.end()) { livox = g_sn_laser[sn]; g_all_laser[handle] = livox; if (livox) livox->UpdataHandle(); } } } // std::cout << "huli LidarDataCallback " << std::endl; if (data && livox) { // std::cout << "huli m_laser_scan_flag = " << livox->m_laser_scan_flag << 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; livox->stop_scan(); return; } else { 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; g_count[handle]++; } /* else { std::cout << "huli 1z error " << "data = "<< data << std::endl; std::cout << "huli 1z error " << "livox = "<< livox << std::endl; //????????????????? livox->m_laser_statu = LASER_READY; usleep(10*1000); }*/ } else { std::cout << "huli 2z error " << "data = "<< data << std::endl; std::cout << "huli 2z error " << "livox = "<< livox << std::endl; } }