You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
167 lines
6.0 KiB
167 lines
6.0 KiB
#include "mode.h" |
|
#include "Rover.h" |
|
|
|
Mode::Mode() : |
|
g(rover.g), |
|
g2(rover.g2), |
|
channel_steer(rover.channel_steer), |
|
channel_throttle(rover.channel_throttle), |
|
mission(rover.mission) |
|
{ } |
|
|
|
void Mode::exit() |
|
{ |
|
// call sub-classes exit |
|
_exit(); |
|
|
|
lateral_acceleration = 0.0f; |
|
rover.throttle = 500; |
|
rover.g.pidSpeedThrottle.reset_I(); |
|
if (!rover.in_auto_reverse) { |
|
rover.set_reverse(false); |
|
} |
|
rover.rtl_complete = false; |
|
} |
|
|
|
bool Mode::enter() |
|
{ |
|
g2.motors.slew_limit_throttle(false); |
|
return _enter(); |
|
} |
|
|
|
void Mode::calc_throttle(float target_speed) |
|
{ |
|
int16_t &throttle = rover.throttle; |
|
const int32_t next_navigation_leg_cd = rover.next_navigation_leg_cd; |
|
const AP_AHRS &ahrs = rover.ahrs; |
|
const float wp_distance = rover.wp_distance; |
|
float &groundspeed_error = rover.groundspeed_error; |
|
const float ground_speed = rover.ground_speed; |
|
|
|
const float throttle_base = (fabsf(target_speed) / g.speed_cruise) * g.throttle_cruise; |
|
const int throttle_target = throttle_base + calc_throttle_nudge(); |
|
|
|
/* |
|
reduce target speed in proportion to turning rate, up to the |
|
SPEED_TURN_GAIN percentage. |
|
*/ |
|
float steer_rate = fabsf(lateral_acceleration / (g.turn_max_g * GRAVITY_MSS)); |
|
steer_rate = constrain_float(steer_rate, 0.0f, 1.0f); |
|
|
|
// use g.speed_turn_gain for a 90 degree turn, and in proportion |
|
// for other turn angles |
|
const int32_t turn_angle = wrap_180_cd(next_navigation_leg_cd - ahrs.yaw_sensor); |
|
const float speed_turn_ratio = constrain_float(fabsf(turn_angle / 9000.0f), 0.0f, 1.0f); |
|
const float speed_turn_reduction = (100 - g.speed_turn_gain) * speed_turn_ratio * 0.01f; |
|
|
|
float reduction = 1.0f - steer_rate * speed_turn_reduction; |
|
|
|
if (is_autopilot_mode() && rover.mode_guided.guided_mode != ModeGuided::Guided_Velocity && wp_distance <= g.speed_turn_dist) { |
|
// in auto-modes we reduce speed when approaching waypoints |
|
const float reduction2 = 1.0f - speed_turn_reduction; |
|
if (reduction2 < reduction) { |
|
reduction = reduction2; |
|
} |
|
} |
|
|
|
// reduce the target speed by the reduction factor |
|
target_speed *= reduction; |
|
|
|
groundspeed_error = fabsf(target_speed) - ground_speed; |
|
|
|
throttle = throttle_target + (g.pidSpeedThrottle.get_pid(groundspeed_error * 100.0f) / 100.0f); |
|
|
|
// also reduce the throttle by the reduction factor. This gives a |
|
// much faster response in turns |
|
throttle *= reduction; |
|
|
|
if (rover.in_reverse) { |
|
g2.motors.set_throttle(constrain_int16(-throttle, -g.throttle_max, -g.throttle_min)); |
|
} else { |
|
g2.motors.set_throttle(constrain_int16(throttle, g.throttle_min, g.throttle_max)); |
|
} |
|
|
|
if (!rover.in_reverse && g.braking_percent != 0 && groundspeed_error < -g.braking_speederr) { |
|
// the user has asked to use reverse throttle to brake. Apply |
|
// it in proportion to the ground speed error, but only when |
|
// our ground speed error is more than BRAKING_SPEEDERR. |
|
// |
|
// We use a linear gain, with 0 gain at a ground speed error |
|
// of braking_speederr, and 100% gain when groundspeed_error |
|
// is 2*braking_speederr |
|
const float brake_gain = constrain_float(((-groundspeed_error)-g.braking_speederr)/g.braking_speederr, 0.0f, 1.0f); |
|
const int16_t braking_throttle = g.throttle_max * (g.braking_percent * 0.01f) * brake_gain; |
|
g2.motors.set_throttle(constrain_int16(-braking_throttle, -g.throttle_max, -g.throttle_min)); |
|
|
|
// temporarily set us in reverse to allow the PWM setting to |
|
// go negative |
|
rover.set_reverse(true); |
|
} |
|
|
|
if (rover.mode_guided.guided_mode != ModeGuided::Guided_Velocity) { |
|
if (rover.use_pivot_steering()) { |
|
// In Guided Velocity, only the steering input is used to calculate the pivot turn. |
|
g2.motors.set_throttle(0.0f); |
|
} |
|
} |
|
} |
|
|
|
void Mode::calc_lateral_acceleration() |
|
{ |
|
calc_lateral_acceleration(rover.current_loc, rover.next_WP); |
|
} |
|
|
|
// calculate pilot input to nudge throttle up or down |
|
int16_t Mode::calc_throttle_nudge() |
|
{ |
|
// get pilot throttle input (-100 to +100) |
|
int16_t pilot_throttle = rover.channel_throttle->get_control_in(); |
|
int16_t throttle_nudge = 0; |
|
|
|
// Check if the throttle value is above 50% and we need to nudge |
|
// Make sure its above 50% in the direction we are travelling |
|
if ((fabsf(pilot_throttle) > 50.0f) && |
|
(((pilot_throttle < 0) && rover.in_reverse) || |
|
((pilot_throttle > 0) && !rover.in_reverse))) { |
|
throttle_nudge = (rover.g.throttle_max - rover.g.throttle_cruise) * ((fabsf(rover.channel_throttle->norm_input()) - 0.5f) / 0.5f); |
|
} |
|
|
|
return throttle_nudge; |
|
} |
|
|
|
/* |
|
* Calculate desired turn angles (in medium freq loop) |
|
*/ |
|
void Mode::calc_lateral_acceleration(const struct Location &last_WP, const struct Location &next_WP) |
|
{ |
|
// Calculate the required turn of the wheels |
|
// negative error = left turn |
|
// positive error = right turn |
|
rover.nav_controller->update_waypoint(last_WP, next_WP); |
|
lateral_acceleration = rover.nav_controller->lateral_acceleration(); |
|
if (rover.use_pivot_steering()) { |
|
const int16_t bearing_error = wrap_180_cd(rover.nav_controller->target_bearing_cd() - rover.ahrs.yaw_sensor) / 100; |
|
if (bearing_error > 0) { |
|
lateral_acceleration = g.turn_max_g * GRAVITY_MSS; |
|
} else { |
|
lateral_acceleration = -g.turn_max_g * GRAVITY_MSS; |
|
} |
|
} |
|
} |
|
|
|
/* |
|
calculate steering angle given lateral_acceleration |
|
*/ |
|
void Mode::calc_nav_steer() |
|
{ |
|
// add in obstacle avoidance |
|
if (!rover.in_reverse) { |
|
lateral_acceleration += (rover.obstacle.turn_angle / 45.0f) * g.turn_max_g; |
|
} |
|
|
|
// constrain to max G force |
|
lateral_acceleration = constrain_float(lateral_acceleration, -g.turn_max_g * GRAVITY_MSS, g.turn_max_g * GRAVITY_MSS); |
|
|
|
// send final steering command to motor library |
|
g2.motors.set_steering(rover.steerController.get_steering_out_lat_accel(lateral_acceleration)); |
|
}
|
|
|