paparazzi-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Paparazzi-devel] Interest for a new survey pattern? (Zamboni-survey


From: Jorn Anke
Subject: Re: [Paparazzi-devel] Interest for a new survey pattern? (Zamboni-survey)
Date: Wed, 9 Jan 2013 22:39:32 +0100

Hi,

Here is the subroutine I came up with as an implementation of a zamboni survey pattern. The routine has only been tested in simulator, but it appears to be working as intended, except the yellow photo-shot dots seemes to appear somehow irregulary. I can however not figure out why.

For those who might be interested in testing the routine, the code and instructions are attached under.

The routine takes 7 parameters:

- center_wp, (wp defining the center of the area to be surveyed)
- dir_wp, (wp only used to define the flight direction, -from center_wp against dir_wp)
- sweep_length, (length of the flightlines)
- sweep_spacing, (spacing between flight lines)
- sweep_lines, (number of parallel flightlines,  must be an odd number, 5 or greater)
- shot_dist,
- altitude

Note that the width of the field to be surveyed is calculated from number of (sweep_lines-1) * sweep_spacing.

The turn-direction is by default to the right, seen in the flight direction, but the turn-direction/flight-pattern can be reversed/mirrored by assigning a negative value for sweep_spacing.

I should probably also be noted that this the first lines of code I have ever written in C -or for paparazzi, so the code may not follow the required programming standards. (If it by accident do, it's probably because I used the poly_survey_adv routine as a template). 
 

Cheers,
 
Jorn



As Chistopher explained to me in an earlier post to this thread, the routine has to be referenced for the linker, e.g. like this;
__________________________________________________________________________________________________________________

"You can add it for instance in /conf/firmwares/subsystems/fixedwing/navigation_extra.makefile or make a new subsystem makefile for just your files. Or alternatively add a <makefile> section in your airframe file containing ap.srcs += subsystems/navigation/zamboni_survey.c"

(It may also be neccessary to comment out the reference to the poly_survey_adv routine, since some of the parameter names might be conflicting)


Sample "header" and "block" from the flightplan:
__________________________________________________________________________________________________________________
<header>
#include "subsystems/navigation/zamboni_survey.h"
#include "subsystems/datalink/datalink.h"
/*
#ifndef VARDECLARED
#define VARDECLARED
float varsweepsize=110;
#endif
*/
#ifdef DC_AUTOSHOOT_METER_GRID
#include "modules/digital_cam/dc.h"
//#define LINE_START_FUNCTION dc_autoshoot = DC_AUTOSHOOT_PERIODIC;
#define LINE_START_FUNCTION dc_Survey(dc_gps_dist);
#define LINE_STOP_FUNCTION dc_autoshoot = DC_AUTOSHOOT_STOP;
#endif
</header>

...

      <block name="ZamboniSurvey" strip_button="Zamboni 1" strip_icon="survey.png">
      <!-- init_zamboni_survey(uint8_t center_wp, uint8_t dir_wp, float sweep_length, float sweep_spacing, int sweep_lines, float shot_dist, float altitude) /-->
      <call fun="init_zamboni_survey(WP_Z_CENTER, WP_Z_DIR, 300, -40, 7, 40, 250)"/>
      <call fun="zamboni_survey()"/>
    </block>
__________________________________________________________________________________________________________________



File to be saved in folder: sw/airborne/subsystems/navigation/ e.g. as "zamboni_survey.h"
__________________________________________________________________________________________________________________
#ifndef ZAMBONI_H
#define ZAMBONI_H

#include "std.h"

typedef struct {float x; float y;} point2d;
typedef enum {ERR, ENTRY, SEG, TURN1, RET, TURN2} survey_stage;


extern bool_t init_zamboni_survey(uint8_t center_wp, uint8_t dir_wp, float sweep_length, float sweep_spacing, int sweep_lines, float shot_dist, float altitude);
extern bool_t zamboni_survey(void);

#endif
__________________________________________________________________________________________________________________



File to be saved in folder: sw/airborne/subsystems/navigation/ e.g. as "zamboni_survey.c"
__________________________________________________________________________________________________________________
#include "zamboni_survey.h"

#include "subsystems/nav.h"
#include "estimator.h"
#include "autopilot.h"
#include "generated/flight_plan.h"

#ifdef DIGITAL_CAM
#include "modules/digital_cam/dc.h"
#endif

int counter;
/**
variables used to store values from the flight plan
**/
float x_wp_center, y_wp_center;
float x_wp_dir, y_wp_dir;
float z_sweep_length;
float z_sweep_spacing;
int z_sweep_lines;
float z_shot_dist;
float z_altitude;

/**
static variables, used for initial calculations
**/
// properties for the filightpattern
float flight_angle, return_angle;
float dx_sweep_width, dy_sweep_width;
float dx_flightline, dy_flightline;
float dx_flight_vec, dy_flight_vec;
float turnradius1, turnradius2;
int laps;

// points for navigation
float x_seg_start, y_seg_start;
float x_seg_end, y_seg_end;
float x_turn_center1, y_turn_center1;
float x_turn_center2, y_turn_center2;
float x_ret_start, y_ret_start;
float x_ret_end, y_ret_end;

// variables used or initial calculations 
  float dx_flight_wpts, dy_flight_wpts;
  float len;

survey_stage z_stage;
/*
z_stage starts at ENTRY and than circles trought the other
states until to rectangle 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
*/

/**
   initializes the variables needed for the survey to start
   center_wp   :  the waypoint difining the center of the survey-rectangle
   sweep_length:  the length of the survey-rectangle
   angle       :  angle in which to do the flyovers. (0 = north, 90 = east, 180 = south, 270 = west)
   sweep_width :  distance between the sweeps
   shot_dist   :  distance between the shots
   min_rad     :  minimal radius when navigating
   altitude    :  the altitude that must be reached before the flyover starts
**/
bool_t init_zamboni_survey(uint8_t center_wp, uint8_t dir_wp, float sweep_length, float sweep_spacing, int sweep_lines, float shot_dist, float altitude)
{
  counter = 0;
  // copy variables from the flight plan
  x_wp_center = waypoints[center_wp].x;
  y_wp_center = waypoints[center_wp].y;
  x_wp_dir = waypoints[dir_wp].x;
  y_wp_dir = waypoints[dir_wp].y;
  z_sweep_length = sweep_length;
  z_sweep_spacing = sweep_spacing;
  z_sweep_lines = sweep_lines;
  z_shot_dist = shot_dist;
  z_altitude = altitude;

  // calculate the flight_angle
  dx_flight_wpts = x_wp_dir - x_wp_center;
  dy_flight_wpts = y_wp_dir - y_wp_center;
  if (dy_flight_wpts == 0) dy_flight_wpts = 0.01; // to avoid dividing by zero
  flight_angle = 180*atan2(dx_flight_wpts, dy_flight_wpts)/M_PI;
  return_angle = flight_angle + 180;
  if (return_angle > 359) return_angle -= 360;
 
  // calculate the flightline vector from start to end of one flightline, (delta x and delta y for one flightline)
  // (used later to move the flight pattern one flightline up for each round)
  len = sqrtf(dx_flight_wpts * dx_flight_wpts + dy_flight_wpts * dy_flight_wpts);
  dx_flight_vec = dx_flight_wpts/len;
  dy_flight_vec = dy_flight_wpts/len;
  dx_flightline = dx_flight_vec * z_sweep_length;
  dy_flightline = dy_flight_vec * z_sweep_length;
 
  // calculate the vector from one flightline perpendicular to the next flightline left, seen in the flightdirection. (Delta x and delta y betwen two adjecent flightlines)
  // (used later to move the flight pattern one flightline up for each round)
  dx_sweep_width = -(dy_flight_wpts/len) * z_sweep_spacing;
  dy_sweep_width = +(dx_flight_wpts/len) * z_sweep_spacing;
   
  // calculate number of laps to fly and turning radius for each end
  laps = (z_sweep_lines+1)/2;
  turnradius1 = (laps-1) * z_sweep_spacing * 0.5;
  turnradius2 = laps * z_sweep_spacing * 0.5;
 
  //CALCULATE THE NAVIGATION POINTS
  //start and end of flight-line in flight-direction
  x_seg_start = x_wp_center - dx_flightline * 0.5;
  y_seg_start = y_wp_center - dy_flightline * 0.5;
  x_seg_end = x_wp_center + dx_flightline * 0.5;
  y_seg_end = y_wp_center + dy_flightline * 0.5;
 
  //start and end of flight-line in return-direction
  x_ret_start = x_seg_end - dx_sweep_width * (laps-1);
  y_ret_start = y_seg_end - dy_sweep_width * (laps-1);
  x_ret_end = x_seg_start - dx_sweep_width * (laps-1);
  y_ret_end = y_seg_start - dy_sweep_width * (laps-1);

  //turn-centers at both ends
  x_turn_center1 = (x_seg_end + x_ret_start)/2;
  y_turn_center1 = (y_seg_end + y_ret_start)/2;
  x_turn_center2 = (x_seg_start + x_ret_end + dx_sweep_width) / 2;
  y_turn_center2 = (y_seg_start + y_ret_end + dy_sweep_width) / 2;

  //fast climbing to desired altitude
  NavVerticalAutoThrottleMode(100.0);
  NavVerticalAltitudeMode(z_altitude, 0.0);
 
  z_stage = ENTRY;
 
  return FALSE;
}

/**
   main navigation routine. This is called periodically evaluates the current
   Position and stage and navigates accordingly.
   Returns True until the survey is finished
**/
bool_t zamboni_survey(void)
{
  // retain altitude
  NavVerticalAutoThrottleMode(0.0);
  NavVerticalAltitudeMode(z_altitude, 0.0);
 
  //entry circle around entry-center until the desired altitude is reached
  if (z_stage == ENTRY) {
    nav_route_xy(x_wp_center, y_wp_center, x_seg_end, y_seg_end);
    if (nav_approaching_xy(x_seg_end, y_seg_end, x_wp_center, y_wp_center, CARROT)) {
      z_stage = TURN1;
      NavVerticalAutoThrottleMode(0.0);
      nav_init_stage();
    }
  }
 
  //Turn from stage to return
  else if (z_stage == TURN1) {
    nav_circle_XY(x_turn_center1, y_turn_center1, turnradius1);
    if (NavCourseCloseTo(return_angle)){
        // && nav_approaching_xy(x_seg_end, y_seg_end, x_seg_start, y_seg_start, CARROT
      //calculate SEG-points for the next flyover
      x_seg_start = x_seg_start + dx_sweep_width;
      y_seg_start = y_seg_start + dy_sweep_width;
      x_seg_end = x_seg_end + dx_sweep_width;
      y_seg_end = y_seg_end + dy_sweep_width;
     
      z_stage = RET;
      nav_init_stage();
      #ifdef DIGITAL_CAM
        dc_survey(z_shot_dist, x_ret_start - dx_flight_vec * z_shot_dist, y_ret_start - dy_flight_vec * z_shot_dist);
      #endif
    }
  }
 
  //fly the segment until seg_end is reached
  else if (z_stage == RET) {
    nav_route_xy(x_ret_start, y_ret_start, x_ret_end, y_ret_end);
    if (nav_approaching_xy(x_ret_end, y_ret_end, x_ret_start, y_ret_start, CARROT)) {
      #ifdef DIGITAL_CAM
        dc_stop();
      #endif
      z_stage = TURN2;  
    }
  }

  //turn from stage to return
  else if (z_stage == TURN2) {
    nav_circle_XY(x_turn_center2, y_turn_center2, turnradius2);
    if (NavCourseCloseTo(flight_angle)) {
      counter = counter + 1;
      z_stage = SEG;
      nav_init_stage();
      #ifdef DIGITAL_CAM
        dc_survey(z_shot_dist, x_seg_start + dx_flight_vec * z_shot_dist, y_seg_start + dy_flight_vec * z_shot_dist);
      #endif
    }
 
  //return
  } else if (z_stage == SEG) {
    nav_route_xy(x_seg_start, y_seg_start, x_seg_end, y_seg_end);
    if (nav_approaching_xy(x_seg_end, y_seg_end, x_seg_start, y_seg_start, 0)) {
     
      // calculate the rest of the points for the next fly-over
      x_ret_start = x_ret_start + dx_sweep_width;
      y_ret_start = y_ret_start + dy_sweep_width;
      x_ret_end = x_ret_end + dx_sweep_width;
      y_ret_end = y_ret_end + dy_sweep_width;
      x_turn_center1 = (x_seg_end + x_ret_start)/2;
      y_turn_center1 = (y_seg_end + y_ret_start)/2;
      x_turn_center2 = (x_seg_start + x_ret_end + dx_sweep_width) / 2;
      y_turn_center2 = (y_seg_start + y_ret_end + dy_sweep_width) / 2;
 
      z_stage = TURN1;
      nav_init_stage();
      #ifdef DIGITAL_CAM
        dc_stop();
      #endif
    }
  }
  if (counter >= laps) {
    return FALSE;
  }
  else {
    return TRUE;
  }
}
__________________________________________________________________________________________________________________
 


reply via email to

[Prev in Thread] Current Thread [Next in Thread]