measuretask.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. #include "measuretask.h"
  2. #include "pathcreator.h"
  3. std::string Error_string(ERROR_CODE code)
  4. {
  5. std::string StrError;
  6. switch (code)
  7. {
  8. case eSucc:StrError = "测量正确";
  9. break;
  10. case eArea:StrError = "跨车位区域或者车位区域无车";
  11. break;
  12. case eLidar:
  13. StrError = "两雷达数据不重合";
  14. break;
  15. case eLimitL:
  16. StrError = "左边界超界";
  17. break;
  18. case eLimitR:
  19. StrError = "右边界超界";
  20. break;
  21. case eLimitT:
  22. StrError = "上边界超界";
  23. break;
  24. case eLimitB:
  25. StrError = "下边界超界";
  26. break;
  27. case eNoCar:
  28. StrError = "测量失败, 场景内未找到车辆";
  29. break;
  30. case eMulCar:
  31. StrError = "车位区域内存在多辆车";
  32. break;
  33. case eDistance:
  34. StrError = "车辆间距离过进,机械臂无法下降";
  35. break;
  36. case eCloud:
  37. StrError = "雷达断线,无点云数据";
  38. break;
  39. default:
  40. break;
  41. }
  42. return StrError;
  43. }
  44. bool RegionInRegion(std::vector<cv::Point2f>& mini_poly, std::vector<cv::Point2f>& large_poly)
  45. {
  46. for (int i = 0; i < mini_poly.size(); ++i)
  47. {
  48. if (cv::pointPolygonTest(large_poly, mini_poly[i], false) < 0)
  49. return false;
  50. }
  51. return true;
  52. }
  53. double distance_polys(std::vector<cv::Point2f> poly1, std::vector<cv::Point2f> poly2)
  54. {
  55. std::vector<cv::Point2f>& minpoly = poly1.size() >= poly2.size() ? poly2 : poly1;
  56. std::vector<cv::Point2f>& maxpoly = poly1.size() >= poly2.size() ? poly1 : poly2;
  57. double mindis = (numeric_limits<double>::max)();
  58. for (int i = 0; i < minpoly.size(); ++i)
  59. {
  60. double dis = -cv::pointPolygonTest(maxpoly, minpoly[i], true);
  61. if (dis < mindis)
  62. {
  63. mindis = dis;
  64. }
  65. }
  66. return mindis;
  67. }
  68. std::mutex* MeasureTask::g_mutex = new std::mutex();
  69. MeasureTask::MeasureTask(std::vector<CLaser*> lasers, void* locater,int positon_id,
  70. modbus::CPLCMonitor* plc,Automatic::stCalibParam param)
  71. {
  72. m_lasers = lasers;
  73. m_locater = locater;
  74. m_plc = plc;
  75. m_exit = false;
  76. m_calib_param = param;
  77. m_position_id = positon_id;
  78. m_ptr = 0;
  79. m_post_result_func=0;
  80. }
  81. ERROR_CODE MeasureTask::SelectResult(int plate_index, std::vector<CarPosition> results, CarPosition& result)
  82. {
  83. //一两车不考虑区域问题
  84. if (results.size() == 1)
  85. {
  86. result = results[0];
  87. return eSucc;
  88. }
  89. LOG(INFO) << "选择号牌机对应车辆,号牌编号:" << plate_index;
  90. if (plate_index >= m_calib_param.plate_area_size() || plate_index < 0)
  91. {
  92. LOG(ERROR) << "当前车位没有车辆,车位ID:" << plate_index;
  93. return eArea;
  94. }
  95. std::vector<cv::Point2f> area;
  96. for (int i = 0; i < m_calib_param.plate_area(plate_index).point_size(); ++i)
  97. {
  98. Automatic::stPoint stP = m_calib_param.plate_area(plate_index).point(i);
  99. cv::Point2f point;
  100. point.x = stP.x();
  101. point.y = stP.y();
  102. area.push_back(point);
  103. }
  104. if (area.size() < 3)
  105. {
  106. LOG(ERROR) << " plate aera points size<3 size=" << area.size();
  107. return eArea;
  108. }
  109. double max_distance = -1.0;
  110. int num = 0;
  111. int id = -1;
  112. for (int i = 0; i < results.size(); ++i)
  113. {
  114. cv::Point2f vtx[4];
  115. results[i].rrect.points(vtx);
  116. std::vector<cv::Point2f> poly(vtx, vtx + 4);
  117. if (RegionInRegion(poly, area))
  118. {
  119. result = results[i];
  120. LOG(INFO) << vtx[0] << " " << vtx[1] << " " << vtx[2] << " " << vtx[3] << " ";
  121. num++;
  122. id = i;
  123. }
  124. }
  125. if (num == 1) //找到符合要求车辆,rs[id]
  126. {
  127. cv::Point2f vtx[4];
  128. results[id].rrect.points(vtx);
  129. std::vector<cv::Point2f> poly(vtx, vtx + 4);
  130. for (int i = 0; i < results.size(); ++i)
  131. {
  132. if (i != id)
  133. {
  134. cv::Point2f vtx1[4];
  135. results[i].rrect.points(vtx1);
  136. std::vector<cv::Point2f> poly1(vtx1, vtx1 + 4);
  137. if (distance_polys(poly, poly1) < 400.)
  138. return eDistance;
  139. }
  140. }
  141. return eSucc;
  142. }
  143. if (num > 1)
  144. return eMulCar;
  145. return eArea;
  146. }
  147. ERROR_CODE MeasureTask::Dispatch_posID(std::vector<CarPosition>& results)
  148. {
  149. if (results.size() == 0)
  150. return eNoCar;
  151. if ( m_calib_param.plate_area_size()==0 )
  152. {
  153. LOG(ERROR) << "\t未配置车位信息,无法标识车位";
  154. return eArea;
  155. }
  156. std::vector<std::vector<cv::Point2f>> areas;
  157. for (int k = 0; k < m_calib_param.plate_area_size(); ++k)
  158. {
  159. std::vector<cv::Point2f> area;
  160. for (int i = 0; i < m_calib_param.plate_area(k).point_size(); ++i)
  161. {
  162. Automatic::stPoint stP = m_calib_param.plate_area(k).point(i);
  163. cv::Point2f point;
  164. point.x = stP.x();
  165. point.y = stP.y();
  166. area.push_back(point);
  167. }
  168. areas.push_back(area);
  169. }
  170. double max_distance = -1.0;
  171. int num = 0;
  172. for (int i = 0; i < results.size(); ++i)
  173. {
  174. //判断结果是否合法
  175. CarPosition rs = results[i];
  176. ERROR_CODE code = rs.error_code;
  177. if (rs.x < 0 || rs.y < 0)
  178. {
  179. code = eArea;
  180. continue;
  181. }
  182. //// 分配车位
  183. cv::Point2f center = results[i].rrect.center;
  184. for (int j = 0; j < areas.size(); ++j)
  185. {
  186. if (cv::pointPolygonTest(areas[j], center, false) >= 0)
  187. {
  188. results[i].pos_id = j;
  189. LOG(INFO) << "\tCar[" << i << "],center:" << results[i].rrect.center << ",size:" << results[i].rrect.size << ",车位ID:" << j;
  190. num++;
  191. }
  192. }
  193. /*cv::Point2f vtx[4];
  194. results[i].rrect.points(vtx);
  195. std::vector<cv::Point2f> poly(vtx, vtx + 4);
  196. for (int j = 0; j < areas.size(); ++j)
  197. {
  198. if (RegionInRegion(poly, areas[j]))
  199. {
  200. results[i].pos_id = j;
  201. LOG(INFO) << "\tCar[" << i << "],center:" << results[i].rrect.center << ",size:" << results[i].rrect.size << ",车位ID:" << j;
  202. num++;
  203. }
  204. }*/
  205. if (results[i].pos_id < 0)
  206. continue;
  207. float l = 4200;
  208. float w = 2630;
  209. cv::RotatedRect rect = rs.rrect;
  210. rect.center = rs.rrect.center;
  211. cv::Point2f pt[4];
  212. rect.points(pt);
  213. float minx = areas[results[i].pos_id][0].x;//m_calib_param.valid_region().min_x();
  214. float maxx = areas[results[i].pos_id][3].x;//m_calib_param.valid_region().max_x();
  215. float miny = areas[results[i].pos_id][1].y;//m_calib_param.valid_region().min_y();
  216. float maxy = areas[results[i].pos_id][0].y;//m_calib_param.valid_region().max_y();
  217. for (int i = 0; i < 4; ++i)
  218. {
  219. cv::Point2f point = pt[i];
  220. LOG(INFO) << "error pt " << i << ":" << point.x << "," << point.y;
  221. if (point.x < minx)
  222. {
  223. code = eLimitL;
  224. //break;
  225. }
  226. if (point.x > maxx)
  227. {
  228. code = eLimitR;
  229. //break;
  230. }
  231. if (point.y < miny)
  232. {
  233. code = eLimitB;
  234. //break;
  235. }
  236. }
  237. results[i].error_code = code;
  238. if (code != eSucc)
  239. {
  240. LOG(INFO) << "\tCar[" << i << "] error,info:"<<Error_string(code);
  241. continue;
  242. }
  243. }
  244. if (num >= 1) //找到符合要求车辆,rs[id]
  245. {
  246. return eSucc;
  247. }
  248. return eArea;
  249. }
  250. void MeasureTask::PushPoint(CPoint3D point, void* pointer)
  251. {
  252. MeasureTask* task = reinterpret_cast<MeasureTask*>(pointer);
  253. PointT pcl_point;
  254. pcl_point.x = point.x;
  255. pcl_point.y = point.y;
  256. pcl_point.z = point.z;
  257. float min_x = task->m_calib_param.valid_region().min_x();
  258. float max_x = task->m_calib_param.valid_region().max_x();
  259. float min_y = task->m_calib_param.valid_region().min_y();
  260. float max_y = task->m_calib_param.valid_region().max_y();
  261. float min_z = task->m_calib_param.valid_region().min_z();
  262. float max_z = task->m_calib_param.valid_region().max_z();
  263. if (pcl_point.x<min_x || pcl_point.x>max_x || pcl_point.y<min_y ||
  264. pcl_point.y>max_y || pcl_point.z<min_z || pcl_point.z>max_z)
  265. return;
  266. std::lock_guard<std::mutex> lk(task->m_mutex);
  267. task->m_cloud.push_back(pcl_point);
  268. }
  269. void MeasureTask::SetResultCallback(void *ptr, ResultCallback func)
  270. {
  271. m_post_result_func=func;
  272. m_ptr=ptr;
  273. }
  274. void MeasureTask::Main()
  275. {
  276. ////等待雷达空闲资源
  277. PathCreator pathCreator;
  278. while (!m_exit)
  279. {
  280. g_mutex->lock();
  281. if (IsLaserReady())
  282. {
  283. pathCreator.CreateDatePath(m_calib_param.project_dir());
  284. LOG(INFO) << "\tTask dir:" << pathCreator.GetCurPath();
  285. //启动摆扫
  286. for (int i = 0; i < m_lasers.size(); ++i)
  287. {
  288. m_lasers[i]->SetSaveDir(pathCreator.GetCurPath());
  289. m_lasers[i]->SetPointCallBack(PushPoint, this);
  290. m_lasers[i]->Start();
  291. }
  292. g_mutex->unlock();
  293. break;
  294. }
  295. g_mutex->unlock();
  296. usleep(100*1000);
  297. }
  298. while (!m_exit && !IsLaserReady()) { usleep(1000); } //等待摆扫结束
  299. std::vector<CarPosition> results;
  300. ERROR_CODE code = eSucc;
  301. if (m_locater)
  302. {
  303. //m_locater->Locate(m_cloud.makeShared(), results, strPath.GetBuffer(), code)
  304. if (m_cloud.size() == 0)
  305. {
  306. code = eCloud;
  307. }
  308. else if (0)
  309. {
  310. code = Dispatch_posID(results);
  311. if (code == eSucc)
  312. {
  313. /////写入结果到plc
  314. for (int i = 0; i < results.size(); ++i)
  315. {
  316. CarPosition rs = results[i];
  317. rs.pos_id = 0;
  318. whiskboom_laser_value value;
  319. //value.a = int((rs.a+4.1) * 100);
  320. value.a = int((rs.a) * 100);
  321. value.corrected = (rs.error_code == eSucc);
  322. value.h = rs.h;
  323. value.l = rs.l;
  324. value.w = rs.w;
  325. value.x = rs.x ;
  326. value.y = rs.y;
  327. // 正常返回状态3
  328. LOG(INFO) << "\t post:" << rs.a << "°" << ", " << " center:(" <<
  329. rs.x << "," << rs.y << "), size:" << "(" << rs.l << ", " << rs.w << ", " << rs.h << ")"<<",rs.code:"<<Error_string(rs.error_code);
  330. if (m_plc)
  331. m_plc->setMeasureResult(m_calib_param.plate_area(rs.pos_id).plc_addr(), &value);
  332. }
  333. }
  334. }
  335. else
  336. {
  337. LOG(ERROR) << "\t测量失败 : " << Error_string(code);
  338. }
  339. }
  340. ///写入测量完成信号
  341. if (m_plc)
  342. m_plc->MeasureComplete(code==eSucc);
  343. /////回调函数,窗口显示结果
  344. QtMessageData msg;
  345. msg.msg_type=eMeasure;
  346. if(results.size()>0)
  347. {
  348. msg.OK=1;
  349. msg.x=results[0].x;
  350. msg.y=results[0].y;
  351. msg.c=results[0].a;
  352. msg.l=std::max(results[0].rrect.size.width,results[0].rrect.size.height);
  353. msg.w=results[0].w;
  354. msg.h=results[0].h;
  355. msg.d=results[0].l;
  356. }
  357. else
  358. {
  359. msg.OK=0;
  360. }
  361. ///// id time
  362. short id=0;
  363. for(int i=0;i<m_lasers.size();++i)
  364. {
  365. id =id | (0x01<<m_lasers[i]->ID());
  366. }
  367. msg.lasers_id=id;
  368. time_t tt = time(0);//时间cuo
  369. tm* t = localtime(&tt);
  370. memset(msg.time_str,0,255);
  371. sprintf(msg.time_str, "%d-%02d-%02d %02d:%02d:%02d", t->tm_year + 1900, t->tm_mon + 1,
  372. t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
  373. memset(msg.project_dir,0,255);
  374. sprintf(msg.project_dir,"%s",pathCreator.GetCurPath().c_str());
  375. if(m_post_result_func)
  376. m_post_result_func(msg,m_ptr);
  377. }
  378. void MeasureTask::Cancel()
  379. {
  380. m_exit = true;
  381. }
  382. bool MeasureTask::IsLaserReady()
  383. {
  384. bool ready = true;
  385. for (int i = 0; i < m_lasers.size(); ++i)
  386. {
  387. ready = (ready && m_lasers[i]->IsReady());
  388. }
  389. return ready;
  390. }
  391. ////////////////////////////////