Beispiel #1
0
static void integrate( uint8_t wp_target ) {
  /* Inspired from Arnold Schroeter's code */
  int i = 0;
  while (bomb_z > 0. && i < MAX_STEPS) {
    /* relative wind experienced by the ball (wind in NED frame) */
    float airx = -bomb_vx + stateGetHorizontalWindspeed_f()->y;
    float airy = -bomb_vy + stateGetHorizontalWindspeed_f()->x;
    float airz = -bomb_vz;

    /* alpha / m * air */
    float beta = ALPHA_M * sqrt(airx*airx+airy*airy+airz*airz);

    /* Euler integration */
    bomb_vx += airx * beta * DT;
    bomb_vy += airy * beta * DT;
    bomb_vz += (airz * beta - G) * DT;

    bomb_x += bomb_vx * DT;
    bomb_y += bomb_vy * DT;
    bomb_z += bomb_vz * DT;

    i++;
  }

  if (bomb_z > 0.) {
    /* Integration not finished -> approximation of the time with the current
       speed  */
    float t = - bomb_z / bomb_vz;
    bomb_x += bomb_vx * t;
    bomb_y += bomb_vy * t;
  }

  waypoints[WP_RELEASE].x = waypoints[wp_target].x - bomb_x;
  waypoints[WP_RELEASE].y = waypoints[wp_target].y - bomb_y;
}
Beispiel #2
0
void parse_mf_daq_msg(void)
{
    mf_daq.nb = dl_buffer[2];
    if (mf_daq.nb > 0) {
        if (mf_daq.nb > MF_DAQ_SIZE) {
            mf_daq.nb = MF_DAQ_SIZE;
        }
        // Store data struct directly from dl_buffer
        float *buf = (float*)(dl_buffer+3);
        memcpy(mf_daq.values, buf, mf_daq.nb * sizeof(float));
        // Log on SD card
        if (log_started) {
            DOWNLINK_SEND_PAYLOAD_FLOAT(pprzlog_tp, chibios_sdlog, mf_daq.nb, mf_daq.values);
            DOWNLINK_SEND_MF_DAQ_STATE(pprzlog_tp, chibios_sdlog,
                                       &autopilot_flight_time,
                                       &stateGetBodyRates_f()->p,
                                       &stateGetBodyRates_f()->q,
                                       &stateGetBodyRates_f()->r,
                                       &stateGetNedToBodyEulers_f()->phi,
                                       &stateGetNedToBodyEulers_f()->theta,
                                       &stateGetNedToBodyEulers_f()->psi,
                                       &stateGetAccelNed_f()->x,
                                       &stateGetAccelNed_f()->y,
                                       &stateGetAccelNed_f()->z,
                                       &stateGetSpeedEnu_f()->x,
                                       &stateGetSpeedEnu_f()->y,
                                       &stateGetSpeedEnu_f()->z,
                                       &stateGetPositionLla_f()->lat,
                                       &stateGetPositionLla_f()->lon,
                                       &stateGetPositionLla_f()->alt,
                                       &stateGetHorizontalWindspeed_f()->y,
                                       &stateGetHorizontalWindspeed_f()->x);
        }
    }
}
Beispiel #3
0
/*�Adjusting a circle around CA, tangent in A, to end at snav_desired_tow */
bool snav_on_time(float nominal_radius)
{
  nominal_radius = fabs(nominal_radius);

  float current_qdr = M_PI_2 - atan2(stateGetPositionEnu_f()->y - wp_ca.y, stateGetPositionEnu_f()->x - wp_ca.x);
  float remaining_angle = Norm2Pi(Sign(a_radius) * (qdr_a - current_qdr));
  float remaining_time = snav_desired_tow - gps.tow / 1000.;

  /* Use the nominal airspeed if the estimated one is not realistic */
  float airspeed = stateGetAirspeed_f();
  if (airspeed < NOMINAL_AIRSPEED / 2. ||
      airspeed > 2.* NOMINAL_AIRSPEED) {
    airspeed = NOMINAL_AIRSPEED;
  }

  /* Recompute ground speeds every 10 s */
  if (ground_speed_timer == 0) {
    ground_speed_timer = 40; /* every 10s, called at 40Hz */
    compute_ground_speed(airspeed, stateGetHorizontalWindspeed_f()->y,
                         stateGetHorizontalWindspeed_f()->x); // Wind in NED frame
  }
  ground_speed_timer--;

  /* Time to complete the circle at nominal_radius */
  float nominal_time = 0.;

  float a;
  float ground_speed = NOMINAL_AIRSPEED; /* Init to avoid a warning */
  /* Going one step too far */
  for (a = 0; a < remaining_angle + ANGLE_STEP; a += ANGLE_STEP) {
    float qdr = current_qdr + Sign(a_radius) * a;
    ground_speed = ground_speed_of_course(qdr + Sign(a_radius) * M_PI_2);
    nominal_time += ANGLE_STEP * nominal_radius / ground_speed;
  }
  /* Removing what exceeds remaining_angle */
  nominal_time -= (a - remaining_angle) * nominal_radius / ground_speed;

  /* Radius size to finish in one single circle */
  float radius = remaining_time / nominal_time * nominal_radius;
  if (radius > 2. * nominal_radius) {
    radius = nominal_radius;
  }

  NavVerticalAutoThrottleMode(0); /* No pitch */
  NavVerticalAltitudeMode(wp_cd.a, 0.);

  radius *= Sign(a_radius);
  wp_ca.x = WaypointX(wp_a) + radius * u_a_ca_x;
  wp_ca.y = WaypointY(wp_a) + radius * u_a_ca_y;
  nav_circle_XY(wp_ca.x, wp_ca.y, radius);

  /* Stay in this mode until the end of time */
  return (remaining_time > 0);
}
Beispiel #4
0
void ahrs_update_gps(void) {

  float hspeed_mod_f = gps.gspeed / 100.;
  float course_f = gps.course / 1e7;

  // Heading estimator from wind-information, usually computed with -DWIND_INFO
  // wind_north and wind_east initialized to 0, so still correct if not updated
  float w_vn = cosf(course_f) * hspeed_mod_f - stateGetHorizontalWindspeed_f()->x;
  float w_ve = sinf(course_f) * hspeed_mod_f - stateGetHorizontalWindspeed_f()->y;
  heading = atan2f(w_ve, w_vn);
  if (heading < 0.)
    heading += 2 * M_PI;

}
Beispiel #5
0
bool_t nav_anemotaxis_downwind( uint8_t c, float radius ) {
  struct FloatVect2* wind = stateGetHorizontalWindspeed_f();
  float wind_dir = atan2(wind->x, wind->y);
  waypoints[c].x = waypoints[WP_HOME].x + radius*cos(wind_dir);
  waypoints[c].y = waypoints[WP_HOME].y + radius*sin(wind_dir);
  return FALSE;
}
Beispiel #6
0
/** Compute a first approximation for the RELEASE waypoint from wind and
    expected airspeed and altitude */
unit_t nav_drop_compute_approach( uint8_t wp_target, uint8_t wp_start, float nav_drop_radius ) {
  waypoints[WP_RELEASE].a = waypoints[wp_start].a;
  nav_drop_z = waypoints[WP_RELEASE].a - waypoints[wp_target].a;
  nav_drop_x = 0.;
  nav_drop_y = 0.;

  /* We approximate vx and vy, taking into account that RELEASE is next to
     TARGET */
  float x_0 = waypoints[wp_target].x - waypoints[wp_start].x;
  float y_0 = waypoints[wp_target].y - waypoints[wp_start].y;

  /* Unit vector from START to TARGET */
  float d = sqrt(x_0*x_0+y_0*y_0);
  float x1 = x_0 / d;
  float y_1 = y_0 / d;

  waypoints[WP_BASELEG].x = waypoints[wp_start].x + y_1 * nav_drop_radius;
  waypoints[WP_BASELEG].y = waypoints[wp_start].y - x1 * nav_drop_radius;
  waypoints[WP_BASELEG].a = waypoints[wp_start].a;
  nav_drop_start_qdr = M_PI - atan2(-y_1, -x1);
  if (nav_drop_radius < 0)
    nav_drop_start_qdr += M_PI;

  // wind in NED frame
  if (stateIsAirspeedValid()) {
    nav_drop_vx = x1 * *stateGetAirspeed_f() + stateGetHorizontalWindspeed_f()->y;
    nav_drop_vy = y_1 * *stateGetAirspeed_f() + stateGetHorizontalWindspeed_f()->x;
  }
  else {
    // use approximate airspeed, initially set to AIRSPEED_AT_RELEASE
    nav_drop_vx = x1 * airspeed + stateGetHorizontalWindspeed_f()->y;
    nav_drop_vy = y_1 * airspeed + stateGetHorizontalWindspeed_f()->x;
  }
  nav_drop_vz = 0.;

  float vx0 = nav_drop_vx;
  float vy0 = nav_drop_vy;

  integrate(wp_target);

  waypoints[WP_CLIMB].x = waypoints[WP_RELEASE].x + (CLIMB_TIME + CARROT) * vx0;
  waypoints[WP_CLIMB].y = waypoints[WP_RELEASE].y + (CLIMB_TIME + CARROT) * vy0;
  waypoints[WP_CLIMB].a = waypoints[WP_RELEASE].a + SAFE_CLIMB;

  return 0;
}
Beispiel #7
0
bool_t nav_anemotaxis_init( uint8_t c ) {
  status = UTURN;
  sign = 1;
  struct FloatVect2* wind = stateGetHorizontalWindspeed_f();
  float wind_dir = atan2(wind->x, wind->y);
  waypoints[c].x = stateGetPositionEnu_f()->x + DEFAULT_CIRCLE_RADIUS*cos(wind_dir+M_PI);
  waypoints[c].y = stateGetPositionEnu_f()->y + DEFAULT_CIRCLE_RADIUS*sin(wind_dir+M_PI);
  last_plume_was_here();
  return FALSE;
}
Beispiel #8
0
/* For a landing UPWIND.
   Computes Top Of Descent waypoint from Touch Down and Approach Fix
   waypoints, using glide airspeed, glide vertical speed and wind */
static inline bool_t compute_TOD(uint8_t _af, uint8_t _td, uint8_t _tod, float glide_airspeed, float glide_vspeed) {
  struct FloatVect2* wind = stateGetHorizontalWindspeed_f();
  float td_af_x = WaypointX(_af) - WaypointX(_td);
  float td_af_y = WaypointY(_af) - WaypointY(_td);
  float td_af = sqrtf( td_af_x*td_af_x + td_af_y*td_af_y);
  float td_tod = (WaypointAlt(_af) - WaypointAlt(_td)) / glide_vspeed * (glide_airspeed - sqrtf(wind->x*wind->x + wind->y*wind->y));
  WaypointX(_tod) = WaypointX(_td) + td_af_x / td_af * td_tod;
  WaypointY(_tod) = WaypointY(_td) + td_af_y / td_af * td_tod;
  WaypointAlt(_tod) = WaypointAlt(_af);
  return FALSE;
}
Beispiel #9
0
/** Compute a first approximation for the RELEASE waypoint from wind and
    expected airspeed and altitude */
unit_t bomb_compute_approach( uint8_t wp_target, uint8_t wp_start, float bomb_radius ) {
  waypoints[WP_RELEASE].a = waypoints[wp_start].a;
  bomb_z = waypoints[WP_RELEASE].a - waypoints[wp_target].a;
  bomb_x = 0.;
  bomb_y = 0.;

  /* We approximate vx and vy, taking into account that RELEASE is next to
     TARGET */
  float x_0 = waypoints[wp_target].x - waypoints[wp_start].x;
  float y_0 = waypoints[wp_target].y - waypoints[wp_start].y;

  /* Unit vector from START to TARGET */
  float d = sqrt(x_0*x_0+y_0*y_0);
  float x1 = x_0 / d;
  float y_1 = y_0 / d;

  waypoints[WP_BASELEG].x = waypoints[wp_start].x + y_1 * bomb_radius;
  waypoints[WP_BASELEG].y = waypoints[wp_start].y - x1 * bomb_radius;
  waypoints[WP_BASELEG].a = waypoints[wp_start].a;
  bomb_start_qdr = M_PI - atan2(-y_1, -x1);
  if (bomb_radius < 0)
    bomb_start_qdr += M_PI;

  // wind in NED frame
  bomb_vx = x1 * airspeed + stateGetHorizontalWindspeed_f()->y;
  bomb_vy = y_1 * airspeed + stateGetHorizontalWindspeed_f()->x;
  bomb_vz = 0.;

  float vx0 = bomb_vx;
  float vy0 = bomb_vy;

  integrate(wp_target);

  waypoints[WP_CLIMB].x = waypoints[WP_RELEASE].x + (CLIMB_TIME + CARROT) * vx0;
  waypoints[WP_CLIMB].y = waypoints[WP_RELEASE].y + (CLIMB_TIME + CARROT) * vy0;
  waypoints[WP_CLIMB].a = waypoints[WP_RELEASE].a + SAFE_CLIMB;

  return 0;
}
Beispiel #10
0
static inline bool_t gls_compute_TOD(uint8_t _af, uint8_t _sd, uint8_t _tod, uint8_t _td)
{

  if ((WaypointX(_af) == WaypointX(_td)) && (WaypointY(_af) == WaypointY(_td))) {
    WaypointX(_af) = WaypointX(_td) - 1;
  }

  float td_af_x = WaypointX(_af) - WaypointX(_td);
  float td_af_y = WaypointY(_af) - WaypointY(_td);
  float td_af = sqrt(td_af_x * td_af_x + td_af_y * td_af_y);
  float td_tod = (WaypointAlt(_af) - WaypointAlt(_td)) / (tanf(app_angle));

  // set wapoint TOD (top of decent)
  WaypointX(_tod) = WaypointX(_td) + td_af_x / td_af * td_tod;
  WaypointY(_tod) = WaypointY(_td) + td_af_y / td_af * td_tod;
  WaypointAlt(_tod) = WaypointAlt(_af);

  // calculate ground speed on final (target_speed - head wind)
  struct FloatVect2 *wind = stateGetHorizontalWindspeed_f();
  float wind_norm = sqrt(wind->x * wind->x + wind->y * wind->y);
  float wind_on_final = wind_norm * (((td_af_x * wind->y) / (td_af * wind_norm)) +
                                     ((td_af_y * wind->x) / (td_af * wind_norm)));
  Bound(wind_on_final, -MAX_WIND_ON_FINAL, MAX_WIND_ON_FINAL);
  gs_on_final = target_speed - wind_on_final;

  // calculate position of SD (start decent)
  float t_sd_intercept = (gs_on_final * tanf(app_angle)) / app_intercept_rate; //time
  sd_intercept = gs_on_final * t_sd_intercept; // distance
  sd_tod = 0.5 * sd_intercept;

  // set waypoint SD (start decent)
  WaypointX(_sd) = WaypointX(_tod) + td_af_x / td_af * sd_tod;
  WaypointY(_sd) = WaypointY(_tod) + td_af_y / td_af * sd_tod;
  WaypointAlt(_sd) = WaypointAlt(_af);

  // calculate td_sd
  float td_sd_x = WaypointX(_sd) - WaypointX(_td);
  float td_sd_y = WaypointY(_sd) - WaypointY(_td);
  float td_sd = sqrt(td_sd_x * td_sd_x + td_sd_y * td_sd_y);

  // calculate sd_tod in x,y
  sd_tod_x = WaypointX(_tod) - WaypointX(_sd);
  sd_tod_y = WaypointY(_tod) - WaypointY(_sd);

  // set Waypoint AF at least befor SD
  if ((td_sd + app_distance_af_sd) > td_af) {
    WaypointX(_af) = WaypointX(_sd) + td_af_x / td_af * app_distance_af_sd;
    WaypointY(_af) = WaypointY(_sd) + td_af_y / td_af * app_distance_af_sd;
  }
  return FALSE;
} /* end of gls_copute_TOD */
Beispiel #11
0
void mf_daq_send_state(void)
{
    // Send aircraft state to DAQ board
    DOWNLINK_SEND_MF_DAQ_STATE(extra_pprz_tp, EXTRA_DOWNLINK_DEVICE,
                               &autopilot_flight_time,
                               &stateGetBodyRates_f()->p,
                               &stateGetBodyRates_f()->q,
                               &stateGetBodyRates_f()->r,
                               &stateGetNedToBodyEulers_f()->phi,
                               &stateGetNedToBodyEulers_f()->theta,
                               &stateGetNedToBodyEulers_f()->psi,
                               &stateGetAccelNed_f()->x,
                               &stateGetAccelNed_f()->y,
                               &stateGetAccelNed_f()->z,
                               &stateGetSpeedEnu_f()->x,
                               &stateGetSpeedEnu_f()->y,
                               &stateGetSpeedEnu_f()->z,
                               &stateGetPositionLla_f()->lat,
                               &stateGetPositionLla_f()->lon,
                               &stateGetPositionLla_f()->alt,
                               &stateGetHorizontalWindspeed_f()->y,
                               &stateGetHorizontalWindspeed_f()->x);
}
Beispiel #12
0
bool_t nav_anemotaxis( uint8_t c, uint8_t c1, uint8_t c2, uint8_t plume ) {
  if (chemo_sensor) {
    last_plume_was_here();
    waypoints[plume].x = stateGetPositionEnu_f()->x;
    waypoints[plume].y = stateGetPositionEnu_f()->y;
    //    DownlinkSendWp(plume);
  }

  struct FloatVect2* wind = stateGetHorizontalWindspeed_f();
  float wind_dir = atan2(wind->x, wind->y) + M_PI;

  /** Not null even if wind_east=wind_north=0 */
  float upwind_x = cos(wind_dir);
  float upwind_y = sin(wind_dir);

  switch (status) {
  case UTURN:
    NavCircleWaypoint(c, DEFAULT_CIRCLE_RADIUS*sign);
    if (NavQdrCloseTo(DegOfRad(M_PI_2-wind_dir))) {
      float crosswind_x = - upwind_y;
      float crosswind_y = upwind_x;
      waypoints[c1].x = waypoints[c].x + DEFAULT_CIRCLE_RADIUS*upwind_x;
      waypoints[c1].y = waypoints[c].y + DEFAULT_CIRCLE_RADIUS*upwind_y;

      float width = Max(2*ScalarProduct(upwind_x, upwind_y, stateGetPositionEnu_f()->x-last_plume.x, stateGetPositionEnu_f()->y-last_plume.y), DEFAULT_CIRCLE_RADIUS);

      waypoints[c2].x = waypoints[c1].x - width*crosswind_x*sign;
      waypoints[c2].y = waypoints[c1].y - width*crosswind_y*sign;

      //      DownlinkSendWp(c1);
      //      DownlinkSendWp(c2);

      status = CROSSWIND;
      nav_init_stage();
    }
    break;

  case CROSSWIND:
    NavSegment(c1, c2);
    if (NavApproaching(c2, CARROT)) {
      waypoints[c].x = waypoints[c2].x + DEFAULT_CIRCLE_RADIUS*upwind_x;
      waypoints[c].y = waypoints[c2].y + DEFAULT_CIRCLE_RADIUS*upwind_y;

      // DownlinkSendWp(c);

      sign = -sign;
      status = UTURN;
      nav_init_stage();
    }

    if (chemo_sensor) {
      waypoints[c].x = stateGetPositionEnu_f()->x + DEFAULT_CIRCLE_RADIUS*upwind_x;
      waypoints[c].y = stateGetPositionEnu_f()->y + DEFAULT_CIRCLE_RADIUS*upwind_y;

      // DownlinkSendWp(c);

      sign = -sign;
      status = UTURN;
      nav_init_stage();
    }
    break;
  }
  chemo_sensor = 0;
  return TRUE;
}
Beispiel #13
0
bool nav_survey_disc_run(uint8_t center_wp, float radius)
{
  struct FloatVect2 *wind = stateGetHorizontalWindspeed_f();
  float wind_dir = atan2(wind->x, wind->y) + M_PI;

  /** Not null even if wind_east=wind_north=0 */
  struct FloatVect2 upwind;
  upwind.x = cos(wind_dir);
  upwind.y = sin(wind_dir);

  float grid = nav_survey_shift / 2;

  switch (disc_survey.status) {
    case UTURN:
      nav_circle_XY(disc_survey.c.x, disc_survey.c.y, grid * disc_survey.sign);
      if (NavQdrCloseTo(DegOfRad(M_PI_2 - wind_dir))) {
        disc_survey.c1.x = stateGetPositionEnu_f()->x;
        disc_survey.c1.y = stateGetPositionEnu_f()->y;

        struct FloatVect2 dist;
        VECT2_DIFF(dist, disc_survey.c1, waypoints[center_wp]);
        float d = VECT2_DOT_PRODUCT(upwind, dist);
        if (d > radius) {
          disc_survey.status = DOWNWIND;
        } else {
          float w = sqrtf(radius * radius - d * d) - 1.5 * grid;

          struct FloatVect2 crosswind;
          crosswind.x = -upwind.y;
          crosswind.y = upwind.x;

          disc_survey.c2.x = waypoints[center_wp].x + d * upwind.x - w * disc_survey.sign * crosswind.x;
          disc_survey.c2.y = waypoints[center_wp].y + d * upwind.y - w * disc_survey.sign * crosswind.y;

          disc_survey.status = SEGMENT;
        }
        nav_init_stage();
      }
      break;

    case DOWNWIND:
      disc_survey.c2.x = waypoints[center_wp].x - upwind.x * radius;
      disc_survey.c2.y = waypoints[center_wp].y - upwind.y * radius;
      disc_survey.status = SEGMENT;
      /* No break; */

    case SEGMENT:
      nav_route_xy(disc_survey.c1.x, disc_survey.c1.y, disc_survey.c2.x, disc_survey.c2.y);
      if (nav_approaching_xy(disc_survey.c2.x, disc_survey.c2.y, disc_survey.c1.x, disc_survey.c1.y, CARROT)) {
        disc_survey.c.x = disc_survey.c2.x + grid * upwind.x;
        disc_survey.c.y = disc_survey.c2.y + grid * upwind.y;

        disc_survey.sign = -disc_survey.sign;
        disc_survey.status = UTURN;
        nav_init_stage();
      }
      break;
    default:
      break;
  }

  NavVerticalAutoThrottleMode(0.); /* No pitch */
  NavVerticalAltitudeMode(WaypointAlt(center_wp), 0.); /* No preclimb */

  return true;
}
Beispiel #14
0
bool_t disc_survey( uint8_t center, float radius) {
  struct FloatVect2* wind = stateGetHorizontalWindspeed_f();
  float wind_dir = atan2(wind->x, wind->y) + M_PI;

  /** Not null even if wind_east=wind_north=0 */
  float upwind_x = cos(wind_dir);
  float upwind_y = sin(wind_dir);

  float grid = nav_survey_shift / 2;

  switch (status) {
  case UTURN:    U形弯模式
    nav_circle_XY(c.x, c.y, grid*sign);
    if (NavQdrCloseTo(DegOfRad(M_PI_2-wind_dir))) {
      c1.x = stateGetPositionEnu_f()->x;
      c1.y = stateGetPositionEnu_f()->y;

      float d = ScalarProduct(upwind_x, upwind_y, stateGetPositionEnu_f()->x-WaypointX(center), stateGetPositionEnu_f()->y-WaypointY(center));
      if (d > radius) {
        status = DOWNWIND;
      } else {
        float w = sqrt(radius*radius - d*d) - 1.5*grid;

        float crosswind_x = - upwind_y;
        float crosswind_y = upwind_x;

        c2.x = WaypointX(center)+d*upwind_x-w*sign*crosswind_x;
        c2.y = WaypointY(center)+d*upwind_y-w*sign*crosswind_y;

        status = SEGMENT;
      }
      nav_init_stage();
    }
    break;

  case DOWNWIND:    //这是什么模式?
    c2.x = WaypointX(center) - upwind_x * radius;
    c2.y = WaypointY(center) - upwind_y * radius;
    status = SEGMENT;
    /* No break; */

  case SEGMENT:   //线段模式
    nav_route_xy(c1.x, c1.y, c2.x, c2.y);
    if (nav_approaching_xy(c2.x, c2.y, c1.x, c1.y, CARROT)) {
      c.x = c2.x + grid*upwind_x;
      c.y = c2.y + grid*upwind_y;

      sign = -sign;
      status = UTURN;
      nav_init_stage();
    }
    break;
  default:
    break;
  }

  NavVerticalAutoThrottleMode(0.); /* No pitch */
  NavVerticalAltitudeMode(WaypointAlt(center), 0.); /* No preclimb */

  return TRUE;
}