region_worker.cpp 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219
  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. * 外部调用更新区域检测用点云
  80. * */
  81. void Region_worker::update_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in)
  82. {
  83. if(cloud_in->size() <=0){
  84. return;
  85. }
  86. // LOG(INFO) << "worker update cloud";
  87. std::lock_guard<std::mutex> lck(m_mutex);
  88. m_cloud->clear();
  89. m_cloud->operator+=(*cloud_in);
  90. // for (int i = 0; i < cloud_in->size(); ++i)
  91. // {
  92. // m_cloud->push_back(cloud_in->points[i]);
  93. // }
  94. mb_cloud_updated = true;
  95. }
  96. /**
  97. * 实时检测与更新线程函数
  98. * */
  99. void Region_worker::detect_loop(Region_worker *worker)
  100. {
  101. // 1.参数检查
  102. if (worker == 0)
  103. return;
  104. if (worker->m_detector == 0)
  105. return;
  106. // 2.检测与更新循环
  107. while (!worker->m_cond_exit.WaitFor(200))
  108. {
  109. // LOG(INFO) << "worker detect loop";
  110. // 检查当前状态
  111. if (worker->mb_cloud_updated)
  112. {
  113. std::lock_guard<std::mutex> lck(worker->m_mutex);
  114. int code = REGION_WORKER_RESULT_DEFAULT;
  115. int border_status = REGION_WORKER_RESULT_DEFAULT;
  116. worker->mb_cloud_updated = false;
  117. double x,y,angle,wheelbase,width;
  118. Error_manager result = worker->m_detector->detect(worker->m_cloud, x, y, angle, wheelbase, width, false);
  119. if(worker->mp_verify_handle == nullptr)
  120. {
  121. LOG(WARNING) << "verify handle null pointer";
  122. continue;
  123. }
  124. // LOG(INFO) << "worker detect loop end detect";
  125. if (result == WJ_REGION_EMPTY_CLOUD)
  126. {
  127. code = REGION_WORKER_EMPTY_SPACE;
  128. }
  129. else if (result == SUCCESS)
  130. {
  131. cv::RotatedRect car_border;
  132. float ext_length=720;
  133. float new_length=wheelbase*1000.0+2.0*ext_length;
  134. float new_width=2650;
  135. car_border=create_rotate_rect(new_length,new_width,angle,1000.0*x,1000.0*y);
  136. int verify_return_code = 0;
  137. int terminal_id=worker->get_id();
  138. Error_manager verify_error_code = worker->mp_verify_handle->verify(car_border, terminal_id, verify_return_code);
  139. // Error_manager verify_error_code = SUCCESS;
  140. if(verify_error_code == SUCCESS) {
  141. code = REGION_WORKER_HAS_CAR;
  142. }else{
  143. code = REGION_WORKER_HAS_CAR;
  144. border_status = verify_return_code;
  145. //LOG(WARNING) << "region worker verify result: " << code;
  146. }
  147. }
  148. else
  149. {
  150. code = REGION_WORKER_DETECT_ERROR;
  151. }
  152. // LOG(INFO) << "worker detect loop 000";
  153. // 判断与上次读取是否相同,并计数
  154. if(worker->m_last_read_code != code)
  155. {
  156. worker->m_read_code_count = 0;
  157. }
  158. worker->m_last_read_code = code;
  159. worker->m_read_code_count += 1;
  160. /*if(worker->get_id() == 3) {
  161. LOG(WARNING) << "worker id: " << worker->get_id()<<" code: "<<code;
  162. }*/
  163. // 写入plc,加入写入频率限制
  164. int duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - worker->m_update_plc_time).count();
  165. Plc_data *p = Plc_data::get_instance();
  166. // 写入间隔必须超过500ms,当前状态不同于上次写入状态,且该状态已连续读到三次
  167. if (p!=0 && duration > 500 && worker->m_last_sent_code != worker->m_last_read_code && worker->m_read_code_count > 3)
  168. {
  169. worker->m_last_sent_code = worker->m_last_read_code;
  170. p->update_data(code, border_status, worker->m_detector->get_region_id());
  171. worker->m_update_plc_time = std::chrono::steady_clock::now();
  172. }
  173. }
  174. }
  175. }
  176. cv::RotatedRect Region_worker::create_rotate_rect(float length,float width,float angle,float cx,float cy)
  177. {
  178. const double C_PI=3.14159265;
  179. float theta=C_PI*(angle/180.0);
  180. float a00=cos(theta);
  181. float a01=-sin(theta);
  182. float a10=sin(theta);
  183. float a11=cos(theta);
  184. cv::Point2f point[4];
  185. point[0].x=-length/2.0;
  186. point[0].y=-width/2.0;
  187. point[1].x=-length/2.0;
  188. point[1].y=width/2.0;
  189. point[2].x=length/2.0;
  190. point[2].y=-width/2.0;
  191. point[3].x=length/2.0;
  192. point[3].y=width/2.0;
  193. std::vector<cv::Point2f> point_vec;
  194. for(int i=0;i<4;++i)
  195. {
  196. float x=point[i].x*a00+point[i].y*a01+cx;
  197. float y=point[i].x*a10+point[i].y*a11+cy;
  198. point_vec.push_back(cv::Point2f(x,y));
  199. }
  200. return cv::minAreaRect(point_vec);
  201. }