Path: blob/master/libraries/AC_AttitudeControl/AC_AttitudeControl_TS.cpp
9383 views
/*1This program is free software: you can redistribute it and/or modify2it under the terms of the GNU General Public License as published by3the Free Software Foundation, either version 3 of the License, or4(at your option) any later version.56This program is distributed in the hope that it will be useful,7but WITHOUT ANY WARRANTY; without even the implied warranty of8MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9GNU General Public License for more details.1011You should have received a copy of the GNU General Public License12along with this program. If not, see <http://www.gnu.org/licenses/>.1314This class inherits from AC_AttitudeControl_Multi and provides functionality15specific to tailsitter quadplanes.161) "body-frame" roll control mode for all tailsitters172) a relax_attitude_controller method needed for coping with vectored tailsitters18*/19#include "AC_AttitudeControl_TS.h"2021void AC_AttitudeControl_TS::relax_attitude_controllers(bool exclude_pitch)22{23// If exclude_pitch: relax roll and yaw rate controller outputs only,24// leaving pitch controller active to let TVBS motors tilt up while in throttle_wait25if (exclude_pitch) {26// Get the current attitude quaternion27Quaternion current_attitude;28_ahrs.get_quat_body_to_ned(current_attitude);2930Vector3f current_eulers;31current_attitude.to_euler(current_eulers.x, current_eulers.y, current_eulers.z);3233// set target attitude to zero pitch with (approximate) current roll and yaw34// by rotating the current_attitude quaternion by the error in desired pitch35Quaternion pitch_rotation;36pitch_rotation.from_axis_angle(Vector3f{0, -1, 0}, current_eulers.y);37_attitude_target = current_attitude * pitch_rotation;38_attitude_target.normalize();39_attitude_target.to_euler(_euler_angle_target_rad.x, _euler_angle_target_rad.y, _euler_angle_target_rad.z);40_attitude_ang_error = current_attitude.inverse() * _attitude_target;4142// Initialize the roll and yaw angular rate variables to the current rate43_ang_vel_target_rads = _ahrs.get_gyro();44body_to_euler_derivative(_attitude_target, _ang_vel_target_rads, _euler_rate_target_rads);45_ang_vel_body_rads.x = _ahrs.get_gyro().x;46_ang_vel_body_rads.z = _ahrs.get_gyro().z;4748// Reset the roll and yaw I terms49get_rate_roll_pid().reset_I();50get_rate_yaw_pid().reset_I();51} else {52// relax all attitude controllers53AC_AttitudeControl::relax_attitude_controllers();54}55}5657// Commands a body-frame roll angle (in centidegrees), an euler pitch angle (in centidegrees), and a yaw rate (in centidegrees/s).58// See input_euler_rate_yaw_euler_angle_pitch_bf_roll_rad() for full details.59void AC_AttitudeControl_TS::input_euler_rate_yaw_euler_angle_pitch_bf_roll_cd(bool plane_controls, float body_roll_cd, float euler_pitch_cd, float euler_yaw_rate_cds)60{61// Convert from centidegrees on public interface to radians62float euler_yaw_rate_rads = cd_to_rad(euler_yaw_rate_cds);63float euler_pitch_rad = cd_to_rad(euler_pitch_cd);64float body_roll_rad = cd_to_rad(body_roll_cd);6566input_euler_rate_yaw_euler_angle_pitch_bf_roll_rad(plane_controls, body_roll_rad, euler_pitch_rad, euler_yaw_rate_rads);67}6869// Commands a body-frame roll angle (in radians), an euler pitch angle (in radians), and a yaw rate (in radians/s).70// Used by tailsitter quadplanes. Optionally swaps roll and yaw effects as pitch nears 90° if plane_controls is true.71void AC_AttitudeControl_TS::input_euler_rate_yaw_euler_angle_pitch_bf_roll_rad(bool plane_controls, float body_roll_rad, float euler_pitch_rad, float euler_yaw_rate_rads)72{73euler_pitch_rad = constrain_float(euler_pitch_rad, -radians(90.0), radians(90.0));74body_roll_rad = -body_roll_rad;7576const float cpitch = cosf(euler_pitch_rad);77const float spitch = fabsf(sinf(euler_pitch_rad));7879// Compute attitude error80Quaternion attitude_body;81Quaternion error_quat;82_ahrs.get_quat_body_to_ned(attitude_body);83error_quat = attitude_body.inverse() * _attitude_target;84Vector3f att_error;85error_quat.to_axis_angle(att_error);8687// update heading88float yaw_rate_rads = euler_yaw_rate_rads;89if (plane_controls) {90yaw_rate_rads = (euler_yaw_rate_rads * spitch) + (body_roll_rad * cpitch);91}92// limit yaw error93float yaw_error = fabsf(att_error.z);94float error_ratio = yaw_error / M_PI_2;95if (error_ratio > 1) {96yaw_rate_rads /= (error_ratio * error_ratio);97}98_euler_angle_target_rad.z = wrap_PI(_euler_angle_target_rad.z + yaw_rate_rads * _dt_s);99100// init attitude target to desired euler yaw and pitch with zero roll101_attitude_target.from_euler(0, euler_pitch_rad, _euler_angle_target_rad.z);102103// apply body-frame yaw/roll (this is roll/yaw for a tailsitter in forward flight)104// rotate body_roll_rad axis by |sin(pitch angle)|105Quaternion bf_roll_Q;106bf_roll_Q.from_axis_angle(Vector3f{0, 0, spitch * body_roll_rad});107108// rotate body_yaw axis by cos(pitch angle)109Quaternion bf_yaw_Q;110if (plane_controls) {111bf_yaw_Q.from_axis_angle(Vector3f{cpitch, 0, 0}, euler_yaw_rate_rads);112} else {113bf_yaw_Q.from_axis_angle(Vector3f{-cpitch * body_roll_rad, 0, 0});114}115_attitude_target = _attitude_target * bf_roll_Q * bf_yaw_Q;116117// _euler_angle_target_rad roll and pitch: Note: roll/yaw will be indeterminate when pitch is near +/-90118// These should be used only for logging target eulers, with the caveat noted above.119// Also note that _attitude_target.from_euler() should only be used in special circumstances120// such as when attitude is specified directly in terms of Euler angles.121// _euler_angle_target_rad.x = _attitude_target.get_euler_roll();122// _euler_angle_target_rad.y = euler_pitch_rad;123124// Set rate feedforward requests to zero125_euler_rate_target_rads.zero();126_ang_accel_target_rads.zero();127_ang_vel_target_rads.zero();128129// Compute attitude error130error_quat = attitude_body.inverse() * _attitude_target;131error_quat.to_axis_angle(att_error);132133// Compute the angular velocity target from the attitude error134_ang_vel_body_rads = update_ang_vel_target_from_att_error(att_error);135}136137138