123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277 |
- #include "AP_OABendyRuler.h"
- #include <AC_Avoidance/AP_OADatabase.h>
- #include <AC_Fence/AC_Fence.h>
- #include <AP_AHRS/AP_AHRS.h>
- #include <AP_Logger/AP_Logger.h>
- const int16_t OA_BENDYRULER_BEARING_INC = 5;
- const float OA_BENDYRULER_LOOKAHEAD_STEP2_RATIO = 1.0f;
- const float OA_BENDYRULER_LOOKAHEAD_STEP2_MIN = 2.0f;
- const float OA_BENDYRULER_LOOKAHEAD_PAST_DEST = 2.0f;
- const float OA_BENDYRULER_LOW_SPEED_SQUARED = (0.2f * 0.2f);
- bool AP_OABendyRuler::update(const Location& current_loc, const Location& destination, const Vector2f &ground_speed_vec, Location &origin_new, Location &destination_new)
- {
-
- origin_new = current_loc;
-
- const float bearing_to_dest = current_loc.get_bearing_to(destination) * 0.01f;
- const float distance_to_dest = current_loc.get_distance(destination);
-
- _current_lookahead = constrain_float(_current_lookahead, _lookahead * 0.5f, _lookahead);
-
-
- const float lookahead_step1_dist = MIN(_current_lookahead, distance_to_dest + OA_BENDYRULER_LOOKAHEAD_PAST_DEST);
-
- const float lookahead_step2_dist = _current_lookahead * OA_BENDYRULER_LOOKAHEAD_STEP2_RATIO;
-
- float ground_course_deg;
- if (ground_speed_vec.length_squared() < OA_BENDYRULER_LOW_SPEED_SQUARED) {
-
- ground_course_deg = AP::ahrs().yaw_sensor * 0.01f;
- } else {
- ground_course_deg = degrees(ground_speed_vec.angle());
- }
-
- static_assert(360 % OA_BENDYRULER_BEARING_INC == 0, "check 360 is a multiple of OA_BEARING_INC");
-
-
- float best_bearing = bearing_to_dest;
- bool have_best_bearing = false;
- float best_margin = -FLT_MAX;
- float best_margin_bearing = best_bearing;
- for (uint8_t i = 0; i <= (170 / OA_BENDYRULER_BEARING_INC); i++) {
- for (uint8_t bdir = 0; bdir <= 1; bdir++) {
-
- if ((i==0) && (bdir > 0)) {
- continue;
- }
-
- const float bearing_delta = i * OA_BENDYRULER_BEARING_INC * (bdir == 0 ? -1.0f : 1.0f);
- const float bearing_test = wrap_180(bearing_to_dest + bearing_delta);
-
-
-
- Location test_loc = current_loc;
- test_loc.offset_bearing(bearing_test, lookahead_step1_dist);
-
- float margin = calc_avoidance_margin(current_loc, test_loc);
- if (margin > best_margin) {
- best_margin_bearing = bearing_test;
- best_margin = margin;
- }
- if (margin > _margin_max) {
-
-
- if (!have_best_bearing) {
- best_bearing = bearing_test;
- have_best_bearing = true;
- } else if (fabsf(wrap_180(ground_course_deg - bearing_test)) <
- fabsf(wrap_180(ground_course_deg - best_bearing))) {
-
- best_bearing = bearing_test;
- }
-
- const float test_bearings[] { 0.0f, 45.0f, -45.0f };
- const float bearing_to_dest2 = test_loc.get_bearing_to(destination) * 0.01f;
- float distance2 = constrain_float(lookahead_step2_dist, OA_BENDYRULER_LOOKAHEAD_STEP2_MIN, test_loc.get_distance(destination));
- for (uint8_t j = 0; j < ARRAY_SIZE(test_bearings); j++) {
- float bearing_test2 = wrap_180(bearing_to_dest2 + test_bearings[j]);
- Location test_loc2 = test_loc;
- test_loc2.offset_bearing(bearing_test2, distance2);
-
- float margin2 = calc_avoidance_margin(test_loc, test_loc2);
- if (margin2 > _margin_max) {
-
- destination_new = current_loc;
- destination_new.offset_bearing(bearing_test, distance_to_dest);
- _current_lookahead = MIN(_lookahead, _current_lookahead * 1.1f);
-
- const bool active = (i != 0 || j != 0);
- AP::logger().Write_OABendyRuler(active, bearing_to_dest, margin, destination, destination_new);
- return active;
- }
- }
- }
- }
- }
- float chosen_bearing;
- if (have_best_bearing) {
-
-
- chosen_bearing = best_bearing;
- _current_lookahead = MIN(_lookahead, _current_lookahead * 1.05f);
- } else {
-
-
- chosen_bearing = best_margin_bearing;
- _current_lookahead = MAX(_lookahead * 0.5f, _current_lookahead * 0.9f);
- }
-
- destination_new = current_loc;
- destination_new.offset_bearing(chosen_bearing, distance_to_dest);
-
- AP::logger().Write_OABendyRuler(true, chosen_bearing, best_margin, destination, destination_new);
- return true;
- }
- float AP_OABendyRuler::calc_avoidance_margin(const Location &start, const Location &end)
- {
- float circular_fence_margin;
- if (!calc_margin_from_circular_fence(start, end, circular_fence_margin)) {
- circular_fence_margin = FLT_MAX;
- }
- float polygon_fence_margin;
- if (!calc_margin_from_polygon_fence(start, end, polygon_fence_margin)) {
- polygon_fence_margin = FLT_MAX;
- }
- float proximity_margin;
- if (!calc_margin_from_object_database(start, end, proximity_margin)) {
- proximity_margin = FLT_MAX;
- }
-
- return MIN(MIN(circular_fence_margin, polygon_fence_margin), proximity_margin);
- }
- bool AP_OABendyRuler::calc_margin_from_circular_fence(const Location &start, const Location &end, float &margin)
- {
-
- const AC_Fence *fence = AC_Fence::get_singleton();
- if (fence == nullptr) {
- return false;
- }
- if ((fence->get_enabled_fences() & AC_FENCE_TYPE_CIRCLE) == 0) {
- return false;
- }
-
- const Location &ahrs_home = AP::ahrs().get_home();
- const float start_dist_sq = ahrs_home.get_distance_NE(start).length_squared();
- const float end_dist_sq = ahrs_home.get_distance_NE(end).length_squared();
-
- const float fence_radius = fence->get_radius();
-
- margin = fence_radius - sqrtf(MAX(start_dist_sq, end_dist_sq));
- return true;
- }
- bool AP_OABendyRuler::calc_margin_from_polygon_fence(const Location &start, const Location &end, float &margin)
- {
-
- const AC_Fence *fence = AC_Fence::get_singleton();
- if (fence == nullptr) {
- return false;
- }
- if (((fence->get_enabled_fences() & AC_FENCE_TYPE_POLYGON) == 0) || !fence->is_polygon_valid()) {
- return false;
- }
-
- uint16_t num_points;
- const Vector2f* boundary = fence->get_boundary_points(num_points);
- if (num_points < 3) {
-
- return false;
- }
-
- Vector2f start_NE, end_NE;
- if (!start.get_vector_xy_from_origin_NE(start_NE) || !end.get_vector_xy_from_origin_NE(end_NE)) {
- return false;
- }
-
- const float sign = Polygon_outside(start_NE, boundary, num_points) ? -1.0f : 1.0f;
-
- margin = sign * Polygon_closest_distance_line(boundary, num_points, start_NE, end_NE) * 0.01f;
- return true;
- }
- bool AP_OABendyRuler::calc_margin_from_object_database(const Location &start, const Location &end, float &margin)
- {
- #if !HAL_MINIMIZE_FEATURES
-
- AP_OADatabase *oaDb = AP::oadatabase();
- if (oaDb == nullptr || !oaDb->healthy()) {
- return false;
- }
-
- Vector2f start_NE, end_NE;
- if (!start.get_vector_xy_from_origin_NE(start_NE) || !end.get_vector_xy_from_origin_NE(end_NE)) {
- return false;
- }
-
- float smallest_margin = FLT_MAX;
- for (uint16_t i=0; i<oaDb->database_count(); i++) {
-
- Vector2f point;
- if (!oaDb->get_item(i).loc.get_vector_xy_from_origin_NE(point)) {
- continue;
- }
-
- const float m = Vector2f::closest_distance_between_line_and_point(start_NE, end_NE, point) * 0.01f - oaDb->get_accuracy();
- if (m < smallest_margin) {
- smallest_margin = m;
- }
- }
-
- if (smallest_margin < FLT_MAX) {
- margin = smallest_margin;
- return true;
- }
- #endif
- return false;
- }
|