| Earth Observation Mission CFI Software Usage Guide for Object Oriented Software |

# SIMPLE INSTRUMENT SIMULATOR

The following program is a simple simulator that calculates orbit, attitude and geolocation geometric properties based on a simple instrument (push broom sensor at a fixed azimuth and a certain numbers of pixels). Observation are above a certain area:

    // ------------------------------------------------------------------------
    //
    //                           JAVA Example Program.
    //                           FULLY-FEATURED PROGRAM
    //
    // ------------------------------------------------------------------------

    import java.io.File;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Locale;
    import java.util.Vector;
    import java.util.logging.*;
    import java.lang.*;
    import java.io.BufferedWriter;
    import java.io.FileWriter;
    import java.io.IOException;

    import EECFI.*;
    import static EECFI.EnumDataHandling.*;
    import static EECFI.EnumLib.*;
    import static EECFI.EnumOrbit.*;
    import static EECFI.EnumPointing.*;
    import static EECFI.EnumVisibility.*;

    // ------------
    // Main program
    // ------------
    public class qsgExample
    {
      public static void main(String[] args)
      {
        Vector<String> errorMessages = new Vector<String>();

        // Variables to initialize dem_id
        long useDEMFlag = 0; // If 0, DEM will NOT be used. If 1, DEM will be used

        try
        {

          // Initialize default model id
          long mode = XLCFI_MODEL_DEFAULT;
          Vector<Long>models = new Vector<Long>(); //not used when mode is XLCFI_MODEL_DEFAULT
          ModelId modelId = new ModelId(mode, models);

          // Initialize time correlations with orbit file
          // (using all the file validity interval)
          String orbitFile = "orbit_file.xml";
          long timeModel = XLCFI_TIMEMOD_AUTO;
          long timeRef   = XLCFI_TIME_UTC;
          Vector <String> inputFiles = new Vector<String>();
          inputFiles.add(orbitFile);
          TimeInterval validityTime = new TimeInterval();;

          TimeCorrelation timeId = new TimeCorrelation(timeModel, inputFiles, timeRef, validityTime);

          // Initialize orbit
          // The same orbit files as for TimeCorrelation will be used
          SatId satId = new SatId(XOCFI_SAT_METOP_SG_A1); // METOP satellite
          long   initModel = XOCFI_ORBIT_INIT_AUTO; // Detect automatically the type of orbit file
          long   initMode  = XOCFI_SEL_FILE; // Use all file, time and orbit intervals are dummy
          // time0, time1, orbi0, orbit1 are not used for XLCFI_SEL_FILE option
          double time0     = 0.;
          double time1     = 0.;
          long   orbit0    = 0;
          long   orbit1    = 0;

          OrbitId orbitId = new OrbitId(satId, modelId, timeId,
                                        timeRef, initModel, inputFiles,
                                        initMode, time0, time1, orbit0, orbit1);

          // Initialize dem id if required
          DemId demId = new DemId();
          if (useDEMFlag == 1)
          {
            String demConfigFile = "dem_config_file.xml";
            initMode  = XDCFI_DEM_GETASSE30_V1; // it is not needed, but it is better to have it
                                                // in line with the content of DEM configuration file
            initModel = 0; // Dummy parameter

            demId.init(initMode, initModel, demConfigFile);

          }

          // Initialize atmos id with no atmosphere model
          initMode  = XPCFI_NO_REF_INIT; // No atmosphere model
          initModel = 0;              // dummy parameter
          String atmosDummyFile = ""; // dummy parameter
          AtmosId atmosId = new AtmosId();
          atmosId.init(initMode, initModel, atmosDummyFile);

          // Initialize satellite attitudes to perform.
          // We use an attitude definition file, this way we can initialize all the
          // atttitudes at the same time.
          AttitudeDefinitionData attDefData = new AttitudeDefinitionData("attitude_definition_file.xml");
          attDefData.read();

          AttitudeDef attDef = PointingFunc.attitudeDefine(attDefData);

          attDef.type = XPCFI_SAT_ATT;
          Attitude attId = new Attitude(timeId,
                                        attDef.satNomTransId,
                                        attDef.satTransId,
                                        attDef.instrTransId);

          // Define zone (Spain polygon)
          Vector<ZonePoint> zonePoints = new Vector<ZonePoint>();
          zonePoints.addElement(new ZonePoint( 3.813258057950049,  42.5091355830345));
          zonePoints.addElement(new ZonePoint(-1.706802028054565,  35.82814264689165));
          zonePoints.addElement(new ZonePoint(-9.155852980327245,  36.05894971586847));
          zonePoints.addElement(new ZonePoint(-9.876611106388474,  44.21197011498435));
          zonePoints.addElement(new ZonePoint( 3.813258057950049,  42.5091355830345));
          ZoneRec zoneData = new ZoneRec("TEST_ZONE",
                                         "Spain zone",
                                         "", //surface type
                                         "User",
                                         XDCFI_POLYGON,
                                         XDCFI_RECTANGULAR,
                                         0, //diameter
                                         zonePoints);

          ZoneInfoList zoneInfoList = new ZoneInfoList();
          zoneInfoList.zoneInfo     = new ZoneInfo[1];
          zoneInfoList.zoneInfo[0]  = new ZoneInfo(zoneData,
                                                   XDCFI_RECTANGULAR,
                                                   0.); // min duration
          zoneInfoList.calcFlag = XVCFI_COMPUTE;

          // Define visibility interval from start of orbit validity and 1 day more.
          ValidityTime orbitVal =   orbitId.getValTime();
          Time valTime0 = new Time(timeId, orbitVal.start, orbitVal.timeRef, XLCFI_PROC);

          Time valUTC0 = valTime0.getProcessing(XLCFI_TIME_UTC, XLCFI_PROC);

          VisTimeInterval interval = new VisTimeInterval();
          interval.tstart.type    = XVCFI_UTC_TYPE;
          interval.tstart.utcTime = valUTC0.time;
          interval.tstop.type     = XVCFI_UTC_TYPE;
          interval.tstop.utcTime  = valUTC0.time + 1.;

          // Initialize swath id with Swath definition file
          SwathInfo swathInfo      = new SwathInfo();
          swathInfo.type           = XVCFI_FILE_SDF; // Initialize with Swath definition file
          swathInfo.filename       = "swath_definition_file.xml";
          swathInfo.nofRegenOrbits = 10; // Regenerate internal STF every 10 orbits
          SwathId swathId= new SwathId(atmosId, swathInfo);

          Swath swath = new Swath(orbitId, 1, "");
          VisibilityList visList = swath.zoneVisTimeCompute(attDef,
                                                            swathId,
                                                            zoneInfoList,
                                                            interval);

          System.out.println("Number of visibility segments found: "+ visList.segments.size());

          // Prepare inputs for xp_target_list_inter
          int nofPixels = 3;
          int az_i;

          InstrumentData instData = new InstrumentData();
          instData.type            = XPCFI_AZ_EL_LIST;
          instData.signalFrequency = 1.e10;

          double[] azimuthList   = {90.,90.,270.};
          double[] elevationList = {75.,90.,60.};
          AzimuthElevation [] azEl = new AzimuthElevation[3];
          for (az_i = 0 ; az_i < nofPixels ; az_i ++)
          {
            azEl[az_i].azimuth        = azimuthList[az_i];
            azEl[az_i].elevation      = elevationList[az_i];
            azEl[az_i].azimuthRate   = 0.;
            azEl[az_i].elevationRate = 0.;

          }
          instData.azimuthElevationList = new AzimuthElevationList(azEl);

          // Perform some computations in the visibility intervals
          // We will use a time step of 5 seconds:
          double timeStep = 5. / 86400.;

          // Select the type of target to be computed
          long targetType;
          if (useDEMFlag == 1) targetType = XPCFI_DEM_TARGET_TYPE;
          else                 targetType = XPCFI_USER_TARGET_TYPE;

          // Open csv info file to store information and write header line
          FileWriter     csvFile   = new FileWriter("out.csv");
          BufferedWriter csvWriter = new BufferedWriter(csvFile);

          csvWriter.write("UTC_TIME,SAT_POSITION_X,SAT_POSITION_Y,SAT_POSITION_Z," +
                          "SAT_VELOCITY_X,SAT_VELOCITY_Y,SAT_VELOCITY_Z,"+
                          "PIXEL_0_TARGET_LON,PIXEL_0_TARGET_LAT,"+
                          "PIXEL_1_TARGET_LON,PIXEL_1_TARGET_LAT,"+
                          "PIXEL_2_TARGET_LON,PIXEL_2_TARGET_LAT\n");

          int seg_i;
          long propagModel = 0; // Dummy

          for (seg_i = 0 ; seg_i < visList.segments.size() ; seg_i ++)
          {
            // Loop to visibility interval
            double timePointsInInterval = (visList.segments.elementAt(seg_i).utcTimeStop -
                                           visList.segments.elementAt(seg_i).utcTimeStart) / timeStep;

            System.out.println("\tSegment " + seg_i +
                               " Number of 5 seconds intervals = " + timePointsInInterval);

            int time_i;
            for (time_i = 0 ; time_i < timePointsInInterval; time_i ++)
            {
              double loopTime = visList.segments.elementAt(seg_i).utcTimeStart + time_i * timeStep;

              // Compute Orbit State Vector at current time
              StateVector osv =     orbitId.osvCompute(propagModel, timeRef, loopTime);

              // Compute attitude at current time (satellite attitude)
              attId.compute (modelId, osv, XPCFI_SAT_ATT);

              // Compute target METHOD 1: Compute pixels one by one
              int pixel_i;
              for (pixel_i = 0 ; pixel_i < nofPixels ; pixel_i++)
              {
                Target targetId = new Target(attId, demId, atmosId);

                targetId.targetInter(satId,
                                     XPCFI_NO_DER,
                                     XPCFI_INTER_1ST,
                                     azimuthList[pixel_i],
                                     elevationList[pixel_i],
                                     0.,     //geodetic altitude
                                     0., 0,  //azimuth and elevation rates
                                     0,      //iray (dummy)
                                     1.e10); //signal frequency

                TargetExtra mainRes = targetId.extraMain(XPCFI_TARG_EXTRA_MAIN_GEO,
                                                         XPCFI_USER_TARGET_TYPE,
                                                         0); // targetNumber
              } // end loop to pixels

              // Compute target METHOD 2: Compute all pixels at the same time
              Target targetListId = new Target(attId, demId, atmosId);
              TargetOutput targOut = targetListId.targetListInter(satId,
                                                                  XPCFI_NO_DER,
                                                                  XPCFI_INTER_1ST,
                                                                  instData,
                                                                  0.);  //geodetic altitude

              TargetExtraResultsList resultslist = targetListId.extraListMain(XPCFI_TARG_EXTRA_MAIN_GEO,
                                                                              XPCFI_USER_TARGET_TYPE);

              csvWriter.write(loopTime + ","
                      + osv.coord.pos[0] + "," + osv.coord.pos[1] + "," + osv.coord.pos[2] + ","
                      + osv.coord.vel[0] + "," + osv.coord.vel[1] + "," + osv.coord.vel[2] + ","
                      + resultslist.extraResults[0].results[0] + ","
                      + resultslist.extraResults[0].results[2] + ","
                      + resultslist.extraResults[1].results[0] + ","
                      + resultslist.extraResults[1].results[2] + ","
                      + resultslist.extraResults[2].results[0] + ","
                      + resultslist.extraResults[2].results[2] + "\n");

            } // End loop to interval

          } // end loop to visibility intervals

          // Close output file and writer
          csvWriter.close();
          csvFile.close();

        }
        catch( CfiError cfiError )
        {
          System.out.println("\tERROR IN EXAMPLE!!!");
          errorMessages = cfiError.getMsg( errorMessages );
        }
        catch( IOException ioexp )
        {
          System.out.println("\tERROR IN EXAMPLE!!!");
          System.out.println("\tOutput CSV file cannot be written");
        }

        //Print result
        if ( errorMessages.size() > 0)
        {
          System.out.println("*** ERRORS DURING EXECUTION ***");
          for (int cont = 0 ; cont < errorMessages.size() ; cont++ )
          {
            System.out.println("Message error " + (cont + 1) +
                               ":" + errorMessages.elementAt(cont));
          }
          System.out.println("*** EXAMPLE: FAILED ***");

        }//end if errVec.size
        else
        {
          System.out.println("*** USAGE EXAMPLE COMPLETED SUCCESSFULLY ***");
        }

        return;

      } // end main

    } // end class