AP_Scripting: Add Altitude Callout script to examples
[ardupilot.git] / ArduCopter / avoidance_adsb.cpp
blob5a1c306b8424e28a186cc620240f5b3b3fd292d3
1 #include "Copter.h"
2 #include <AP_Notify/AP_Notify.h>
4 #if HAL_ADSB_ENABLED
5 void Copter::avoidance_adsb_update(void)
7 adsb.update();
8 avoidance_adsb.update();
11 #include <stdio.h>
13 MAV_COLLISION_ACTION AP_Avoidance_Copter::handle_avoidance(const AP_Avoidance::Obstacle *obstacle, MAV_COLLISION_ACTION requested_action)
15 MAV_COLLISION_ACTION actual_action = requested_action;
16 bool failsafe_state_change = false;
18 // check for changes in failsafe
19 if (!copter.failsafe.adsb) {
20 copter.failsafe.adsb = true;
21 failsafe_state_change = true;
22 // record flight mode in case it's required for the recovery
23 prev_control_mode = copter.flightmode->mode_number();
26 // take no action in some flight modes
27 if (copter.flightmode->mode_number() == Mode::Number::LAND ||
28 #if MODE_THROW_ENABLED
29 copter.flightmode->mode_number() == Mode::Number::THROW ||
30 #endif
31 copter.flightmode->mode_number() == Mode::Number::FLIP) {
32 actual_action = MAV_COLLISION_ACTION_NONE;
35 // if landed and we will take some kind of action, just disarm
36 if ((actual_action > MAV_COLLISION_ACTION_REPORT) && copter.should_disarm_on_failsafe()) {
37 copter.arming.disarm(AP_Arming::Method::ADSBCOLLISIONACTION);
38 actual_action = MAV_COLLISION_ACTION_NONE;
39 } else {
41 // take action based on requested action
42 switch (actual_action) {
44 case MAV_COLLISION_ACTION_RTL:
45 // attempt to switch to RTL, if this fails (i.e. flying in manual mode with bad position) do nothing
46 if (failsafe_state_change) {
47 if (!copter.set_mode(Mode::Number::RTL, ModeReason::AVOIDANCE)) {
48 actual_action = MAV_COLLISION_ACTION_NONE;
51 break;
53 case MAV_COLLISION_ACTION_HOVER:
54 // attempt to switch to Loiter, if this fails (i.e. flying in manual mode with bad position) do nothing
55 if (failsafe_state_change) {
56 if (!copter.set_mode(Mode::Number::LOITER, ModeReason::AVOIDANCE)) {
57 actual_action = MAV_COLLISION_ACTION_NONE;
60 break;
62 case MAV_COLLISION_ACTION_ASCEND_OR_DESCEND:
63 // climb or descend to avoid obstacle
64 if (!handle_avoidance_vertical(obstacle, failsafe_state_change)) {
65 actual_action = MAV_COLLISION_ACTION_NONE;
67 break;
69 case MAV_COLLISION_ACTION_MOVE_HORIZONTALLY:
70 // move horizontally to avoid obstacle
71 if (!handle_avoidance_horizontal(obstacle, failsafe_state_change)) {
72 actual_action = MAV_COLLISION_ACTION_NONE;
74 break;
76 case MAV_COLLISION_ACTION_MOVE_PERPENDICULAR:
77 if (!handle_avoidance_perpendicular(obstacle, failsafe_state_change)) {
78 actual_action = MAV_COLLISION_ACTION_NONE;
80 break;
82 // unsupported actions and those that require no response
83 case MAV_COLLISION_ACTION_NONE:
84 return actual_action;
85 case MAV_COLLISION_ACTION_REPORT:
86 default:
87 break;
91 #if HAL_LOGGING_ENABLED
92 if (failsafe_state_change) {
93 AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_ADSB,
94 LogErrorCode(actual_action));
96 #endif
98 // return with action taken
99 return actual_action;
102 void AP_Avoidance_Copter::handle_recovery(RecoveryAction recovery_action)
104 // check we are coming out of failsafe
105 if (copter.failsafe.adsb) {
106 copter.failsafe.adsb = false;
107 LOGGER_WRITE_ERROR(LogErrorSubsystem::FAILSAFE_ADSB,
108 LogErrorCode::ERROR_RESOLVED);
110 // restore flight mode if requested and user has not changed mode since
111 if (copter.control_mode_reason == ModeReason::AVOIDANCE) {
112 switch (recovery_action) {
114 case RecoveryAction::REMAIN_IN_AVOID_ADSB:
115 // do nothing, we'll stay in the AVOID_ADSB mode which is guided which will loiter forever
116 break;
118 case RecoveryAction::RESUME_PREVIOUS_FLIGHTMODE:
119 set_mode_else_try_RTL_else_LAND(prev_control_mode);
120 break;
122 case RecoveryAction::RTL:
123 set_mode_else_try_RTL_else_LAND(Mode::Number::RTL);
124 break;
126 case RecoveryAction::RESUME_IF_AUTO_ELSE_LOITER:
127 if (prev_control_mode == Mode::Number::AUTO) {
128 set_mode_else_try_RTL_else_LAND(Mode::Number::AUTO);
130 break;
132 default:
133 break;
134 } // switch
139 void AP_Avoidance_Copter::set_mode_else_try_RTL_else_LAND(Mode::Number mode)
141 if (!copter.set_mode(mode, ModeReason::AVOIDANCE_RECOVERY)) {
142 // on failure RTL or LAND
143 if (!copter.set_mode(Mode::Number::RTL, ModeReason::AVOIDANCE_RECOVERY)) {
144 copter.set_mode(Mode::Number::LAND, ModeReason::AVOIDANCE_RECOVERY);
149 int32_t AP_Avoidance_Copter::get_altitude_minimum() const
151 #if MODE_RTL_ENABLED
152 // do not descend if below RTL alt
153 return copter.g.rtl_altitude;
154 #else
155 return 0;
156 #endif
159 // check flight mode is avoid_adsb
160 bool AP_Avoidance_Copter::check_flightmode(bool allow_mode_change)
162 // ensure copter is in avoid_adsb mode
163 if (allow_mode_change && copter.flightmode->mode_number() != Mode::Number::AVOID_ADSB) {
164 if (!copter.set_mode(Mode::Number::AVOID_ADSB, ModeReason::AVOIDANCE)) {
165 // failed to set mode so exit immediately
166 return false;
170 // check flight mode
171 return (copter.flightmode->mode_number() == Mode::Number::AVOID_ADSB);
174 bool AP_Avoidance_Copter::handle_avoidance_vertical(const AP_Avoidance::Obstacle *obstacle, bool allow_mode_change)
176 // ensure copter is in avoid_adsb mode
177 if (!check_flightmode(allow_mode_change)) {
178 return false;
181 // decide on whether we should climb or descend
182 bool should_climb = false;
183 Location my_loc;
184 if (AP::ahrs().get_location(my_loc)) {
185 should_climb = my_loc.alt > obstacle->_location.alt;
188 // get best vector away from obstacle
189 Vector3f velocity_neu;
190 if (should_climb) {
191 velocity_neu.z = copter.wp_nav->get_default_speed_up();
192 } else {
193 velocity_neu.z = -copter.wp_nav->get_default_speed_down();
194 // do not descend if below minimum altitude
195 if (copter.current_loc.alt < get_altitude_minimum()) {
196 velocity_neu.z = 0.0f;
200 // send target velocity
201 copter.mode_avoid_adsb.set_velocity(velocity_neu);
202 return true;
205 bool AP_Avoidance_Copter::handle_avoidance_horizontal(const AP_Avoidance::Obstacle *obstacle, bool allow_mode_change)
207 // ensure copter is in avoid_adsb mode
208 if (!check_flightmode(allow_mode_change)) {
209 return false;
212 // get best vector away from obstacle
213 Vector3f velocity_neu;
214 if (get_vector_perpendicular(obstacle, velocity_neu)) {
215 // remove vertical component
216 velocity_neu.z = 0.0f;
217 // check for divide by zero
218 if (is_zero(velocity_neu.x) && is_zero(velocity_neu.y)) {
219 return false;
221 // re-normalise
222 velocity_neu.normalize();
223 // convert horizontal components to velocities
224 velocity_neu.x *= copter.wp_nav->get_default_speed_xy();
225 velocity_neu.y *= copter.wp_nav->get_default_speed_xy();
226 // send target velocity
227 copter.mode_avoid_adsb.set_velocity(velocity_neu);
228 return true;
231 // if we got this far we failed to set the new target
232 return false;
235 bool AP_Avoidance_Copter::handle_avoidance_perpendicular(const AP_Avoidance::Obstacle *obstacle, bool allow_mode_change)
237 // ensure copter is in avoid_adsb mode
238 if (!check_flightmode(allow_mode_change)) {
239 return false;
242 // get best vector away from obstacle
243 Vector3f velocity_neu;
244 if (get_vector_perpendicular(obstacle, velocity_neu)) {
245 // convert horizontal components to velocities
246 velocity_neu.x *= copter.wp_nav->get_default_speed_xy();
247 velocity_neu.y *= copter.wp_nav->get_default_speed_xy();
248 // use up and down waypoint speeds
249 if (velocity_neu.z > 0.0f) {
250 velocity_neu.z *= copter.wp_nav->get_default_speed_up();
251 } else {
252 velocity_neu.z *= copter.wp_nav->get_default_speed_down();
253 // do not descend if below minimum altitude
254 if (copter.current_loc.alt < get_altitude_minimum()) {
255 velocity_neu.z = 0.0f;
258 // send target velocity
259 copter.mode_avoid_adsb.set_velocity(velocity_neu);
260 return true;
263 // if we got this far we failed to set the new target
264 return false;
266 #endif