region_worker.cpp 10 KB

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