locater.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385
  1. //
  2. // Created by zx on 2019/12/30.
  3. //
  4. #include "locater.h"
  5. #include <pcl/filters//voxel_grid.h>
  6. #include <pcl/filters/passthrough.h>
  7. #include <glog/logging.h>
  8. Locater::Locater():mp_yolo_detector(0),mp_point_sift(0),mp_cnn3d(0)
  9. {
  10. }
  11. Locater::~Locater()
  12. {}
  13. Error_manager Locater::get_error()
  14. {
  15. return SUCCESS;
  16. }
  17. Error_manager Locater::init(Measure::LocateParameter parameter)
  18. {
  19. Error_manager code;
  20. {
  21. int point_size = parameter.seg_parameter().point_size();
  22. int cls_num = parameter.seg_parameter().cls_num();
  23. double freq = parameter.seg_parameter().freq();
  24. std::string graph = parameter.seg_parameter().graph();
  25. std::string cpkt = parameter.seg_parameter().cpkt();
  26. Measure::Area3d area = parameter.seg_parameter().area();
  27. pcl::PointXYZ minp(area.x_min(), area.y_min(), area.z_min());
  28. pcl::PointXYZ maxp(area.x_max(), area.y_max(), area.z_max());
  29. LOG(INFO)<<"Creating pointSift net ...";
  30. mp_point_sift = new Point_sift_segmentation(point_size,cls_num,freq,minp,maxp);
  31. std::string graph_file = graph;
  32. std::string cpkt_file = cpkt;
  33. LOG(INFO)<<"init pointSift net graph:"<<graph;
  34. code=mp_point_sift->init(graph_file,cpkt_file);
  35. if(code!=SUCCESS)
  36. {
  37. LOG(ERROR)<<code.to_string();
  38. return code;
  39. }
  40. }
  41. {
  42. LOG(INFO)<<"Creating darknet ...";
  43. float min_x = parameter.yolo_parameter().min_x();
  44. float max_x = parameter.yolo_parameter().max_x();
  45. float min_y = parameter.yolo_parameter().min_y();
  46. float max_y = parameter.yolo_parameter().max_y();
  47. float freq = parameter.yolo_parameter().freq();
  48. std::string cfg = parameter.yolo_parameter().cfg();
  49. std::string weights = parameter.yolo_parameter().weights();
  50. mp_yolo_detector = new YoloDetector(cfg, weights, min_x, max_x, min_y, max_y, freq);
  51. }
  52. int l = parameter.net_3dcnn_parameter().length();
  53. int w = parameter.net_3dcnn_parameter().width();
  54. int h = parameter.net_3dcnn_parameter().height();
  55. int nClass = parameter.net_3dcnn_parameter().nclass();
  56. int freq = parameter.net_3dcnn_parameter().freq();
  57. mp_cnn3d = new Cnn3d_segmentation(l, w, h, freq, nClass);
  58. LOG(INFO)<<"Init 3dcnn ...";
  59. std::string weights = parameter.net_3dcnn_parameter().weights_file();
  60. code=mp_cnn3d->init(weights);
  61. if(code!=SUCCESS)
  62. {
  63. return code;
  64. }
  65. return SUCCESS;
  66. }
  67. Error_manager Locater::execute_task(Task_Base* task,double time_out)
  68. {
  69. LOG(INFO)<<"NEW LOCATE TASK ==============================================================================";
  70. Locate_information locate_information;
  71. locate_information.locate_correct=false;
  72. //判断task是否合法
  73. if(task==0) return LOCATER_TASK_ERROR;
  74. if(task->get_task_type()!=LOCATE_TASK)
  75. {
  76. task->update_statu(TASK_OVER,"locate task type error");
  77. return Error_manager(LOCATER_TASK_ERROR,NORMAL,"locate Task type error");
  78. }
  79. Locate_task* locate_task=(Locate_task*)task;
  80. locate_task->update_statu(TASK_SIGNED);
  81. Error_manager code;
  82. ///第一步,获取task中input点云,文件保存路径
  83. pcl::PointCloud<pcl::PointXYZ>::Ptr t_cloud_input=locate_task->get_locate_cloud();
  84. std::string save_path=locate_task->get_save_path();
  85. if(t_cloud_input.get()==0)
  86. {
  87. locate_task->update_statu(TASK_OVER,"Task set cloud is uninit");
  88. return Error_manager(LOCATER_INPUT_CLOUD_UNINIT,NORMAL,"Task set cloud is uninit");
  89. }
  90. //第二步,加锁,更新task状态,调用locate,进入测量中
  91. std::lock_guard<std::mutex> t_lock(m_mutex_lock);
  92. locate_task->update_statu(TASK_WORKING);
  93. code=locate(t_cloud_input,locate_information,save_path);
  94. locate_task->set_locate_cloud(t_cloud_input);
  95. locate_task->set_locate_information(locate_information);
  96. if(code!=SUCCESS)
  97. {
  98. locate_task->update_statu(TASK_OVER,"Locate Failed");
  99. return code;
  100. }
  101. locate_task->update_statu(TASK_OVER,"Locate OK");
  102. return code;
  103. }
  104. Error_manager Locater::locate_yolo(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in,
  105. std::vector<YoloBox>& boxes, std::string work_dir)
  106. {
  107. if(cloud_in.get()==0)
  108. {
  109. return Error_manager(LOCATER_YOLO_INPUT_CLOUD_UNINIT,NORMAL,"yolo input cloud uninit");
  110. }
  111. if(cloud_in->size()==0)
  112. {
  113. return Error_manager(LOCATER_INPUT_YOLO_CLOUD_EMPTY,NORMAL,"locate_yolo input cloud empty");
  114. }
  115. if(mp_yolo_detector==0)
  116. {
  117. return Error_manager(LOCATER_YOLO_UNINIT,NORMAL,"locate_yolo yolo is not init");
  118. }
  119. //1,根据点云区域,调整yolo边界参数,边界参数必须保证长宽 1:1
  120. pcl::PointXYZ min_point,max_point;
  121. pcl::getMinMax3D(*cloud_in,min_point,max_point);
  122. float yolo_minx=min_point.x;
  123. float yolo_maxx=max_point.x;
  124. float yolo_miny=min_point.y;
  125. float yolo_maxy=max_point.y;
  126. float length=yolo_maxx-yolo_minx;
  127. float width=yolo_maxy-yolo_miny;
  128. if(length>2*width) yolo_maxy=(length/2.0)+yolo_miny;
  129. else if(length<2*width) yolo_maxx=(2*width)+yolo_minx;
  130. Error_manager code=mp_yolo_detector->set_region(yolo_minx,yolo_maxx,yolo_miny,
  131. yolo_maxy,m_locate_parameter.yolo_parameter().freq());
  132. if(code!=SUCCESS)
  133. {
  134. return code;
  135. }
  136. //2,识别车辆位置
  137. boxes.clear();
  138. return mp_yolo_detector->detect(cloud_in,boxes,work_dir);
  139. }
  140. Error_manager Locater::locate_sift(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in, std::vector<YoloBox> boxes,
  141. pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_wheel,pcl::PointCloud<pcl::PointXYZ>::Ptr& cloud_car,
  142. std::string work_dir)
  143. {
  144. if(cloud_in.get()==0)
  145. {
  146. return Error_manager(LOCATER_SIFT_INPUT_CLOUD_UNINIT,NORMAL,"sift input cloud uninit");
  147. }
  148. if(cloud_in->size()==0)
  149. {
  150. return Error_manager(LOCATER_SIFT_INPUT_CLOUD_EMPTY,NORMAL,"locate_sift input cloud empty");
  151. }
  152. if(mp_point_sift==0)
  153. {
  154. return Error_manager(LOCATER_POINTSIFT_UNINIT,NORMAL,"Point Sift unInit");
  155. }
  156. //第一步,根据点云边界调整PointSIft 参数
  157. pcl::PointXYZ min_point,max_point;
  158. pcl::getMinMax3D(*cloud_in,min_point,max_point);
  159. Error_manager code ;
  160. code=mp_point_sift->set_region(min_point,max_point);
  161. if(code!=SUCCESS)
  162. {
  163. return code;
  164. }
  165. //第二步,点云抽稀,抽稀后的点云大约在8192左右,
  166. // 如果有多辆车(多个yolo框),取第一个框
  167. YoloBox yolo_box=boxes[0];
  168. pcl::PointXYZ minp, maxp;
  169. minp.x = yolo_box.x;
  170. minp.y = yolo_box.y;
  171. maxp.x = minp.x + yolo_box.w;
  172. maxp.y = minp.y + yolo_box.h;
  173. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_input_sift(new pcl::PointCloud<pcl::PointXYZ>());
  174. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_downsample(new pcl::PointCloud<pcl::PointXYZ>());
  175. /// ///体素网格 下采样
  176. pcl::VoxelGrid<pcl::PointXYZ> vgfilter;
  177. vgfilter.setInputCloud(cloud_in);
  178. vgfilter.setLeafSize(60.f, 60.f, 50.f);
  179. vgfilter.filter(*cloud_downsample);
  180. //限制 x y
  181. pcl::PassThrough<pcl::PointXYZ> passX;
  182. pcl::PassThrough<pcl::PointXYZ> passY;
  183. pcl::PassThrough<pcl::PointXYZ> passZ;
  184. passX.setInputCloud(cloud_downsample);
  185. passX.setFilterFieldName("x");
  186. passX.setFilterLimits(minp.x, maxp.x);
  187. passX.filter(*cloud_in);
  188. passY.setInputCloud(cloud_in);
  189. passY.setFilterFieldName("y");
  190. passY.setFilterLimits(minp.y, maxp.y);
  191. passY.filter(*cloud_in);
  192. passY.setInputCloud(cloud_in);
  193. passY.setFilterFieldName("z");
  194. passY.setFilterLimits(40, 2000);
  195. passY.filter(*cloud_in);
  196. //第三步,分割车辆点云
  197. std::vector<pcl::PointCloud<pcl::PointXYZRGB>::Ptr> segmentation_clouds;
  198. code=mp_point_sift->seg(cloud_in, segmentation_clouds, work_dir);
  199. if(code!=SUCCESS)
  200. {
  201. return code;
  202. }
  203. if(segmentation_clouds[0]->size()==0||segmentation_clouds[2]->size()==0)
  204. {
  205. return Error_manager(LOCATER_SIFT_PREDICT_NO_CAR_POINT,NORMAL,"sift predict no car or wheel");
  206. }
  207. pcl::PointCloud<pcl::PointXYZ>::Ptr t_cloud_car(new pcl::PointCloud<pcl::PointXYZ>);
  208. pcl::PointCloud<pcl::PointXYZ>::Ptr t_cloud_wheel(new pcl::PointCloud<pcl::PointXYZ>);
  209. //第0类即是轮胎点云,第二类为车身点云
  210. pcl::copyPointCloud(*segmentation_clouds[0], *t_cloud_wheel);
  211. pcl::copyPointCloud(*segmentation_clouds[2], *t_cloud_car);
  212. cloud_wheel=t_cloud_wheel;
  213. cloud_car=t_cloud_car;
  214. return SUCCESS;
  215. }
  216. Error_manager Locater::locate_wheel(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,
  217. float& center_x,float& center_y,
  218. float& wheel_base,float& width,float& angle,
  219. std::string work_dir)
  220. {
  221. if(cloud.get()==0)
  222. {
  223. return Error_manager(LOCATER_3DCNN_INPUT_CLOUD_UNINIT,NORMAL,"3dcnn input cloud uninit");
  224. }
  225. if(cloud->size()==0)
  226. {
  227. return Error_manager(LOCATER_3DCNN_INPUT_CLOUD_EMPTY,NORMAL,"locate_3dcnn input cloud empty");
  228. }
  229. if(mp_cnn3d==0)
  230. {
  231. return Error_manager(LOCATER_3DCNN_UNINIT,NORMAL,"locate_wheel 3dcnn is not init");
  232. }
  233. //识别车轮
  234. Error_manager code;
  235. code=mp_cnn3d->predict(cloud,center_x,center_y,wheel_base,width,angle,work_dir);
  236. if(code!=SUCCESS)
  237. {
  238. return code;
  239. }
  240. //根据plc限制判断合法性
  241. if(center_y>=930 || center_y<=200)
  242. {
  243. char description[255]={0};
  244. sprintf(description,"Y is out of range by plc (200 , 900) Y:%.2f",center_y);
  245. return Error_manager(LOCATER_Y_OUT_RANGE_BY_PLC,NORMAL,description);
  246. }
  247. return SUCCESS;
  248. }
  249. Error_manager Locater::measure_height(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_car,float& height)
  250. {
  251. if(cloud_car.get()==0)
  252. {
  253. return Error_manager(LOCATER_MEASURE_HEIGHT_CLOUD_UNINIT,NORMAL,"measure height input cloud uninit");
  254. }
  255. if(cloud_car->size()==0)
  256. {
  257. return Error_manager(LOCATER_MEASURE_HEIGHT_CLOUD_EMPTY,NORMAL,"measure height input cloud is empty");
  258. }
  259. pcl::PointXYZ min_point,max_point;
  260. pcl::getMinMax3D(*cloud_car,min_point,max_point);
  261. //限制车高的范围,检验结果
  262. height=max_point.z;
  263. return SUCCESS;
  264. }
  265. void Locater::save_cloud_txt(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud,std::string save_file)
  266. {
  267. FILE* pfile=fopen(save_file.c_str(),"w");
  268. for(int i=0;i<cloud->size();++i)
  269. {
  270. fprintf(pfile,"%.3f %.3f %.3f\n",cloud->points[i].x,cloud->points[i].y,cloud->points[i].z);
  271. }
  272. fclose(pfile);
  273. }
  274. Error_manager Locater::locate(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_src,
  275. Locate_information& locate_information, std::string work_dir)
  276. {
  277. if(cloud_src.get()==0)
  278. {
  279. return Error_manager(LOCATER_INPUT_CLOUD_UNINIT,NORMAL,"locate input cloud is not init");
  280. }
  281. if(cloud_src->size()==0) {
  282. return Error_manager(LOCATER_INPUT_CLOUD_EMPTY,NORMAL,"input cloud is empty");
  283. }
  284. //10mm网格过滤
  285. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in(new pcl::PointCloud<pcl::PointXYZ>);
  286. /// ///体素网格 下采样
  287. pcl::VoxelGrid<pcl::PointXYZ> vgfilter;
  288. vgfilter.setInputCloud(cloud_src);
  289. vgfilter.setLeafSize(30.f, 30.f, 30.f);
  290. vgfilter.filter(*cloud_in);
  291. //保存原始点云 src.txt
  292. std::string src_cloud_file=work_dir+"/src.txt";
  293. save_cloud_txt(cloud_in,src_cloud_file);
  294. //置初始结果为错误
  295. locate_information.locate_correct=false;
  296. Error_manager code;
  297. //第一步 yolo定位车辆外接矩形
  298. std::vector<YoloBox> t_yolo_boxes;
  299. code=locate_yolo(cloud_in,t_yolo_boxes,work_dir);
  300. if(code!=SUCCESS)
  301. {
  302. return code;
  303. }
  304. //第二步 ,根据yolo框结合PointSift识别车身点云,第0类即轮胎,第二类为车身
  305. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_wheel(new pcl::PointCloud<pcl::PointXYZ>);
  306. pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_car(new pcl::PointCloud<pcl::PointXYZ>);
  307. code=locate_sift(cloud_in,t_yolo_boxes,cloud_wheel,cloud_car,work_dir);
  308. // added by yct, 传出车轮点云,放入任务中替换完整点云
  309. cloud_src = cloud_wheel;
  310. if(code!=SUCCESS)
  311. {
  312. return code;
  313. }
  314. //第三步,计算车辆高度
  315. float height_car=0;
  316. code=measure_height(cloud_car,height_car);
  317. if(code!=SUCCESS)
  318. {
  319. return code;
  320. }
  321. locate_information.locate_hight=height_car;
  322. //第四步,识别轮胎,并根据轮胎数量计算旋转矩形
  323. float center_x;
  324. float center_y;
  325. float wheel_base;
  326. float width;
  327. float angle;
  328. code=locate_wheel(cloud_wheel,center_x,center_y,wheel_base,width,angle,work_dir);
  329. if(code!=SUCCESS)
  330. {
  331. return code;
  332. }
  333. //第六步,结果赋值
  334. //角度以度为单位
  335. locate_information.locate_x=center_x;
  336. locate_information.locate_y=center_y;
  337. locate_information.locate_theta = angle;
  338. locate_information.locate_length=wheel_base;
  339. locate_information.locate_width=width;
  340. locate_information.locate_hight=height_car;
  341. locate_information.locate_wheel_base=wheel_base;
  342. locate_information.locate_correct=true;
  343. LOG(INFO) << "Locate SUCCESS :" << " center:" << "[" << locate_information.locate_x
  344. << "," << locate_information.locate_y<< "] size= "
  345. << locate_information.locate_length << ", "
  346. << locate_information.locate_width << "," << locate_information.locate_hight
  347. << " angle=" << locate_information.locate_theta ;
  348. return SUCCESS;
  349. }