region_worker.cpp 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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, false);
  91. //if(result != SUCCESS)
  92. // result = m_detector->detect(cloud_in, x, y, c, wheelbase, width);
  93. }
  94. else
  95. {
  96. result = Error_manager(Error_code::POINTER_IS_NULL);
  97. }
  98. return result;
  99. }
  100. /**
  101. * 外部调用更新区域检测用点云
  102. * */
  103. void Region_worker::update_cloud(pcl::PointCloud<pcl::PointXYZ>::Ptr cloud_in)
  104. {
  105. if(cloud_in->size() <=0){
  106. return;
  107. }
  108. // LOG(INFO) << "worker update cloud";
  109. std::lock_guard<std::mutex> lck(m_mutex);
  110. m_cloud->clear();
  111. m_cloud->operator+=(*cloud_in);
  112. // for (int i = 0; i < cloud_in->size(); ++i)
  113. // {
  114. // m_cloud->push_back(cloud_in->points[i]);
  115. // }
  116. mb_cloud_updated = true;
  117. }
  118. /**
  119. * 实时检测与更新线程函数
  120. * */
  121. void Region_worker::detect_loop(Region_worker *worker)
  122. {
  123. // 1.参数检查
  124. if (worker == 0)
  125. return;
  126. if (worker->m_detector == 0)
  127. return;
  128. // 2.检测与更新循环
  129. while (!worker->m_cond_exit.WaitFor(200))
  130. {
  131. // LOG(INFO) << "worker detect loop";
  132. // 检查当前状态
  133. if (worker->mb_cloud_updated)
  134. {
  135. std::lock_guard<std::mutex> lck(worker->m_mutex);
  136. int code = REGION_WORKER_RESULT_DEFAULT;
  137. int border_status = REGION_WORKER_RESULT_DEFAULT;
  138. worker->mb_cloud_updated = false;
  139. double x,y,angle,wheelbase,width,front_theta;
  140. Error_manager result = worker->m_detector->detect(worker->m_cloud, x, y, angle, wheelbase, width,front_theta, false);
  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. }
  170. else
  171. {
  172. code = REGION_WORKER_DETECT_ERROR;
  173. }
  174. // LOG(INFO) << "worker detect loop 000";
  175. // 判断与上次读取是否相同,并计数
  176. if(worker->m_last_read_code != code)
  177. {
  178. worker->m_read_code_count = 0;
  179. }
  180. worker->m_last_read_code = code;
  181. worker->m_read_code_count += 1;
  182. /*if(worker->get_id() == 3) {
  183. LOG(WARNING) << "worker id: " << worker->get_id()<<" code: "<<code;
  184. }*/
  185. // 写入plc,加入写入频率限制
  186. int duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - worker->m_update_plc_time).count();
  187. Plc_data *p = Plc_data::get_instance();
  188. // 写入间隔必须超过500ms,当前状态不同于上次写入状态,且该状态已连续读到三次
  189. if (p!=0 && duration > 500 && ((worker->m_last_sent_code != worker->m_last_read_code) || worker->m_last_border_status != border_status) && worker->m_read_code_count > 3)
  190. {
  191. worker->m_last_sent_code = worker->m_last_read_code;
  192. worker->m_last_border_status = border_status;
  193. p->update_data(code, border_status, worker->m_detector->get_region_id());
  194. worker->m_update_plc_time = std::chrono::steady_clock::now();
  195. }
  196. }
  197. }
  198. }
  199. cv::RotatedRect Region_worker::create_rotate_rect(float length,float width,float angle,float cx,float cy)
  200. {
  201. const double C_PI=3.14159265;
  202. float theta=C_PI*(angle/180.0);
  203. float a00=cos(theta);
  204. float a01=-sin(theta);
  205. float a10=sin(theta);
  206. float a11=cos(theta);
  207. cv::Point2f point[4];
  208. point[0].x=-length/2.0;
  209. point[0].y=-width/2.0;
  210. point[1].x=-length/2.0;
  211. point[1].y=width/2.0;
  212. point[2].x=length/2.0;
  213. point[2].y=-width/2.0;
  214. point[3].x=length/2.0;
  215. point[3].y=width/2.0;
  216. std::vector<cv::Point2f> point_vec;
  217. for(int i=0;i<4;++i)
  218. {
  219. float x=point[i].x*a00+point[i].y*a01+cx;
  220. float y=point[i].x*a10+point[i].y*a11+cy;
  221. point_vec.push_back(cv::Point2f(x,y));
  222. }
  223. return cv::minAreaRect(point_vec);
  224. }