/* $Id: pid.c,v 1.2 2011-01-21 11:52:44 moellmer Exp $ Copyright (C) 2003 Pascal Brisset, Antoine Drouin This file is part of paparazzi. paparazzi is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. paparazzi is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with paparazzi; see the file COPYING. If not, write to the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /** \file pid.c \brief PID controllers (roll, pitch, climb, altitude, course). */ //#include #include #include "pid.h" #include "autopilot.h" #include "infrared.h" #include "estimator.h" #include "nav.h" float desired_roll = 0.; float desired_pitch = 0.; int16_t desired_gaz, desired_aileron, desired_elevator; float roll_pgain = ROLL_PGAIN; float pitch_pgain = PITCH_PGAIN; float pitch_of_roll = PITCH_OF_ROLL; float pitch_of_vz_pgain = CLIMB_PITCH_OF_VZ_PGAIN; float pitch_of_vz = 0.; /** \brief Computes ::desired_aileron and ::desired_elevator from attitude estimation and expected attitude. */ void roll_pitch_pid_run( void ) { float err = estimator_phi - desired_roll; desired_aileron = TRIM_PPRZ( roll_pgain * err ); if ( pitch_of_roll < 0. ) pitch_of_roll = 0.; err = -( estimator_theta - desired_pitch - pitch_of_roll * fabs( estimator_phi ) ); desired_elevator = TRIM_PPRZ( pitch_pgain * err ); } float course_pgain = COURSE_PGAIN; float desired_course = 0.; float max_roll = MAX_ROLL; void course_pid_run( void ) { float err = estimator_hspeed_dir - desired_course; //NORM_RAD_ANGLE(err); _Pragma( "loopbound min 0 max 1" ) while ( err > M_PI ) err -= 2 * M_PI; _Pragma( "loopbound min 0 max 1" ) while ( err < -M_PI ) err += 2 * M_PI; nav_desired_roll = course_pgain * err; // * fspeed / AIR_SPEED; if ( nav_desired_roll > max_roll ) nav_desired_roll = max_roll; else if ( nav_desired_roll < -max_roll ) nav_desired_roll = -max_roll; } const float climb_pgain = CLIMB_PGAIN; const float climb_igain = CLIMB_IGAIN; float desired_climb = 0., pre_climb = 0.; static const float level_gaz = CLIMB_LEVEL_GAZ; float climb_sum_err = 0; float climb_pitch_pgain = CLIMB_PITCH_PGAIN; float climb_pitch_igain = CLIMB_PITCH_IGAIN; float climb_pitch_sum_err = 0.; float max_pitch = MAX_PITCH; float min_pitch = MIN_PITCH; #define MAX_CLIMB_SUM_ERR 100 #define MAX_PITCH_CLIMB_SUM_ERR 100 /** \brief Computes desired_gaz and desired_pitch from desired_climb */ void climb_pid_run ( void ) { float err = estimator_z_dot - desired_climb; float fgaz; if ( auto_pitch ) { /* gaz constant */ desired_gaz = nav_desired_gaz; desired_pitch = climb_pitch_pgain * ( err + climb_pitch_igain * climb_pitch_sum_err ); if ( desired_pitch > max_pitch ) desired_pitch = max_pitch; if ( desired_pitch < min_pitch ) desired_pitch = min_pitch; climb_pitch_sum_err += err; if ( climb_pitch_sum_err > MAX_PITCH_CLIMB_SUM_ERR ) climb_pitch_sum_err = MAX_PITCH_CLIMB_SUM_ERR; if ( climb_pitch_sum_err < - MAX_PITCH_CLIMB_SUM_ERR ) climb_pitch_sum_err = - MAX_PITCH_CLIMB_SUM_ERR; } else { /* pitch almost constant */ /* pitch offset for climb */ pitch_of_vz = ( desired_climb > 0 ) ? desired_climb * pitch_of_vz_pgain : 0.; fgaz = climb_pgain * ( err + climb_igain * climb_sum_err ) + CLIMB_LEVEL_GAZ + CLIMB_GAZ_OF_CLIMB * desired_climb; climb_sum_err += err; if ( climb_sum_err > MAX_CLIMB_SUM_ERR ) climb_sum_err = MAX_CLIMB_SUM_ERR; if ( climb_sum_err < - MAX_CLIMB_SUM_ERR ) climb_sum_err = - MAX_CLIMB_SUM_ERR; desired_gaz = TRIM_UPPRZ( fgaz * MAX_PPRZ ); desired_pitch = nav_pitch + pitch_of_vz; } } float altitude_pgain = ALTITUDE_PGAIN; void altitude_pid_run( void ) { float err = estimator_z - desired_altitude; desired_climb = pre_climb + altitude_pgain * err; if ( desired_climb < -CLIMB_MAX ) desired_climb = -CLIMB_MAX; if ( desired_climb > CLIMB_MAX ) desired_climb = CLIMB_MAX; }