/* $Id: nav.c,v 1.3 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. */ #define NAV_C #include "math.h" #include "nav.h" #include "estimator.h" #include "pid.h" #include "autopilot.h" #include "link_fbw.h" #include "airframe.h" uint8_t nav_stage, nav_block; uint8_t excpt_stage; /*To save the current stage when an exception is raised */ static float last_x, last_y; static uint8_t last_wp; float rc_pitch; uint16_t stage_time, block_time; float stage_time_ds; #define RcRoll(travel) (from_fbw.channels[ RADIO_ROLL ]* (float)travel /(float)MAX_PPRZ) #define RcEvent1() CheckEvent(rc_event_1) #define RcEvent2() CheckEvent(rc_event_2) #define Block(x) case x: nav_block=x; #define InitBlock() { nav_stage = 0; block_time = 0; InitStage(); } #define NextBlock() { nav_block++; InitBlock(); } #define GotoBlock(b) { nav_block=b; InitBlock(); } #define Stage(s) case s: nav_stage=s; #define InitStage() { last_x = estimator_x; last_y = estimator_y; stage_time = 0; stage_time_ds = 0.0; return; } #define NextStage() { nav_stage++; InitStage() } #define NextStageFrom(wp) { last_wp = wp; NextStage() } #define GotoStage(s) { nav_stage = s; InitStage() } #define Label(x) label_ ## x: #define Goto(x) { goto label_ ## x; } #define Exception(x) { excpt_stage = nav_stage; goto label_ ## x; } #define ReturnFromException(_) { GotoStage(excpt_stage) } static bool_t approaching( uint8_t ); static inline void fly_to_xy( float x, float y ); static void fly_to( uint8_t wp ); static void route_to( uint8_t last_wp, uint8_t wp ); //static void glide_to(uint8_t last_wp, uint8_t wp); #define MIN_DX ((int16_t)(MAX_PPRZ * 0.05)) #define DegOfRad(x) ((x) / M_PI * 180.) #define RadOfDeg(x) ((x)/180. * M_PI) #define NormCourse(x) { _Pragma("loopbound min 0 max 0") while (x < 0) x += 360; _Pragma("loopbound min 0 max 0") while (x >= 360) x -= 360;} static float qdr; /* Degrees from 0 to 360 */ #define CircleXY(x,y,radius) { float alpha = atan2(estimator_y - y, estimator_x - x);float alpha_carrot = alpha + CARROT / (-radius * estimator_hspeed_mod); fly_to_xy(x+cos(alpha_carrot)*fabs(radius),y+sin(alpha_carrot)*fabs(radius)); qdr = DegOfRad(M_PI/2 - alpha_carrot); NormCourse(qdr);} #define MAX_DIST_CARROT 250. #define MIN_HEIGHT_CARROT 50. #define MAX_HEIGHT_CARROT 150. #define Goto3D(radius) { static float carrot_x, carrot_y; int16_t pitch; int16_t roll; if (pprz_mode == PPRZ_MODE_AUTO2) { int16_t yaw = from_fbw.channels[ RADIO_YAW ]; if (yaw > MIN_DX || yaw < -MIN_DX) { carrot_x += FLOAT_OF_PPRZ(yaw, 0, -20.);carrot_x = Min(carrot_x, MAX_DIST_CARROT); carrot_x = Max(carrot_x, -MAX_DIST_CARROT); } pitch = from_fbw.channels[ RADIO_PITCH ]; if (pitch > MIN_DX || pitch < -MIN_DX) { carrot_y += FLOAT_OF_PPRZ(pitch, 0, -20.); carrot_y = Min(carrot_y, MAX_DIST_CARROT); carrot_y = Max(carrot_y, -MAX_DIST_CARROT);} vertical_mode = VERTICAL_MODE_AUTO_ALT; roll = from_fbw.channels[ RADIO_ROLL ]; if (roll > MIN_DX || roll < -MIN_DX) { desired_altitude += FLOAT_OF_PPRZ(roll, 0, -1.0); desired_altitude = Max(desired_altitude, MIN_HEIGHT_CARROT+GROUND_ALT); desired_altitude = Min(desired_altitude, MAX_HEIGHT_CARROT+GROUND_ALT); } } CircleXY(carrot_x, carrot_y, radius); } #define Circle(wp, radius) CircleXY(waypoints[ wp ].x, waypoints[ wp ].y, radius) #define And(x, y) ((x) && (y)) #define Or(x, y) ((x) || (y)) //#define Min(x,y) (x < y ? x : y) //#define Max(x,y) (x > y ? x : y) #define Qdr(x) (Min(x, 350) < qdr && qdr < x+10) #include "flight_plan.h" #define MIN_DIST2_WP (15.*15.) #define DISTANCE2(p1_x, p1_y, p2) ((p1_x-p2.x)*(p1_x-p2.x)+(p1_y-p2.y)*(p1_y-p2.y)) const int32_t nav_east0 = NAV_UTM_EAST0; const int32_t nav_north0 = NAV_UTM_NORTH0; float desired_altitude = GROUND_ALT + MIN_HEIGHT_CARROT; float desired_x, desired_y; uint16_t nav_desired_gaz; float nav_pitch = NAV_PITCH; float nav_desired_roll; float dist2_to_wp, dist2_to_home; bool_t too_far_from_home; const uint8_t nb_waypoint = NB_WAYPOINT; struct point waypoints[ NB_WAYPOINT + 1 ] = WAYPOINTS static float carrot; static bool_t approaching( uint8_t wp ) { float pw_x = waypoints[ wp ].x - estimator_x; float pw_y = waypoints[ wp ].y - estimator_y; float scal_prod;//changes for PowerPc Fev-06 dist2_to_wp = pw_x * pw_x + pw_y * pw_y; carrot = CARROT * estimator_hspeed_mod; carrot = ( carrot < 40 ? 40 : carrot ); if ( dist2_to_wp < carrot * carrot ) return TRUE; scal_prod = ( waypoints[ wp ].x - last_x ) * pw_x + ( waypoints[ wp ].y - last_y ) * pw_y; return ( scal_prod < 0 ); } static inline void fly_to_xy( float x, float y ) { desired_x = x; desired_y = y; desired_course = M_PI / 2. - atan2( y - estimator_y, x - estimator_x ); } static void fly_to( uint8_t wp ) { fly_to_xy( waypoints[ wp ].x, waypoints[ wp ].y ); } static float alpha, leg; static void route_to( uint8_t _last_wp, uint8_t wp ) { float last_wp_x = waypoints[ _last_wp ].x; float last_wp_y = waypoints[ _last_wp ].y; float leg_x = waypoints[ wp ].x - last_wp_x; float leg_y = waypoints[ wp ].y - last_wp_y; float leg2 = leg_x * leg_x + leg_y * leg_y; alpha = ( ( estimator_x - last_wp_x ) * leg_x + ( estimator_y - last_wp_y ) * leg_y ) / leg2; alpha = Max( alpha, 0. ); leg = sqrt( leg2 ); alpha += Max( carrot / leg, 0. ); /* carrot computed in approaching() */ alpha = Min( 1., alpha ); fly_to_xy( last_wp_x + alpha * leg_x, last_wp_y + alpha * leg_y ); } /*static void glide_to(uint8_t _last_wp, uint8_t wp) { float last_alt = waypoints[ _last_wp ].a; desired_altitude = last_alt + alpha * (waypoints[ wp ].a - last_alt); pre_climb = NOMINAL_AIRSPEED * (waypoints[ wp ].a - last_alt) / leg; }*/ static inline void compute_dist2_to_home( void ) { float ph_x = waypoints[ WP_HOME ].x - estimator_x; float ph_y = waypoints[ WP_HOME ].y - estimator_y; dist2_to_home = ph_x * ph_x + ph_y * ph_y; too_far_from_home = dist2_to_home > ( MAX_DIST_FROM_HOME * MAX_DIST_FROM_HOME ); } void nav_home( void ) { //Circle(WP_HOME, 50); /* FIXME: radius should be defined elsewhere */ { float alpha = atan2( estimator_y - waypoints[ WP_HOME ].y, estimator_x - waypoints[ WP_HOME ].x ); float alpha_carrot = alpha + CARROT / ( -50 * estimator_hspeed_mod ); fly_to_xy( waypoints[ WP_HOME ].x + cos( alpha_carrot )*fabs( 50 ), waypoints[ WP_HOME ].y + sin( alpha_carrot )*fabs( 50 ) ); qdr = DegOfRad( M_PI / 2 - alpha_carrot ); { _Pragma( "loopbounds min 0 max 2" ) while ( qdr < 0 ) qdr += 360; _Pragma( "loopbounds min 0 max 2" ) while ( qdr >= 360 ) qdr -= 360; } } nav_pitch = 0.; /* Nominal speed */ vertical_mode = VERTICAL_MODE_AUTO_ALT; desired_altitude = GROUND_ALT + 50; compute_dist2_to_home(); dist2_to_wp = dist2_to_home; } void nav_update( void ) { compute_dist2_to_home(); auto_nav(); } void nav_init( void ) { nav_block = 0; nav_stage = 0; }