2017-07-18 23:17:45 -03:00
# include "mode.h"
# include "Rover.h"
Mode : : Mode ( ) :
2017-08-03 05:08:09 -03:00
ahrs ( rover . ahrs ) ,
2017-07-18 23:17:45 -03:00
g ( rover . g ) ,
g2 ( rover . g2 ) ,
channel_steer ( rover . channel_steer ) ,
channel_throttle ( rover . channel_throttle ) ,
2018-05-10 04:10:34 -03:00
channel_lateral ( rover . channel_lateral ) ,
2017-08-08 02:37:21 -03:00
attitude_control ( rover . g2 . attitude_control )
2017-07-18 23:17:45 -03:00
{ }
void Mode : : exit ( )
{
// call sub-classes exit
_exit ( ) ;
}
2018-01-22 07:00:47 -04:00
bool Mode : : enter ( )
2017-11-29 02:30:37 -04:00
{
2018-01-22 07:00:47 -04:00
const bool ignore_checks = ! hal . util - > get_soft_armed ( ) ; // allow switching to any mode if disarmed. We rely on the arming check to perform
if ( ! ignore_checks ) {
2017-11-29 02:30:37 -04:00
2018-01-22 07:00:47 -04:00
// get EKF filter status
nav_filter_status filt_status ;
rover . ahrs . get_filter_status ( filt_status ) ;
2017-11-29 02:30:37 -04:00
2018-01-22 07:00:47 -04:00
// check position estimate. requires origin and at least one horizontal position flag to be true
2018-12-18 06:28:20 -04:00
const bool position_ok = rover . ekf_position_ok ( ) & & ! rover . failsafe . ekf ;
2018-01-22 07:00:47 -04:00
if ( requires_position ( ) & & ! position_ok ) {
2017-11-29 02:30:37 -04:00
return false ;
}
2018-01-22 07:00:47 -04:00
// check velocity estimate (if we have position estimate, we must have velocity estimate)
if ( requires_velocity ( ) & & ! position_ok & & ! filt_status . flags . horiz_vel ) {
2017-11-29 02:30:37 -04:00
return false ;
}
}
2018-08-22 02:21:37 -03:00
bool ret = _enter ( ) ;
// initialisation common to all modes
if ( ret ) {
set_reversed ( false ) ;
2018-09-14 04:09:07 -03:00
// clear sailboat tacking flags
2019-05-07 15:20:02 -03:00
rover . g2 . sailboat . clear_tack ( ) ;
2018-08-22 02:21:37 -03:00
}
return ret ;
2017-07-18 23:17:45 -03:00
}
2018-05-05 22:47:59 -03:00
// decode pilot steering and throttle inputs and return in steer_out and throttle_out arguments
2018-05-03 05:57:40 -03:00
// steering_out is in the range -4500 ~ +4500 with positive numbers meaning rotate clockwise
// throttle_out is in the range -100 ~ +100
2018-05-05 22:47:59 -03:00
void Mode : : get_pilot_input ( float & steering_out , float & throttle_out )
2017-11-27 09:11:45 -04:00
{
2017-11-29 03:12:13 -04:00
// no RC input means no throttle and centered steering
if ( rover . failsafe . bits & FAILSAFE_EVENT_THROTTLE ) {
steering_out = 0 ;
throttle_out = 0 ;
return ;
}
2017-11-27 09:11:45 -04:00
// apply RC skid steer mixing
switch ( ( enum pilot_steer_type_t ) rover . g . pilot_steer_type . get ( ) )
{
case PILOT_STEER_TYPE_DEFAULT :
2018-05-03 05:57:40 -03:00
case PILOT_STEER_TYPE_DIR_REVERSED_WHEN_REVERSING :
2017-11-27 09:11:45 -04:00
default : {
// by default regular and skid-steering vehicles reverse their rotation direction when backing up
throttle_out = rover . channel_throttle - > get_control_in ( ) ;
2018-05-03 05:57:40 -03:00
const float steering_dir = is_negative ( throttle_out ) ? - 1 : 1 ;
steering_out = steering_dir * rover . channel_steer - > get_control_in ( ) ;
2017-11-27 09:11:45 -04:00
break ;
}
case PILOT_STEER_TYPE_TWO_PADDLES : {
// convert the two radio_in values from skid steering values
// left paddle from steering input channel, right paddle from throttle input channel
// steering = left-paddle - right-paddle
// throttle = average(left-paddle, right-paddle)
const float left_paddle = rover . channel_steer - > norm_input ( ) ;
const float right_paddle = rover . channel_throttle - > norm_input ( ) ;
throttle_out = 0.5f * ( left_paddle + right_paddle ) * 100.0f ;
2018-05-03 05:57:40 -03:00
steering_out = ( left_paddle - right_paddle ) * 0.5f * 4500.0f ;
2017-11-27 09:11:45 -04:00
break ;
}
case PILOT_STEER_TYPE_DIR_UNCHANGED_WHEN_REVERSING : {
throttle_out = rover . channel_throttle - > get_control_in ( ) ;
2018-05-03 05:57:40 -03:00
steering_out = rover . channel_steer - > get_control_in ( ) ;
2017-11-27 09:11:45 -04:00
break ;
}
}
}
2018-05-05 22:47:59 -03:00
// decode pilot steering and throttle inputs and return in steer_out and throttle_out arguments
// steering_out is in the range -4500 ~ +4500 with positive numbers meaning rotate clockwise
// throttle_out is in the range -100 ~ +100
void Mode : : get_pilot_desired_steering_and_throttle ( float & steering_out , float & throttle_out )
{
// do basic conversion
get_pilot_input ( steering_out , throttle_out ) ;
// check for special case of input and output throttle being in opposite directions
float throttle_out_limited = g2 . motors . get_slew_limited_throttle ( throttle_out , rover . G_Dt ) ;
if ( ( is_negative ( throttle_out ) ! = is_negative ( throttle_out_limited ) ) & &
( ( g . pilot_steer_type = = PILOT_STEER_TYPE_DEFAULT ) | |
( g . pilot_steer_type = = PILOT_STEER_TYPE_DIR_REVERSED_WHEN_REVERSING ) ) ) {
steering_out * = - 1 ;
}
throttle_out = throttle_out_limited ;
}
// decode pilot steering and return steering_out and speed_out (in m/s)
void Mode : : get_pilot_desired_steering_and_speed ( float & steering_out , float & speed_out )
{
float desired_throttle ;
get_pilot_input ( steering_out , desired_throttle ) ;
speed_out = desired_throttle * 0.01f * calc_speed_max ( g . speed_cruise , g . throttle_cruise * 0.01f ) ;
// check for special case of input and output throttle being in opposite directions
2018-05-21 22:05:20 -03:00
float speed_out_limited = g2 . attitude_control . get_desired_speed_accel_limited ( speed_out , rover . G_Dt ) ;
2018-05-05 22:47:59 -03:00
if ( ( is_negative ( speed_out ) ! = is_negative ( speed_out_limited ) ) & &
( ( g . pilot_steer_type = = PILOT_STEER_TYPE_DEFAULT ) | |
( g . pilot_steer_type = = PILOT_STEER_TYPE_DIR_REVERSED_WHEN_REVERSING ) ) ) {
steering_out * = - 1 ;
}
speed_out = speed_out_limited ;
}
2018-05-10 04:10:34 -03:00
// decode pilot lateral movement input and return in lateral_out argument
void Mode : : get_pilot_desired_lateral ( float & lateral_out )
{
// no RC input means no lateral input
2019-07-16 17:40:08 -03:00
if ( ( rover . failsafe . bits & FAILSAFE_EVENT_THROTTLE ) | | ( rover . channel_lateral = = nullptr ) ) {
2018-05-10 04:10:34 -03:00
lateral_out = 0 ;
return ;
}
// get pilot lateral input
lateral_out = rover . channel_lateral - > get_control_in ( ) ;
}
2018-07-02 04:21:37 -03:00
// decode pilot's input and return heading_out (in cd) and speed_out (in m/s)
void Mode : : get_pilot_desired_heading_and_speed ( float & heading_out , float & speed_out )
{
2018-09-10 01:45:06 -03:00
// get steering and throttle in the -1 to +1 range
2018-09-11 02:20:39 -03:00
const float desired_steering = constrain_float ( rover . channel_steer - > norm_input_dz ( ) , - 1.0f , 1.0f ) ;
const float desired_throttle = constrain_float ( rover . channel_throttle - > norm_input_dz ( ) , - 1.0f , 1.0f ) ;
2018-07-02 04:21:37 -03:00
// calculate angle of input stick vector
2018-09-10 01:45:06 -03:00
heading_out = wrap_360_cd ( atan2f ( desired_steering , desired_throttle ) * DEGX100 ) ;
2018-07-02 04:21:37 -03:00
2018-09-11 02:20:39 -03:00
// calculate throttle using magnitude of input stick vector
const float throttle = MIN ( safe_sqrt ( sq ( desired_throttle ) + sq ( desired_steering ) ) , 1.0f ) ;
2018-07-02 04:21:37 -03:00
speed_out = throttle * calc_speed_max ( g . speed_cruise , g . throttle_cruise * 0.01f ) ;
}
2018-12-11 10:04:50 -04:00
// return heading (in degrees) to target destination (aka waypoint)
float Mode : : wp_bearing ( ) const
{
if ( ! is_autopilot_mode ( ) ) {
return 0.0f ;
}
2019-04-29 03:31:45 -03:00
return g2 . wp_nav . wp_bearing_cd ( ) * 0.01f ;
2018-12-11 10:04:50 -04:00
}
// return short-term target heading in degrees (i.e. target heading back to line between waypoints)
float Mode : : nav_bearing ( ) const
{
if ( ! is_autopilot_mode ( ) ) {
return 0.0f ;
}
2019-04-29 03:31:45 -03:00
return g2 . wp_nav . nav_bearing_cd ( ) * 0.01f ;
2018-12-11 10:04:50 -04:00
}
// return cross track error (i.e. vehicle's distance from the line between waypoints)
float Mode : : crosstrack_error ( ) const
{
if ( ! is_autopilot_mode ( ) ) {
return 0.0f ;
}
2019-04-29 03:31:45 -03:00
return g2 . wp_nav . crosstrack_error ( ) ;
2018-12-11 10:04:50 -04:00
}
2019-05-06 02:57:03 -03:00
// return desired lateral acceleration
float Mode : : get_desired_lat_accel ( ) const
{
if ( ! is_autopilot_mode ( ) ) {
return 0.0f ;
}
return g2 . wp_nav . get_lat_accel ( ) ;
}
2018-12-11 10:04:50 -04:00
2017-08-03 05:08:09 -03:00
// set desired location
2019-05-08 21:54:40 -03:00
bool Mode : : set_desired_location ( const struct Location & destination , float next_leg_bearing_cd )
2017-07-18 23:17:45 -03:00
{
2019-05-08 21:54:40 -03:00
if ( ! g2 . wp_nav . set_desired_location ( destination , next_leg_bearing_cd ) ) {
return false ;
}
2017-08-03 05:08:09 -03:00
// initialise distance
2019-04-29 03:31:45 -03:00
_distance_to_destination = g2 . wp_nav . get_distance_to_destination ( ) ;
2017-08-03 05:08:09 -03:00
_reached_destination = false ;
2019-05-08 21:54:40 -03:00
return true ;
2017-11-30 00:08:49 -04:00
}
2017-08-03 05:08:09 -03:00
// set desired heading and speed
void Mode : : set_desired_heading_and_speed ( float yaw_angle_cd , float target_speed )
{
// handle initialisation
_reached_destination = false ;
2017-07-18 23:17:45 -03:00
2017-08-03 05:08:09 -03:00
// record targets
_desired_yaw_cd = yaw_angle_cd ;
_desired_speed = target_speed ;
}
2017-07-18 23:17:45 -03:00
2019-05-09 08:22:51 -03:00
// get default speed for this mode (held in WP_SPEED or RTL_SPEED)
2017-12-05 21:41:28 -04:00
float Mode : : get_speed_default ( bool rtl ) const
{
if ( rtl & & is_positive ( g2 . rtl_speed ) ) {
return g2 . rtl_speed ;
}
2019-04-29 03:31:45 -03:00
return g2 . wp_nav . get_default_speed ( ) ;
2017-12-05 21:41:28 -04:00
}
2019-04-29 03:31:45 -03:00
// restore desired speed to default from parameter values (WP_SPEED)
2017-12-05 21:41:28 -04:00
void Mode : : set_desired_speed_to_default ( bool rtl )
{
_desired_speed = get_speed_default ( rtl ) ;
}
2018-06-08 22:19:41 -03:00
// set desired speed in m/s
bool Mode : : set_desired_speed ( float speed )
{
if ( ! is_negative ( speed ) ) {
_desired_speed = speed ;
return true ;
}
return false ;
}
2018-08-08 01:48:38 -03:00
// execute the mission in reverse (i.e. backing up)
void Mode : : set_reversed ( bool value )
{
2019-04-29 03:31:45 -03:00
g2 . wp_nav . set_reversed ( value ) ;
2018-08-08 01:48:38 -03:00
}
2018-09-14 04:09:07 -03:00
// handle tacking request (from auxiliary switch) in sailboats
void Mode : : handle_tack_request ( )
{
// autopilot modes handle tacking
if ( is_autopilot_mode ( ) ) {
2019-05-07 15:20:02 -03:00
rover . g2 . sailboat . handle_tack_request_auto ( ) ;
2018-09-14 04:09:07 -03:00
}
}
2019-05-04 00:09:24 -03:00
void Mode : : calc_throttle ( float target_speed , bool avoidance_enabled )
2017-08-03 05:08:09 -03:00
{
2018-04-21 03:45:12 -03:00
// get acceleration limited target speed
2018-05-21 22:05:20 -03:00
target_speed = attitude_control . get_desired_speed_accel_limited ( target_speed , rover . G_Dt ) ;
2018-04-21 03:45:12 -03:00
2018-05-22 01:30:32 -03:00
// apply object avoidance to desired speed using half vehicle's maximum deceleration
2018-04-21 03:45:12 -03:00
if ( avoidance_enabled ) {
2018-05-22 01:30:32 -03:00
g2 . avoid . adjust_speed ( 0.0f , 0.5f * attitude_control . get_decel_max ( ) , ahrs . yaw , target_speed , rover . G_Dt ) ;
2018-04-21 03:45:12 -03:00
}
2017-08-08 21:24:30 -03:00
// call throttle controller and convert output to -100 to +100 range
2018-02-18 21:29:49 -04:00
float throttle_out ;
// call speed or stop controller
2018-12-13 03:54:02 -04:00
if ( is_zero ( target_speed ) & & ! rover . is_balancebot ( ) ) {
2018-02-18 21:29:49 -04:00
bool stopped ;
2018-05-21 22:05:20 -03:00
throttle_out = 100.0f * attitude_control . get_throttle_out_stop ( g2 . motors . limit . throttle_lower , g2 . motors . limit . throttle_upper , g . speed_cruise , g . throttle_cruise * 0.01f , rover . G_Dt , stopped ) ;
2018-02-18 21:29:49 -04:00
} else {
2018-05-21 22:05:20 -03:00
throttle_out = 100.0f * attitude_control . get_throttle_out_speed ( target_speed , g2 . motors . limit . throttle_lower , g2 . motors . limit . throttle_upper , g . speed_cruise , g . throttle_cruise * 0.01f , rover . G_Dt ) ;
2018-02-18 21:29:49 -04:00
}
2017-07-18 23:17:45 -03:00
2018-06-21 09:36:58 -03:00
// if vehicle is balance bot, calculate actual throttle required for balancing
if ( rover . is_balancebot ( ) ) {
2018-08-04 04:25:07 -03:00
rover . balancebot_pitch_control ( throttle_out ) ;
2018-06-21 09:36:58 -03:00
}
2018-09-25 10:09:47 -03:00
// update mainsail position if present
2019-05-07 15:20:02 -03:00
rover . g2 . sailboat . update_mainsail ( target_speed ) ;
2018-09-25 10:09:47 -03:00
2017-08-15 22:32:56 -03:00
// send to motor
g2 . motors . set_throttle ( throttle_out ) ;
2017-08-08 21:24:30 -03:00
}
2017-07-18 23:17:45 -03:00
2017-08-10 00:06:43 -03:00
// performs a controlled stop with steering centered
bool Mode : : stop_vehicle ( )
{
// call throttle controller and convert output to -100 to +100 range
bool stopped = false ;
2018-12-13 03:54:02 -04:00
float throttle_out ;
2017-08-10 00:06:43 -03:00
2018-12-13 03:54:02 -04:00
// if vehicle is balance bot, calculate throttle required for balancing
2018-07-23 03:20:46 -03:00
if ( rover . is_balancebot ( ) ) {
2018-12-13 03:54:02 -04:00
throttle_out = 100.0f * attitude_control . get_throttle_out_speed ( 0 , g2 . motors . limit . throttle_lower , g2 . motors . limit . throttle_upper , g . speed_cruise , g . throttle_cruise * 0.01f , rover . G_Dt ) ;
2018-08-04 04:25:07 -03:00
rover . balancebot_pitch_control ( throttle_out ) ;
2018-12-13 03:54:02 -04:00
} else {
throttle_out = 100.0f * attitude_control . get_throttle_out_stop ( g2 . motors . limit . throttle_lower , g2 . motors . limit . throttle_upper , g . speed_cruise , g . throttle_cruise * 0.01f , rover . G_Dt , stopped ) ;
2018-07-23 03:20:46 -03:00
}
2018-09-25 10:09:47 -03:00
// relax mainsail if present
g2 . motors . set_mainsail ( 100.0f ) ;
2017-08-15 22:32:56 -03:00
// send to motor
g2 . motors . set_throttle ( throttle_out ) ;
2017-08-10 00:06:43 -03:00
// do not attempt to steer
g2 . motors . set_steering ( 0.0f ) ;
// return true once stopped
return stopped ;
}
2017-08-08 21:24:30 -03:00
// estimate maximum vehicle speed (in m/s)
2017-12-31 23:46:46 -04:00
// cruise_speed is in m/s, cruise_throttle should be in the range -1 to +1
float Mode : : calc_speed_max ( float cruise_speed , float cruise_throttle ) const
2017-08-08 21:24:30 -03:00
{
float speed_max ;
2017-07-18 23:17:45 -03:00
2017-08-08 21:24:30 -03:00
// sanity checks
if ( cruise_throttle > 1.0f | | cruise_throttle < 0.05f ) {
speed_max = cruise_speed ;
2017-07-18 23:17:45 -03:00
} else {
2017-08-08 21:24:30 -03:00
// project vehicle's maximum speed
speed_max = ( 1.0f / cruise_throttle ) * cruise_speed ;
2017-07-18 23:17:45 -03:00
}
2017-08-08 21:24:30 -03:00
// constrain to 30m/s (108km/h) and return
return constrain_float ( speed_max , 0.0f , 30.0f ) ;
2017-07-18 23:17:45 -03:00
}
2017-08-08 21:24:30 -03:00
// calculate pilot input to nudge speed up or down
// target_speed should be in meters/sec
2019-05-04 00:09:24 -03:00
// reversed should be true if the vehicle is intentionally backing up which allows the pilot to increase the backing up speed by pulling the throttle stick down
float Mode : : calc_speed_nudge ( float target_speed , bool reversed )
2017-07-18 04:27:05 -03:00
{
2018-11-13 22:47:34 -04:00
// return immediately during RC/GCS failsafe
if ( rover . failsafe . bits & FAILSAFE_EVENT_THROTTLE ) {
return target_speed ;
}
2017-08-08 21:24:30 -03:00
// return immediately if pilot is not attempting to nudge speed
// pilot can nudge up speed if throttle (in range -100 to +100) is above 50% of center in direction of travel
const int16_t pilot_throttle = constrain_int16 ( rover . channel_throttle - > get_control_in ( ) , - 100 , 100 ) ;
2019-05-04 00:09:24 -03:00
if ( ( ( pilot_throttle < = 50 ) & & ! reversed ) | |
( ( pilot_throttle > = - 50 ) & & reversed ) ) {
2017-08-08 21:24:30 -03:00
return target_speed ;
}
// sanity checks
2019-05-04 00:09:24 -03:00
if ( g . throttle_cruise > 100 | | g . throttle_cruise < 5 ) {
2017-08-08 21:24:30 -03:00
return target_speed ;
}
// project vehicle's maximum speed
2019-05-04 00:09:24 -03:00
const float vehicle_speed_max = calc_speed_max ( g . speed_cruise , g . throttle_cruise * 0.01f ) ;
2017-08-08 21:24:30 -03:00
// return unadjusted target if already over vehicle's projected maximum speed
2018-01-18 20:23:33 -04:00
if ( fabsf ( target_speed ) > = vehicle_speed_max ) {
2017-08-08 21:24:30 -03:00
return target_speed ;
}
const float speed_increase_max = vehicle_speed_max - fabsf ( target_speed ) ;
2017-08-16 05:35:36 -03:00
float speed_nudge = ( ( static_cast < float > ( abs ( pilot_throttle ) ) - 50.0f ) * 0.02f ) * speed_increase_max ;
2017-08-08 21:24:30 -03:00
if ( pilot_throttle < 0 ) {
speed_nudge = - speed_nudge ;
2017-07-18 04:27:05 -03:00
}
2017-08-08 21:24:30 -03:00
return target_speed + speed_nudge ;
2017-07-18 04:27:05 -03:00
}
2019-04-29 03:31:45 -03:00
// high level call to navigate to waypoint
// uses wp_nav to calculate turn rate and speed to drive along the path from origin to destination
2019-05-04 03:29:18 -03:00
// this function updates _distance_to_destination
2019-04-29 03:31:45 -03:00
void Mode : : navigate_to_waypoint ( )
2017-08-03 05:08:09 -03:00
{
2019-04-29 03:31:45 -03:00
// update navigation controller
g2 . wp_nav . update ( rover . G_Dt ) ;
_distance_to_destination = g2 . wp_nav . get_distance_to_destination ( ) ;
2017-08-03 05:08:09 -03:00
2019-05-04 00:09:24 -03:00
// pass speed to throttle controller after applying nudge from pilot
float desired_speed = g2 . wp_nav . get_speed ( ) ;
desired_speed = calc_speed_nudge ( desired_speed , g2 . wp_nav . get_reversed ( ) ) ;
calc_throttle ( desired_speed , true ) ;
2017-08-03 05:08:09 -03:00
2019-04-29 03:31:45 -03:00
float desired_heading_cd = g2 . wp_nav . wp_bearing_cd ( ) ;
2019-05-07 15:20:02 -03:00
if ( g2 . sailboat . use_indirect_route ( desired_heading_cd ) ) {
2019-04-29 03:31:45 -03:00
// sailboats use heading controller when tacking upwind
2019-05-07 15:20:02 -03:00
desired_heading_cd = g2 . sailboat . calc_heading ( desired_heading_cd ) ;
2019-04-29 03:31:45 -03:00
calc_steering_to_heading ( desired_heading_cd , g2 . wp_nav . get_pivot_rate ( ) ) ;
} else {
// call turn rate steering controller
calc_steering_from_turn_rate ( g2 . wp_nav . get_turn_rate_rads ( ) , desired_speed , g2 . wp_nav . get_reversed ( ) ) ;
2017-08-03 05:08:09 -03:00
}
}
2019-04-29 03:31:45 -03:00
// calculate steering output given a turn rate and speed
void Mode : : calc_steering_from_turn_rate ( float turn_rate , float speed , bool reversed )
2017-07-18 23:17:45 -03:00
{
2019-04-29 03:31:45 -03:00
// add obstacle avoidance response to lateral acceleration target
// ToDo: replace this type of object avoidance with path planning
if ( ! reversed ) {
const float lat_accel_adj = ( rover . obstacle . turn_angle / 45.0f ) * g . turn_max_g ;
turn_rate + = attitude_control . get_turn_rate_from_lat_accel ( lat_accel_adj , speed ) ;
}
// calculate and send final steering command to motor library
const float steering_out = attitude_control . get_steering_out_rate ( turn_rate ,
g2 . motors . limit . steer_left ,
g2 . motors . limit . steer_right ,
rover . G_Dt ) ;
g2 . motors . set_steering ( steering_out * 4500.0f ) ;
2017-07-18 23:17:45 -03:00
}
/*
2017-11-27 07:57:59 -04:00
calculate steering output given lateral_acceleration
2017-07-18 23:17:45 -03:00
*/
2017-12-23 02:17:49 -04:00
void Mode : : calc_steering_from_lateral_acceleration ( float lat_accel , bool reversed )
2017-07-18 23:17:45 -03:00
{
2017-08-03 05:08:09 -03:00
// add obstacle avoidance response to lateral acceleration target
2018-05-06 01:41:37 -03:00
// ToDo: replace this type of object avoidance with path planning
2017-08-03 03:19:57 -03:00
if ( ! reversed ) {
2017-12-23 02:17:49 -04:00
lat_accel + = ( rover . obstacle . turn_angle / 45.0f ) * g . turn_max_g ;
2017-07-18 23:17:45 -03:00
}
// constrain to max G force
2017-12-23 02:17:49 -04:00
lat_accel = constrain_float ( lat_accel , - g . turn_max_g * GRAVITY_MSS , g . turn_max_g * GRAVITY_MSS ) ;
2017-07-18 23:17:45 -03:00
// send final steering command to motor library
2018-04-09 09:12:07 -03:00
const float steering_out = attitude_control . get_steering_out_lat_accel ( lat_accel ,
g2 . motors . limit . steer_left ,
2018-05-21 22:05:20 -03:00
g2 . motors . limit . steer_right ,
rover . G_Dt ) ;
2019-04-20 20:02:51 -03:00
set_steering ( steering_out * 4500.0f ) ;
2017-07-18 23:17:45 -03:00
}
2017-12-23 01:54:35 -04:00
// calculate steering output to drive towards desired heading
2018-09-10 04:25:27 -03:00
// rate_max is a maximum turn rate in deg/s. set to zero to use default turn rate limits
void Mode : : calc_steering_to_heading ( float desired_heading_cd , float rate_max_degs )
2017-12-23 01:54:35 -04:00
{
2018-07-07 04:04:54 -03:00
// call heading controller
2018-04-09 09:12:07 -03:00
const float steering_out = attitude_control . get_steering_out_heading ( radians ( desired_heading_cd * 0.01f ) ,
2018-09-10 04:25:27 -03:00
radians ( rate_max_degs ) ,
2018-04-09 09:12:07 -03:00
g2 . motors . limit . steer_left ,
2018-05-21 22:05:20 -03:00
g2 . motors . limit . steer_right ,
rover . G_Dt ) ;
2019-04-20 20:02:51 -03:00
set_steering ( steering_out * 4500.0f ) ;
2017-12-23 01:54:35 -04:00
}
2018-03-13 09:06:13 -03:00
// calculate vehicle stopping point using current location, velocity and maximum acceleration
void Mode : : calc_stopping_location ( Location & stopping_loc )
{
// default stopping location
stopping_loc = rover . current_loc ;
// get current velocity vector and speed
const Vector2f velocity = ahrs . groundspeed_vector ( ) ;
const float speed = velocity . length ( ) ;
// avoid divide by zero
if ( ! is_positive ( speed ) ) {
stopping_loc = rover . current_loc ;
return ;
}
// get stopping distance in meters
const float stopping_dist = attitude_control . get_stopping_distance ( speed ) ;
// calculate stopping position from current location in meters
const Vector2f stopping_offset = velocity . normalized ( ) * stopping_dist ;
2019-02-24 20:10:39 -04:00
stopping_loc . offset ( stopping_offset . x , stopping_offset . y ) ;
2018-03-13 09:06:13 -03:00
}
2019-01-07 13:22:03 -04:00
2019-04-20 20:02:51 -03:00
void Mode : : set_steering ( float steering_value )
{
2019-04-20 20:10:51 -03:00
if ( allows_stick_mixing ( ) & & g2 . stick_mixing > 0 ) {
steering_value = channel_steer - > stick_mixing ( ( int16_t ) steering_value ) ;
}
steering_value = constrain_float ( steering_value , - 4500.0f , 4500.0f ) ;
2019-04-20 20:02:51 -03:00
g2 . motors . set_steering ( steering_value ) ;
}
2019-01-07 13:22:03 -04:00
Mode * Rover : : mode_from_mode_num ( const enum Mode : : Number num )
{
Mode * ret = nullptr ;
switch ( num ) {
case Mode : : Number : : MANUAL :
ret = & mode_manual ;
break ;
case Mode : : Number : : ACRO :
ret = & mode_acro ;
break ;
case Mode : : Number : : STEERING :
ret = & mode_steering ;
break ;
case Mode : : Number : : HOLD :
ret = & mode_hold ;
break ;
case Mode : : Number : : LOITER :
ret = & mode_loiter ;
break ;
case Mode : : Number : : FOLLOW :
ret = & mode_follow ;
break ;
case Mode : : Number : : SIMPLE :
ret = & mode_simple ;
break ;
case Mode : : Number : : AUTO :
ret = & mode_auto ;
break ;
case Mode : : Number : : RTL :
ret = & mode_rtl ;
break ;
case Mode : : Number : : SMART_RTL :
ret = & mode_smartrtl ;
break ;
case Mode : : Number : : GUIDED :
ret = & mode_guided ;
break ;
case Mode : : Number : : INITIALISING :
ret = & mode_initializing ;
break ;
default :
break ;
}
return ret ;
}