region_worker.cpp 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. //
  2. // Created by zx on 2019/12/9.
  3. //
  4. #include "region_worker.h"
  5. //#include "plc_data.h"
  6. // 测量结果滤波,不影响现有结构
  7. #include "../tool/measure_filter.h"
  8. Region_worker::Region_worker()
  9. {
  10. m_region_worker_status = E_UNKNOWN;
  11. mp_cloud_collection_mutex = NULL;
  12. mp_cloud_collection = NULL;
  13. m_detect_updata_time = std::chrono::system_clock::now() - std::chrono::hours(1);
  14. mp_auto_detect_thread = NULL;
  15. }
  16. /**
  17. * 析构
  18. * */
  19. Region_worker::~Region_worker()
  20. {
  21. }
  22. Error_manager Region_worker::init(Point2D_tool::Point2D_box point2D_box, std::mutex* p_cloud_collection_mutex,
  23. pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_collection)
  24. {
  25. m_detector.init(point2D_box);
  26. mp_cloud_collection_mutex = p_cloud_collection_mutex;
  27. mp_cloud_collection = p_cloud_collection;
  28. m_auto_detect_condition.reset(false, false, false);
  29. mp_auto_detect_thread = new std::thread(&Region_worker::auto_detect_thread_fun, this);
  30. m_region_worker_status = E_READY;
  31. return Error_code::SUCCESS;
  32. }
  33. Error_manager Region_worker::init(Point2D_tool::Point2D_box point2D_box, std::mutex* p_cloud_collection_mutex,
  34. pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_collection, int index)
  35. {
  36. m_index = index;
  37. return init(point2D_box, p_cloud_collection_mutex, p_cloud_collection);
  38. }
  39. //开始自动预测的算法线程
  40. Error_manager Region_worker::start_auto_detect()
  41. {
  42. //唤醒一次
  43. m_auto_detect_condition.notify_all(false, true);
  44. return Error_code::SUCCESS;
  45. }
  46. //关闭自动预测的算法线程
  47. Error_manager Region_worker::stop_auto_detect()
  48. {
  49. //唤醒一次
  50. m_auto_detect_condition.notify_all(false);
  51. return Error_code::SUCCESS;
  52. }
  53. // 获得中心点、角度等测量数据
  54. Error_manager Region_worker::detect_wheel_result(std::mutex* p_cloud_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_in, Common_data::Car_wheel_information& car_wheel_information)
  55. {
  56. return m_detector.detect(p_cloud_mutex, p_cloud_in, car_wheel_information);
  57. }
  58. // 获得中心点、角度等测量数据, 新算法, 可以测量前轮旋转
  59. Error_manager Region_worker::detect_wheel_result_ex(std::mutex* p_cloud_mutex, pcl::PointCloud<pcl::PointXYZ>::Ptr p_cloud_in, Common_data::Car_wheel_information& car_wheel_information)
  60. {
  61. return m_detector.detect_ex(p_cloud_mutex, p_cloud_in, car_wheel_information);
  62. }
  63. //外部调用获取新的车轮定位信息, 获取指令时间之后的车轮定位信息, 如果没有就会等待车轮定位信息刷新, 直到超时, (内置while)
  64. Error_manager Region_worker::get_new_wheel_information_and_wait(Common_data::Car_wheel_information* p_car_wheel_information,
  65. std::chrono::system_clock::time_point command_time, int timeout_ms)
  66. {
  67. if ( p_car_wheel_information == NULL )
  68. {
  69. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  70. " POINTER IS NULL ");
  71. }
  72. //判断是否超时
  73. while (std::chrono::system_clock::now() - command_time < std::chrono::milliseconds(timeout_ms))
  74. {
  75. //获取指令时间之后的信息, 如果没有就会循环
  76. if(m_detect_updata_time > command_time )
  77. {
  78. *p_car_wheel_information = m_car_wheel_information;
  79. return Error_code::SUCCESS;
  80. }
  81. //else 等待下一次数据更新
  82. //等1ms
  83. std::this_thread::sleep_for(std::chrono::milliseconds(1));
  84. }
  85. //超时退出就报错
  86. return Error_manager(Error_code::WJ_REGION_EMPTY_NO_WHEEL_INFORMATION, Error_level::MINOR_ERROR,
  87. " Region_worker::get_new_wheel_information_and_wait error ");
  88. }
  89. //外部调用获取当前车轮定位信息, 获取指令时间之后的车轮定位信息, 如果没有就会报错, 不会等待
  90. Error_manager Region_worker::get_current_wheel_information(Common_data::Car_wheel_information* p_car_wheel_information,
  91. std::chrono::system_clock::time_point command_time)
  92. {
  93. if ( p_car_wheel_information == NULL )
  94. {
  95. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  96. " POINTER IS NULL ");
  97. }
  98. //获取指令时间之后的信息, 如果没有就会报错, 不会等待
  99. if( m_detect_updata_time > command_time )
  100. {
  101. *p_car_wheel_information = m_car_wheel_information;
  102. return Error_code::SUCCESS;
  103. }
  104. else
  105. {
  106. return Error_manager(Error_code::WJ_REGION_EMPTY_NO_WHEEL_INFORMATION, Error_level::MINOR_ERROR,
  107. " Region_worker::get_current_wheel_information error ");
  108. }
  109. }
  110. //外部调用获取最新的车轮定位信息, 获取指令时间往前一个周期内的车轮定位信息, 如果没有就会报错, 不会等待
  111. Error_manager Region_worker::get_last_wheel_information(Common_data::Car_wheel_information* p_car_wheel_information,
  112. std::chrono::system_clock::time_point command_time)
  113. {
  114. if ( p_car_wheel_information == NULL )
  115. {
  116. return Error_manager(Error_code::POINTER_IS_NULL, Error_level::MINOR_ERROR,
  117. " POINTER IS NULL ");
  118. }
  119. //将指令时间提前一个扫描周期, 然后获取这个时间后面的点云.
  120. //就是说, 在收到指令的时候, 可以使用一个周期以前的数据, 不用获取最新的点云.
  121. if( m_detect_updata_time > command_time - std::chrono::milliseconds(REGION_WORKER_DETECT_CYCLE_MS*2) )
  122. {
  123. *p_car_wheel_information = m_car_wheel_information;
  124. return Error_code::SUCCESS;
  125. }
  126. else
  127. {
  128. return Error_manager(Error_code::WJ_REGION_EMPTY_NO_WHEEL_INFORMATION, Error_level::MINOR_ERROR,
  129. " Region_worker::get_last_wheel_information error ");
  130. }
  131. }
  132. Region_worker::Region_worker_status Region_worker::get_status()
  133. {
  134. return m_region_worker_status;
  135. }
  136. std::chrono::system_clock::time_point Region_worker::get_detect_updata_time()
  137. {
  138. return m_detect_updata_time;
  139. }
  140. cv::RotatedRect Region_worker::create_rotate_rect(float length,float width,float angle,float cx,float cy)
  141. {
  142. const double C_PI=3.14159265;
  143. float theta=C_PI*(angle/180.0);
  144. float a00=cos(theta);
  145. float a01=-sin(theta);
  146. float a10=sin(theta);
  147. float a11=cos(theta);
  148. cv::Point2f point[4];
  149. point[0].x=-length/2.0;
  150. point[0].y=-width/2.0;
  151. point[1].x=-length/2.0;
  152. point[1].y=width/2.0;
  153. point[2].x=length/2.0;
  154. point[2].y=-width/2.0;
  155. point[3].x=length/2.0;
  156. point[3].y=width/2.0;
  157. std::vector<cv::Point2f> point_vec;
  158. for(int i=0;i<4;++i)
  159. {
  160. float x=point[i].x*a00+point[i].y*a01+cx;
  161. float y=point[i].x*a10+point[i].y*a11+cy;
  162. point_vec.push_back(cv::Point2f(x,y));
  163. }
  164. return cv::minAreaRect(point_vec);
  165. }
  166. //自动预测的线程函数
  167. void Region_worker::auto_detect_thread_fun()
  168. {
  169. LOG(INFO) << " Wanji_manager::collect_cloud_thread_fun() start "<< this;
  170. Error_manager t_error;
  171. Error_manager t_result;
  172. while (m_auto_detect_condition.is_alive())
  173. {
  174. //暂时固定为一个扫描周期, 就循环一次
  175. //后期可以根据每个小雷达的刷新情况, 实时更改总点云.....
  176. // if(m_index==5)
  177. // LOG(INFO) << "before wait";
  178. m_auto_detect_condition.wait();
  179. // if(m_index==5)
  180. // LOG(INFO) << "after wait";
  181. if ( m_auto_detect_condition.is_alive() )
  182. {
  183. // std::cout << " huli test :::: " << " = " << "---------------------------------------------------------------------------------" << std::endl;
  184. // if(m_index==5)
  185. // LOG(INFO) << " huli test :::: " << " mp_cloud_collection->size() = " << mp_cloud_collection->size();
  186. //
  187. // auto start = std::chrono::system_clock::now();
  188. t_error = detect_wheel_result_ex(mp_cloud_collection_mutex, mp_cloud_collection, m_car_wheel_information);
  189. // auto end = std::chrono::system_clock::now();
  190. // auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end - start);
  191. // std::cout << "花费了"
  192. // << double(duration.count()*1000) * std::chrono::microseconds::period::num / std::chrono::microseconds::period::den << "毫秒" << std::endl;
  193. if ( t_error == SUCCESS )
  194. {
  195. std::unique_lock<std::mutex> t_lock(*mp_cloud_collection_mutex);
  196. m_car_wheel_information.correctness = true;
  197. // if(m_index==5) {
  198. // std::cout << " huli test :::: " << " x = " << m_car_wheel_information.center_x << std::endl;
  199. // std::cout << " huli test :::: " << " y = " << m_car_wheel_information.center_y << std::endl;
  200. // std::cout << " huli test :::: " << " c = " << m_car_wheel_information.car_angle << std::endl;
  201. // std::cout << " huli test :::: " << " wheelbase = " << m_car_wheel_information.wheel_base
  202. // << std::endl;
  203. // std::cout << " huli test :::: " << " width = " << m_car_wheel_information.wheel_width << std::endl;
  204. // std::cout << " huli test :::: " << " front_theta = " << m_car_wheel_information.front_theta
  205. // << std::endl;
  206. // std::cout << " huli test :::: " << " correctness = " << m_car_wheel_information.correctness
  207. // << std::endl;
  208. // }
  209. }
  210. else
  211. {
  212. std::unique_lock<std::mutex> t_lock(*mp_cloud_collection_mutex);
  213. m_car_wheel_information.correctness = false;
  214. // if(m_index==5)
  215. // LOG(WARNING)<< " t_error = " << t_error;
  216. }
  217. //无论结果如何,都要刷新时间, 表示这次定位已经执行了.
  218. m_detect_updata_time = std::chrono::system_clock::now();
  219. // if(m_index==5)
  220. // LOG(INFO) << "before filter";
  221. // 测量正确,更新到滤波器
  222. if(m_car_wheel_information.correctness)
  223. {
  224. Common_data::Car_wheel_information_stamped t_wheel_info_stamped;
  225. t_wheel_info_stamped.wheel_data = m_car_wheel_information;
  226. t_wheel_info_stamped.measure_time = m_detect_updata_time;
  227. Measure_filter::get_instance_references().update_data(m_index, t_wheel_info_stamped);
  228. }
  229. // if(m_index==5)
  230. // LOG(INFO) << "after filter";
  231. }
  232. }
  233. LOG(INFO) << " Wanji_manager::collect_cloud_thread_fun() end "<< this;
  234. return;
  235. }