SIM_ADSB.cpp 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. /*
  2. This program is free software: you can redistribute it and/or modify
  3. it under the terms of the GNU General Public License as published by
  4. the Free Software Foundation, either version 3 of the License, or
  5. (at your option) any later version.
  6. This program is distributed in the hope that it will be useful,
  7. but WITHOUT ANY WARRANTY; without even the implied warranty of
  8. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  9. GNU General Public License for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with this program. If not, see <http://www.gnu.org/licenses/>.
  12. */
  13. /*
  14. ADSB simulator class for MAVLink ADSB peripheral
  15. */
  16. #include "SIM_ADSB.h"
  17. #include "SITL.h"
  18. #include <stdio.h>
  19. #include "SIM_Aircraft.h"
  20. #include <AP_HAL_SITL/SITL_State.h>
  21. namespace SITL {
  22. SITL *_sitl;
  23. ADSB::ADSB(const struct sitl_fdm &_fdm, const char *_home_str)
  24. {
  25. float yaw_degrees;
  26. HALSITL::SITL_State::parse_home(_home_str, home, yaw_degrees);
  27. }
  28. /*
  29. update a simulated vehicle
  30. */
  31. void ADSB_Vehicle::update(float delta_t)
  32. {
  33. if (!initialised) {
  34. initialised = true;
  35. ICAO_address = (uint32_t)(rand() % 10000);
  36. snprintf(callsign, sizeof(callsign), "SIM%u", ICAO_address);
  37. position.x = Aircraft::rand_normal(0, _sitl->adsb_radius_m);
  38. position.y = Aircraft::rand_normal(0, _sitl->adsb_radius_m);
  39. position.z = -fabsf(_sitl->adsb_altitude_m);
  40. double vel_min = 5, vel_max = 20;
  41. if (position.length() > 500) {
  42. vel_min *= 3;
  43. vel_max *= 3;
  44. } else if (position.length() > 10000) {
  45. vel_min *= 10;
  46. vel_max *= 10;
  47. }
  48. velocity_ef.x = Aircraft::rand_normal(vel_min, vel_max);
  49. velocity_ef.y = Aircraft::rand_normal(vel_min, vel_max);
  50. velocity_ef.z = Aircraft::rand_normal(0, 3);
  51. }
  52. position += velocity_ef * delta_t;
  53. if (position.z > 0) {
  54. // it has crashed! reset
  55. initialised = false;
  56. }
  57. }
  58. /*
  59. update the ADSB peripheral state
  60. */
  61. void ADSB::update(void)
  62. {
  63. if (_sitl == nullptr) {
  64. _sitl = AP::sitl();
  65. return;
  66. } else if (_sitl->adsb_plane_count <= 0) {
  67. return;
  68. } else if (_sitl->adsb_plane_count >= num_vehicles_MAX) {
  69. _sitl->adsb_plane_count.set_and_save(0);
  70. num_vehicles = 0;
  71. return;
  72. } else if (num_vehicles != _sitl->adsb_plane_count) {
  73. num_vehicles = _sitl->adsb_plane_count;
  74. for (uint8_t i=0; i<num_vehicles_MAX; i++) {
  75. vehicles[i].initialised = false;
  76. }
  77. }
  78. // calculate delta time in seconds
  79. uint32_t now_us = AP_HAL::micros();
  80. float delta_t = (now_us - last_update_us) * 1.0e-6f;
  81. last_update_us = now_us;
  82. for (uint8_t i=0; i<num_vehicles; i++) {
  83. vehicles[i].update(delta_t);
  84. }
  85. // see if we should do a report
  86. send_report();
  87. }
  88. /*
  89. send a report to the vehicle control code over MAVLink
  90. */
  91. void ADSB::send_report(void)
  92. {
  93. if (AP_HAL::millis() < 10000) {
  94. // simulated aircraft don't appear until 10s after startup. This avoids a windows
  95. // threading issue with non-blocking sockets and the initial wait on uartA
  96. return;
  97. }
  98. if (!mavlink.connected && mav_socket.connect(target_address, target_port)) {
  99. ::printf("ADSB connected to %s:%u\n", target_address, (unsigned)target_port);
  100. mavlink.connected = true;
  101. }
  102. if (!mavlink.connected) {
  103. return;
  104. }
  105. // check for incoming MAVLink messages
  106. uint8_t buf[100];
  107. ssize_t ret;
  108. while ((ret=mav_socket.recv(buf, sizeof(buf), 0)) > 0) {
  109. for (uint8_t i=0; i<ret; i++) {
  110. mavlink_message_t msg;
  111. mavlink_status_t status;
  112. if (mavlink_frame_char_buffer(&mavlink.rxmsg, &mavlink.status,
  113. buf[i],
  114. &msg, &status) == MAVLINK_FRAMING_OK) {
  115. switch (msg.msgid) {
  116. case MAVLINK_MSG_ID_HEARTBEAT: {
  117. if (!seen_heartbeat) {
  118. seen_heartbeat = true;
  119. vehicle_component_id = msg.compid;
  120. vehicle_system_id = msg.sysid;
  121. ::printf("ADSB using srcSystem %u\n", (unsigned)vehicle_system_id);
  122. }
  123. break;
  124. }
  125. }
  126. }
  127. }
  128. }
  129. if (!seen_heartbeat) {
  130. return;
  131. }
  132. uint32_t now = AP_HAL::millis();
  133. mavlink_message_t msg;
  134. uint16_t len;
  135. if (now - last_heartbeat_ms >= 1000) {
  136. mavlink_heartbeat_t heartbeat;
  137. heartbeat.type = MAV_TYPE_ADSB;
  138. heartbeat.autopilot = MAV_AUTOPILOT_ARDUPILOTMEGA;
  139. heartbeat.base_mode = 0;
  140. heartbeat.system_status = 0;
  141. heartbeat.mavlink_version = 0;
  142. heartbeat.custom_mode = 0;
  143. /*
  144. save and restore sequence number for chan0, as it is used by
  145. generated encode functions
  146. */
  147. mavlink_status_t *chan0_status = mavlink_get_channel_status(MAVLINK_COMM_0);
  148. uint8_t saved_seq = chan0_status->current_tx_seq;
  149. chan0_status->current_tx_seq = mavlink.seq;
  150. len = mavlink_msg_heartbeat_encode(vehicle_system_id,
  151. vehicle_component_id,
  152. &msg, &heartbeat);
  153. chan0_status->current_tx_seq = saved_seq;
  154. mav_socket.send(&msg.magic, len);
  155. last_heartbeat_ms = now;
  156. }
  157. /*
  158. send a ADSB_VEHICLE messages
  159. */
  160. uint32_t now_us = AP_HAL::micros();
  161. if (now_us - last_report_us >= reporting_period_ms*1000UL) {
  162. for (uint8_t i=0; i<num_vehicles; i++) {
  163. ADSB_Vehicle &vehicle = vehicles[i];
  164. Location loc = home;
  165. loc.offset(vehicle.position.x, vehicle.position.y);
  166. // re-init when exceeding radius range
  167. if (home.get_distance(loc) > _sitl->adsb_radius_m) {
  168. vehicle.initialised = false;
  169. }
  170. mavlink_adsb_vehicle_t adsb_vehicle {};
  171. last_report_us = now_us;
  172. adsb_vehicle.ICAO_address = vehicle.ICAO_address;
  173. adsb_vehicle.lat = loc.lat;
  174. adsb_vehicle.lon = loc.lng;
  175. adsb_vehicle.altitude_type = ADSB_ALTITUDE_TYPE_PRESSURE_QNH;
  176. adsb_vehicle.altitude = -vehicle.position.z * 1000;
  177. adsb_vehicle.heading = wrap_360_cd(100*degrees(atan2f(vehicle.velocity_ef.y, vehicle.velocity_ef.x)));
  178. adsb_vehicle.hor_velocity = norm(vehicle.velocity_ef.x, vehicle.velocity_ef.y) * 100;
  179. adsb_vehicle.ver_velocity = -vehicle.velocity_ef.z * 100;
  180. memcpy(adsb_vehicle.callsign, vehicle.callsign, sizeof(adsb_vehicle.callsign));
  181. adsb_vehicle.emitter_type = ADSB_EMITTER_TYPE_LARGE;
  182. adsb_vehicle.tslc = 1;
  183. adsb_vehicle.flags =
  184. ADSB_FLAGS_VALID_COORDS |
  185. ADSB_FLAGS_VALID_ALTITUDE |
  186. ADSB_FLAGS_VALID_HEADING |
  187. ADSB_FLAGS_VALID_VELOCITY |
  188. ADSB_FLAGS_VALID_CALLSIGN |
  189. ADSB_FLAGS_SIMULATED;
  190. adsb_vehicle.squawk = 0; // NOTE: ADSB_FLAGS_VALID_SQUAWK bit is not set
  191. mavlink_status_t *chan0_status = mavlink_get_channel_status(MAVLINK_COMM_0);
  192. uint8_t saved_seq = chan0_status->current_tx_seq;
  193. chan0_status->current_tx_seq = mavlink.seq;
  194. len = mavlink_msg_adsb_vehicle_encode(vehicle_system_id,
  195. MAV_COMP_ID_ADSB,
  196. &msg, &adsb_vehicle);
  197. chan0_status->current_tx_seq = saved_seq;
  198. uint8_t msgbuf[len];
  199. len = mavlink_msg_to_send_buffer(msgbuf, &msg);
  200. if (len > 0) {
  201. mav_socket.send(msgbuf, len);
  202. }
  203. }
  204. }
  205. // ADSB_transceiever is enabled, send the status report.
  206. if (_sitl->adsb_tx && now - last_tx_report_ms > 1000) {
  207. last_tx_report_ms = now;
  208. mavlink_status_t *chan0_status = mavlink_get_channel_status(MAVLINK_COMM_0);
  209. uint8_t saved_seq = chan0_status->current_tx_seq;
  210. uint8_t saved_flags = chan0_status->flags;
  211. chan0_status->flags &= ~MAVLINK_STATUS_FLAG_OUT_MAVLINK1;
  212. chan0_status->current_tx_seq = mavlink.seq;
  213. const mavlink_uavionix_adsb_transceiver_health_report_t health_report = {UAVIONIX_ADSB_RF_HEALTH_OK};
  214. len = mavlink_msg_uavionix_adsb_transceiver_health_report_encode(vehicle_system_id,
  215. MAV_COMP_ID_ADSB,
  216. &msg, &health_report);
  217. chan0_status->current_tx_seq = saved_seq;
  218. chan0_status->flags = saved_flags;
  219. uint8_t msgbuf[len];
  220. len = mavlink_msg_to_send_buffer(msgbuf, &msg);
  221. if (len > 0) {
  222. mav_socket.send(msgbuf, len);
  223. ::printf("ADSBsim send tx health packet\n");
  224. }
  225. }
  226. }
  227. } // namespace SITL