pipe_apsr.c 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. #include "stdint.h"
  2. #include "board.h"
  3. #include "tdc_tof.h"
  4. #if 0
  5. float bilinear_quad_apsr(float WatSpdLvl, float WatTemp)
  6. {
  7. uint16_t row;
  8. uint16_t start, end, mid;
  9. float TmpFloat;
  10. float *CoePtr;
  11. start = 0;
  12. end = pTdcItf->row_num;
  13. while((start+1)<end){
  14. mid = (start + end)>>1;
  15. TmpFloat = pTdcItf->row_temp_ary[mid];
  16. if (TmpFloat<=WatTemp){
  17. start = mid;
  18. } else {
  19. end = mid;
  20. }
  21. }
  22. row = start;
  23. start = row*pTdcItf->col_num;
  24. end = start+pTdcItf->col_num;
  25. while((start+1)<end){
  26. mid = (start + end)>>1;
  27. TmpFloat = pTdcItf->quad_cell_ary[mid].SpdLvl;
  28. // for ascending array
  29. if (TmpFloat<=WatSpdLvl){
  30. start = mid;
  31. } else {
  32. end = mid;
  33. }
  34. }
  35. CoePtr = (float *)(pTdcItf->quad_cell_ary[start].Coe);
  36. TmpFloat = *CoePtr++;
  37. TmpFloat += (*CoePtr++)*WatSpdLvl;
  38. TmpFloat += (*CoePtr++)*WatTemp;
  39. TmpFloat += (*CoePtr)*WatSpdLvl*WatTemp;
  40. LOG("WatSpdLvl=%.6f, SpdLvl=%.6f, m0=%.6f, m1=%.6f, m2=%.6f, m3=%.6f\n",WatSpdLvl,pTdcItf->quad_cell_ary[mid].SpdLvl,pTdcItf->quad_cell_ary[start].Coe[0],pTdcItf->quad_cell_ary[start].Coe[1],pTdcItf->quad_cell_ary[start].Coe[2],pTdcItf->quad_cell_ary[start].Coe[3]);
  41. return(TmpFloat);
  42. }
  43. #endif
  44. #if 0
  45. float bilinear_quad_apsr(float WatSpdLvl, float WatTemp)
  46. {
  47. // 空指针安全判断
  48. if (pTdcItf == NULL) {
  49. LOG("[Error] pTdcItf is NULL\n");
  50. return 0.0f;
  51. }
  52. uint16_t start, end, mid;
  53. uint16_t row, row1;
  54. uint16_t col, col1;
  55. float t0, t1, s0, s1;
  56. float wt, ws;
  57. float F00, F01, F10, F11;
  58. float Res;
  59. //------------------------------------------------------------------------
  60. // 1. 二分查找:温度所在行(使用 pTdcItf->row_num)
  61. //------------------------------------------------------------------------
  62. start = 0;
  63. end = pTdcItf->row_num; // 这里替换成你的结构体成员
  64. while ((start + 1) < end) {
  65. mid = (start + end) >> 1;
  66. if (pTdcItf->row_temp_ary[mid] <= WatTemp)
  67. start = mid;
  68. else
  69. end = mid;
  70. }
  71. row = start;
  72. row1 = (row >= pTdcItf->row_num - 1) ? row : row + 1; // 边界保护
  73. //------------------------------------------------------------------------
  74. // 2. 二分查找:速度所在列
  75. //------------------------------------------------------------------------
  76. start = row * pTdcItf->col_num;
  77. end = start + pTdcItf->col_num;
  78. while ((start + 1) < end) {
  79. mid = (start + end) >> 1;
  80. if (pTdcItf->quad_cell_ary[mid].SpdLvl <= WatSpdLvl)
  81. start = mid;
  82. else
  83. end = mid;
  84. }
  85. col = start % pTdcItf->col_num;
  86. col1 = (col >= pTdcItf->col_num - 1) ? col : col + 1;
  87. //------------------------------------------------------------------------
  88. // 3. 计算权重(关键:解决来回跳、抖动)
  89. //------------------------------------------------------------------------
  90. t0 = pTdcItf->row_temp_ary[row];
  91. t1 = pTdcItf->row_temp_ary[row1];
  92. s0 = pTdcItf->quad_cell_ary[row * pTdcItf->col_num + col ].SpdLvl;
  93. s1 = pTdcItf->quad_cell_ary[row * pTdcItf->col_num + col1].SpdLvl;
  94. // 计算 0~1 之间的连续权重,彻底避免索引跳变
  95. wt = (t1 == t0) ? 0.0f : (WatTemp - t0) / (t1 - t0);
  96. ws = (s1 == s0) ? 0.0f : (WatSpdLvl - s0) / (s1 - s0);
  97. //------------------------------------------------------------------------
  98. // 4. 取出 4 个点的系数
  99. //------------------------------------------------------------------------
  100. const float *C00 = pTdcItf->quad_cell_ary[row * pTdcItf->col_num + col ].Coe;
  101. const float *C01 = pTdcItf->quad_cell_ary[row * pTdcItf->col_num + col1].Coe;
  102. const float *C10 = pTdcItf->quad_cell_ary[row1 * pTdcItf->col_num + col ].Coe;
  103. const float *C11 = pTdcItf->quad_cell_ary[row1 * pTdcItf->col_num + col1].Coe;
  104. //------------------------------------------------------------------------
  105. // 5. 4 个点分别计算结果
  106. //------------------------------------------------------------------------
  107. F00 = C00[0] + C00[1] * WatSpdLvl + C00[2] * WatTemp + C00[3] * WatSpdLvl * WatTemp;
  108. F01 = C01[0] + C01[1] * WatSpdLvl + C01[2] * WatTemp + C01[3] * WatSpdLvl * WatTemp;
  109. F10 = C10[0] + C10[1] * WatSpdLvl + C10[2] * WatTemp + C10[3] * WatSpdLvl * WatTemp;
  110. F11 = C11[0] + C11[1] * WatSpdLvl + C11[2] * WatTemp + C11[3] * WatSpdLvl * WatTemp;
  111. //------------------------------------------------------------------------
  112. // 6. 真正双线性插值(平滑输出,不跳变)
  113. //------------------------------------------------------------------------
  114. Res = (1.0f - ws) * (1.0f - wt) * F00
  115. + ( ws) * (1.0f - wt) * F01
  116. + (1.0f - ws) * ( wt) * F10
  117. + ( ws) * ( wt) * F11;
  118. //------------------------------------------------------------------------
  119. // 日志(修复了越界问题)
  120. //------------------------------------------------------------------------
  121. /*
  122. LOG("WatSpdLvl=%.6f, SpdLvl=%.6f, m0=%.6f, m1=%.6f, m2=%.6f, m3=%.6f\n",
  123. WatSpdLvl,
  124. pTdcItf->quad_cell_ary[start].SpdLvl,
  125. C00[0], C00[1], C00[2], C00[3]);
  126. LOG("F00=%.6f, F01=%.6f, F10=%.6f, F11=%.6f, ws=%.6f, wt=%.6f, Res=%.6f\n",
  127. F00,F01,F10,F11,ws,wt,Res);
  128. */
  129. return Res;
  130. }
  131. #endif
  132. // ===================== 配置常量 =====================
  133. #define TEMP_POINT_NUM 8 // 温度点数量
  134. #define FLOW_POINT_NUM 20 // 流速点数量
  135. #define TEMP_START_IDX 0 // 温度起始索引
  136. #define FLOW_START_IDX 8 // 流速起始索引
  137. // ===================== 双线性插值(带权重)最终函数 =====================
  138. float bilinear_quad_apsr(float WatSpdLvl, float WatTemp)
  139. {
  140. // 1. 边界限制
  141. if (WatTemp < 5.0f) WatTemp = 5.0f;
  142. if (WatTemp > 50.0f) WatTemp = 50.0f;
  143. if (WatSpdLvl < 0.0f) WatSpdLvl = 0.0f;
  144. uint16_t start, end, mid;
  145. uint16_t t0_idx, t1_idx; // 温度两个点
  146. uint16_t f0_idx, f1_idx; // 流速两个点
  147. float t0, t1; // 温度值
  148. float f0, f1; // 流速等级值
  149. float wt, ws; // 权重(0~1)
  150. float temp_comp0, temp_comp1;
  151. float flow_comp0, flow_comp1;
  152. float F00, F01, F10, F11;
  153. float result;
  154. //------------------------------------------------------------------------
  155. // 2. 二分查找温度区间
  156. //------------------------------------------------------------------------
  157. start = TEMP_START_IDX;
  158. end = TEMP_START_IDX + TEMP_POINT_NUM;
  159. while ((start + 1) < end) {
  160. mid = (start + end) >> 1;
  161. if (Quad_Cell_Ary[mid].value <= WatTemp)
  162. start = mid;
  163. else
  164. end = mid;
  165. }
  166. t0_idx = start;
  167. t1_idx = (t0_idx >= TEMP_POINT_NUM - 1) ? t0_idx : t0_idx + 1;
  168. //------------------------------------------------------------------------
  169. // 3. 二分查找流速区间
  170. //------------------------------------------------------------------------
  171. start = FLOW_START_IDX;
  172. end = FLOW_START_IDX + FLOW_POINT_NUM;
  173. while ((start + 1) < end) {
  174. mid = (start + end) >> 1;
  175. if (Quad_Cell_Ary[mid].value <= WatSpdLvl)
  176. start = mid;
  177. else
  178. end = mid;
  179. }
  180. f0_idx = start;
  181. f1_idx = (f0_idx >= FLOW_START_IDX + FLOW_POINT_NUM - 1) ? f0_idx : f0_idx + 1;
  182. //------------------------------------------------------------------------
  183. // 4. 读取两个温度、两个流速的点数值
  184. //------------------------------------------------------------------------
  185. t0 = Quad_Cell_Ary[t0_idx].value;
  186. t1 = Quad_Cell_Ary[t1_idx].value;
  187. f0 = Quad_Cell_Ary[f0_idx].value;
  188. f1 = Quad_Cell_Ary[f1_idx].value;
  189. //------------------------------------------------------------------------
  190. // 5. 计算权重(核心:平滑插值)
  191. //------------------------------------------------------------------------
  192. wt = (t1 == t0) ? 0.0f : (WatTemp - t0) / (t1 - t0);
  193. ws = (f1 == f0) ? 0.0f : (WatSpdLvl - f0) / (f1 - f0);
  194. //------------------------------------------------------------------------
  195. // 6. 计算温度补偿 & 流速补偿
  196. //------------------------------------------------------------------------
  197. // 温度补偿
  198. temp_comp0 = Quad_Cell_Ary[t0_idx].coe.m + Quad_Cell_Ary[t0_idx].coe.k;
  199. temp_comp1 = Quad_Cell_Ary[t1_idx].coe.m + Quad_Cell_Ary[t1_idx].coe.k;
  200. // 流速补偿:如果全是0 → 不补偿,直接=1.0f
  201. if (f0 == 0.0f && f1 == 0.0f) {
  202. flow_comp0 = 1.0f;
  203. flow_comp1 = 1.0f;
  204. } else {
  205. flow_comp0 = Quad_Cell_Ary[f0_idx].coe.m + Quad_Cell_Ary[f0_idx].coe.k;
  206. flow_comp1 = Quad_Cell_Ary[f1_idx].coe.m + Quad_Cell_Ary[f1_idx].coe.k;
  207. }
  208. //------------------------------------------------------------------------
  209. // 7. 四个顶点 = 温度补偿 * 流速补偿
  210. //------------------------------------------------------------------------
  211. F00 = temp_comp0 * flow_comp0;
  212. F01 = temp_comp0 * flow_comp1;
  213. F10 = temp_comp1 * flow_comp0;
  214. F11 = temp_comp1 * flow_comp1;
  215. //------------------------------------------------------------------------
  216. // 8. 双线性插值(带权重,平滑输出)
  217. //------------------------------------------------------------------------
  218. result = (1.0f - ws) * (1.0f - wt) * F00
  219. + ( ws) * (1.0f - wt) * F01
  220. + (1.0f - ws) * ( wt) * F10
  221. + ( ws) * ( wt) * F11;
  222. LOG("F00=%.6f,F01=%.6f,F10=%.6f,F11=%.6f,result=%.6f\r\n",F00,F01,F10,F11,result);
  223. return result;
  224. }