algorithm.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099
  1. #include <rtthread.h>
  2. #include <stdio.h>
  3. #include "gpio.h"
  4. #include "iwdg.h"
  5. #include "algorithm.h"
  6. #include "log.h"
  7. #include "drv_hwtimer.h"
  8. #include "usart.h"
  9. #include "dri_can.h"
  10. #include "quaternion.h"
  11. #include "euler.h"
  12. #include "dri_Flash.h"
  13. #include "stdlib.h"
  14. #include <dronecan_msgs.h>
  15. #define M_PI_ 3.1415926f
  16. #define Rng_res 0.6958f //范围矫正值
  17. #define Vel_res 0.3519f //速度校正值
  18. #define MAX_FRAME_NUM 15 //点云最大帧数
  19. #define MAX_Z_AXIS_POINTS 70 //点云最大帧数
  20. bool filter_flag = 0;
  21. bool terrain_flag = 0;
  22. extern rt_sem_t cluster_sem_t;
  23. static Point_Cloud_Frame radar_frame_buffer[MAX_FRAME_NUM];
  24. static int frame_write_index = 0;
  25. static FinalPointCloutStruct cluster;
  26. static FinalPointCloutStruct TerrainPoints;
  27. float q_now[4] = {1, 0, 0, 0}; //飞控传递的四元数
  28. float p_now[3] = {0}; //飞控坐标向量
  29. uint8_t other[4] = {0};
  30. int16_t euler[3] = {0};
  31. static RegionResult ObstacleDistance = {0};
  32. float min[2] = {0};
  33. uint8_t can_obstacle[8] = {0};
  34. uint8_t terrain_predict[50] = {0};
  35. extern struct rt_mutex queue_lock;
  36. extern uint8_t temp_buf[8192];
  37. extern uint8_t temp_len;
  38. typedef struct {
  39. uint32_t valid;
  40. float points_z[MAX_Z_AXIS_POINTS];
  41. uint32_t TerrainFlag;
  42. float TerrainHeight;
  43. }TerrianBinStat;
  44. TerrianBinStat terrain_bins[25] = {0};
  45. /*KalmanFilter Parameters*/
  46. uint32_t hitcnt = 0;
  47. float cy_last = 0;
  48. float cy_kfy = 0;
  49. bool doReset = true;
  50. uint32_t misscnt = 0;
  51. uint32_t KFActive = 0;
  52. //typedef struct {
  53. // float z[50];
  54. // uint32_t valid;
  55. // float z_axis;
  56. // uint32_t HeightFlag;
  57. //}ObstacleHeight;
  58. //ObstacleHeight ObstacleZ={0};
  59. extern CanardInstance canard;
  60. struct uavcan_equipment_range_sensor_Measurement radarMsg = {0};
  61. struct uavcan_protocol_NodeStatus NodeStatusMsg = {0};
  62. /**
  63. * @Name ClusterTask
  64. * @brief
  65. * @param parameter: [输入/出]
  66. * @retval
  67. * @author zhutianyu
  68. * @Data 2025-10-11
  69. **/
  70. void ClusterTask( void *parameter )
  71. {
  72. while ( 1 )
  73. {
  74. rt_sem_take( cluster_sem_t, RT_WAITING_FOREVER );
  75. // rt_tick_t start = rt_tick_get();
  76. PointCloudFilter();
  77. PointCloudConvert();
  78. DetectObstacle_ByDynamicY();
  79. // if(confInfo.DeviceType == REAR_OBSTACLE_RADAR || confInfo.DeviceType == FRONT_OBSTACLE_RADAR)
  80. // {
  81. // TerrainPointsSegmentation();
  82. // TerrianPointsFilter();
  83. // TerrainPredict();
  84. // }
  85. //
  86. // int16_t tmp_x = 0, tmp_y = 0, tmp_z = 0;
  87. static float obstacleDistance = 10.0f;
  88. obstacleDistance += 1.0f;
  89. if(obstacleDistance >= 35 )
  90. obstacleDistance = 10;
  91. // if (ObstacleZ.HeightFlag == 1)
  92. // {
  93. // tmp_z = ( ( int16_t )( ObstacleZ.z_axis * 100 ) );
  94. // ObstacleZ.HeightFlag = 0;
  95. // ObstacleZ.z_axis = 0;
  96. // }
  97. if( DroneCAN_IsNodeIDAllocated() )
  98. {
  99. radarMsg.sensor_type = UAVCAN_EQUIPMENT_RANGE_SENSOR_MEASUREMENT_SENSOR_TYPE_RADAR;
  100. radarMsg.reading_type = UAVCAN_EQUIPMENT_RANGE_SENSOR_MEASUREMENT_READING_TYPE_VALID_RANGE;
  101. radarMsg.range = obstacleDistance;
  102. radarMsg.sensor_id = FRONT_OBSTACLE_RADAR;
  103. DroneCAN_SendRangeSensorMeasurement(&radarMsg);
  104. }
  105. }
  106. }
  107. void NodeStatusTask( void *parameter )
  108. {
  109. ( void )parameter;
  110. while ( 1 )
  111. {
  112. if ( DroneCAN_IsNodeIDAllocated() )
  113. {
  114. NodeStatusMsg.uptime_sec = rt_tick_get() / RT_TICK_PER_SECOND;
  115. NodeStatusMsg.health = UAVCAN_PROTOCOL_NODESTATUS_HEALTH_OK;
  116. NodeStatusMsg.mode = UAVCAN_PROTOCOL_NODESTATUS_MODE_OPERATIONAL;
  117. // 可以放你的雷达状态码,例如 bit0=雷达在线, bit1=测距有效, bit2=故障
  118. NodeStatusMsg.vendor_specific_status_code = UAVCAN_EQUIPMENT_RANGE_SENSOR_MEASUREMENT_READING_TYPE_VALID_RANGE;
  119. DroneCAN_SendNodeStatus( &NodeStatusMsg );
  120. }
  121. rt_thread_mdelay( UAVCAN_PROTOCOL_NODESTATUS_MAX_BROADCASTING_PERIOD_MS );
  122. }
  123. }
  124. typedef struct usart_can
  125. {
  126. uint8_t head[8];
  127. uint32_t length;
  128. uint32_t rt_pointds; // 类型
  129. uint32_t FrameIdxy; // 帧索引
  130. uint32_t Tick; // 时间计数器
  131. uint32_t NumPointUsed; // 有效点数统计
  132. uint8_t data[0];
  133. } usart_can_data;
  134. struct Can2PMU_Data RadarRawData = {0};
  135. static uint32_t a1 = 0, a = 0, power;
  136. static uint32_t numl1 = 0, numl2 = 0, numl3 = 0, numl4 = 0;
  137. static float range = 0, azi = 0, ele = 0;
  138. //static uint32_t positive_num = 0;
  139. //static uint32_t negative_num = 0;
  140. //static float fmu_yaw, fmu_pitch, fmu_roll;
  141. /**
  142. * @brief 接收射频单元的原始点云数据并进行转换
  143. *
  144. */
  145. void PointCloudFilter( void )
  146. {
  147. usart_can_data *point_data = ( usart_can_data * )temp_buf;
  148. uint8_t *usart_data_p = point_data->data;
  149. static Point_Cloud_Frame radar_frame;
  150. memset( &radar_frame, 0, sizeof( radar_frame ) );
  151. radar_frame.ValidFlag = 1;
  152. //补偿角度转换
  153. float compensate_angle = 0;
  154. if ( confInfo.CompensateAngle <= 150 && confInfo.CompensateAngle >= -150 )
  155. {
  156. compensate_angle = ( float )confInfo.CompensateAngle / 10.0f * M_PI_ / 180.0f;
  157. }
  158. //点云转换
  159. for ( int i = 0; i < point_data -> NumPointUsed; i++ )
  160. {
  161. azi = usart_data_p[i * 8 + 2] * 0.5f - 60.0f;
  162. if ( azi < -45.0f || azi > 45.0f ) // 滤除偏航角+-45之外的点
  163. continue;
  164. azi = azi * M_PI_ / 180.0f + compensate_angle; //角度补偿
  165. range = usart_data_p[i * 8 + 0];
  166. numl1 = ( usart_data_p[i * 8 + 4] );
  167. numl2 = ( usart_data_p[i * 8 + 5] << 8 );
  168. numl3 = ( usart_data_p[i * 8 + 6] << 16 );
  169. numl4 = ( usart_data_p[i * 8 + 7] << 24 );
  170. power = numl1 + numl2 + numl3 + numl4;
  171. if ( PowerFilter( range, power ) == 0 )
  172. continue;
  173. ele = usart_data_p[i * 8 + 3] - 90.0f;
  174. ele = -( ele * M_PI_ / 180.0f ); // 电目俯仰角标定错误,需补偿
  175. range = range * Rng_res;
  176. radar_point *pt = &radar_frame.vaild_point_arr[radar_frame.vaild_point_num++];
  177. pt->z = range * cosf( ele ) * sinf( azi ); // 电目传输错误,X值需取反
  178. if ( confInfo.DeviceType == REAR_OBSTACLE_RADAR )
  179. {
  180. pt->y = -range * cosf( ele ) * cosf( azi );
  181. pt->x = -range * sinf( ele );
  182. }
  183. else if ( confInfo.DeviceType == FRONT_OBSTACLE_RADAR )
  184. {
  185. pt->y = range * cosf( ele ) * cosf( azi );
  186. pt->x = range * sinf( ele );
  187. }
  188. else if ( confInfo.DeviceType == LEFT_OBSTACLE_RADAR )
  189. {
  190. pt->x = -range * cosf( ele ) * cosf( azi );
  191. pt->y = range * sinf( ele );
  192. }
  193. else if ( confInfo.DeviceType == RIGHT_OBSTACLE_RADAR )
  194. {
  195. pt->x = range * cosf( ele ) * cosf( azi );
  196. pt->y = -range * sinf( ele );
  197. }
  198. pt->pow = power;
  199. if ( radar_frame.vaild_point_num >= 99 )
  200. {
  201. log_info( "point_cloud_filter full\n" );
  202. break;
  203. }
  204. }
  205. if ( radar_frame.vaild_point_num > 0 )
  206. {
  207. //获取当前姿态四元数和相对起飞点向量(ENU)
  208. rt_enter_critical();
  209. // fmu_roll = (float) euler[0] * (M_PI_ / 180.0f);
  210. // fmu_pitch = (float) euler[1] * (M_PI_ / 180.0f);
  211. // fmu_yaw = (float) euler[2] * (M_PI_ / 180.0f);
  212. // Quaternion_Enu_ByEuler(fmu_yaw, fmu_pitch, fmu_roll, q_now);
  213. memcpy( radar_frame.q, q_now, 16 );
  214. memcpy( radar_frame.p, p_now, 12 );
  215. rt_exit_critical();
  216. euler_angle_t euler_temp = {0};
  217. float q_new[4] = {0};
  218. memcpy ( q_new, radar_frame.q, 16 );
  219. Euler_ByQuaternionEnu( q_new, &euler_temp );
  220. Quaternion_Enu_ByEuler( euler_temp.yaw, 0, 0, q_new );
  221. float xyz[3] = {0};
  222. uint8_t new_count = 0;
  223. for ( int j = 0; j < radar_frame.vaild_point_num ; j++ )
  224. {
  225. //点云旋转
  226. quat_rotate_point_filter( q_new, radar_frame.q,
  227. radar_frame.vaild_point_arr[j].x,
  228. radar_frame.vaild_point_arr[j].y,
  229. radar_frame.vaild_point_arr[j].z,
  230. xyz );
  231. if ( confInfo.DeviceType == REAR_OBSTACLE_RADAR )
  232. {
  233. xyz[1] = -xyz[1];
  234. }
  235. if ( confInfo.DeviceType == LEFT_OBSTACLE_RADAR )
  236. {
  237. float tempLeft = xyz[0];
  238. xyz[0] = xyz[1];
  239. xyz[1] = -tempLeft;
  240. }
  241. if ( confInfo.DeviceType == RIGHT_OBSTACLE_RADAR )
  242. {
  243. float tempRight = xyz[0];
  244. xyz[0] = -xyz[1];
  245. xyz[1] = tempRight;
  246. }
  247. //去除前三米的倍频影响
  248. if ( xyz[2] > 0 || xyz[1] >3 )
  249. {
  250. radar_frame.vaild_point_arr[new_count++] = radar_frame.vaild_point_arr[j];
  251. }
  252. }
  253. radar_frame.vaild_point_num = new_count;
  254. //留存点云 做处理
  255. memcpy( &radar_frame_buffer[frame_write_index], &radar_frame, sizeof( Point_Cloud_Frame ) );
  256. frame_write_index = ( frame_write_index + 1 ) % MAX_FRAME_NUM;
  257. }
  258. }
  259. /**
  260. * @brief 原始点点云过滤,以距离和强度共同作为过滤条件
  261. * @param fRangeValue 点云距离信息
  262. * @param uPowerValue 点云能量信息
  263. *
  264. */
  265. bool PowerFilter( float fRangeValue, uint32_t uPowerValue )
  266. {
  267. bool bFlag = 0;
  268. if ( fRangeValue < 10 && uPowerValue > 1200000 )
  269. bFlag = 1;
  270. else if ( fRangeValue >= 10 && fRangeValue < 20 && uPowerValue > 800000 )
  271. bFlag = 1;
  272. else if ( fRangeValue >= 20 && fRangeValue < 30 && uPowerValue > 500000 )
  273. bFlag = 1;
  274. else if ( fRangeValue >= 30 && fRangeValue < 40 && uPowerValue > 400000 )
  275. bFlag = 1;
  276. else if ( fRangeValue >= 40 && fRangeValue < 50 && uPowerValue > 300000 )
  277. bFlag = 1;
  278. return bFlag ;
  279. }
  280. /**
  281. * @brief 点云坐标系旋转
  282. *
  283. */
  284. void PointCloudConvert( void )
  285. {
  286. cluster.vaild_len = 0 ;
  287. TerrainPoints.vaild_len = 0;
  288. uint8_t index = frame_write_index;
  289. euler_angle_t euler_temp = {0};
  290. //判断最新帧的位置
  291. index = ( index == 0 ) ? ( MAX_FRAME_NUM - 1 ) : ( index - 1 );
  292. float q_new[4] = {0};
  293. memcpy ( q_new, radar_frame_buffer[index].q, 16 );
  294. Euler_ByQuaternionEnu( q_new, &euler_temp );
  295. Quaternion_Enu_ByEuler( euler_temp.yaw, 0, 0, q_new );
  296. float point_new[3] = {0};
  297. memcpy ( point_new, radar_frame_buffer[index].p, 12 );
  298. float xyz[3] = {0};
  299. //盲区距离
  300. float blind_distance = ( float )( confInfo.BlindDistance / 100.0f );
  301. uint16_t terrain_hight = 0;
  302. memcpy(&terrain_hight, &other[0], 2);
  303. uint8_t drone_status_flag = other[3];
  304. //高度过滤系数
  305. uint16_t hight_filter_value = 5;
  306. if ( confInfo.HeightFilterValue <= 10 )
  307. {
  308. // 10 为最高,0为最低 这里做取反,方便过滤计算
  309. hight_filter_value = 10 - confInfo.HeightFilterValue;
  310. }
  311. if ( terrain_hight > 0 )
  312. {
  313. if (terrain_hight <= 100 )
  314. {
  315. hight_filter_value = (hight_filter_value <= 1) ? hight_filter_value : 1;
  316. } else if ( terrain_hight <= 150 )
  317. {
  318. hight_filter_value = (hight_filter_value <= 2) ? hight_filter_value : 2;
  319. } else if ( terrain_hight <= 200 )
  320. {
  321. hight_filter_value = (hight_filter_value <= 3) ? hight_filter_value : 3;
  322. } else if ( terrain_hight <= 230 )
  323. {
  324. hight_filter_value = (hight_filter_value <= 4) ? hight_filter_value : 4;
  325. }
  326. }
  327. if (drone_status_flag == 0)
  328. {
  329. hight_filter_value = 0;
  330. }
  331. for ( int i = 0 ; i < MAX_FRAME_NUM ; i++ )
  332. {
  333. if ( radar_frame_buffer[i].ValidFlag == 0 )
  334. continue;
  335. for ( int j = 0; j < radar_frame_buffer[i].vaild_point_num ; j++ )
  336. {
  337. //点云旋转
  338. quat_rotate_point( q_new, radar_frame_buffer[i].q, point_new, radar_frame_buffer[i].p,
  339. radar_frame_buffer[i].vaild_point_arr[j].x,
  340. radar_frame_buffer[i].vaild_point_arr[j].y,
  341. radar_frame_buffer[i].vaild_point_arr[j].z,
  342. xyz );
  343. if ( confInfo.DeviceType == REAR_OBSTACLE_RADAR )
  344. {
  345. xyz[1] = -xyz[1];
  346. }
  347. if ( confInfo.DeviceType == LEFT_OBSTACLE_RADAR )
  348. {
  349. float tempLeft = xyz[0];
  350. xyz[0] = xyz[1];
  351. xyz[1] = -tempLeft;
  352. }
  353. if ( confInfo.DeviceType == RIGHT_OBSTACLE_RADAR )
  354. {
  355. float tempRight = xyz[0];
  356. xyz[0] = -xyz[1];
  357. xyz[1] = tempRight;
  358. }
  359. //根据Y值匹配Z轴过滤值
  360. filter_flag = 1;
  361. terrain_flag = 1;
  362. if ( xyz[1] <= blind_distance || xyz[1] >= 35.0f )
  363. {
  364. filter_flag = 0;
  365. terrain_flag = 0;
  366. }
  367. else if ( xyz[0] >= 5.0f || xyz[0] <= -5.0f )
  368. {
  369. filter_flag = 0;
  370. terrain_flag = 0;
  371. }
  372. else if ( xyz[1] < 5 )
  373. {
  374. if ( xyz[2] <= -0.1f * hight_filter_value )
  375. filter_flag = 0;
  376. }
  377. else if ( xyz[1] >= 5.0f && xyz[1] < 10.0f )
  378. {
  379. if ( xyz[2] <= -0.12f * hight_filter_value )
  380. filter_flag = 0;
  381. }
  382. else if ( xyz[1] >= 10 )
  383. {
  384. if ( xyz[2] <= -0.1f * hight_filter_value )
  385. filter_flag = 0;
  386. }
  387. if ( filter_flag )
  388. {
  389. if (cluster.vaild_len < 1499 )
  390. {
  391. cluster.all_point[cluster.vaild_len].x = xyz[0];
  392. cluster.all_point[cluster.vaild_len].y = xyz[1];
  393. cluster.all_point[cluster.vaild_len].z = xyz[2];
  394. cluster.all_point[cluster.vaild_len].pow = radar_frame_buffer[i].vaild_point_arr[j].pow;
  395. cluster.vaild_len++;
  396. } else {
  397. log_info( "point_cloud_convert full\n" );
  398. break;
  399. }
  400. }
  401. if( terrain_flag && TerrainPoints.vaild_len < 1499)
  402. {
  403. TerrainPoints.all_point[TerrainPoints.vaild_len].x = xyz[0];
  404. TerrainPoints.all_point[TerrainPoints.vaild_len].y = xyz[1];
  405. TerrainPoints.all_point[TerrainPoints.vaild_len].z = xyz[2];
  406. TerrainPoints.all_point[TerrainPoints.vaild_len].pow = radar_frame_buffer[i].vaild_point_arr[j].pow;
  407. TerrainPoints.vaild_len++;
  408. if (TerrainPoints.vaild_len >= 1499)
  409. {
  410. log_info( "TerrainPoints is full\n" );
  411. break;
  412. }
  413. }
  414. }
  415. }
  416. }
  417. /**
  418. * @Name quat_rotate_point_filter
  419. * @brief
  420. * @param q_new[4]: [输入/出]
  421. * @retval
  422. * @author zhutianyu
  423. * @Data 2025-10-11
  424. **/
  425. void quat_rotate_point_filter( float q_new[4], float q_old[4], float x, float y, float z, float * xyz )
  426. {
  427. float point_src[3] = {x, y, z};
  428. float point_dst[3] = {0};
  429. float temp[3] = {0};
  430. // 旋转公式:q * p * q_inv
  431. Quaternion_Conj( q_old, point_src, temp );
  432. Quaternion_ConjInv( q_new, temp, point_dst );
  433. xyz[0] = point_dst[0];
  434. xyz[1] = point_dst[1];
  435. xyz[2] = point_dst[2];
  436. }
  437. void TerrainPointsSegmentation (void)
  438. {
  439. for(uint8_t j=0; j < 25 ; j++)
  440. {
  441. terrain_bins[j].valid = 0;
  442. terrain_bins[j].TerrainHeight = 0;
  443. terrain_bins[j].TerrainFlag = 0;
  444. }
  445. for(int i=0; i < TerrainPoints.vaild_len; i++)
  446. {
  447. if (TerrainPoints.all_point[i].y <= 25)
  448. {
  449. for(uint8_t j=0; j < 25 ; j++)
  450. {
  451. if(TerrainPoints.all_point[i].y >= j && TerrainPoints.all_point[i].y < (j+1))
  452. {
  453. if(terrain_bins[j].valid < MAX_Z_AXIS_POINTS - 1)
  454. terrain_bins[j].points_z[terrain_bins[j].valid++] = TerrainPoints.all_point[i].z;
  455. }
  456. }
  457. }
  458. }
  459. }
  460. static int Z_ValueCompare(const void * a, const void *b)
  461. {
  462. float a_value = *(const float *) a;
  463. float b_value = *(const float *) b;
  464. return (a_value > b_value) - (a_value < b_value);
  465. }
  466. static float prctile( float * data, uint32_t vaild_len, float precentile)
  467. {
  468. if ( vaild_len <= 0)
  469. return 0;
  470. qsort(data, vaild_len, sizeof(float), Z_ValueCompare);
  471. if (precentile <= 0)
  472. {
  473. float value = data[0];
  474. return value;
  475. }
  476. if (precentile >= 100)
  477. {
  478. float value = data[vaild_len - 1];
  479. return value;
  480. }
  481. float pos = (precentile / 100.0f) * (vaild_len - 1);
  482. int idx = (int)pos;
  483. float frac = pos - idx;
  484. float result = 0;
  485. if (idx >= vaild_len - 1)
  486. {
  487. result = data[vaild_len - 1];
  488. } else {
  489. result = data[idx] + frac * (data[idx+1] - data[idx]);
  490. }
  491. return result;
  492. }
  493. #define MIN_Points 10
  494. void TerrianPointsFilter (void )
  495. {
  496. float value_25prctile = 0;
  497. float value_75prctile = 0;
  498. float IQR = 0;
  499. float lowerFence = 0;
  500. float upperFence = 0;
  501. uint32_t valid_temp = 0;
  502. // uint32_t ObstacleFlag = 0;
  503. // ObstacleZ.valid = 0;
  504. // uint16_t hight_filter_value = 5;
  505. // if ( ObstacleDistance.valid == 1)
  506. // {
  507. // ObstacleDistance.valid = 0;
  508. // ObstacleFlag = (uint32_t)ObstacleDistance.y;
  509. // uint16_t terrain_hight = 0;
  510. // memcpy(&terrain_hight, &other[0], 2);
  511. // uint8_t drone_status_flag = other[3];
  512. // //高度过滤系数
  513. // if ( confInfo.HeightFilterValue <= 10 )
  514. // {
  515. // // 10 为最高,0为最低 这里做取反,方便过滤计算
  516. // hight_filter_value = 10 - confInfo.HeightFilterValue;
  517. // }
  518. // if (terrain_hight <= 100 )
  519. // {
  520. // hight_filter_value = (hight_filter_value <= 1) ? hight_filter_value : 1;
  521. // } else if ( terrain_hight <= 150 )
  522. // {
  523. // hight_filter_value = (hight_filter_value <= 2) ? hight_filter_value : 2;
  524. // } else if ( terrain_hight <= 200 )
  525. // {
  526. // hight_filter_value = (hight_filter_value <= 3) ? hight_filter_value : 3;
  527. // } else if ( terrain_hight <= 230 )
  528. // {
  529. // hight_filter_value = (hight_filter_value <= 4) ? hight_filter_value : 4;
  530. // }
  531. // if (drone_status_flag == 0)
  532. // {
  533. // hight_filter_value = 0;
  534. // }
  535. // }
  536. for(uint32_t i = 0; i < 25; i++)
  537. {
  538. if(terrain_bins[i].valid >= MIN_Points)
  539. {
  540. value_25prctile = prctile(terrain_bins[i].points_z, terrain_bins[i].valid, 25);
  541. value_75prctile = prctile(terrain_bins[i].points_z, terrain_bins[i].valid, 75);
  542. IQR = value_75prctile - value_25prctile;
  543. lowerFence = value_25prctile - 1.5f * IQR;
  544. upperFence = value_75prctile + 1.5f * IQR;
  545. for(int j =0; j < terrain_bins[i].valid; j++)
  546. {
  547. if(terrain_bins[i].points_z[j] >= lowerFence && terrain_bins[i].points_z[j] <= upperFence)
  548. terrain_bins[i].points_z[valid_temp++] = terrain_bins[i].points_z[j];
  549. }
  550. terrain_bins[i].valid = valid_temp;
  551. int index_40prc = ( int ) ceilf(0.5f * valid_temp);
  552. int index_80prc = ( int ) floorf(0.9f * valid_temp);
  553. // /*计算障碍物z轴高度*/
  554. // if (i == ObstacleFlag && ObstacleFlag != 0)
  555. // {
  556. // for (uint32_t k = 0; k < terrain_bins[i].valid; k++)
  557. // {
  558. // filter_flag = 1;
  559. // if ( i < 5 )
  560. // {
  561. // if ( terrain_bins[i].points_z[k] <= -0.1f * hight_filter_value )
  562. // filter_flag = 0;
  563. // }
  564. // else if ( i >= 5.0f && i < 10.0f )
  565. // {
  566. // if ( terrain_bins[i].points_z[k] <= -0.12f * hight_filter_value )
  567. // filter_flag = 0;
  568. // }
  569. // else if ( i >= 10 )
  570. // {
  571. // if ( terrain_bins[i].points_z[k] <= -0.1f * hight_filter_value )
  572. // filter_flag = 0;
  573. // }
  574. // if(filter_flag == 1)
  575. // {
  576. // ObstacleZ.z[ObstacleZ.valid++] = terrain_bins[i].points_z[k];
  577. // if (ObstacleZ.valid >= 49 )
  578. // break;
  579. // }
  580. // }
  581. // float height_25prctile = prctile(ObstacleZ.z, ObstacleZ.valid, 25);
  582. // float height_75prctile = prctile(ObstacleZ.z, ObstacleZ.valid, 75);
  583. // float height_IQR = height_75prctile - height_25prctile;
  584. // float height_lowerFence = value_25prctile - 1.5f * IQR;
  585. // float height_upperFence = value_75prctile + 1.5f * IQR;
  586. // uint32_t height_valid_temp = 0;
  587. // for(int j =0; j < ObstacleZ.valid; j++)
  588. // {
  589. // if(ObstacleZ.z[j] >= height_lowerFence && ObstacleZ.z[j] <= height_upperFence)
  590. // ObstacleZ.z[height_valid_temp++] = ObstacleZ.z[j];
  591. // }
  592. // ObstacleZ.valid = height_valid_temp;
  593. // int height_index_80prc = ( int ) ceilf(0.8f * height_valid_temp);
  594. // int height_index_90prc = ( int ) floorf(0.9f * height_valid_temp);
  595. // for(int k = height_index_80prc; k <height_index_90prc; k++)
  596. // {
  597. // ObstacleZ.z_axis += ObstacleZ.z[k];
  598. // }
  599. // ObstacleZ.z_axis /= (height_index_90prc - height_index_80prc);
  600. // ObstacleZ.HeightFlag = 1;
  601. // }
  602. // /*障碍物z轴高度计算结束*/
  603. if (terrain_bins[i].valid > (MIN_Points / 2))
  604. {
  605. for(int k = index_40prc; k <index_80prc; k++)
  606. {
  607. terrain_bins[i].TerrainHeight += terrain_bins[i].points_z[k];
  608. }
  609. terrain_bins[i].TerrainHeight /= (index_80prc - index_40prc);
  610. terrain_bins[i].TerrainFlag = 1;
  611. }
  612. valid_temp = 0;
  613. }
  614. }
  615. }
  616. rt_tick_t Terrain_time_old = 0, Terrain_time_new = 0;
  617. void TerrainPredict ( void )
  618. {
  619. memset(terrain_predict, 0, 50);
  620. int16_t temp = 0;
  621. for(int i = 0 ; i < 25 ; i++)
  622. {
  623. if (terrain_bins[i].TerrainFlag == 1)
  624. {
  625. temp = ((int16_t)(terrain_bins[i].TerrainHeight * 100));
  626. } else {
  627. temp = 0;
  628. }
  629. if( i<3 )
  630. {
  631. temp = 0;
  632. }
  633. memcpy(&terrain_predict[2*i],&temp,2);
  634. }
  635. Terrain_time_new = rt_tick_get();
  636. uint16_t Can_Crc = Get_Crc16( terrain_predict, 50 );
  637. FlagUnion TerrainFlag = {0};
  638. uint8_t FrameNum = 10;
  639. uint8_t uFlag = 0;
  640. uint8_t send_buf[8] = {0};
  641. for (int i = 0; i< FrameNum; i++)
  642. {
  643. memset(send_buf, 0, 8);
  644. uFlag = calculate_flag( i+1, FrameNum, &TerrainFlag );
  645. if (i == 0)
  646. {
  647. send_buf[0] = 25;
  648. send_buf[1] = Terrain_time_new ;
  649. send_buf[2] = Terrain_time_new >> 8;
  650. send_buf[3] = Can_Crc;
  651. send_buf[4] = Can_Crc >> 8;
  652. send_buf[7] = uFlag;
  653. } else {
  654. if ( i != 9 )
  655. {
  656. send_buf[0] = 0xFE;
  657. memcpy( &send_buf[1], &terrain_predict[6*(i-1)], 6);
  658. send_buf[7] = uFlag;
  659. }
  660. else{
  661. send_buf[0] = 0xFE;
  662. memcpy( &send_buf[1], &terrain_predict[6*(i-1)], 2);
  663. send_buf[7] = uFlag;
  664. }
  665. }
  666. //发送Can数据
  667. MyCAN_Transmit( TerrainHeightCanID, 8, send_buf, 0 );
  668. }
  669. }
  670. #define MAX_RANGE_Y 50.0f // 最大检测距离
  671. #define MAX_BINS 35 // 最大可能bin数
  672. typedef struct
  673. {
  674. uint16_t count;
  675. float sum_pow;
  676. float sum_y;
  677. float sum_x;
  678. float sum_z;
  679. float avg_y;
  680. float avg_pow;
  681. float avg_x;
  682. float avg_z;
  683. uint8_t valid;
  684. } BinStat;
  685. void DetectObstacle_ByDynamicY( void )
  686. {
  687. BinStat bins[MAX_BINS] = {0};
  688. int bin_count = 0;
  689. float y_step = 0;
  690. ObstacleDistance.valid = 1;
  691. // 初始化动态bin边界
  692. float bin_edges[MAX_BINS + 1];
  693. float y = 0;
  694. while ( y < MAX_RANGE_Y && bin_count < MAX_BINS )
  695. {
  696. if ( y < 10.0f ) y_step = 1.0f;
  697. else if ( y < 16.0f ) y_step = 1.5f;
  698. else y_step = 2.0f;
  699. bin_edges[bin_count] = y;
  700. y += y_step;
  701. bin_count++;
  702. }
  703. for ( int i = 0; i < cluster.vaild_len; i++ )
  704. {
  705. //float x = cluster.all_point[i].x;
  706. float y = cluster.all_point[i].y;
  707. //float z = cluster.all_point[i].z;
  708. //float pow = cluster.all_point[i].pow;
  709. // 找到对应的Y区间bin
  710. int8_t idx = -1;
  711. for ( uint8_t b = 0; b < bin_count; b++ )
  712. {
  713. if ( y >= bin_edges[b] && y < bin_edges[b + 1] )
  714. {
  715. idx = b;
  716. break;
  717. }
  718. }
  719. if ( idx < 0 || idx >= MAX_BINS ) continue;
  720. bins[idx].count++;
  721. //bins[idx].sum_pow += pow;
  722. bins[idx].sum_y += y;
  723. }
  724. // 计算平均值并判断障碍条件
  725. int valid_bins[MAX_BINS];
  726. int valid_cnt = 0;
  727. for ( uint8_t i = 0; i < bin_count; i++ )
  728. {
  729. if ( bins[i].count == 0 ) continue;
  730. bins[i].avg_pow = bins[i].sum_pow / bins[i].count;
  731. bins[i].avg_y = bins[i].sum_y / bins[i].count;
  732. // 动态最小点数阈值
  733. uint8_t min_points = 0;
  734. if ( bins[i].avg_y <= 10.0f ) min_points = 8; //10
  735. else if ( bins[i].avg_y <= 20.0f ) min_points = 5; //7
  736. else min_points = 4; //5
  737. if ( bins[i].count >= min_points )
  738. {
  739. bins[i].valid = 1;
  740. valid_bins[valid_cnt++] = i;
  741. }
  742. }
  743. float DetectDist = confInfo.MaxDist / 100.0f;
  744. float y1 = 0;
  745. // 找出最近有效区间
  746. if ( valid_cnt != 0 )
  747. {
  748. int idx1 = valid_bins[0];
  749. //障碍距离
  750. y1 = bins[idx1].avg_y;
  751. }
  752. if ( y1 <= 30.0f ) //25
  753. {
  754. ObstacleDistance.y = y1;
  755. ObstacleDistance.valid = 1;
  756. }
  757. else
  758. {
  759. ObstacleDistance.y = 0;
  760. ObstacleDistance.valid = 0;
  761. }
  762. if (ObstacleDistance.y > 0 )
  763. {
  764. misscnt = 0;
  765. hitcnt += 1;
  766. if (hitcnt < 3)
  767. {
  768. cy_kfy = 0;
  769. doReset = true;
  770. KFActive = 0;
  771. cy_last = ObstacleDistance.y;
  772. }
  773. else
  774. {
  775. if (KFActive == 0)
  776. doReset = true;
  777. cy_kfy = KelmanFilter_1Dimension(ObstacleDistance.y, doReset);
  778. doReset = false;
  779. KFActive = 1;
  780. cy_last = cy_kfy;
  781. }
  782. }
  783. else
  784. {
  785. hitcnt = 0;
  786. if (KFActive == 1)
  787. {
  788. misscnt += 1;
  789. if(misscnt<=3)
  790. {
  791. cy_kfy = KelmanFilter_1Dimension(cy_last, doReset);
  792. cy_last = cy_kfy;
  793. doReset = false;
  794. }
  795. else
  796. {
  797. cy_kfy = 0;
  798. cy_last = 0;
  799. doReset = false;
  800. KFActive = 0;
  801. misscnt = 0;
  802. }
  803. }
  804. else
  805. {
  806. cy_kfy = ObstacleDistance.y;
  807. doReset = true;
  808. misscnt = 0;
  809. }
  810. }
  811. }
  812. void quat_rotate_point( float q_new[4], float q_old[4], float p_enu_new[3], float p_enu_old[3], float x, float y, float z, float * xyz )
  813. {
  814. float point_src[3] = {x, y, z};
  815. float point_dst[3] = {0};
  816. float temp[3] = {0};
  817. uint8_t i = 0;
  818. // 旋转公式:q * p * q_inv
  819. Quaternion_Conj( q_old, point_src, temp );
  820. //坐标向量计算,对历史点云做偏移
  821. for ( i = 0 ; i < 3 ; i++ )
  822. {
  823. temp[i] = temp[i] + p_enu_old[i] - p_enu_new[i];
  824. }
  825. Quaternion_ConjInv( q_new, temp, point_dst );
  826. xyz[0] = point_dst[0];
  827. xyz[1] = point_dst[1];
  828. xyz[2] = point_dst[2];
  829. }
  830. // 计算并设置FlagUnion的原始字节值
  831. uint8_t calculate_flag( int index, int pack, FlagUnion* _f )
  832. {
  833. _f->flags.seq = index ; // 帧序号(从1开始)
  834. _f->flags.sof = ( index == 1 ) ? 1 : 0; // 首帧SOF置1
  835. _f->flags.eof = ( index == pack ) ? 1 : 0; // 末帧EOF置1
  836. return _f->u8flag;
  837. }
  838. rt_tick_t can_old = 0, can_new = 0;
  839. uint8_t calculate_sequence( int pack, FlagUnion * _f){
  840. uint8_t sequence = 0;
  841. if ( _f ->flags.sof == 1)
  842. sequence = 1;
  843. return sequence;
  844. }
  845. /**
  846. * @brief can口输出数据用于飞控记录雷达原始点云数据、四元数及位置向量
  847. *
  848. */
  849. void parse_radar_response( const uint8_t *usart_data, uint32_t len )
  850. {
  851. usart_can_data *can_data = ( usart_can_data * )usart_data;
  852. memset( &RadarRawData, 0, sizeof( RadarRawData ) );
  853. uint8_t send_buff[8] = {0};
  854. RadarRawData.head[0] = can_data->NumPointUsed;
  855. uint8_t *radar_info_data = &( RadarRawData.data[0] );
  856. memset( send_buff, 0, 8 );
  857. uint8_t *usart_data_p = can_data->data;
  858. uint16_t num = 0;
  859. uint16_t data_len = 0;
  860. for ( int i = 0; i < ( can_data->NumPointUsed ) * 5; i++ )
  861. {
  862. switch ( ( i + 1 ) % 5 )
  863. {
  864. case 1:
  865. // 获取d1idx
  866. radar_info_data[data_len++] = usart_data_p[num * 8];
  867. break;
  868. case 2:
  869. // 获取d2idx
  870. radar_info_data[data_len++] = usart_data_p[num * 8 + 1];
  871. break;
  872. case 3:
  873. // 获取d3idx
  874. radar_info_data[data_len++] = usart_data_p[num * 8 + 2];
  875. break;
  876. case 4:
  877. // 获取d4idx
  878. radar_info_data[data_len++] = usart_data_p[num * 8 + 3];
  879. break;
  880. case 0:
  881. // 获取power
  882. numl1 = ( usart_data_p[num * 8 + 4] );
  883. numl2 = ( usart_data_p[num * 8 + 5] << 8 );
  884. numl3 = ( usart_data_p[num * 8 + 6] << 16 );
  885. numl4 = ( usart_data_p[num * 8 + 7] << 24 );
  886. a = numl1 + numl2 + numl3 + numl4;
  887. a1 = a / 10000;
  888. if ( a1 >= 255 ) a1 = 255;
  889. radar_info_data[data_len++] = a1;
  890. num++;
  891. break;
  892. default:
  893. break;
  894. }
  895. }
  896. can_new = rt_tick_get();
  897. rt_tick_t can_time = can_new - can_old;
  898. can_old = can_new;
  899. uint16_t Can_Crc = Get_Crc16( radar_info_data, data_len );
  900. uint8_t FrameNum = ( data_len % 7 ) == 0 ? ( data_len / 7 ) + 1 : ( data_len / 7 ) + 1 + 1;
  901. FlagUnion Can_Flag = {0};
  902. RadarRawData.head[1] = can_time;
  903. RadarRawData.head[2] = can_time >> 8;
  904. RadarRawData.head[3] = Can_Crc;
  905. RadarRawData.head[4] = Can_Crc >> 8;
  906. uint8_t uFlag = 0;
  907. uint16_t offset = 0, remain = 0;
  908. for ( int i = 1 ; i <= FrameNum ; i++ )
  909. {
  910. memset( send_buff, 0, 8 );
  911. uFlag = calculate_flag( i, FrameNum, &Can_Flag );
  912. if ( i == 1 ) // 帧头
  913. memcpy( &send_buff[0], &RadarRawData.head[0], 7 );
  914. else
  915. {
  916. offset = ( i - 2 ) * 7;
  917. remain = data_len - offset;
  918. if ( remain >= 7 ) remain = 7;
  919. memcpy( send_buff, &RadarRawData.data[offset], remain );
  920. }
  921. send_buff[7] = uFlag;
  922. //发送Can数据
  923. MyCAN_Transmit( RawPointCloudCanID, 8, send_buff, 0 );
  924. }
  925. }