AP_RangeFinder_Wasp.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  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_RangeFinder_Wasp.h"
  15. #include <AP_SerialManager/AP_SerialManager.h>
  16. #include <ctype.h>
  17. extern const AP_HAL::HAL& hal;
  18. const AP_Param::GroupInfo AP_RangeFinder_Wasp::var_info[] = {
  19. // @Param: WSP_MAVG
  20. // @DisplayName: Moving Average Range
  21. // @Description: Sets the number of historic range results to use for calculating the current range result. When MAVG is greater than 1, the current range result will be the current measured value averaged with the N-1 previous results
  22. // @Range: 0 255
  23. // @User: Advanced
  24. AP_GROUPINFO("WSP_MAVG", 1, AP_RangeFinder_Wasp, mavg, 4),
  25. // @Param: WSP_MEDF
  26. // @DisplayName: Moving Median Filter
  27. // @Description: Sets the window size for the real-time median filter. When MEDF is greater than 0 the median filter is active
  28. // @Range: 0 255
  29. // @User: Advanced
  30. AP_GROUPINFO("WSP_MEDF", 2, AP_RangeFinder_Wasp, medf, 4),
  31. // @Param: WSP_FRQ
  32. // @DisplayName: Frequency
  33. // @Description: Sets the repetition frequency of the ranging operation in Hertz. Upon entering the desired frequency the system will calculate the nearest frequency that it can handle according to the resolution of internal timers.
  34. // @Range: 0 10000
  35. // @User: Advanced
  36. AP_GROUPINFO("WSP_FRQ", 3, AP_RangeFinder_Wasp, frq, 20),
  37. // @Param: WSP_AVG
  38. // @DisplayName: Multi-pulse averages
  39. // @Description: Sets the number of pulses to be used in multi-pulse averaging mode. In this mode, a sequence of rapid fire ranges are taken and then averaged to improve the accuracy of the measurement
  40. // @Range: 0 255
  41. // @User: Advanced
  42. AP_GROUPINFO("WSP_AVG", 4, AP_RangeFinder_Wasp, avg, 2),
  43. // @Param: WSP_THR
  44. // @DisplayName: Sensitivity threshold
  45. // @Description: Sets the system sensitivity. Larger values of THR represent higher sensitivity. The system may limit the maximum value of THR to prevent excessive false alarm rates based on settings made at the factory. Set to -1 for automatic threshold adjustments
  46. // @Range: -1 255
  47. // @User: Advanced
  48. AP_GROUPINFO("WSP_THR", 5, AP_RangeFinder_Wasp, thr, -1),
  49. // @Param: WSP_BAUD
  50. // @DisplayName: Baud rate
  51. // @Description: Desired baud rate
  52. // @Values: 0:Low Speed,1:High Speed
  53. // @User: Advanced
  54. AP_GROUPINFO("WSP_BAUD", 6, AP_RangeFinder_Wasp, baud, 0),
  55. AP_GROUPEND
  56. };
  57. AP_RangeFinder_Wasp::AP_RangeFinder_Wasp(RangeFinder::RangeFinder_State &_state,
  58. AP_RangeFinder_Params &_params,
  59. uint8_t serial_instance) :
  60. AP_RangeFinder_Backend(_state, _params) {
  61. AP_Param::setup_object_defaults(this, var_info);
  62. const AP_SerialManager &serial_manager = AP::serialmanager();
  63. uart = serial_manager.find_serial(AP_SerialManager::SerialProtocol_Rangefinder, serial_instance);
  64. if (uart != nullptr) {
  65. uart->begin(115200);
  66. // register Wasp specific parameters
  67. state.var_info = var_info;
  68. configuration_state = WASP_CFG_PROTOCOL;
  69. }
  70. }
  71. // detection is considered as locating a serial port
  72. bool AP_RangeFinder_Wasp::detect(uint8_t serial_instance) {
  73. return AP::serialmanager().find_serial(AP_SerialManager::SerialProtocol_Rangefinder, serial_instance) != nullptr;
  74. }
  75. // read - return last value measured by sensor
  76. bool AP_RangeFinder_Wasp::get_reading(uint16_t &reading_cm) {
  77. if (uart == nullptr) {
  78. return false;
  79. }
  80. // read any available lines from the lidar
  81. float sum = 0;
  82. uint16_t count = 0;
  83. int16_t nbytes = uart->available();
  84. while (nbytes-- > 0) {
  85. char c = uart->read();
  86. if (c == '\n') {
  87. linebuf[linebuf_len] = 0;
  88. linebuf_len = 0;
  89. state.last_reading_ms = AP_HAL::millis();
  90. if (isalpha(linebuf[0])) {
  91. parse_response();
  92. } else {
  93. float read_value = (float)atof(linebuf);
  94. if (read_value > 0) {
  95. sum += read_value;
  96. count++;
  97. }
  98. }
  99. } else if (isalnum(c) || c == '.' || c == '-') {
  100. linebuf[linebuf_len++] = c;
  101. }
  102. // discard excessively long buffers
  103. if (linebuf_len == sizeof(linebuf)) {
  104. linebuf_len = 0;
  105. }
  106. }
  107. if (configuration_state == WASP_CFG_RATE && uart->tx_pending() == 0) {
  108. configuration_state = WASP_CFG_ENCODING;
  109. }
  110. if (count == 0) {
  111. return false;
  112. }
  113. reading_cm = 100 * sum / count;
  114. set_status(RangeFinder::RangeFinder_Good);
  115. return true;
  116. }
  117. #define COMMAND_BUFFER_LEN 15
  118. void AP_RangeFinder_Wasp::update(void) {
  119. if (!get_reading(state.distance_cm)) {
  120. set_status(RangeFinder::RangeFinder_NoData);
  121. }
  122. if (AP_HAL::millis() - state.last_reading_ms > 500) {
  123. // attempt to reconfigure on the assumption this was a bad baud setting
  124. configuration_state = WASP_CFG_RATE;
  125. }
  126. char command[COMMAND_BUFFER_LEN] = {};
  127. switch (configuration_state) {
  128. case WASP_CFG_RATE:
  129. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">BAUD %s\n", baud > 0 ? "HIGH" : "LOW");
  130. break;
  131. case WASP_CFG_ENCODING:
  132. uart->end();
  133. uart->begin(baud > 0 ? 921600 : 115200);
  134. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">LBE LITTLE\n");
  135. break;
  136. case WASP_CFG_PROTOCOL:
  137. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">FMT ASCII\n");
  138. break;
  139. case WASP_CFG_FRQ:
  140. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">FRQ %d\n", constrain_int16(frq, 20, baud > 0 ? 10000 : 1440));
  141. break;
  142. case WASP_CFG_GO:
  143. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">GO\n");
  144. break;
  145. case WASP_CFG_AUT:
  146. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">AUT %d\n", thr >= 0 ? 0 : 1);
  147. break;
  148. case WASP_CFG_THR:
  149. if (thr >= 0) {
  150. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">THR %d\n", constrain_int16(thr, 0,255));
  151. } else {
  152. configuration_state = WASP_CFG_MAVG;
  153. }
  154. break;
  155. case WASP_CFG_MAVG:
  156. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">MAVG %d\n", constrain_int16(mavg, 0, 255));
  157. break;
  158. case WASP_CFG_MEDF:
  159. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">MEDF %d\n", constrain_int16(medf, 0, 255));
  160. break;
  161. case WASP_CFG_AVG:
  162. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">AVG %d\n", constrain_int16(avg, 0, 255));
  163. break;
  164. case WASP_CFG_AUV:
  165. hal.util->snprintf(command, COMMAND_BUFFER_LEN, ">AUV 1\n");
  166. break;
  167. case WASP_CFG_DONE:
  168. return;
  169. }
  170. if (command[0] != 0) {
  171. uart->write((uint8_t *)command, strlen(command));
  172. }
  173. }
  174. void AP_RangeFinder_Wasp::parse_response(void) {
  175. switch (configuration_state) {
  176. case WASP_CFG_RATE:
  177. configuration_state = WASP_CFG_ENCODING;
  178. break;
  179. case WASP_CFG_ENCODING:
  180. if (strncmp(linebuf, "LBE", 3) == 0) {
  181. configuration_state = WASP_CFG_PROTOCOL;
  182. }
  183. break;
  184. case WASP_CFG_PROTOCOL:
  185. if (strncmp(linebuf, "FMT", 3) == 0) {
  186. configuration_state = WASP_CFG_FRQ;
  187. }
  188. break;
  189. case WASP_CFG_FRQ:
  190. if (strncmp(linebuf, "FRQ", 3) == 0) {
  191. configuration_state = WASP_CFG_GO;
  192. }
  193. break;
  194. case WASP_CFG_GO:
  195. if (strncmp(linebuf, "GO", 2) == 0) {
  196. configuration_state = WASP_CFG_AUT;
  197. }
  198. break;
  199. case WASP_CFG_AUT:
  200. if (strncmp(linebuf, "AUT", 3) == 0) {
  201. configuration_state = WASP_CFG_THR;
  202. }
  203. break;
  204. case WASP_CFG_THR:
  205. if (strncmp(linebuf, "THR", 3) == 0) {
  206. configuration_state = WASP_CFG_MAVG;
  207. }
  208. break;
  209. case WASP_CFG_MAVG:
  210. if (strncmp(linebuf, "MAVG", 4) == 0) {
  211. configuration_state = WASP_CFG_MEDF;
  212. }
  213. break;
  214. case WASP_CFG_MEDF:
  215. if (strncmp(linebuf, "MEDF", 4) == 0) {
  216. configuration_state = WASP_CFG_AVG;
  217. }
  218. break;
  219. case WASP_CFG_AVG:
  220. if (strncmp(linebuf, "AVG", 3) == 0) {
  221. configuration_state = WASP_CFG_AUV;
  222. }
  223. break;
  224. case WASP_CFG_AUV:
  225. if (strncmp(linebuf, "AUV", 3) == 0) {
  226. configuration_state = WASP_CFG_DONE;
  227. }
  228. break;
  229. case WASP_CFG_DONE:
  230. return;
  231. }
  232. }