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: Sat, 12 Jan 2013 19:11:32 +0100

We had really nice weather conditions today, so I decided to go test-fly the zamboni flight-pattern. As far as I could tell from looking at the plane from the ground, the flight went even better the I would dear to hope. In particular because this was also the maiden flight for me with paparazzi.

The only thing which did not work as expected (I think) was the phototriggering - from the yellow dots appearing in the GCS . I may have misunderstood how to interact with the distance-based trigger, and will have a closer look into that.

The flight-log and a kml-file from the flight is attached. Note that there are actually two zamboni missions in the log - where the last mission was flown in reversed direction - on top of the first mission. The whole flight was in Auto2, except the final part of the landing.

I am still no good in analyzing log-files, so If anyone would have a look, and comment of anything strange or worth improving, I would be really grateful.


Cheers,

Jørn



From: address@hidden
To: address@hidden
Subject: RE: 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;
  }
}
__________________________________________________________________________________________________________________
 

Attachment: zamboni_test_13_01_12.kml
Description: Binary data

Attachment: zamboni_test_13_27_05.data
Description: Binary data

Attachment: zamboni_test_13_27_05.log
Description: Text document


reply via email to

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