Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.
Path: blob/master/ArduCopter/autoyaw.cpp
Views: 1798
#include "Copter.h"12Mode::AutoYaw Mode::auto_yaw;34// roi_yaw - returns heading towards location held in roi5float Mode::AutoYaw::roi_yaw() const6{7return get_bearing_cd(copter.inertial_nav.get_position_xy_cm(), roi.xy());8}910// returns a yaw in degrees, direction of vehicle travel:11float Mode::AutoYaw::look_ahead_yaw()12{13const Vector3f& vel = copter.inertial_nav.get_velocity_neu_cms();14const float speed_sq = vel.xy().length_squared();15// Commanded Yaw to automatically look ahead.16if (copter.position_ok() && (speed_sq > (YAW_LOOK_AHEAD_MIN_SPEED * YAW_LOOK_AHEAD_MIN_SPEED))) {17_look_ahead_yaw = degrees(atan2f(vel.y,vel.x));18}19return _look_ahead_yaw;20}2122void Mode::AutoYaw::set_mode_to_default(bool rtl)23{24set_mode(default_mode(rtl));25}2627// default_mode - returns auto_yaw.mode() based on WP_YAW_BEHAVIOR parameter28// set rtl parameter to true if this is during an RTL29Mode::AutoYaw::Mode Mode::AutoYaw::default_mode(bool rtl) const30{31switch (copter.g.wp_yaw_behavior) {3233case WP_YAW_BEHAVIOR_NONE:34return Mode::HOLD;3536case WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP_EXCEPT_RTL:37if (rtl) {38return Mode::HOLD;39} else {40return Mode::LOOK_AT_NEXT_WP;41}4243case WP_YAW_BEHAVIOR_LOOK_AHEAD:44return Mode::LOOK_AHEAD;4546case WP_YAW_BEHAVIOR_LOOK_AT_NEXT_WP:47default:48return Mode::LOOK_AT_NEXT_WP;49}50}5152// set_mode - sets the yaw mode for auto53void Mode::AutoYaw::set_mode(Mode yaw_mode)54{55// return immediately if no change56if (_mode == yaw_mode) {57return;58}59_last_mode = _mode;60_mode = yaw_mode;6162// perform initialisation63switch (_mode) {6465case Mode::HOLD:66break;6768case Mode::LOOK_AT_NEXT_WP:69// wpnav will initialise heading when wpnav's set_destination method is called70break;7172case Mode::ROI:73// look ahead until we know otherwise74break;7576case Mode::FIXED:77// keep heading pointing in the direction held in fixed_yaw78// caller should set the fixed_yaw79break;8081case Mode::LOOK_AHEAD:82// Commanded Yaw to automatically look ahead.83_look_ahead_yaw = copter.ahrs.yaw_sensor * 0.01; // cdeg -> deg84break;8586case Mode::RESETTOARMEDYAW:87// initial_armed_bearing will be set during arming so no init required88break;8990case Mode::ANGLE_RATE:91break;9293case Mode::RATE:94// initialise target yaw rate to zero95_yaw_rate_cds = 0.0;96break;9798case Mode::CIRCLE:99case Mode::PILOT_RATE:100case Mode::WEATHERVANE:101// no initialisation required102break;103}104}105106// set_fixed_yaw - sets the yaw look at heading for auto mode107void Mode::AutoYaw::set_fixed_yaw(float angle_deg, float turn_rate_ds, int8_t direction, bool relative_angle)108{109_last_update_ms = millis();110111// calculate final angle as relative to vehicle heading or absolute112if (relative_angle) {113if (_mode == Mode::HOLD) {114_yaw_angle_cd = copter.ahrs.yaw_sensor;115}116_fixed_yaw_offset_cd = angle_deg * 100.0 * (direction >= 0 ? 1.0 : -1.0);117} else {118// absolute angle119_fixed_yaw_offset_cd = wrap_180_cd(angle_deg * 100.0 - _yaw_angle_cd);120if (direction < 0 && is_positive(_fixed_yaw_offset_cd)) {121_fixed_yaw_offset_cd -= 36000.0;122} else if (direction > 0 && is_negative(_fixed_yaw_offset_cd)) {123_fixed_yaw_offset_cd += 36000.0;124}125}126127// get turn speed128if (!is_positive(turn_rate_ds)) {129// default to default slew rate130_fixed_yaw_slewrate_cds = copter.attitude_control->get_slew_yaw_max_degs() * 100.0;131} else {132_fixed_yaw_slewrate_cds = MIN(copter.attitude_control->get_slew_yaw_max_degs(), turn_rate_ds) * 100.0;133}134135// set yaw mode136set_mode(Mode::FIXED);137}138139// set_fixed_yaw - sets the yaw look at heading for auto mode140void Mode::AutoYaw::set_yaw_angle_rate(float yaw_angle_d, float yaw_rate_ds)141{142_last_update_ms = millis();143144_yaw_angle_cd = yaw_angle_d * 100.0;145_yaw_rate_cds = yaw_rate_ds * 100.0;146147// set yaw mode148set_mode(Mode::ANGLE_RATE);149}150151// set_yaw_angle_offset - sets the yaw look at heading for auto mode, as an offset from the current yaw angle152void Mode::AutoYaw::set_yaw_angle_offset(const float yaw_angle_offset_d)153{154_last_update_ms = millis();155156_yaw_angle_cd = wrap_360_cd(_yaw_angle_cd + (yaw_angle_offset_d * 100.0));157_yaw_rate_cds = 0.0f;158159// set yaw mode160set_mode(Mode::ANGLE_RATE);161}162163// set_roi - sets the yaw to look at roi for auto mode164void Mode::AutoYaw::set_roi(const Location &roi_location)165{166// if location is zero lat, lon and altitude turn off ROI167if (roi_location.alt == 0 && roi_location.lat == 0 && roi_location.lng == 0) {168// set auto yaw mode back to default assuming the active command is a waypoint command. A more sophisticated method is required to ensure we return to the proper yaw control for the active command169auto_yaw.set_mode_to_default(false);170#if HAL_MOUNT_ENABLED171// switch off the camera tracking if enabled172copter.camera_mount.clear_roi_target();173#endif // HAL_MOUNT_ENABLED174} else {175#if HAL_MOUNT_ENABLED176// check if mount type requires us to rotate the quad177if (!copter.camera_mount.has_pan_control()) {178if (roi_location.get_vector_from_origin_NEU(roi)) {179auto_yaw.set_mode(Mode::ROI);180}181}182// send the command to the camera mount183copter.camera_mount.set_roi_target(roi_location);184185// TO-DO: expand handling of the do_nav_roi to support all modes of the MAVLink. Currently we only handle mode 4 (see below)186// 0: do nothing187// 1: point at next waypoint188// 2: point at a waypoint taken from WP# parameter (2nd parameter?)189// 3: point at a location given by alt, lon, lat parameters190// 4: point at a target given a target id (can't be implemented)191#else192// if we have no camera mount aim the quad at the location193if (roi_location.get_vector_from_origin_NEU(roi)) {194auto_yaw.set_mode(Mode::ROI);195}196#endif // HAL_MOUNT_ENABLED197}198}199200// set auto yaw rate in centi-degrees per second201void Mode::AutoYaw::set_rate(float turn_rate_cds)202{203set_mode(Mode::RATE);204_yaw_rate_cds = turn_rate_cds;205}206207// return true if fixed yaw target has been reached208bool Mode::AutoYaw::reached_fixed_yaw_target()209{210if (mode() != Mode::FIXED) {211// should not happen, not in the right mode212return true;213}214215if (!is_zero(_fixed_yaw_offset_cd)) {216// still slewing yaw target217return false;218}219220// Within 2 deg of target221return (fabsf(wrap_180_cd(copter.ahrs.yaw_sensor-_yaw_angle_cd)) <= 200);222}223224// yaw_cd - returns target heading depending upon auto_yaw.mode()225float Mode::AutoYaw::yaw_cd()226{227switch (_mode) {228229case Mode::ROI:230// point towards a location held in roi231_yaw_angle_cd = roi_yaw();232break;233234case Mode::FIXED: {235// keep heading pointing in the direction held in fixed_yaw236// with no pilot input allowed237const uint32_t now_ms = millis();238float dt = (now_ms - _last_update_ms) * 0.001;239_last_update_ms = now_ms;240float yaw_angle_step = constrain_float(_fixed_yaw_offset_cd, - dt * _fixed_yaw_slewrate_cds, dt * _fixed_yaw_slewrate_cds);241_fixed_yaw_offset_cd -= yaw_angle_step;242_yaw_angle_cd += yaw_angle_step;243break;244}245246case Mode::LOOK_AHEAD:247// Commanded Yaw to automatically look ahead.248_yaw_angle_cd = look_ahead_yaw() * 100.0;249break;250251case Mode::RESETTOARMEDYAW:252// changes yaw to be same as when quad was armed253_yaw_angle_cd = copter.initial_armed_bearing;254break;255256case Mode::CIRCLE:257#if MODE_CIRCLE_ENABLED258if (copter.circle_nav->is_active()) {259_yaw_angle_cd = copter.circle_nav->get_yaw();260}261#endif262break;263264case Mode::ANGLE_RATE:{265const uint32_t now_ms = millis();266float dt = (now_ms - _last_update_ms) * 0.001;267_last_update_ms = now_ms;268_yaw_angle_cd += _yaw_rate_cds * dt;269break;270}271272case Mode::RATE:273case Mode::WEATHERVANE:274case Mode::PILOT_RATE:275_yaw_angle_cd = copter.attitude_control->get_att_target_euler_cd().z;276break;277278case Mode::LOOK_AT_NEXT_WP:279default:280// point towards next waypoint.281// we don't use wp_bearing because we don't want the copter to turn too much during flight282_yaw_angle_cd = copter.pos_control->get_yaw_cd();283break;284}285286return _yaw_angle_cd;287}288289// returns yaw rate normally set by SET_POSITION_TARGET mavlink290// messages (positive is clockwise, negative is counter clockwise)291float Mode::AutoYaw::rate_cds()292{293switch (_mode) {294295case Mode::HOLD:296case Mode::ROI:297case Mode::FIXED:298case Mode::LOOK_AHEAD:299case Mode::RESETTOARMEDYAW:300case Mode::CIRCLE:301_yaw_rate_cds = 0.0f;302break;303304case Mode::LOOK_AT_NEXT_WP:305_yaw_rate_cds = copter.pos_control->get_yaw_rate_cds();306break;307308case Mode::PILOT_RATE:309_yaw_rate_cds = _pilot_yaw_rate_cds;310break;311312case Mode::ANGLE_RATE:313case Mode::RATE:314case Mode::WEATHERVANE:315break;316}317318// return zero turn rate (this should never happen)319return _yaw_rate_cds;320}321322AC_AttitudeControl::HeadingCommand Mode::AutoYaw::get_heading()323{324// process pilot's yaw input325_pilot_yaw_rate_cds = 0.0;326if (!copter.failsafe.radio && copter.flightmode->use_pilot_yaw()) {327// get pilot's desired yaw rate328_pilot_yaw_rate_cds = copter.flightmode->get_pilot_desired_yaw_rate();329if (!is_zero(_pilot_yaw_rate_cds)) {330auto_yaw.set_mode(AutoYaw::Mode::PILOT_RATE);331}332} else if (auto_yaw.mode() == AutoYaw::Mode::PILOT_RATE) {333// RC failsafe, or disabled make sure not in pilot control334auto_yaw.set_mode(AutoYaw::Mode::HOLD);335}336337#if WEATHERVANE_ENABLED338update_weathervane(_pilot_yaw_rate_cds);339#endif340341AC_AttitudeControl::HeadingCommand heading;342heading.yaw_angle_cd = auto_yaw.yaw_cd();343heading.yaw_rate_cds = auto_yaw.rate_cds();344345switch (auto_yaw.mode()) {346case Mode::HOLD:347case Mode::RATE:348case Mode::PILOT_RATE:349case Mode::WEATHERVANE:350heading.heading_mode = AC_AttitudeControl::HeadingMode::Rate_Only;351break;352case Mode::LOOK_AT_NEXT_WP:353case Mode::ROI:354case Mode::FIXED:355case Mode::LOOK_AHEAD:356case Mode::RESETTOARMEDYAW:357case Mode::ANGLE_RATE:358case Mode::CIRCLE:359heading.heading_mode = AC_AttitudeControl::HeadingMode::Angle_And_Rate;360break;361}362363return heading;364}365366// handle the interface to the weathervane library367// pilot_yaw can be an angle or a rate or rcin from yaw channel. It just needs to represent a pilot's request to yaw the vehicle to enable pilot overrides.368#if WEATHERVANE_ENABLED369void Mode::AutoYaw::update_weathervane(const int16_t pilot_yaw_cds)370{371if (!copter.flightmode->allows_weathervaning()) {372return;373}374375float yaw_rate_cds;376if (copter.g2.weathervane.get_yaw_out(yaw_rate_cds, pilot_yaw_cds, copter.flightmode->get_alt_above_ground_cm()*0.01,377copter.pos_control->get_roll_cd()-copter.attitude_control->get_roll_trim_cd(),378copter.pos_control->get_pitch_cd(),379copter.flightmode->is_taking_off(),380copter.flightmode->is_landing())) {381set_mode(Mode::WEATHERVANE);382_yaw_rate_cds = yaw_rate_cds;383return;384}385386// if the weathervane controller has previously been activated we need to ensure we return control back to what was previously set387if (mode() == Mode::WEATHERVANE) {388_yaw_rate_cds = 0.0;389if (_last_mode == Mode::HOLD) {390set_mode_to_default(false);391} else {392set_mode(_last_mode);393}394}395}396#endif // WEATHERVANE_ENABLED397398399