123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445 |
- #include "LivoxLaser.h"
- RegisterLaser(Livox)
- CLivoxLaser::DeviceItem CLivoxLaser::g_devices[kMaxLidarCount] = { 0 };
- std::map<uint8_t, std::string> CLivoxLaser::g_handle_sn= std::map<uint8_t, std::string>();
- std::map<std::string, uint8_t> CLivoxLaser::g_sn_handle = std::map<std::string, uint8_t>();
- std::map<std::string, CLivoxLaser*> CLivoxLaser::g_sn_laser= std::map<std::string, CLivoxLaser*>();
- 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 :"<<this;
- //清空livox子类的队列,
- m_queue_livox_data.clear_and_delete();
- g_count[m_handle] = 0;
- return Laser_base::start_scan();
- }
- //雷达的停止接口函数, 让雷达停止扫描,一般需要子类重载,不同的雷达结束方式不同。
- Error_manager CLivoxLaser::stop_scan()
- {
- return Laser_base::stop_scan();
- }
- //结束任务单,stop之后,要检查线程状态和数据结果,然后才能 end_task
- Error_manager CLivoxLaser::end_task()
- {
- return Laser_base::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;
- }
- else
- {
- false;
- }
- }
- //接受二进制消息的功能函数,每次只接受一个CBinaryData
- // 纯虚函数,必须由子类重载,
- bool CLivoxLaser::receive_buf_to_queue(Binary_buf& binary_buf)
- {
- Binary_buf* tp_livox_buf;
- if (m_queue_livox_data.try_pop(tp_livox_buf))
- {
- binary_buf = *tp_livox_buf;
- delete tp_livox_buf;
- std::cout << "huli m_queue_livox_data.try_pop" << std::endl;
- return true;
- }
- return false;
- }
- //将二进制消息转化为三维点云的功能函数,每次只转化一个CBinaryData,
- // 纯虚函数,必须由子类重载,
- Buf_type CLivoxLaser::transform_buf_to_points(Binary_buf* p_binary_buf, std::vector<CPoint3D>& 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<<"-----------------------------------------------------------------"<<std::endl;
- std::cout<<" OnDeviceChange handle : "<<info->broadcast_code<<" type : "<<type <<" device_state : "
- <<g_devices[handle].device_state<<std::endl;*/
- if (type == kEventConnect) {
- //QueryDeviceInformation(handle, OnDeviceInformation, NULL);
- if (g_devices[handle].device_state == kDeviceStateDisconnect)
- {
- g_devices[handle].device_state = kDeviceStateConnect;
- g_devices[handle].info = *info;
- }
- }
- else if (type == kEventDisconnect) {
- g_devices[handle].device_state = kDeviceStateDisconnect;
- }
- else if (type == kEventStateChange) {
- g_devices[handle].info = *info;
- }
- if (g_devices[handle].device_state == kDeviceStateConnect)
- {
- if (g_devices[handle].info.state == kLidarStateNormal)
- {
- if (g_devices[handle].info.type == kDeviceTypeHub)
- {
- HubStartSampling(OnSampleCallback, NULL);
- }
- else
- {
- LidarStartSampling(handle, OnSampleCallback, NULL);
- }
- g_devices[handle].device_state = kDeviceStateSampling;
- }
- }
- }
- void CLivoxLaser::OnDeviceBroadcast(const BroadcastDeviceInfo *info)
- {
- if (info == NULL) {
- return;
- }
- //printf("Receive Broadcast Code %s\n", info->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;
- }
- }
|