/**
 * Initialize TLE, read flash to get TLE and update in SGP4 algorithm. If the
 * flash memory is corrupted get the first TLE.
 * @return
 */
adcs_error_status init_tle() {

    adcs_error_status error_status_value = ERROR_OK;
    uint8_t tle_string[TLE_SIZE];
    memset(tle_string, 0, TLE_SIZE);

    /* Read TLE from flash */
    if (flash_read_tle(&temp_tle) == FLASH_ERROR) {
        error_status_value = ERROR_FLASH;
    }
    /* Update if it is correct else get the first TLE */
    if (update_tle(&upsat_tle, temp_tle) == TLE_ERROR) {
        error_status_value = ERROR_TLE;
        sprintf(tle_string,
                "1 25544U 98067A   16229.19636472  .00005500  00000-0  87400-4 0  9991\n2 25544  51.6439 118.5889 0001926 134.0246   3.7037 15.55029964 14324");
        temp_tle = read_tle(tle_string);
        update_tle(&upsat_tle, temp_tle);
    }
    return error_propagation(error_status_value);
}
Пример #2
0
int main(int argc,char *argv[])
{
  int i,j,k,arg=0,satno=0,satname=0,usecatalog=0,imode,m=10;
  long norb;
  char *datafile,*catalog,filename[32];
  int ia[7]={0,0,0,0,0,0,0};
  char line1[70],line2[70],desig[10];
  double mjd,sma,perigee,apogee,xno;
  float mag=0.0,dm;
  xyz_t r,v;
  FILE *file;

  // Decode options
  while ((arg=getopt(argc,argv,"d:c:i:n:m:"))!=-1) {
    switch(arg) {

    case 'd':
      datafile=optarg;
      break;

    case 'c':
      catalog=optarg;
      usecatalog=1;
      break;

    case 'i':
      satno=atoi(optarg);
      break;

    case 'n':
      norb=atoi(optarg);
      if (norb<0)
	norb=0;
      break;

    case 'm':
      mag=atof(optarg);
      break;

    default:
      return 0;
    }
  }

  // Magnitude offset
  dm=5.0*log10(1000.0/40000.0);

  // Reloop stderr
  freopen("/tmp/stderr.txt","w",stderr);

  // Decode filename
  mjd=decode_filename(datafile,&satname);

  // Read data
  d=read_data(datafile,mjd);

  // Write data
  sprintf(filename,"%06d.xyz",satname);
  file=fopen(filename,"w");
  for (i=0;i<d.n;i++) 
    fprintf(file,"%lf %f %f %f\n",d.p[i].mjd,d.p[i].r.x,d.p[i].r.y,d.p[i].r.z);
  fclose(file);

  // Open elements
  sprintf(filename,"%06d.tle",satname);
  file=fopen(filename,"w");

  // Estimate orbit
  k=504;
  if (usecatalog==0) {
    // Set initial state vector
    r.x=d.p[k].r.x;
    r.y=d.p[k].r.y;
    r.z=d.p[k].r.z;
    v.x=(d.p[k+1].r.x-d.p[k].r.x)/60.0;
    v.y=(d.p[k+1].r.y-d.p[k].r.y)/60.0;
    v.z=(d.p[k+1].r.z-d.p[k].r.z)/60.0;
    
    // Estimate initial orbit from elements
    orb=rv2el(99999,d.p[k].mjd,r,v);
    strcpy(orb.desig,"14999A");
    orb.norb=norb;
  } else {
    // Read orbit
    orb=read_tle(catalog,satno);
    strcpy(desig,orb.desig);
    // Propagate
    imode=init_sgdp4(&orb);
    imode=satpos_xyz(d.p[k].mjd+2400000.5,&r,&v);
    orb=rv2el(orb.satno,d.p[k].mjd,r,v);
    //      orb.satno=99999;
    //      strcpy(orb.desig,"14999A");
    strcpy(orb.desig,desig);
    orb.norb=norb;
  }

  // Set flags
  for (j=0;j<d.n;j++)
    d.p[j].flag=0;
    
  for (j=0;j<d.n;j++)
    d.p[j].flag=1;
  
  // Fit orbit
  for (j=0;j<10;j++) {
    if (j==1) ia[4]=1;
    if (j==2) ia[1]=1;
    if (j==3) ia[0]=1;
    if (j==4) ia[5]=1;
    if (j==5) ia[3]=1;
    if (j==6) ia[2]=1;
    if (j==7) ia[6]=1;
    fit(orb,ia);
  }

  // Compute orbit size
  xno=orb.rev*2.0*M_PI/XMNPDA;
  sma=pow(XKE/xno,2.0/3.0)*XKMPER;
  perigee=sma*(1.0-orb.ecc)-XKMPER;
  apogee=sma*(1.0+orb.ecc)-XKMPER;
  
  // Format TLE
  format_tle(orb,line1,line2);

  fprintf(file,"SO %6d                      %4.1f             %7.0fkm  x%7.0fkm\n%s\n%s\n# %d positions, %.1f km rms\n",satname,mag+dm,perigee,apogee,line1,line2,d.nsel,d.rms);
  printf("SO %6d                      %4.1f             %7.0fkm  x%7.0fkm\n%s\n%s\n# %d positions, %.1f km rms\n",satname,mag+dm,perigee,apogee,line1,line2,d.nsel,d.rms);

  // Close output file
  fclose(file);

  return 0;
}
Пример #3
0
int plan(const char *satellite, const char *beam_mode, double look_angle,
         long startdate, long enddate, double min_lat, double max_lat,
         double clat, double clon, int pass_type,
         int zone, Poly *aoi, const char *tle_filename,
         PassCollection **pc_out, char **errorstring)
{
  BeamModeInfo *bmi = get_beam_mode_info(satellite, beam_mode);
  if (!bmi) {
    *errorstring = STRDUP("Unknown satellite/beam mode combination.\n");
    return -1;
  }

  // Convert the input start/end times from longdates (dates as long ints)
  // to seconds from some reference time.  (midnight jan 1, 1900)
  // We add a day to the end date, so that the passed-in range is inclusive
  double start_secs = seconds_from_long(startdate);
  double end_secs = seconds_from_long(add_a_day(enddate));

  sat_t sat;
  read_tle(tle_filename, satellite, &sat);

  // if the planned acquisition period is further away than this amount,
  // we subtract multiples of the repeat cyle time until we are within
  // this threshold time of this tle
  double tle_time =
    time_to_secs(sat.tle.epoch_year, sat.tle.epoch_day, sat.tle.epoch_fod);

  // FIXME this is alos specific FIXME!!
  // should really read this out of a config file... or calculate it
  // from the TLE info?
  const double repeat_days = 46;
  const double orbits_per_cycle = 671;

  // repeat time, in seconds, all time references are in seconds
  double repeat_cycle_time = repeat_days * 24.*60.*60.;

  // how many days to pad the repeat cycle time, before modding the
  // start/end time
  const double days_of_padding = 5;

  // this is the cutoff, 
  double threshold = repeat_cycle_time + 24*60*60 * days_of_padding;

  int cycles_adjustment=0;
  if (start_secs-tle_time > threshold) {
    while (start_secs-tle_time > threshold) {
      start_secs -= repeat_cycle_time;
      end_secs -= repeat_cycle_time;
      ++cycles_adjustment;
    }
  }
  else if (tle_time-start_secs > threshold) { // planning backwards...
    while (tle_time-start_secs > threshold) {
      start_secs += repeat_cycle_time;
      end_secs += repeat_cycle_time;
      --cycles_adjustment;
    }
  }

  double time_adjustment = cycles_adjustment*repeat_cycle_time;
  if (cycles_adjustment != 0)
    asfPrintStatus("Adjusted start/end times %s by %d repeat cycle%s.\n",
           cycles_adjustment > 0 ? "forward" : "backward",
           cycles_adjustment > 0 ? cycles_adjustment : -cycles_adjustment,
           cycles_adjustment == 1 || cycles_adjustment == -1 ? "" : "s");

  // no deep space orbits can be planned
  assert((sat.flags & DEEP_SPACE_EPHEM_FLAG) == 0);

  if (is_utm(zone)) {
    asfPrintStatus("Target: UTM zone %d\n"
                   "  (%10.2f, %10.2f)  (%10.2f, %10.2f)\n"
                   "  (%10.2f, %10.2f)  (%10.2f, %10.2f)\n",
                   zone,
                   aoi->x[0], aoi->y[0],
                   aoi->x[1], aoi->y[1],
                   aoi->x[2], aoi->y[2],
                   aoi->x[3], aoi->y[3]);
  }
  else {
    asfPrintStatus("Target: Polar Stereo %s\n"
                   "  (%10.2f, %10.2f)  (%10.2f, %10.2f)\n"
                   "  (%10.2f, %10.2f)  (%10.2f, %10.2f)\n",
                   zone>0 ? "North" : "South",
                   aoi->x[0], aoi->y[0],
                   aoi->x[1], aoi->y[1],
                   aoi->x[2], aoi->y[2],
                   aoi->x[3], aoi->y[3]);
  }

  double curr = start_secs;
  double incr = bmi->image_time;
  stateVector st = tle_propagate(&sat, start_secs-incr);
  double lat_prev = sat.ssplat;
  int i,num_found = 0;

  // 
  // Calculate the number of frames to include before we hit the
  // area of interest.  Add 1 (i.e., round up), but if user puts in
  // zero seconds, then we want 0 lead-up frames.
  PassCollection *pc = pass_collection_new(clat, clon, aoi);

  asfPrintStatus("Searching...\n");
  while (curr < end_secs) {
    st = tle_propagate(&sat, curr);
    char dir = sat.ssplat > lat_prev ? 'A' : 'D';

    if ((dir=='A' && pass_type!=DESCENDING_ONLY) ||
        (dir=='D' && pass_type!=ASCENDING_ONLY))
    {
      OverlapInfo *oi =
        overlap(curr, &st, bmi, look_angle, zone, clat, clon, aoi);

      if (oi) {
        int n=0;

        // Calculate the orbit number -- we have to fudge this if we
        // modded the start time.
        int orbit_num = sat.orbit + orbits_per_cycle*cycles_adjustment;

        // This is an alternate way of calculating the orbit number that
        // was being used during testing... seems to produce numbers close
        // to (within 1) of the number obtained by sgpsdp...
        //double secs_per_orbit = repeat_cycle_time / orbits_per_cycle;
        // ALOS was launced on 1/24/06
        //double launch_secs = seconds_from_long(20060124);
        //double orbit_num2 = (curr - launch_secs) / secs_per_orbit;
        //orbit_num2 += orbits_per_cycle*cycles_adjustment;
        //printf("%f %f %f\n", orbit_num + sat.orbit_part,
        //       orbit_num2, orbit_num+sat.orbit_part-orbit_num2);

        // UPDATE!!  All this orbit number calculation business doesn't get
        // used for ALOS planning -- orbit number is re-calculated using
        // time since a refrence orbit.
        // See planner.c -- get_alos_orbit_number_at_time()

        PassInfo *pass_info = pass_info_new(orbit_num, sat.orbit_part, dir);
        double start_time = curr - bmi->num_buffer_frames*incr;

        // add on the buffer frames before the area of interest
        for (i=bmi->num_buffer_frames; i>0; --i) {
          double t = curr - i*incr;
          stateVector st1 = tle_propagate(&sat, t);
          double rclat, rclon; // viewable region center lat/lon

          Poly *region = get_viewable_region(&st1, bmi, look_angle,
                                             zone, clat, clon, &rclat, &rclon);

          if (region) {
            OverlapInfo *oi1 = overlap_new(0, 1000, region, zone, clat, clon,
                                           &st1, t);
            pass_info_add(pass_info, t+time_adjustment, oi1);

            if (pass_info->start_lat == -999) {
              // at the first valid buffer frame -- set starting latitude
              double start_lat, end_lat;
              get_latitude_range(region, zone, dir, &start_lat, &end_lat);
              pass_info_set_start_latitude(pass_info, start_lat);
            }
          }
        }

        // add the frames that actually image the area of interest
        while (curr < end_secs && oi) {
          pass_info_add(pass_info, curr+time_adjustment, oi);
          ++n;

          curr += incr;
          st = tle_propagate(&sat, curr);

          oi = overlap(curr, &st, bmi, look_angle, zone, clat, clon, aoi);
        }

        double end_time = curr + (bmi->num_buffer_frames-1)*incr;
        pass_info_set_duration(pass_info, end_time-start_time);

        // add on the buffer frames after the area of interest
        for (i=0; i<bmi->num_buffer_frames; ++i) {
          double t = curr + i*incr;
          stateVector st1 = tle_propagate(&sat, t);
          double rclat, rclon; // viewable region center lat/lon
          Poly *region = get_viewable_region(&st1, bmi, look_angle,
                                             zone, clat, clon, &rclat, &rclon);
          if (region) {
            OverlapInfo *oi1 = overlap_new(0, 1000, region, zone, clat, clon,
                                           &st1, t);
            pass_info_add(pass_info, t+time_adjustment, oi1);

            // set stopping latitude -- each frame overwrites the previous,
            // so the last valid frame will set the stopping latitude
            double start_lat, end_lat;
            get_latitude_range(region, zone, dir, &start_lat, &end_lat);
            pass_info_set_stop_latitude(pass_info, end_lat);
          }
        }

        // make sure we set all the required "after the fact" info
        // if not, then do not add the pass... must be invalid
        // (these used to be asserts, so it doesn't seem to ever happen)
        if (n>0 &&
            pass_info->start_lat != -999 &&
            pass_info->stop_lat != -999 &&
            pass_info->duration != -999)
        {
          // add the pass!
          pass_collection_add(pc, pass_info);
          ++num_found;
        }
        else
        {
          asfPrintStatus("Invalid pass found.  Skipped... \n"
                         " -- number of frames: %d, dir: %c\n"
                         " -- date: %s, orbit %d, %f\n --> (%f,%f,%f)\n",
                         n, pass_info->dir,
                         pass_info->start_time_as_string,
                         pass_info->orbit, pass_info->orbit_part,
                         pass_info->start_lat, pass_info->stop_lat,
                         pass_info->duration);
        }
      }
    }

    curr += incr;
    lat_prev = sat.ssplat;

    //printf("Lat: %f, Orbit: %d, Orbit Part: %f\n", sat.ssplat,
    //       (int)sat.orbit, sat.orbit_part);

    asfPercentMeter((curr-start_secs)/(end_secs-start_secs));
  }
  asfPercentMeter(1.0);

  *pc_out = pc;
  return num_found;
}