payload.c 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338
  1. #include "payload.h"
  2. #include "control_rate.h"
  3. #include "dcm.h"
  4. #include "helpler_funtions.h"
  5. #include "quaternion.h"
  6. #include "soft_imu.h"
  7. /**
  8. * @brief 载荷控制指令
  9. *
  10. * @param ctl_ops_id 控制 id
  11. * @param arg 指令参数
  12. * @param arg_len 指令参数字节数
  13. * @param payload 载荷对象
  14. */
  15. void payload_ctl_received(uint8_t ctl_ops_id, const void *arg, uint32_t arg_len,
  16. struct payload_diaocang *payload)
  17. {
  18. switch (ctl_ops_id)
  19. {
  20. case PAYLOAD_DIAOCANG_OPS_BACK_MID:
  21. if (payload->_ops._return_to_mid)
  22. {
  23. payload->_ops._return_to_mid(payload->_ops._send_data);
  24. }
  25. break;
  26. case PAYLOAD_DIAOCANG_OPS_SET_PITCH:
  27. if (payload->_ops._set_pitch)
  28. {
  29. const int16_t *param = (const int16_t *)arg;
  30. payload->_ops._set_pitch(param[0] * 0.1f, payload->_ops._send_data);
  31. }
  32. break;
  33. case PAYLOAD_DIAOCANG_OPS_SET_YAW:
  34. if (payload->_ops._set_yaw)
  35. {
  36. const int16_t *param = (const int16_t *)arg;
  37. payload->_ops._set_yaw(param[0] * 0.1f, payload->_ops._send_data);
  38. }
  39. break;
  40. case PAYLOAD_DIAOCANG_OPS_LASER_MEASURE:
  41. if (payload->_ops._laser_dist)
  42. {
  43. payload->_ops._laser_dist(payload->_ops._send_data);
  44. }
  45. break;
  46. case PAYLOAD_DIAOCANG_OPS_TAKE_PHOTO:
  47. if (payload->_ops._take_photo)
  48. {
  49. payload->_ops._take_photo(payload->_ops._send_data);
  50. }
  51. break;
  52. case PAYLOAD_DIAOCANG_OPS_TAKE_VEDIO:
  53. if (payload->_ops._take_vedio)
  54. {
  55. const uint16_t *param = (const uint16_t *)arg;
  56. payload->_ops._take_vedio(param[0], payload->_ops._send_data);
  57. }
  58. break;
  59. case PAYLOAD_DIAOCANG_OPS_MOVE:
  60. if (payload->_ops._move)
  61. {
  62. const uint16_t *param = (const uint16_t *)arg;
  63. payload->_ops._move(param[0], param[1] * 0.001f,
  64. payload->_ops._send_data);
  65. }
  66. break;
  67. case PAYLOAD_DIAOCANG_OPS_TOUCH_MOVE:
  68. if (payload->_ops._touch_move)
  69. {
  70. const uint16_t *param = (const uint16_t *)arg;
  71. payload->_ops._touch_move(param[0] * 0.001f, param[1] * 0.001f,
  72. payload->_ops._send_data);
  73. }
  74. break;
  75. case PAYLOAD_DIAOCANG_OPS_ZOOM:
  76. if (payload->_ops._zoom)
  77. {
  78. const uint16_t *param = (const uint16_t *)arg;
  79. payload->_ops._zoom(param[0], param[1] * 0.001f,
  80. payload->_ops._send_data);
  81. }
  82. break;
  83. case PAYLOAD_DIAOCANG_OPS_TAR_TRACE:
  84. if (payload->_ops._trace)
  85. {
  86. const uint16_t *param = (const uint16_t *)arg;
  87. payload->_ops._trace(param[5], param[0] * 0.001f, param[1] * 0.001f,
  88. param[2] * 0.001f, param[3] * 0.001f,
  89. payload->_ops._send_data);
  90. }
  91. break;
  92. case PAYLOAD_DIAOCANG_OPS_FOCUS:
  93. if (payload->_ops._focus)
  94. {
  95. const uint32_t *param = (const uint32_t *)arg;
  96. payload->_ops._focus(param[0], param[1], param[2],
  97. payload->_ops._send_data);
  98. }
  99. break;
  100. case PAYLOAD_DIAOCANG_OPS_OSD_SET:
  101. break;
  102. case PAYLOAD_DIAOCANG_OPS_SENSOR_SWITCH:
  103. if (payload->_ops._sensor_switch)
  104. {
  105. const uint32_t *param = (const uint32_t *)arg;
  106. payload->_ops._sensor_switch(payload->_ops._send_data, param[0]);
  107. }
  108. break;
  109. case PAYLOAD_DIAOCANG_OPS_FOLLOW:
  110. if (payload->_ops._follow_mode)
  111. {
  112. payload->_ops._follow_mode(payload->_ops._send_data);
  113. }
  114. break;
  115. case PAYLOAD_DIAOCANG_OPS_LOOK_DOWN:
  116. if (payload->_ops._look_downward)
  117. {
  118. payload->_ops._look_downward(payload->_ops._send_data);
  119. }
  120. break;
  121. case PAYLOAD_DIAOCANG_OPS_LOCK:
  122. if (payload->_ops._lock_mode)
  123. {
  124. payload->_ops._lock_mode(payload->_ops._send_data);
  125. }
  126. break;
  127. case PAYLOAD_DIAOCANG_OPS_TTRANS:
  128. if (payload->_ops._send_data)
  129. {
  130. payload->_ops._send_data(arg, arg_len);
  131. }
  132. break;
  133. default:
  134. break;
  135. }
  136. }
  137. /**
  138. * @brief 载荷发送轮询
  139. *
  140. * @param tiem_us 当前本地时间 us
  141. * @param payload 载荷对象
  142. */
  143. void payload_tx_poll(uint32_t tiem_us, struct payload_diaocang *payload)
  144. {
  145. if (payload->_ops._tx_poll)
  146. {
  147. payload->_ops._tx_poll(tiem_us, &payload->_last_tx_time,
  148. payload->_ops._send_data);
  149. }
  150. }
  151. /**
  152. * @brief 载荷接收回调
  153. *
  154. * @param ch 接收到的字节数据
  155. * @param payload 载荷对象
  156. * @return int 暂无意义
  157. */
  158. int payload_rx_cbk(uint8_t ch, struct payload_diaocang *payload)
  159. {
  160. int ret = 0;
  161. if (payload->_ops._rx_cbk)
  162. {
  163. ret = payload->_ops._rx_cbk(ch, payload);
  164. }
  165. if (ret > 0)
  166. {
  167. payload->_link_lost_count = 0;
  168. payload->_link_status = COMP_NORMAL;
  169. }
  170. return ret;
  171. }
  172. /**
  173. * @brief 载荷链接状态轮询
  174. *
  175. * @param time_now_us
  176. * @param payload
  177. */
  178. void payload_check_linkstatu_poll(uint32_t time_now_us,
  179. struct payload_diaocang *payload)
  180. {
  181. const float dt = 0.2f;
  182. const float link_lost_time_period = 3.0f;
  183. if (time_now_us - payload->_link_check_time > dt * 1000000)
  184. {
  185. if (payload->_link_status == COMP_NORMAL)
  186. {
  187. payload->_link_check_time = time_now_us;
  188. payload->_link_lost_count++;
  189. if (payload->_link_lost_count * dt > link_lost_time_period)
  190. {
  191. payload->_link_lost_count = 0;
  192. payload->_link_status = COMP_LOST;
  193. }
  194. }
  195. }
  196. }
  197. /**
  198. * @brief 光电吊舱类载荷目标定位
  199. *
  200. * @param payload 载荷对象
  201. * @param gimbal_euler_frame 载荷角度类型 0-相对载具平台 1-相对导航水平平台
  202. */
  203. static int _gimbal_pod_payload_target_locate(struct payload_diaocang *payload,
  204. uint8_t gimbal_euler_frame)
  205. {
  206. if (payload->_link_status == COMP_NORMAL && payload->_status.trace_flag &&
  207. ins.insgps_ok == INSGPS)
  208. {
  209. // camera->ENU
  210. float qCN[4] = {1, 0, 0, 0};
  211. if (gimbal_euler_frame == 0)
  212. {
  213. // body->ENU
  214. float qbN[4];
  215. for (int i = 0; i < 4; ++i)
  216. {
  217. qbN[i] = ins.Q[i];
  218. }
  219. // camera->body
  220. float qCb[4] = {1, 0, 0, 0};
  221. float qtmp1[4], qtmp2[4], qtmp3[4], qtmp4[4];
  222. // gimbal frame sequence is yaw->roll->pitch, which is different from
  223. // body euler angle sequence
  224. Quaternion_ByEuler(deg_to_rad(-payload->_status.yaw), 0, 0, qtmp1);
  225. Quaternion_ByEuler(0, 0, deg_to_rad(payload->_status.roll), qtmp2);
  226. Quaternion_ByEuler(0, deg_to_rad(payload->_status.pitch), 0, qtmp3);
  227. Quaternion_Multiplication(qtmp1, qtmp2, qtmp4);
  228. Quaternion_Normalize(qtmp4);
  229. Quaternion_Multiplication(qtmp4, qtmp3, qCb);
  230. Quaternion_Normalize(qCb);
  231. // camera->ENU
  232. Quaternion_Multiplication(qbN, qCb, qCN);
  233. Quaternion_Normalize(qCN);
  234. }
  235. else if (gimbal_euler_frame == 1)
  236. {
  237. Quaternion_ByEuler(
  238. deg_to_rad(-payload->_status.yaw - pid_m_yaw.angle_c),
  239. deg_to_rad(payload->_status.pitch),
  240. deg_to_rad(payload->_status.roll), qCN);
  241. }
  242. // calculate camera y axis coordinate in NEU frame
  243. float v[3] = {0, 1, 0};
  244. Quaternion_Conj(qCN, v, payload->_status.y_axis);
  245. // 根据载荷光轴的向量和载荷的相对高度,计算载荷的光轴和地面交点向量在地面的投影
  246. float k1 = 0.0f;
  247. float payloadAlt = pid_m_alt.loc_c;
  248. if (fabsf(payload->_status.y_axis[2]) < 0.001f)
  249. {
  250. k1 = payloadAlt / 0.001f;
  251. }
  252. else
  253. {
  254. k1 = payloadAlt / fabsf(payload->_status.y_axis[2]);
  255. }
  256. payload->_diste_filter_buffer[payload->_filter_in_index] =
  257. payload->_status.y_axis[0] * k1;
  258. payload->_distn_filter_buffer[payload->_filter_in_index] =
  259. payload->_status.y_axis[1] * k1;
  260. payload->_filter_in_index++;
  261. if (payload->_filter_in_index >= PAYLOAD_SZHT_FILTER_BUFF_LEN)
  262. payload->_filter_in_index = 0;
  263. float dist_e = 0;
  264. float dist_n = 0;
  265. for (int i = 0; i < PAYLOAD_SZHT_FILTER_BUFF_LEN; ++i)
  266. {
  267. dist_e +=
  268. payload->_diste_filter_buffer[i] / PAYLOAD_SZHT_FILTER_BUFF_LEN;
  269. dist_n +=
  270. payload->_distn_filter_buffer[i] / PAYLOAD_SZHT_FILTER_BUFF_LEN;
  271. }
  272. payload->_status.tar_lon =
  273. pid_m_posx.loc_c + dist_e / ins.delta_lon_to_cm_ratio;
  274. payload->_status.tar_lat =
  275. pid_m_posy.loc_c + dist_n / ins.delta_lat_to_cm_ratio;
  276. payload->_status.tar_alt = 0;
  277. payload->_status.tar_lon_loc =
  278. pid_m_posx.loc_c +
  279. payload->_status.y_axis[0] * payload->_status.laser_dist_m * 100 / ins.delta_lon_to_cm_ratio;
  280. payload->_status.tar_lat_loc =
  281. pid_m_posy.loc_c +
  282. payload->_status.y_axis[1] * payload->_status.laser_dist_m * 100 / ins.delta_lat_to_cm_ratio;
  283. payload->_status.tar_alt_loc = 0;
  284. return 0;
  285. }
  286. return -1;
  287. }
  288. /**
  289. * @brief 载荷目标定位
  290. *
  291. * @param payload
  292. */
  293. void payload_targte_locate(struct payload_diaocang *payload, uint8_t gimbal_euler_frame)
  294. {
  295. if (payload->_type == PAYLOAD_TYPE_GIMBAL_POD)
  296. {
  297. _gimbal_pod_payload_target_locate(payload, gimbal_euler_frame);
  298. }
  299. }