diff --git a/conf/flight_plans/nav_modules.xml b/conf/flight_plans/nav_modules.xml index c1920b1e1d..6bf37fc6e4 100644 --- a/conf/flight_plans/nav_modules.xml +++ b/conf/flight_plans/nav_modules.xml @@ -74,8 +74,8 @@ - - + + @@ -116,10 +116,6 @@ - - - - diff --git a/sw/airborne/modules/nav/nav_survey_poly_adv.c b/sw/airborne/modules/nav/nav_survey_poly_adv.c index 80f71a5128..4b02bc2a90 100644 --- a/sw/airborne/modules/nav/nav_survey_poly_adv.c +++ b/sw/airborne/modules/nav/nav_survey_poly_adv.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Paparazzi Team + * Copyright (C) 2011-2013 The Paparazzi Team * * This file is part of paparazzi. * @@ -37,68 +37,9 @@ #include "modules/digital_cam/dc.h" #endif +struct SurveyPolyAdv survey; -/* - The following variables are set by poly_survey_init and not changed later on -*/ - -// precomputed vectors to ease calculations -point2d dir_vec; -point2d sweep_vec; -point2d rad_vec; - -//the polygon from the flightplan -uint8_t poly_first; -uint8_t poly_count; - -//desired properties of the flyover -float psa_min_rad; -float psa_sweep_width; -float psa_shot_dist; -float psa_altitude; - -//direction for the flyover (0° == N) -int segment_angle; -int return_angle; - -/* - The Following variables are dynamic, changed while navigating. -*/ - -/* - psa_stage starts at ENTRY and than circles trought the other - states until to polygon is completely covered - ENTRY : getting in the right position and height for the first flyover - SEG : fly from seg_start to seg_end and take pictures, - then calculate navigation points of next flyover - TURN1 : do a 180° turn around seg_center1 - RET : fly from ret_start to ret_end - TURN2 : do a 180° turn around seg_center2 -*/ -survey_stage psa_stage; - -// points for navigation -point2d seg_start; -point2d seg_end; -point2d seg_center1; -point2d seg_center2; -point2d entry_center; -point2d ret_start; -point2d ret_end; - - -//helper functions and macro -#define VEC_CALC(A, B, C, OP) A.x = B.x OP C.x; A.y = B.y OP C.y; - -static point2d vec_add(point2d a, point2d b) -{ - point2d tmp; - VEC_CALC(tmp, a, b, +); - - return tmp; -} - -static void nav_points(point2d start, point2d end) +static void nav_points(struct FloatVect2 start, struct FloatVect2 end) { nav_route_xy(start.x, start.y, end.x, end.y); } @@ -111,7 +52,7 @@ static void nav_points(point2d start, point2d end) * @param x, y first line is defined by point x and y (goes through this points) * @param a1, a2, b1, b2 second line by coordinates a1/a2, b1/b2 */ -static bool_t intercept_two_lines(point2d *p, point2d x, point2d y, float a1, float a2, float b1, float b2) +static bool_t intercept_two_lines(struct FloatVect2 *p, struct FloatVect2 x, struct FloatVect2 y, float a1, float a2, float b1, float b2) { float divider, fac; @@ -133,13 +74,13 @@ static bool_t intercept_two_lines(point2d *p, point2d x, point2d y, float a1, fl * @param x, y intersection points * @param a, b define the line to intersection */ -static bool_t get_two_intersects(point2d *x, point2d *y, point2d a, point2d b) +static bool_t get_two_intersects(struct FloatVect2 *x, struct FloatVect2 *y, struct FloatVect2 a, struct FloatVect2 b) { int i, count = 0; - point2d tmp; + struct FloatVect2 tmp; - for (i=0;i fabs(dir_vec.y)) { - if ((y->x - x->x) / dir_vec.x < 0.0){ + if (fabs(survey.dir_vec.x) > fabs(survey.dir_vec.y)) { + if ((y->x - x->x) / survey.dir_vec.x < 0.0){ tmp = *x; *x = *y; *y = tmp; } } else - if ((y->y - x->y) / dir_vec.y < 0.0) { + if ((y->y - x->y) / survey.dir_vec.y < 0.0) { tmp = *x; *x = *y; *y = tmp; @@ -188,106 +129,98 @@ static bool_t get_two_intersects(point2d *x, point2d *y, point2d a, point2d b) * @param min_rad minimal radius when navigating * @param altitude the altitude that must be reached before the flyover starts **/ -bool_t init_poly_survey_adv(uint8_t first_wp, uint8_t size, float angle, float sweep_width, float shot_dist, float min_rad, float altitude) +bool_t poly_survey_adv_start(uint8_t first_wp, uint8_t size, float angle, float sweep_width, float shot_dist, float min_rad, float altitude) { int i; - point2d small, sweep; - float divider, len, angle_rad = angle/180.0*M_PI; + struct FloatVect2 small, sweep; + float divider, angle_rad = angle/180.0*M_PI; if (angle < 0.0) angle += 360.0; if (angle >= 360.0) angle -= 360.0; - poly_first = first_wp; - poly_count = size; + survey.poly_first = first_wp; + survey.poly_count = size; - psa_sweep_width = sweep_width; - psa_min_rad = min_rad; - psa_shot_dist = shot_dist; - psa_altitude = altitude; + survey.psa_sweep_width = sweep_width; + survey.psa_min_rad = min_rad; + survey.psa_shot_dist = shot_dist; + survey.psa_altitude = altitude; - segment_angle = angle; - return_angle = angle+180; - if (return_angle > 359) return_angle -= 360; + survey.segment_angle = angle; + survey.return_angle = angle+180; + if (survey.return_angle > 359) survey.return_angle -= 360; if (angle <= 45.0 || angle >= 315.0) { //north - dir_vec.y = 1.0; - dir_vec.x = 1.0*tanf(angle_rad); + survey.dir_vec.y = 1.0; + survey.dir_vec.x = 1.0*tanf(angle_rad); sweep.x = 1.0; - sweep.y = - dir_vec.x / dir_vec.y; + sweep.y = - survey.dir_vec.x / survey.dir_vec.y; } else if (angle <= 135.0) { //east - dir_vec.x = 1.0; - dir_vec.y = 1.0/tanf(angle_rad); + survey.dir_vec.x = 1.0; + survey.dir_vec.y = 1.0/tanf(angle_rad); sweep.y = - 1.0; - sweep.x = dir_vec.y / dir_vec.x; + sweep.x = survey.dir_vec.y / survey.dir_vec.x; } else if (angle <= 225.0) { //south - dir_vec.y = -1.0; - dir_vec.x = -1.0*tanf(angle_rad); + survey.dir_vec.y = -1.0; + survey.dir_vec.x = -1.0*tanf(angle_rad); sweep.x = -1.0; - sweep.y = dir_vec.x / dir_vec.y; + sweep.y = survey.dir_vec.x / survey.dir_vec.y; } else { //west - dir_vec.x = -1.0; - dir_vec.y = -1.0/tanf(angle_rad); + survey.dir_vec.x = -1.0; + survey.dir_vec.y = -1.0/tanf(angle_rad); sweep.y = 1.0; - sweep.x = - dir_vec.y / dir_vec.x; + sweep.x = - survey.dir_vec.y / survey.dir_vec.x; } //normalize - len = sqrt(sweep.x*sweep.x+sweep.y*sweep.y); - sweep.x = sweep.x / len; - sweep.y = sweep.y / len; + FLOAT_VECT2_NORMALIZE(sweep); - rad_vec.x = sweep.x * psa_min_rad; - rad_vec.y = sweep.y * psa_min_rad; - sweep_vec.x = sweep.x * psa_sweep_width; - sweep_vec.y = sweep.y * psa_sweep_width; + FLOAT_VECT2_SMUL(survey.rad_vec, sweep, survey.psa_min_rad); + FLOAT_VECT2_SMUL(survey.sweep_vec, sweep, survey.psa_sweep_width); - //begin at leftmost position (relative to dir_vec) - small.x = waypoints[poly_first].x; - small.y = waypoints[poly_first].y; + //begin at leftmost position (relative to survey.dir_vec) + FLOAT_VECT2_COPY(small,waypoints[survey.poly_first]); - divider = (sweep_vec.y*dir_vec.x) - (sweep_vec.x*dir_vec.y); + divider = (survey.sweep_vec.y*survey.dir_vec.x) - (survey.sweep_vec.x*survey.dir_vec.y); - //cacluate the leftmost point if one sees the dir vec as going "up" and the sweep vec as going right + //calculate the leftmost point if one sees the dir vec as going "up" and the sweep vec as going right if (divider < 0.0) { - for(i=1;i 0.0) { - small.x = waypoints[poly_first+i].x; - small.y = waypoints[poly_first+i].y; + for(i=1;i 0.0) { + FLOAT_VECT2_COPY(small, waypoints[survey.poly_first+i]); } } else - for(i=1;i 0.0) { - small.x = waypoints[poly_first+i].x; - small.y = waypoints[poly_first+i].y; + for(i=1;i 0.0) { + FLOAT_VECT2_COPY(small, waypoints[survey.poly_first+i]); } //calculate the line the defines the first flyover - seg_start.x = small.x + 0.5*sweep_vec.x; - seg_start.y = small.y + 0.5*sweep_vec.y; - VEC_CALC(seg_end, seg_start, dir_vec, +); + survey.seg_start.x = small.x + 0.5*survey.sweep_vec.x; + survey.seg_start.y = small.y + 0.5*survey.sweep_vec.y; + FLOAT_VECT2_SUM(survey.seg_end, survey.seg_start, survey.dir_vec); - if (!get_two_intersects(&seg_start, &seg_end, seg_start, seg_end)) { - psa_stage = ERR; + if (!get_two_intersects(&survey.seg_start, &survey.seg_end, survey.seg_start, survey.seg_end)) { + survey.stage = ERR; return FALSE; } //center of the entry circle - entry_center.x = seg_start.x - rad_vec.x; - entry_center.y = seg_start.y - rad_vec.y; + FLOAT_VECT2_DIFF(survey.entry_center, survey.seg_start, survey.rad_vec); //fast climbing to desired altitude NavVerticalAutoThrottleMode(0.0); - NavVerticalAltitudeMode(psa_altitude, 0.0); + NavVerticalAltitudeMode(survey.psa_altitude, 0.0); - psa_stage = ENTRY; + survey.stage = ENTRY; return FALSE; } @@ -297,72 +230,76 @@ bool_t init_poly_survey_adv(uint8_t first_wp, uint8_t size, float angle, float s * Position and stage and navigates accordingly. * Returns True until the survey is finished */ -bool_t poly_survey_adv(void) +bool_t poly_survey_adv_run(void) { NavVerticalAutoThrottleMode(0.0); - NavVerticalAltitudeMode(psa_altitude, 0.0); + NavVerticalAltitudeMode(survey.psa_altitude, 0.0); //entry circle around entry-center until the desired altitude is reached - if (psa_stage == ENTRY) { - nav_circle_XY(entry_center.x, entry_center.y, -psa_min_rad); - if (NavCourseCloseTo(segment_angle) - && nav_approaching_xy(seg_start.x, seg_start.y, last_x, last_y, CARROT) - && fabs(stateGetPositionEnu_f()->z - psa_altitude) <= 20) { - psa_stage = SEG; + if (survey.stage == ENTRY) { + nav_circle_XY(survey.entry_center.x, survey.entry_center.y, -survey.psa_min_rad); + if (NavCourseCloseTo(survey.segment_angle) + && nav_approaching_xy(survey.seg_start.x, survey.seg_start.y, last_x, last_y, CARROT) + && fabs(stateGetPositionEnu_f()->z - survey.psa_altitude) <= 20) { + survey.stage = SEG; nav_init_stage(); #ifdef DIGITAL_CAM - dc_survey(psa_shot_dist, seg_start.x - dir_vec.x*psa_shot_dist*0.5, seg_start.y - dir_vec.y*psa_shot_dist*0.5); + dc_survey(survey.psa_shot_dist, survey.seg_start.x - survey.dir_vec.x*survey.psa_shot_dist*0.5, survey.seg_start.y - survey.dir_vec.y*survey.psa_shot_dist*0.5); #endif } } //fly the segment until seg_end is reached - if (psa_stage == SEG) { - nav_points(seg_start, seg_end); + if (survey.stage == SEG) { + nav_points(survey.seg_start, survey.seg_end); //calculate all needed points for the next flyover - if (nav_approaching_xy(seg_end.x, seg_end.y, seg_start.x, seg_start.y, 0)) { + if (nav_approaching_xy(survey.seg_end.x, survey.seg_end.y, survey.seg_start.x, survey.seg_start.y, 0)) { #ifdef DIGITAL_CAM dc_stop(); #endif - VEC_CALC(seg_center1, seg_end, rad_vec, -); - ret_start.x = seg_end.x - 2*rad_vec.x; - ret_start.y = seg_end.y - 2*rad_vec.y; + FLOAT_VECT2_DIFF(survey.seg_center1, survey.seg_end, survey.rad_vec); + survey.ret_start.x = survey.seg_end.x - 2*survey.rad_vec.x; + survey.ret_start.y = survey.seg_end.y - 2*survey.rad_vec.y; //if we get no intersection the survey is finished - if (!get_two_intersects(&seg_start, &seg_end, vec_add(seg_start, sweep_vec), vec_add(seg_end, sweep_vec))) + static struct FloatVect2 sum_start_sweep; + static struct FloatVect2 sum_end_sweep; + VECT2_SUM(sum_start_sweep, survey.seg_start, survey.sweep_vec); + VECT2_SUM(sum_end_sweep, survey.seg_end, survey.sweep_vec); + if (!get_two_intersects(&survey.seg_start, &survey.seg_end, sum_start_sweep, sum_end_sweep)) return FALSE; - ret_end.x = seg_start.x - sweep_vec.x - 2*rad_vec.x; - ret_end.y = seg_start.y - sweep_vec.y - 2*rad_vec.y; + survey.ret_end.x = survey.seg_start.x - survey.sweep_vec.x - 2*survey.rad_vec.x; + survey.ret_end.y = survey.seg_start.y - survey.sweep_vec.y - 2*survey.rad_vec.y; - seg_center2.x = seg_start.x - 0.5*(2.0*rad_vec.x+sweep_vec.x); - seg_center2.y = seg_start.y - 0.5*(2.0*rad_vec.y+sweep_vec.y); + survey.seg_center2.x = survey.seg_start.x - 0.5*(2.0*survey.rad_vec.x+survey.sweep_vec.x); + survey.seg_center2.y = survey.seg_start.y - 0.5*(2.0*survey.rad_vec.y+survey.sweep_vec.y); - psa_stage = TURN1; + survey.stage = TURN1; nav_init_stage(); } } //turn from stage to return - else if (psa_stage == TURN1) { - nav_circle_XY(seg_center1.x, seg_center1.y, -psa_min_rad); - if (NavCourseCloseTo(return_angle)) { - psa_stage = RET; + else if (survey.stage == TURN1) { + nav_circle_XY(survey.seg_center1.x, survey.seg_center1.y, -survey.psa_min_rad); + if (NavCourseCloseTo(survey.return_angle)) { + survey.stage = RET; nav_init_stage(); } //return - } else if (psa_stage == RET) { - nav_points(ret_start, ret_end); - if (nav_approaching_xy(ret_end.x, ret_end.y, ret_start.x, ret_start.y, 0)) { - psa_stage = TURN2; + } else if (survey.stage == RET) { + nav_points(survey.ret_start, survey.ret_end); + if (nav_approaching_xy(survey.ret_end.x, survey.ret_end.y, survey.ret_start.x, survey.ret_start.y, 0)) { + survey.stage = TURN2; nav_init_stage(); } //turn from return to stage - } else if (psa_stage == TURN2) { - nav_circle_XY(seg_center2.x, seg_center2.y, -(2*psa_min_rad+psa_sweep_width)*0.5); - if (NavCourseCloseTo(segment_angle)) { - psa_stage = SEG; + } else if (survey.stage == TURN2) { + nav_circle_XY(survey.seg_center2.x, survey.seg_center2.y, -(2*survey.psa_min_rad+survey.psa_sweep_width)*0.5); + if (NavCourseCloseTo(survey.segment_angle)) { + survey.stage = SEG; nav_init_stage(); #ifdef DIGITAL_CAM - dc_survey(psa_shot_dist, seg_start.x - dir_vec.x*psa_shot_dist*0.5, seg_start.y - dir_vec.y*psa_shot_dist*0.5); + dc_survey(survey.psa_shot_dist, survey.seg_start.x - survey.dir_vec.x*survey.psa_shot_dist*0.5, survey.seg_start.y - survey.dir_vec.y*survey.psa_shot_dist*0.5); #endif } } diff --git a/sw/airborne/modules/nav/nav_survey_poly_adv.h b/sw/airborne/modules/nav/nav_survey_poly_adv.h index 99921aa49f..d4fce0dab8 100644 --- a/sw/airborne/modules/nav/nav_survey_poly_adv.h +++ b/sw/airborne/modules/nav/nav_survey_poly_adv.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2011 The Paparazzi Team + * Copyright (C) 2011-2013 The Paparazzi Team * * This file is part of paparazzi. * @@ -30,12 +30,59 @@ #define POLY_ADV_H #include "std.h" +#include "math/pprz_algebra_float.h" -typedef struct {float x; float y;} point2d; +/* + SurveyStage starts at ENTRY and than circles trought the other + states until to polygon is completely covered + ENTRY : getting in the right position and height for the first flyover + SEG : fly from seg_start to seg_end and take pictures, + then calculate navigation points of next flyover + TURN1 : do a 180° turn around seg_center1 + RET : fly from ret_start to ret_end + TURN2 : do a 180° turn around seg_center2 +*/ +enum SurveyStage {ERR, ENTRY, SEG, TURN1, RET, TURN2}; -typedef enum {ERR, ENTRY, SEG, TURN1, RET, TURN2} survey_stage; +struct SurveyPolyAdv { + /* + The following variables are set by poly_survey_init and not changed later on + */ -extern bool_t init_poly_survey_adv(uint8_t first_wp, uint8_t size, float angle, float sweep_width, float shot_dist, float min_rad, float altitude); -extern bool_t poly_survey_adv(void); + // precomputed vectors to ease calculations + struct FloatVect2 dir_vec; + struct FloatVect2 sweep_vec; + struct FloatVect2 rad_vec; + + //the polygon from the flightplan + uint8_t poly_first; + uint8_t poly_count; + + //desired properties of the flyover + float psa_min_rad; + float psa_sweep_width; + float psa_shot_dist; + float psa_altitude; + + //direction for the flyover (0° == N) + int segment_angle; + int return_angle; + + /* + The Following variables are dynamic, changed while navigating. + */ + enum SurveyStage stage; + // points for navigation + struct FloatVect2 seg_start; + struct FloatVect2 seg_end; + struct FloatVect2 seg_center1; + struct FloatVect2 seg_center2; + struct FloatVect2 entry_center; + struct FloatVect2 ret_start; + struct FloatVect2 ret_end; +}; + +extern bool_t poly_survey_adv_start(uint8_t first_wp, uint8_t size, float angle, float sweep_width, float shot_dist, float min_rad, float altitude); +extern bool_t poly_survey_adv_run(void); #endif