SIM_Vicon.cpp 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168
  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. simple vicon simulator class
  15. XKFR
  16. */
  17. #include "SIM_Vicon.h"
  18. #include <stdio.h>
  19. #include <unistd.h>
  20. #include <fcntl.h>
  21. using namespace SITL;
  22. #define USE_VISION_POSITION_ESTIMATE 1
  23. Vicon::Vicon()
  24. {
  25. int tmp[2];
  26. if (pipe(tmp) == -1) {
  27. AP_HAL::panic("pipe() failed");
  28. }
  29. fd_my_end = tmp[1];
  30. fd_their_end = tmp[0];
  31. // close file descriptors on exec:
  32. fcntl(fd_my_end, F_SETFD, FD_CLOEXEC);
  33. fcntl(fd_their_end, F_SETFD, FD_CLOEXEC);
  34. // make sure we don't screw the simulation up by blocking:
  35. fcntl(fd_my_end, F_SETFL, fcntl(fd_my_end, F_GETFL, 0) | O_NONBLOCK);
  36. fcntl(fd_their_end, F_SETFL, fcntl(fd_their_end, F_GETFL, 0) | O_NONBLOCK);
  37. if (!valid_channel(mavlink_ch)) {
  38. AP_HAL::panic("Invalid mavlink channel");
  39. }
  40. }
  41. void Vicon::maybe_send_heartbeat()
  42. {
  43. const uint32_t now = AP_HAL::millis();
  44. if (now - last_heartbeat_ms < 100) {
  45. // we only provide a heartbeat every so often
  46. return;
  47. }
  48. last_heartbeat_ms = now;
  49. mavlink_message_t msg;
  50. mavlink_msg_heartbeat_pack(system_id,
  51. component_id,
  52. &msg,
  53. MAV_TYPE_GCS,
  54. MAV_AUTOPILOT_INVALID,
  55. 0,
  56. 0,
  57. 0);
  58. }
  59. void Vicon::update_vicon_position_estimate(const Location &loc,
  60. const Vector3f &position,
  61. const Quaternion &attitude)
  62. {
  63. const uint64_t now_us = AP_HAL::micros64();
  64. if (time_offset_us == 0) {
  65. time_offset_us = (unsigned(random()) % 7000) * 1000000ULL;
  66. printf("time_offset_us %llu\n", (long long unsigned)time_offset_us);
  67. }
  68. if (time_send_us && now_us >= time_send_us) {
  69. uint8_t msgbuf[300];
  70. uint16_t msgbuf_len = mavlink_msg_to_send_buffer(msgbuf, &obs_msg);
  71. if (::write(fd_my_end, (void*)&msgbuf, msgbuf_len) != msgbuf_len) {
  72. ::fprintf(stderr, "Vicon: write failure\n");
  73. }
  74. time_send_us = 0;
  75. }
  76. if (time_send_us != 0) {
  77. // waiting for the last msg to go out
  78. return;
  79. }
  80. if (now_us - last_observation_usec < 70000) {
  81. // create observations at 70ms intervals (matches EK2 max rate)
  82. return;
  83. }
  84. float roll;
  85. float pitch;
  86. float yaw;
  87. attitude.to_euler(roll, pitch, yaw);
  88. #if USE_VISION_POSITION_ESTIMATE
  89. // use the more recent VISION_POSITION_ESTIMATE message
  90. mavlink_msg_vision_position_estimate_pack_chan(
  91. system_id,
  92. component_id,
  93. mavlink_ch,
  94. &obs_msg,
  95. now_us + time_offset_us,
  96. position.x,
  97. position.y,
  98. position.z,
  99. roll,
  100. pitch,
  101. yaw,
  102. NULL, 0);
  103. #else
  104. mavlink_msg_vicon_position_estimate_pack_chan(
  105. system_id,
  106. component_id,
  107. mavlink_ch,
  108. &obs_msg,
  109. now_us + time_offset_us,
  110. position.x,
  111. position.y,
  112. position.z,
  113. roll,
  114. pitch,
  115. yaw,
  116. NULL);
  117. #endif // USE_VISION_POSITION_ESTIMATE
  118. uint32_t delay_ms = 25 + unsigned(random()) % 300;
  119. time_send_us = now_us + delay_ms * 1000UL;
  120. }
  121. bool Vicon::init_sitl_pointer()
  122. {
  123. if (_sitl == nullptr) {
  124. _sitl = AP::sitl();
  125. if (_sitl == nullptr) {
  126. return false;
  127. }
  128. }
  129. return true;
  130. }
  131. /*
  132. update vicon sensor state
  133. */
  134. void Vicon::update(const Location &loc, const Vector3f &position, const Quaternion &attitude)
  135. {
  136. if (!init_sitl_pointer()) {
  137. return;
  138. }
  139. maybe_send_heartbeat();
  140. update_vicon_position_estimate(loc, position, attitude);
  141. }