ardupilot/APMrover2/mode_auto.cpp
Randy Mackay 8eb991b610 Rover: boats say active at destination in auto
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.
2017-12-08 08:48:05 +09:00

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);
}