surface_bottom_detector.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // Jacob Walser: jacob@bluerobotics.com
  2. #include "Sub.h"
  3. // counter to verify contact with bottom
  4. static uint32_t bottom_detector_count = 0;
  5. static uint32_t surface_detector_count = 0;
  6. static float current_depth = 0;
  7. // checks if we have have hit bottom or surface and updates the ap.at_bottom and ap.at_surface flags
  8. // called at MAIN_LOOP_RATE
  9. // ToDo: doesn't need to be called this fast
  10. void Sub::update_surface_and_bottom_detector()
  11. {
  12. if (!motors.armed()) { // only update when armed
  13. set_surfaced(false);
  14. set_bottomed(false);
  15. return;
  16. }
  17. Vector3f velocity;
  18. ahrs.get_velocity_NED(velocity);
  19. // check that we are not moving up or down
  20. bool vel_stationary = velocity.z > -0.05 && velocity.z < 0.05;
  21. if (ap.depth_sensor_present && sensor_health.depth) { // we can use the external pressure sensor for a very accurate and current measure of our z axis position
  22. current_depth = barometer.get_altitude(); // cm
  23. if (ap.at_surface) {
  24. set_surfaced(current_depth > g.surface_depth/100.0 - 0.05); // add a 5cm buffer so it doesn't trigger too often
  25. } else {
  26. set_surfaced(current_depth > g.surface_depth/100.0); // If we are above surface depth, we are surfaced
  27. }
  28. if (motors.limit.throttle_lower && vel_stationary) {
  29. // bottom criteria met - increment the counter and check if we've triggered
  30. if (bottom_detector_count < ((float)BOTTOM_DETECTOR_TRIGGER_SEC)*MAIN_LOOP_RATE) {
  31. bottom_detector_count++;
  32. } else {
  33. set_bottomed(true);
  34. }
  35. } else {
  36. set_bottomed(false);
  37. }
  38. // with no external baro, the only thing we have to go by is a vertical velocity estimate
  39. } else if (vel_stationary) {
  40. if (motors.limit.throttle_upper) {
  41. // surface criteria met, increment counter and see if we've triggered
  42. if (surface_detector_count < ((float)SURFACE_DETECTOR_TRIGGER_SEC)*MAIN_LOOP_RATE) {
  43. surface_detector_count++;
  44. } else {
  45. set_surfaced(true);
  46. }
  47. } else if (motors.limit.throttle_lower) {
  48. // bottom criteria met, increment counter and see if we've triggered
  49. if (bottom_detector_count < ((float)BOTTOM_DETECTOR_TRIGGER_SEC)*MAIN_LOOP_RATE) {
  50. bottom_detector_count++;
  51. } else {
  52. set_bottomed(true);
  53. }
  54. } else { // we're not at the limits of throttle, so reset both detectors
  55. set_surfaced(false);
  56. set_bottomed(false);
  57. }
  58. } else { // we're moving up or down, so reset both detectors
  59. set_surfaced(false);
  60. set_bottomed(false);
  61. }
  62. }
  63. void Sub::set_surfaced(bool at_surface)
  64. {
  65. if (ap.at_surface == at_surface) { // do nothing if state unchanged
  66. return;
  67. }
  68. ap.at_surface = at_surface;
  69. surface_detector_count = 0;
  70. if (ap.at_surface) {
  71. Log_Write_Event(DATA_SURFACED);
  72. } else {
  73. Log_Write_Event(DATA_NOT_SURFACED);
  74. }
  75. }
  76. void Sub::set_bottomed(bool at_bottom)
  77. {
  78. if (ap.at_bottom == at_bottom) { // do nothing if state unchanged
  79. return;
  80. }
  81. ap.at_bottom = at_bottom;
  82. bottom_detector_count = 0;
  83. if (ap.at_bottom) {
  84. Log_Write_Event(DATA_BOTTOMED);
  85. } else {
  86. Log_Write_Event(DATA_NOT_BOTTOMED);
  87. }
  88. }