region_worker.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. //
  2. // Created by zx on 2019/12/9.
  3. //
  4. #include "region_worker.h"
  5. #include "plc_data.h"
  6. /**
  7. * 有参构造
  8. * */
  9. Region_worker::Region_worker(int id, wj::Region region, Verify_result* verify_handle):
  10. m_read_code_count(0),
  11. mb_cloud_updated(0),
  12. mp_verify_handle(0)
  13. {
  14. if(verify_handle!= nullptr)
  15. {
  16. mp_verify_handle = verify_handle;
  17. }
  18. m_update_plc_time = std::chrono::steady_clock::now();
  19. m_cloud = pcl::PointCloud<pcl::PointXYZ>::Ptr(new pcl::PointCloud<pcl::PointXYZ>);
  20. m_detector = new Region_detector(id, region);
  21. m_cond_exit.Notify(false);
  22. m_detect_thread = new std::thread(detect_loop, this);
  23. m_detect_thread->detach();
  24. }
  25. /**
  26. * 析构
  27. * */
  28. Region_worker::~Region_worker()
  29. {
  30. m_cond_exit.Notify(true);
  31. std::lock_guard<std::mutex> lck(m_mutex);
  32. if (m_detect_thread)
  33. {
  34. if (m_detect_thread->joinable())
  35. m_detect_thread->join();
  36. delete m_detect_thread;
  37. m_detect_thread = 0;
  38. }
  39. if (m_detector)
  40. {
  41. delete m_detector;
  42. m_detector = 0;
  43. }
  44. }
  45. /**
  46. * 获取区域id号
  47. * */
  48. int Region_worker::get_id()
  49. {
  50. if (m_detector)
  51. {
  52. return m_detector->get_region_id();
  53. }
  54. else
  55. {
  56. LOG(ERROR) << "failed to get worker id";
  57. return -1;
  58. }
  59. }
  60. /**
  61. * 获取轮距等测量结果
  62. * */
  63. Error_manager Region_worker::get_wheel_result(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, double &x, double &y, double &c, double &wheelbase, double &width)
  64. {
  65. Error_manager result;
  66. std::lock_guard<std::mutex> lck(m_mutex);
  67. if (m_detector)
  68. {
  69. LOG(INFO) << "worker getting result";
  70. result = m_detector->detect(cloud_in, x, y, c, wheelbase, width);
  71. }
  72. else
  73. {
  74. result = Error_manager(Error_code::POINTER_IS_NULL);
  75. }
  76. return result;
  77. }
  78. /**
  79. * ceres结果
  80. * 获取轮距等测量结果,包括前轮旋转
  81. * */
  82. Error_manager Region_worker::get_wheel_result(pcl::PointCloud<pcl::PointXYZ>::Ptr &cloud_in, double &x, double &y, double &c,
  83. double &wheelbase, double &width,double& front_theta)
  84. {
  85. Error_manager result;
  86. std::lock_guard<std::mutex> lck(m_mutex);
  87. if (m_detector)
  88. {
  89. LOG(INFO) << "worker getting result";
  90. result = m_detector->detect(cloud_in, x, y, c, wheelbase, width, front_theta);
  91. }
  92. else
  93. {
  94. result = Error_manager(Error_code::POINTER_IS_NULL);
  95. }
  96. return result;
  97. }
  98. /**
  99. * 外部调用更新区域检测用点云
  100. * */
  101. void Region_worker::update_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in)
  102. {
  103. if(cloud_in->size() <=0){
  104. return;
  105. }
  106. // LOG(INFO) << "worker update cloud";
  107. std::lock_guard<std::mutex> lck(m_mutex);
  108. m_cloud->clear();
  109. m_cloud->operator+=(*cloud_in);
  110. // for (int i = 0; i < cloud_in->size(); ++i)
  111. // {
  112. // m_cloud->push_back(cloud_in->points[i]);
  113. // }
  114. mb_cloud_updated = true;
  115. }
  116. /**
  117. * 实时检测与更新线程函数
  118. * */
  119. void Region_worker::detect_loop(Region_worker *worker)
  120. {
  121. // 1.参数检查
  122. if (worker == 0)
  123. return;
  124. if (worker->m_detector == 0)
  125. return;
  126. // 2.检测与更新循环
  127. while (!worker->m_cond_exit.WaitFor(50))
  128. {
  129. // LOG(INFO) << "worker detect loop";
  130. // 检查当前状态
  131. if (worker->mb_cloud_updated)
  132. {
  133. std::lock_guard<std::mutex> lck(worker->m_mutex);
  134. int code = REGION_WORKER_RESULT_DEFAULT;
  135. int border_status = REGION_WORKER_RESULT_DEFAULT;
  136. worker->mb_cloud_updated = false;
  137. double x,y,angle,wheelbase,width,front_theta;
  138. std::string t_error_info_str="";
  139. Error_manager result = worker->m_detector->detect(worker->m_cloud, x, y, angle, front_theta, wheelbase, width, t_error_info_str, false);
  140. // LOG(WARNING) << "worker id: " << worker->get_id()<<" width: "<<width;
  141. if(worker->mp_verify_handle == nullptr)
  142. {
  143. LOG(WARNING) << "verify handle null pointer";
  144. continue;
  145. }
  146. // LOG(INFO) << "worker detect loop end detect";
  147. if (result == WJ_REGION_EMPTY_CLOUD)
  148. {
  149. code = REGION_WORKER_EMPTY_SPACE;
  150. }
  151. else if (result == SUCCESS)
  152. {
  153. cv::RotatedRect car_border;
  154. float ext_length=720;
  155. float new_length=wheelbase*1000.0+2.0*ext_length;
  156. float new_width=2650;
  157. car_border=create_rotate_rect(new_length,new_width,angle,1000.0*x,1000.0*y);
  158. int verify_return_code = 0;
  159. int terminal_id=worker->get_id();
  160. Error_manager verify_error_code = worker->mp_verify_handle->verify(car_border, terminal_id, verify_return_code);
  161. // Error_manager verify_error_code = SUCCESS;
  162. if(verify_error_code == SUCCESS) {
  163. code = REGION_WORKER_HAS_CAR;
  164. }else{
  165. code = REGION_WORKER_HAS_CAR;
  166. border_status = verify_return_code;
  167. //LOG(WARNING) << "region worker verify result: " << code;
  168. }
  169. // added by yct, check car width, width轮距+22cm
  170. if(width > 1.92 || width < 1.55)
  171. {
  172. // LOG(WARNING) << "region worker width: " << width;
  173. border_status |= 0x000020;//第六位为车辆宽度异常
  174. }
  175. }
  176. else
  177. {
  178. code = REGION_WORKER_DETECT_ERROR;
  179. }
  180. // LOG(INFO) << "worker detect loop 000";
  181. // 判断与上次读取是否相同,并计数
  182. if(worker->m_last_read_code != code)
  183. {
  184. worker->m_read_code_count = 0;
  185. }
  186. worker->m_last_read_code = code;
  187. worker->m_read_code_count += 1;
  188. // if(worker->get_id() == 1) {
  189. //// LOG(WARNING) << "worker id: " << worker->get_id()<<" str: "<<t_error_info_str;
  190. // LOG(WARNING) << "worker id: " << worker->get_id()<<" code: "<<code<<", "<<border_status << ", x y: "<<x<< ", "<<y;
  191. // }
  192. // 写入plc,加入写入频率限制
  193. int duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - worker->m_update_plc_time).count();
  194. Plc_data *p = Plc_data::get_instance();
  195. if(p!=0) {
  196. p->update_error_info(worker->m_detector->get_region_id(), t_error_info_str);
  197. }
  198. // 写入间隔必须超过100ms,当前状态不同于上次写入状态,且该状态已连续读到三次
  199. if (p!=0 && duration > 100 && ((worker->m_last_sent_code != worker->m_last_read_code) || worker->m_last_border_status != border_status) && worker->m_read_code_count >= 3)
  200. {
  201. worker->m_last_sent_code = worker->m_last_read_code;
  202. worker->m_last_border_status = border_status;
  203. p->update_data(code, border_status, worker->m_detector->get_region_id());
  204. worker->m_update_plc_time = std::chrono::steady_clock::now();
  205. }
  206. }
  207. }
  208. }
  209. cv::RotatedRect Region_worker::create_rotate_rect(float length,float width,float angle,float cx,float cy)
  210. {
  211. const double C_PI=3.14159265;
  212. float theta=C_PI*(angle/180.0);
  213. float a00=cos(theta);
  214. float a01=-sin(theta);
  215. float a10=sin(theta);
  216. float a11=cos(theta);
  217. cv::Point2f point[4];
  218. point[0].x=-length/2.0;
  219. point[0].y=-width/2.0;
  220. point[1].x=-length/2.0;
  221. point[1].y=width/2.0;
  222. point[2].x=length/2.0;
  223. point[2].y=-width/2.0;
  224. point[3].x=length/2.0;
  225. point[3].y=width/2.0;
  226. std::vector<cv::Point2f> point_vec;
  227. for(int i=0;i<4;++i)
  228. {
  229. float x=point[i].x*a00+point[i].y*a01+cx;
  230. float y=point[i].x*a10+point[i].y*a11+cy;
  231. point_vec.push_back(cv::Point2f(x,y));
  232. }
  233. return cv::minAreaRect(point_vec);
  234. }