2017-11-29 21:58:11 -04:00
|
|
|
#include "Rover.h"
|
|
|
|
|
|
|
|
bool ModeSmartRTL::_enter()
|
|
|
|
{
|
|
|
|
// SmartRTL requires EKF (not DCM)
|
|
|
|
Location ekf_origin;
|
|
|
|
if (!ahrs.get_origin(ekf_origin)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// refuse to enter SmartRTL if smart RTL's home has not been set
|
|
|
|
if (!g2.smart_rtl.is_active()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2022-01-05 20:01:49 -04:00
|
|
|
// initialise waypoint navigation library
|
|
|
|
g2.wp_nav.init(MAX(0, g2.rtl_speed));
|
|
|
|
|
2019-04-29 03:31:45 -03:00
|
|
|
// set desired location to reasonable stopping point
|
|
|
|
if (!g2.wp_nav.set_desired_location_to_stopping_location()) {
|
|
|
|
return false;
|
|
|
|
}
|
2017-12-05 21:41:28 -04:00
|
|
|
|
2017-11-29 21:58:11 -04:00
|
|
|
// init state
|
2023-09-21 10:58:41 -03:00
|
|
|
smart_rtl_state = SmartRTLState::WaitForPathCleanup;
|
2019-10-04 21:20:51 -03:00
|
|
|
_loitering = false;
|
2017-11-29 21:58:11 -04:00
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ModeSmartRTL::update()
|
|
|
|
{
|
|
|
|
switch (smart_rtl_state) {
|
2023-09-21 10:58:41 -03:00
|
|
|
case SmartRTLState::WaitForPathCleanup:
|
2017-11-29 21:58:11 -04:00
|
|
|
// check if return path is computed and if yes, begin journey home
|
|
|
|
if (g2.smart_rtl.request_thorough_cleanup()) {
|
2023-09-21 10:58:41 -03:00
|
|
|
smart_rtl_state = SmartRTLState::PathFollow;
|
2017-11-29 21:58:11 -04:00
|
|
|
_load_point = true;
|
|
|
|
}
|
|
|
|
// Note: this may lead to an unnecessary 20ms slow down of the vehicle (but it is unlikely)
|
|
|
|
stop_vehicle();
|
|
|
|
break;
|
|
|
|
|
2023-09-21 10:58:41 -03:00
|
|
|
case SmartRTLState::PathFollow:
|
2017-11-29 21:58:11 -04:00
|
|
|
// load point if required
|
|
|
|
if (_load_point) {
|
2021-11-18 23:38:12 -04:00
|
|
|
Vector3f dest_NED;
|
|
|
|
if (!g2.smart_rtl.pop_point(dest_NED)) {
|
2017-11-29 21:58:11 -04:00
|
|
|
// if not more points, we have reached home
|
|
|
|
gcs().send_text(MAV_SEVERITY_INFO, "Reached destination");
|
2023-09-21 10:58:41 -03:00
|
|
|
smart_rtl_state = SmartRTLState::StopAtHome;
|
2017-11-29 21:58:11 -04:00
|
|
|
break;
|
2021-11-18 23:38:12 -04:00
|
|
|
} else {
|
|
|
|
// peek at the next point. this can fail if the IO task currently has the path semaphore
|
|
|
|
Vector3f next_dest_NED;
|
|
|
|
if (g2.smart_rtl.peek_point(next_dest_NED)) {
|
|
|
|
if (!g2.wp_nav.set_desired_location_NED(dest_NED, next_dest_NED)) {
|
|
|
|
// this should never happen because the EKF origin should already be set
|
|
|
|
gcs().send_text(MAV_SEVERITY_INFO, "SmartRTL: failed to set destination");
|
2023-09-21 10:58:41 -03:00
|
|
|
smart_rtl_state = SmartRTLState::Failure;
|
2021-11-18 23:38:12 -04:00
|
|
|
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// no next point so add only immediate point
|
|
|
|
if (!g2.wp_nav.set_desired_location_NED(dest_NED)) {
|
|
|
|
// this should never happen because the EKF origin should already be set
|
|
|
|
gcs().send_text(MAV_SEVERITY_INFO, "SmartRTL: failed to set destination");
|
2023-09-21 10:58:41 -03:00
|
|
|
smart_rtl_state = SmartRTLState::Failure;
|
2021-11-18 23:38:12 -04:00
|
|
|
INTERNAL_ERROR(AP_InternalError::error_t::flow_of_control);
|
|
|
|
}
|
|
|
|
}
|
2017-11-29 21:58:11 -04:00
|
|
|
}
|
|
|
|
_load_point = false;
|
|
|
|
}
|
2019-04-29 03:31:45 -03:00
|
|
|
// update navigation controller
|
|
|
|
navigate_to_waypoint();
|
|
|
|
|
2017-11-29 21:58:11 -04:00
|
|
|
// check if we've reached the next point
|
2019-04-29 03:31:45 -03:00
|
|
|
if (g2.wp_nav.reached_destination()) {
|
2017-11-29 21:58:11 -04:00
|
|
|
_load_point = true;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
2023-09-21 10:58:41 -03:00
|
|
|
case SmartRTLState::StopAtHome:
|
|
|
|
case SmartRTLState::Failure:
|
2017-11-29 21:58:11 -04:00
|
|
|
_reached_destination = true;
|
2019-10-04 15:26:56 -03:00
|
|
|
// we have reached the destination
|
|
|
|
// boats loiters, rovers stop
|
|
|
|
if (!rover.is_boat()) {
|
|
|
|
stop_vehicle();
|
2017-12-06 22:43:13 -04:00
|
|
|
} else {
|
2019-10-04 21:20:51 -03:00
|
|
|
// if not loitering yet, start loitering
|
|
|
|
if (!_loitering) {
|
|
|
|
_loitering = rover.mode_loiter.enter();
|
|
|
|
}
|
|
|
|
if (_loitering) {
|
|
|
|
rover.mode_loiter.update();
|
|
|
|
} else {
|
|
|
|
stop_vehicle();
|
2019-10-04 15:26:56 -03:00
|
|
|
}
|
2017-12-06 22:43:13 -04:00
|
|
|
}
|
2017-11-29 21:58:11 -04:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-17 03:55:31 -03:00
|
|
|
// get desired location
|
|
|
|
bool ModeSmartRTL::get_desired_location(Location& destination) const
|
|
|
|
{
|
|
|
|
switch (smart_rtl_state) {
|
2023-09-21 10:58:41 -03:00
|
|
|
case SmartRTLState::WaitForPathCleanup:
|
2019-05-17 03:55:31 -03:00
|
|
|
return false;
|
2023-09-21 10:58:41 -03:00
|
|
|
case SmartRTLState::PathFollow:
|
2019-05-17 03:55:31 -03:00
|
|
|
if (g2.wp_nav.is_destination_valid()) {
|
|
|
|
destination = g2.wp_nav.get_destination();
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
return false;
|
2023-09-21 10:58:41 -03:00
|
|
|
case SmartRTLState::StopAtHome:
|
|
|
|
case SmartRTLState::Failure:
|
2019-05-17 03:55:31 -03:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
// should never reach here but just in case
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2019-11-04 04:31:13 -04:00
|
|
|
// set desired speed in m/s
|
|
|
|
bool ModeSmartRTL::set_desired_speed(float speed)
|
|
|
|
{
|
2022-01-05 20:43:58 -04:00
|
|
|
return g2.wp_nav.set_speed_max(speed);
|
2019-11-04 04:31:13 -04:00
|
|
|
}
|
|
|
|
|
2017-11-29 21:58:11 -04:00
|
|
|
// save current position for use by the smart_rtl flight mode
|
2018-02-12 01:16:23 -04:00
|
|
|
void ModeSmartRTL::save_position()
|
2017-11-29 21:58:11 -04:00
|
|
|
{
|
2018-02-12 01:16:23 -04:00
|
|
|
const bool save_pos = (rover.control_mode != &rover.mode_smartrtl);
|
2017-11-29 21:58:11 -04:00
|
|
|
g2.smart_rtl.update(true, save_pos);
|
|
|
|
}
|