2 #include <AP_Notify/AP_Notify.h>
5 void Copter::avoidance_adsb_update(void)
8 avoidance_adsb
.update();
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
||
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
;
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
;
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
;
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
;
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
;
76 case MAV_COLLISION_ACTION_MOVE_PERPENDICULAR
:
77 if (!handle_avoidance_perpendicular(obstacle
, failsafe_state_change
)) {
78 actual_action
= MAV_COLLISION_ACTION_NONE
;
82 // unsupported actions and those that require no response
83 case MAV_COLLISION_ACTION_NONE
:
85 case MAV_COLLISION_ACTION_REPORT
:
91 #if HAL_LOGGING_ENABLED
92 if (failsafe_state_change
) {
93 AP::logger().Write_Error(LogErrorSubsystem::FAILSAFE_ADSB
,
94 LogErrorCode(actual_action
));
98 // return with action taken
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
118 case RecoveryAction::RESUME_PREVIOUS_FLIGHTMODE
:
119 set_mode_else_try_RTL_else_LAND(prev_control_mode
);
122 case RecoveryAction::RTL
:
123 set_mode_else_try_RTL_else_LAND(Mode::Number::RTL
);
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
);
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
152 // do not descend if below RTL alt
153 return copter
.g
.rtl_altitude
;
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
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
)) {
181 // decide on whether we should climb or descend
182 bool should_climb
= false;
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
;
191 velocity_neu
.z
= copter
.wp_nav
->get_default_speed_up();
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
);
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
)) {
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
)) {
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
);
231 // if we got this far we failed to set the new target
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
)) {
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();
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
);
263 // if we got this far we failed to set the new target