region_worker.cpp 13 KB

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