Line data Source code
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 : 7 : This program is distributed in the hope that it will be useful, 8 : but WITHOUT ANY WARRANTY; without even the implied warranty of 9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 : GNU General Public License for more details. 11 : 12 : You should have received a copy of the GNU General Public License 13 : along with this program. If not, see <http://www.gnu.org/licenses/>. 14 : */ 15 : 16 : #include "AP_Proximity_config.h" 17 : 18 : #if AP_PROXIMITY_SITL_ENABLED 19 : 20 : #include "AP_Proximity_SITL.h" 21 : 22 : #include <AP_HAL/AP_HAL.h> 23 : #include <AP_Param/AP_Param.h> 24 : #include <AC_Fence/AC_Fence.h> 25 : #include <stdio.h> 26 : 27 : extern const AP_HAL::HAL& hal; 28 : 29 : #define PROXIMITY_MAX_RANGE 200.0f 30 : #define PROXIMITY_ACCURACY 0.1f 31 : 32 : /* 33 : The constructor also initialises the proximity sensor. 34 : */ 35 5 : AP_Proximity_SITL::AP_Proximity_SITL(AP_Proximity &_frontend, 36 : AP_Proximity::Proximity_State &_state, 37 5 : AP_Proximity_Params& _params): 38 : AP_Proximity_Backend(_frontend, _state, _params), 39 5 : sitl(AP::sitl()) 40 : { 41 : ap_var_type ptype; 42 5 : fence_alt_max = (AP_Float *)AP_Param::find("FENCE_ALT_MAX", &ptype); 43 5 : if (fence_alt_max == nullptr || ptype != AP_PARAM_FLOAT) { 44 0 : AP_HAL::panic("Proximity_SITL: Failed to find FENCE_ALT_MAX"); 45 : } 46 5 : } 47 : 48 : // update the state of the sensor 49 43919 : void AP_Proximity_SITL::update(void) 50 : { 51 43919 : current_loc.lat = sitl->state.latitude * 1.0e7; 52 43919 : current_loc.lng = sitl->state.longitude * 1.0e7; 53 43919 : current_loc.alt = sitl->state.altitude * 1.0e2; 54 : 55 : #if AP_FENCE_ENABLED 56 43919 : if (!AP::fence()->polyfence().breached()) { 57 : // only called to prompt polyfence to reload fence if required 58 : } 59 43919 : if (AP::fence()->polyfence().inclusion_boundary_available()) { 60 38507 : set_status(AP_Proximity::Status::Good); 61 : // update distance in each sector 62 346563 : for (uint8_t sector=0; sector < PROXIMITY_NUM_SECTORS; sector++) { 63 308056 : const float yaw_angle_deg = sector * 45.0f; 64 308056 : AP_Proximity_Boundary_3D::Face face = frontend.boundary.get_face(yaw_angle_deg); 65 : float fence_distance; 66 308056 : if (get_distance_to_fence(yaw_angle_deg, fence_distance)) { 67 308056 : frontend.boundary.set_face_attributes(face, yaw_angle_deg, fence_distance, state.instance); 68 : // update OA database 69 308056 : database_push(yaw_angle_deg, fence_distance); 70 : } else { 71 0 : frontend.boundary.reset_face(face, state.instance); 72 : } 73 : } 74 : } else { 75 5412 : set_status(AP_Proximity::Status::NoData); 76 : } 77 : #else 78 : set_status(AP_Proximity::Status::NoData); 79 : #endif 80 43919 : } 81 : 82 : // get distance in meters to fence in a particular direction in degrees (0 is forward, angles increase in the clockwise direction) 83 308056 : bool AP_Proximity_SITL::get_distance_to_fence(float angle_deg, float &distance) const 84 : { 85 : #if AP_FENCE_ENABLED 86 308056 : if (!AP::fence()->polyfence().inclusion_boundary_available()) { 87 0 : return false; 88 : } 89 : 90 : // convert to earth frame 91 308056 : angle_deg = wrap_360(sitl->state.yawDeg + angle_deg); 92 : 93 : /* 94 : simple bisection search to find distance. Not really efficient, 95 : but we can afford the CPU in SITL 96 : */ 97 308056 : float min_dist = 0, max_dist = PROXIMITY_MAX_RANGE; 98 3696672 : while (max_dist - min_dist > PROXIMITY_ACCURACY) { 99 3388616 : float test_dist = (max_dist+min_dist)*0.5f; 100 : 101 3388616 : Location loc = current_loc; 102 3388616 : loc.offset_bearing(angle_deg, test_dist); 103 3388616 : if (AP::fence()->polyfence().breached(loc)) { 104 2334234 : max_dist = test_dist; 105 : } else { 106 1054382 : min_dist = test_dist; 107 : } 108 : } 109 308056 : distance = min_dist; 110 308056 : if (ignore_reading(angle_deg, distance, false)) { 111 : // obstacle near land, lets ignore it 112 0 : return false; 113 : } 114 308056 : return true; 115 : #else 116 : return false; 117 : #endif 118 : } 119 : 120 : // get maximum and minimum distances (in meters) of primary sensor 121 18370 : float AP_Proximity_SITL::distance_max_m() const 122 : { 123 18370 : return PROXIMITY_MAX_RANGE; 124 : } 125 1946 : float AP_Proximity_SITL::distance_min_m() const 126 : { 127 1946 : return 0.0f; 128 : } 129 : 130 : // get distance upwards in meters. returns true on success 131 10689 : bool AP_Proximity_SITL::get_upward_distance(float &distance) const 132 : { 133 : // return distance to fence altitude 134 10689 : distance = MAX(0.0f, fence_alt_max->get() - sitl->state.height_agl); 135 10689 : return true; 136 : } 137 : 138 : #endif // AP_PROXIMITY_SITL_ENABLED