AP_Beacon_Pozyx.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  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. #include <AP_HAL/AP_HAL.h>
  14. #include "AP_Beacon_Pozyx.h"
  15. #include <ctype.h>
  16. #include <stdio.h>
  17. extern const AP_HAL::HAL& hal;
  18. // constructor
  19. AP_Beacon_Pozyx::AP_Beacon_Pozyx(AP_Beacon &frontend, AP_SerialManager &serial_manager) :
  20. AP_Beacon_Backend(frontend),
  21. linebuf_len(0)
  22. {
  23. uart = serial_manager.find_serial(AP_SerialManager::SerialProtocol_Beacon, 0);
  24. if (uart != nullptr) {
  25. uart->begin(serial_manager.find_baudrate(AP_SerialManager::SerialProtocol_Beacon, 0));
  26. }
  27. }
  28. // return true if sensor is basically healthy (we are receiving data)
  29. bool AP_Beacon_Pozyx::healthy()
  30. {
  31. // healthy if we have parsed a message within the past 300ms
  32. return ((AP_HAL::millis() - last_update_ms) < AP_BEACON_TIMEOUT_MS);
  33. }
  34. // update the state of the sensor
  35. void AP_Beacon_Pozyx::update(void)
  36. {
  37. static uint8_t counter = 0;
  38. counter++;
  39. if (counter > 200) {
  40. counter = 0;
  41. }
  42. if (uart == nullptr) {
  43. return;
  44. }
  45. // read any available characters
  46. int16_t nbytes = uart->available();
  47. while (nbytes-- > 0) {
  48. char c = uart->read();
  49. switch (parse_state) {
  50. default:
  51. case ParseState_WaitingForHeader:
  52. if (c == AP_BEACON_POZYX_HEADER) {
  53. parse_state = ParseState_WaitingForMsgId;
  54. linebuf_len = 0;
  55. }
  56. break;
  57. case ParseState_WaitingForMsgId:
  58. parse_msg_id = c;
  59. switch (parse_msg_id) {
  60. case AP_BEACON_POZYX_MSGID_BEACON_CONFIG:
  61. case AP_BEACON_POZYX_MSGID_BEACON_DIST:
  62. case AP_BEACON_POZYX_MSGID_POSITION:
  63. parse_state = ParseState_WaitingForLen;
  64. break;
  65. default:
  66. // invalid message id
  67. parse_state = ParseState_WaitingForHeader;
  68. break;
  69. }
  70. break;
  71. case ParseState_WaitingForLen:
  72. parse_msg_len = c;
  73. if (parse_msg_len > AP_BEACON_POZYX_MSG_LEN_MAX) {
  74. // invalid message length
  75. parse_state = ParseState_WaitingForHeader;
  76. } else {
  77. parse_state = ParseState_WaitingForContents;
  78. }
  79. break;
  80. case ParseState_WaitingForContents:
  81. // add to buffer
  82. linebuf[linebuf_len++] = c;
  83. if ((linebuf_len == parse_msg_len) || (linebuf_len == sizeof(linebuf))) {
  84. // process buffer
  85. parse_buffer();
  86. // reset state for next message
  87. parse_state = ParseState_WaitingForHeader;
  88. }
  89. break;
  90. }
  91. }
  92. }
  93. // parse buffer
  94. void AP_Beacon_Pozyx::parse_buffer()
  95. {
  96. // check crc
  97. uint8_t checksum = 0;
  98. checksum ^= parse_msg_id;
  99. checksum ^= parse_msg_len;
  100. for (uint8_t i=0; i<linebuf_len; i++) {
  101. checksum ^= linebuf[i];
  102. }
  103. // return if failed checksum check
  104. if (checksum != 0) {
  105. return;
  106. }
  107. bool parsed = false;
  108. switch (parse_msg_id) {
  109. case AP_BEACON_POZYX_MSGID_BEACON_CONFIG:
  110. {
  111. uint8_t beacon_id = linebuf[0];
  112. //uint8_t beacon_count = linebuf[1];
  113. int32_t beacon_x = (uint32_t)linebuf[5] << 24 | (uint32_t)linebuf[4] << 16 | (uint32_t)linebuf[3] << 8 | (uint32_t)linebuf[2];
  114. int32_t beacon_y = (uint32_t)linebuf[9] << 24 | (uint32_t)linebuf[8] << 16 | (uint32_t)linebuf[7] << 8 | (uint32_t)linebuf[6];
  115. int32_t beacon_z = (uint32_t)linebuf[13] << 24 | (uint32_t)linebuf[12] << 16 | (uint32_t)linebuf[11] << 8 | (uint32_t)linebuf[10];
  116. Vector3f beacon_pos(beacon_x / 1000.0f, beacon_y / 1000.0f, -beacon_z / 1000.0f);
  117. if (beacon_pos.length() <= AP_BEACON_DISTANCE_MAX) {
  118. set_beacon_position(beacon_id, beacon_pos);
  119. parsed = true;
  120. }
  121. }
  122. break;
  123. case AP_BEACON_POZYX_MSGID_BEACON_DIST:
  124. {
  125. uint8_t beacon_id = linebuf[0];
  126. uint32_t beacon_distance = (uint32_t)linebuf[4] << 24 | (uint32_t)linebuf[3] << 16 | (uint32_t)linebuf[2] << 8 | (uint32_t)linebuf[1];
  127. float beacon_dist = beacon_distance/1000.0f;
  128. if (beacon_dist <= AP_BEACON_DISTANCE_MAX) {
  129. set_beacon_distance(beacon_id, beacon_dist);
  130. parsed = true;
  131. }
  132. }
  133. break;
  134. case AP_BEACON_POZYX_MSGID_POSITION:
  135. {
  136. int32_t vehicle_x = (uint32_t)linebuf[3] << 24 | (uint32_t)linebuf[2] << 16 | (uint32_t)linebuf[1] << 8 | (uint32_t)linebuf[0];
  137. int32_t vehicle_y = (uint32_t)linebuf[7] << 24 | (uint32_t)linebuf[6] << 16 | (uint32_t)linebuf[5] << 8 | (uint32_t)linebuf[4];
  138. int32_t vehicle_z = (uint32_t)linebuf[11] << 24 | (uint32_t)linebuf[10] << 16 | (uint32_t)linebuf[9] << 8 | (uint32_t)linebuf[8];
  139. int16_t position_error = (uint32_t)linebuf[13] << 8 | (uint32_t)linebuf[12];
  140. Vector3f veh_pos(Vector3f(vehicle_x / 1000.0f, vehicle_y / 1000.0f, -vehicle_z / 1000.0f));
  141. if (veh_pos.length() <= AP_BEACON_DISTANCE_MAX) {
  142. set_vehicle_position(veh_pos, position_error);
  143. parsed = true;
  144. }
  145. }
  146. break;
  147. default:
  148. // unrecognised message id
  149. break;
  150. }
  151. // record success
  152. if (parsed) {
  153. last_update_ms = AP_HAL::millis();
  154. }
  155. }