mirror of
https://github.com/ArduPilot/ardupilot
synced 2025-01-04 23:18:28 -04:00
8eb991b610
previously the user would use the LOITER_UNLIMITED or LOITER_TIME mission commands to specify that the vehicle should remain active at the destination. This was cumbersome and not the best way to specify this behaviour because these two commands are valid for regular rovers that should not try to remain active at the destination.
203 lines
5.9 KiB
C++
203 lines
5.9 KiB
C++
#include "mode.h"
|
|
#include "Rover.h"
|
|
|
|
// constructor
|
|
ModeAuto::ModeAuto(ModeRTL& mode_rtl) :
|
|
_mode_rtl(mode_rtl)
|
|
{
|
|
}
|
|
|
|
bool ModeAuto::_enter()
|
|
{
|
|
// fail to enter auto if no mission commands
|
|
if (mission.num_commands() == 0) {
|
|
gcs().send_text(MAV_SEVERITY_NOTICE, "No Mission. Can't set AUTO.");
|
|
return false;
|
|
}
|
|
|
|
// initialise waypoint speed
|
|
set_desired_speed_to_default();
|
|
|
|
// init location target
|
|
set_desired_location(rover.current_loc);
|
|
|
|
// other initialisation
|
|
auto_triggered = false;
|
|
|
|
// initialise reversed to be false
|
|
set_reversed(false);
|
|
|
|
// restart mission processing
|
|
mission.start_or_resume();
|
|
return true;
|
|
}
|
|
|
|
void ModeAuto::_exit()
|
|
{
|
|
// stop running the mission
|
|
if (mission.state() == AP_Mission::MISSION_RUNNING) {
|
|
mission.stop();
|
|
}
|
|
}
|
|
|
|
void ModeAuto::update()
|
|
{
|
|
switch (_submode) {
|
|
case Auto_WP:
|
|
{
|
|
_distance_to_destination = get_distance(rover.current_loc, _destination);
|
|
// check if we've reached the destination
|
|
if (!_reached_destination) {
|
|
if (_distance_to_destination <= rover.g.waypoint_radius || location_passed_point(rover.current_loc, _origin, _destination)) {
|
|
// trigger reached
|
|
_reached_destination = true;
|
|
}
|
|
}
|
|
if (!_reached_destination || rover.is_boat()) {
|
|
// continue driving towards destination
|
|
calc_steering_to_waypoint(_reached_destination ? rover.current_loc : _origin, _destination, _reversed);
|
|
calc_throttle(calc_reduced_speed_for_turn_or_distance(_reversed ? -_desired_speed : _desired_speed), true);
|
|
} else {
|
|
// we have reached the destination so stop
|
|
stop_vehicle();
|
|
lateral_acceleration = 0.0f;
|
|
}
|
|
break;
|
|
}
|
|
|
|
case Auto_HeadingAndSpeed:
|
|
{
|
|
if (!_reached_heading) {
|
|
// run steering and throttle controllers
|
|
const float yaw_error = wrap_PI(radians((_desired_yaw_cd - ahrs.yaw_sensor) * 0.01f));
|
|
const float steering_out = attitude_control.get_steering_out_angle_error(yaw_error, g2.motors.have_skid_steering(), g2.motors.limit.steer_left, g2.motors.limit.steer_right, _desired_speed < 0);
|
|
g2.motors.set_steering(steering_out * 4500.0f);
|
|
calc_throttle(_desired_speed, true);
|
|
// check if we have reached target
|
|
_reached_heading = (fabsf(yaw_error) < radians(5));
|
|
} else {
|
|
stop_vehicle();
|
|
}
|
|
break;
|
|
}
|
|
|
|
case Auto_RTL:
|
|
_mode_rtl.update();
|
|
break;
|
|
}
|
|
}
|
|
|
|
// set desired location to drive to
|
|
void ModeAuto::set_desired_location(const struct Location& destination, float next_leg_bearing_cd)
|
|
{
|
|
// call parent
|
|
Mode::set_desired_location(destination, next_leg_bearing_cd);
|
|
|
|
_submode = Auto_WP;
|
|
}
|
|
|
|
// return true if vehicle has reached or even passed destination
|
|
bool ModeAuto::reached_destination()
|
|
{
|
|
if (_submode == Auto_WP) {
|
|
return _reached_destination;
|
|
}
|
|
if (_submode == Auto_RTL) {
|
|
return _mode_rtl.reached_destination();
|
|
}
|
|
// we should never reach here but just in case, return true to allow missions to continue
|
|
return true;
|
|
}
|
|
|
|
// set desired heading in centidegrees (vehicle will turn to this heading)
|
|
void ModeAuto::set_desired_heading_and_speed(float yaw_angle_cd, float target_speed)
|
|
{
|
|
// call parent
|
|
Mode::set_desired_heading_and_speed(yaw_angle_cd, target_speed);
|
|
|
|
_submode = Auto_HeadingAndSpeed;
|
|
_reached_heading = false;
|
|
}
|
|
|
|
// return true if vehicle has reached desired heading
|
|
bool ModeAuto::reached_heading()
|
|
{
|
|
if (_submode == Auto_HeadingAndSpeed) {
|
|
return _reached_heading;
|
|
}
|
|
// we should never reach here but just in case, return true to allow missions to continue
|
|
return true;
|
|
}
|
|
|
|
// start RTL (within auto)
|
|
void ModeAuto::start_RTL()
|
|
{
|
|
if (_mode_rtl.enter()) {
|
|
_submode = Auto_RTL;
|
|
}
|
|
}
|
|
|
|
// execute the mission in reverse (i.e. backing up)
|
|
void ModeAuto::set_reversed(bool value)
|
|
{
|
|
if (_reversed != value) {
|
|
_reversed = value;
|
|
rover.set_reverse(_reversed);
|
|
}
|
|
}
|
|
|
|
/*
|
|
check for triggering of start of auto mode
|
|
*/
|
|
bool ModeAuto::check_trigger(void)
|
|
{
|
|
// check for user pressing the auto trigger to off
|
|
if (auto_triggered && g.auto_trigger_pin != -1 && rover.check_digital_pin(g.auto_trigger_pin) == 1) {
|
|
gcs().send_text(MAV_SEVERITY_WARNING, "AUTO triggered off");
|
|
auto_triggered = false;
|
|
return false;
|
|
}
|
|
|
|
// if already triggered, then return true, so you don't
|
|
// need to hold the switch down
|
|
if (auto_triggered) {
|
|
return true;
|
|
}
|
|
|
|
// return true if auto trigger and kickstart are disabled
|
|
if (g.auto_trigger_pin == -1 && is_zero(g.auto_kickstart)) {
|
|
// no trigger configured - let's go!
|
|
auto_triggered = true;
|
|
return true;
|
|
}
|
|
|
|
// check if trigger pin has been pushed
|
|
if (g.auto_trigger_pin != -1 && rover.check_digital_pin(g.auto_trigger_pin) == 0) {
|
|
gcs().send_text(MAV_SEVERITY_WARNING, "Triggered AUTO with pin");
|
|
auto_triggered = true;
|
|
return true;
|
|
}
|
|
|
|
// check if mission is started by giving vehicle a kick with acceleration > AUTO_KICKSTART
|
|
if (!is_zero(g.auto_kickstart)) {
|
|
const float xaccel = rover.ins.get_accel().x;
|
|
if (xaccel >= g.auto_kickstart) {
|
|
gcs().send_text(MAV_SEVERITY_WARNING, "Triggered AUTO xaccel=%.1f", static_cast<double>(xaccel));
|
|
auto_triggered = true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void ModeAuto::calc_throttle(float target_speed, bool nudge_allowed)
|
|
{
|
|
// If not autostarting set the throttle to minimum
|
|
if (!check_trigger()) {
|
|
stop_vehicle();
|
|
return;
|
|
}
|
|
Mode::calc_throttle(target_speed, nudge_allowed);
|
|
}
|