region_worker.cpp 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  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(200))
  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. Error_manager result = worker->m_detector->detect(worker->m_cloud, x, y, angle, wheelbase, width, false);
  139. if(worker->mp_verify_handle == nullptr)
  140. {
  141. LOG(WARNING) << "verify handle null pointer";
  142. continue;
  143. }
  144. // LOG(INFO) << "worker detect loop end detect";
  145. if (result == WJ_REGION_EMPTY_CLOUD)
  146. {
  147. code = REGION_WORKER_EMPTY_SPACE;
  148. }
  149. else if (result == SUCCESS)
  150. {
  151. cv::RotatedRect car_border;
  152. float ext_length=720;
  153. float new_length=wheelbase*1000.0+2.0*ext_length;
  154. float new_width=2650;
  155. car_border=create_rotate_rect(new_length,new_width,angle,1000.0*x,1000.0*y);
  156. int verify_return_code = 0;
  157. int terminal_id=worker->get_id();
  158. Error_manager verify_error_code = worker->mp_verify_handle->verify(car_border, terminal_id, verify_return_code);
  159. // Error_manager verify_error_code = SUCCESS;
  160. if(verify_error_code == SUCCESS) {
  161. code = REGION_WORKER_HAS_CAR;
  162. }else{
  163. code = REGION_WORKER_HAS_CAR;
  164. border_status = verify_return_code;
  165. //LOG(WARNING) << "region worker verify result: " << code;
  166. }
  167. }
  168. else
  169. {
  170. code = REGION_WORKER_DETECT_ERROR;
  171. }
  172. // LOG(INFO) << "worker detect loop 000";
  173. // 判断与上次读取是否相同,并计数
  174. if(worker->m_last_read_code != code)
  175. {
  176. worker->m_read_code_count = 0;
  177. }
  178. worker->m_last_read_code = code;
  179. worker->m_read_code_count += 1;
  180. /*if(worker->get_id() == 3) {
  181. LOG(WARNING) << "worker id: " << worker->get_id()<<" code: "<<code;
  182. }*/
  183. // 写入plc,加入写入频率限制
  184. int duration = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::steady_clock::now() - worker->m_update_plc_time).count();
  185. Plc_data *p = Plc_data::get_instance();
  186. // 写入间隔必须超过500ms,当前状态不同于上次写入状态,且该状态已连续读到三次
  187. 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)
  188. {
  189. worker->m_last_sent_code = worker->m_last_read_code;
  190. worker->m_last_border_status = border_status;
  191. p->update_data(code, border_status, worker->m_detector->get_region_id());
  192. worker->m_update_plc_time = std::chrono::steady_clock::now();
  193. }
  194. }
  195. }
  196. }
  197. cv::RotatedRect Region_worker::create_rotate_rect(float length,float width,float angle,float cx,float cy)
  198. {
  199. const double C_PI=3.14159265;
  200. float theta=C_PI*(angle/180.0);
  201. float a00=cos(theta);
  202. float a01=-sin(theta);
  203. float a10=sin(theta);
  204. float a11=cos(theta);
  205. cv::Point2f point[4];
  206. point[0].x=-length/2.0;
  207. point[0].y=-width/2.0;
  208. point[1].x=-length/2.0;
  209. point[1].y=width/2.0;
  210. point[2].x=length/2.0;
  211. point[2].y=-width/2.0;
  212. point[3].x=length/2.0;
  213. point[3].y=width/2.0;
  214. std::vector<cv::Point2f> point_vec;
  215. for(int i=0;i<4;++i)
  216. {
  217. float x=point[i].x*a00+point[i].y*a01+cx;
  218. float y=point[i].x*a10+point[i].y*a11+cy;
  219. point_vec.push_back(cv::Point2f(x,y));
  220. }
  221. return cv::minAreaRect(point_vec);
  222. }