Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use elevation data #9

Open
danielrichman opened this issue Sep 18, 2013 · 2 comments
Open

Use elevation data #9

danielrichman opened this issue Sep 18, 2013 · 2 comments

Comments

@danielrichman
Copy link
Member

  • for landing
  • for automatically setting launch altitude

Daniel Kunzler de S. Carmo [email protected] has provided a patch for the former (i.e., landing only). It downloads data from http://www2.jpl.nasa.gov/srtm/ as it needs it in the pred binary (and keeps it permanently, since it doesn't change).

We can't use this immediately since we've been avoiding having the predictor binary download anything while it is running like the plague (it has caused a lot of problems in the past; we now download whole GFS datasets in advance).

Need to:

  • sort out downloading in advance
  • add auto launch altitude (probably to the PHP)

Maybe:

  • average data to reduce disk space requirement for holding the whole elevation dataset. Investigate how much it varies?
@danielrichman
Copy link
Member Author

// --------------------------------------------------------------
// CU Spaceflight Landing Prediction
// Copyright (c) CU Spaceflight 2013, All Rights Reserved
//
// Written by Daniel Kunzler
//
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// --------------------------------------------------------------
//
// Description:
// Get elevation (ground level) of a certain location, uses NASA SRTM data: 
// http://www2.jpl.nasa.gov/srtm/ (SRTM 3arcsec, version 2.1). SRTM data is
// automatically downloaded when necessary, but if you need offline data 
// just store all HGT files in ./hgt folder as these are not dynamic.
//
// An even better source would be 
// http://www.viewfinderpanoramas.org/Coverage%20map%20viewfinderpanoramas_org3.htm
// (better resolution in north america and better void filling). If offline 
// storage is available, you can download HGT files from it too and disable
// the lat>60 limitation.
//

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "miniz.c"
#include "elev.h"

int get_elevation(float lat, float lng){

    static char HGTList[15000][40] = { "", };
    static int HGTListLen = 0;
    static char error = 0;
    static char firstcall = 1;
    static char lastHGT[20];        
    int hgt, i, j;
    int ilat, ilng;         //Integer part
    float ixlat, ixlng;     //Floating point part
    FILE* file;
    char filename[20];
    char filepath[30];
    char filenameD[20];
    char filepathD[30];
    char url[120];
    char samefile = 0;

    if (error==1) return 0;     //ignore this function in case of previous fatal error

    if (firstcall==1){
        //Read all HGTList.csv when called for the first time only
        file=fopen("./pred_src/elev/HGTList.csv","r");
        if (!file){
            fprintf(stderr, "ERROR: Cannot open HGTList.csv file. Using sea level instead.\n");
            error=1;
            return 0;
        }

        while (!feof(file)){
            fscanf(file, "%s\n", HGTList[HGTListLen]);
            //fprintf(stderr,"%s\n", HGTList[HGTListLen]);
            HGTListLen++;
        }
        fclose(file);
        firstcall=0;
        fprintf(stderr, "INFO: HGTList.csv was read.\n");
    }

    //Assemble appropriate filename
    strcpy(filename,"x00x000.hgt");
    ilat=(int)lat;
    ilng=(int)lng;
    ixlat = lat-(float)ilat;
    ixlng = lng-(float)ilng;    

    //Final adjustments of filename for each "half-hemisphere"
    if (lat>=0) {
        ixlat = (int)((-ixlat+1)*1200);
    }else{
        ixlat = (int)(-ixlat*1200);
        ilat = (int)abs(lat)+1;
    }

    if (lng>=0){
        ixlng = (int)(ixlng*1200);
    }else{
        ixlng = (int)((ixlng+1)*1200);
        ilng = (int)abs(lng)+1;
    }

    //fprintf(stderr,"%f %f\n", lat, lng);
    //fprintf(stderr,"%i %i\n", ilat, ilng);
    //fprintf(stderr,"%f %f\n", ixlat, ixlng);

    if (lat>0) filename[0]='N'; else filename[0]='S';
    filename[1]='0'+ilat/10;
    filename[2]='0'+ilat%10;
    if (lng>0) filename[3]='E'; else filename[3]='W';
    filename[4]='0'+ilng/100;
    filename[5]='0'+(ilng%100)/10;
    filename[6]='0'+ilng%10;
    //fprintf(stderr, "INFO: Elevation file name: %s\n", filename);
        strcpy(filepath,"./hgt/");
    strcat(filepath,filename);

    //To avoid repetitive INFO prints
    if (strcmp(filename,lastHGT)==0){
        samefile=1;             
    }else{
        strcpy(lastHGT,filename);
        samefile=0;
    }

    if ((abs(lat)>60) && (samefile==0)){
        fprintf(stderr, "INFO: This latitude (%0.f) is out of SRTM elevation survey. Using sea level instead.\n", lat);
        return 0;
    }

    //Try to open local file (if exists)    
    file=fopen(filepath,"rb");
    if (file){
        //File available, read it 
        hgt = readHgt(file, (unsigned int)ixlat, (unsigned int)ixlng);
        fclose(file); 
    }else{
        if (samefile==1) return 0;      //do not proceed if online file was not available before
        //Local file not available, download
        fprintf(stderr, "INFO: Elevation file %s is not present, needs to be downloaded.\n", filename);
        strcpy(filenameD,filename);
        strcat(filenameD,".zip");
        strcpy(url,"http://dds.cr.usgs.gov/srtm/version2_1/SRTM3/");
        //Locate online file folder (regions)
        for (j=0;j<HGTListLen;j++){
            if (strstr(HGTList[j],filenameD)!=NULL) strcat(url,HGTList[j]);
        }

        if (strstr(url,".zip") == NULL){
            fprintf(stderr, "INFO: Elevation file %s doesn't exist online (it's not covered by SRTM or it's above sea area).\n", filenameD);
            return 0;
        }

        strcpy(filepathD,"./hgt/");
        strcat(filepathD,filenameD);
        get_file(url,filepathD);

        //Test downloaded file
        file=fopen(filepathD,"rb");
        if (!file) {
            fprintf(stderr, "ERROR: Elevation file %s could not be downloaded.\n", filenameD);
            fprintf(stderr, "       So, it is going to be ignored from now on. Using sea level instead.\n");
            error=1;
            return 0;
        }else{
            fprintf(stderr, "INFO: Elevation file %s downloaded.\n", filenameD);
            fclose(file);
        }

        //Uncompress zip file
        if (uncomp(filepathD, filename, filepath) == 0) {
            fprintf(stderr, "ERROR: Elevation file %s archive error.\n", filenameD);
            fprintf(stderr, "       So, it is going to be ignored from now on. Using sea level instead.\n");
            error=1;
            return 0;
        }

        //Delete zip file
        remove(filepathD);

        //Second try to open local file
        //printf("%s \n", filepath);
        file=fopen(filepath,"rb");
            if(!file) {
            fprintf(stderr, "ERROR: Elevation file %s doesn't exist in ./hgt or cannot be opened.\n", filename);
            fprintf(stderr, "       So, it is going to be ignored from now on. Using sea level instead.\n");
            error=1;
            return 0;
        }else{
            //File is now available, read it 
            hgt = readHgt(file, (unsigned int)ixlat, (unsigned int)ixlng);
            fclose(file); 
        }
    }

    return hgt;
}

//Read HGT file to find elevation
//r,c: HGT row and column identifier (file contents grouped by 16-bit words)
int readHgt(FILE* file, unsigned int r, unsigned int c)     
{
    int hgt;
    unsigned char* buf;     
    unsigned long lSize;

    //Reserve space for the full HGT file
    buf = malloc(1210*1210*2);

    //Read HGT file
    fseek (file , 0 , SEEK_END);            // obtain file size
    lSize = ftell (file);
    rewind (file);
    fread(buf, sizeof(buf),lSize,file);
    hgt = (buf[(2*c)+(r*2402)] <<8) + buf[(2 * c) + (r * 2402) + 1];    
    if (hgt<-32000) {
        hgt=0;              //on a void SRTM data, consider elevation=0 (rare, ~0.2%)
        fprintf(stderr,"Void\n");
    }
    free(buf);

    return hgt;
}


//--------------------------------------------------------------------------------------------------
//Utility functions

//Download functions (libcurl)

static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream)
{
  size_t written = fwrite(ptr, size, nmemb, (FILE *)stream);
  return written;
}

void get_file(char* url, char* file_name)
{
  CURL *curl_handle;
  FILE *pagefile;

  curl_global_init(CURL_GLOBAL_ALL);
  /* init the curl session */
  curl_handle = curl_easy_init();
  /* set URL to get here */
  curl_easy_setopt(curl_handle, CURLOPT_URL, url);
  /* Switch on full protocol/debug output while testing */
  curl_easy_setopt(curl_handle, CURLOPT_VERBOSE, 1L);
  /* disable progress meter, set to 0L to enable and disable debug output */
  curl_easy_setopt(curl_handle, CURLOPT_NOPROGRESS, 1L);
  /* send all data to this function  */
  curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, write_data);
  /* open the file */
  pagefile = fopen(file_name, "wb");
  if (pagefile) {
    /* write the page body to this file handle. CURLOPT_FILE is also known as
       CURLOPT_WRITEDATA*/
    curl_easy_setopt(curl_handle, CURLOPT_FILE, pagefile);
    /* get it! */
    curl_easy_perform(curl_handle);
    /* close the header file */
    fclose(pagefile);
  }
  /* cleanup curl stuff */
  curl_easy_cleanup(curl_handle);
}

//ZIP functions (miniz)

//Extract one file to heap
int uncomp(char* archivepath, char* filename, char* filePathToSave)
{
    //Open ZIP archive (miniz)
    uint i;
    mz_bool status;
    size_t uncomp_size;
    mz_zip_archive zip_archive;
    void *p;
    FILE* file2;

    memset(&zip_archive, 0, sizeof(zip_archive));
    status = mz_zip_reader_init_file(&zip_archive, archivepath, 0);
    if (!status) return 0;

    // Try to extract to the heap.
    p = mz_zip_reader_extract_file_to_heap(&zip_archive, filename, &uncomp_size, 0);
    if (!p) return 0;

    file2 = fopen (filePathToSave, "wb");
    fwrite(p,sizeof(char),uncomp_size,file2);
    fclose(file2);

    return 1;
}

@danielrichman
Copy link
Member Author

diff --git a/hgt/.placeholder b/hgt/.placeholder
new file mode 100644
index 0000000..e69de29
diff --git a/pred_src/CMakeLists.txt b/pred_src/CMakeLists.txt
index c6665fb..95b8f37 100644
--- a/pred_src/CMakeLists.txt
+++ b/pred_src/CMakeLists.txt
@@ -10,6 +10,11 @@ pkg_check_modules(GLIB REQUIRED glib-2.0)
 include_directories(${GLIB_INCLUDE_DIRS})
 link_directories(${GLIB_LIBRARY_DIRS})

+pkg_check_modules(CURL REQUIRED libcurl)
+
+include_directories(${CURL_INCLUDE_DIRS})
+link_directories(${CURL_LIBRARY_DIRS})
+
 add_executable(pred
    util/gopt.c
    util/getdelim.c
@@ -29,10 +34,12 @@ add_executable(pred
    run_model.c
    pred.h
    run_model.h
+   elev/elev.c
+   elev/elev.h
    ini/iniparser.c
    ini/iniparser.h
    ini/dictionary.h
    ini/dictionary.c
 )

-target_link_libraries(pred ${GLIB_LIBRARIES} -lm)
+target_link_libraries(pred ${CURL_LIBRARIES} ${GLIB_LIBRARIES} -lm)
diff --git a/pred_src/altitude.c b/pred_src/altitude.c
index b58214c..7ab4566 100644
--- a/pred_src/altitude.c
+++ b/pred_src/altitude.c
@@ -18,6 +18,7 @@
 #include "pred.h"
 #include "altitude.h"
 #include "run_model.h"
+#include "elev/elev.h"

 // get density of atmosphere at a given altitude
 // uses NASA model from http://www.grc.nasa.gov/WWW/K-12/airplane/atmosmet.html
@@ -63,7 +64,7 @@ altitude_model_free(altitude_model_t* self)
 }

 int 
-altitude_model_get_altitude(altitude_model_t* self, int time_into_flight, float* alt) {
+altitude_model_get_altitude(altitude_model_t* self, int time_into_flight, float* alt, float lat, float lng) {
     // TODO: this section needs some work to make it more flexible

     // time == 0 so setup initial altitude stuff
@@ -98,8 +99,15 @@ altitude_model_get_altitude(altitude_model_t* self, int time_into_flight, float*
    *alt += TIMESTEP * vertical_speed;
    */

-    if (*alt <= 0)
+    if (*alt <= get_elevation(lat,lng)){
+   //fprintf(stderr,"%i\n",get_elevation(lat,lng));
+   if (get_elevation(lat,lng) !=0) {
+       fprintf(stderr,"INFO: Stopped descent on %0.f m ASL (elevation at %0.4f, %0.4f).\n", *alt, lat, lng);
+   }else{
+       fprintf(stderr,"INFO: Stopped descent on sea level (%0.4f, %0.4f).\n", lat, lng);
+   }
         return 0;
+   }

     return 1;

diff --git a/pred_src/altitude.h b/pred_src/altitude.h
index 2d9326a..2e62cee 100644
--- a/pred_src/altitude.h
+++ b/pred_src/altitude.h
@@ -35,7 +35,9 @@ void                 altitude_model_free   (altitude_model_t   *model);
 int                  altitude_model_get_altitude
                                            (altitude_model_t   *model,
                                             int                 time_into_flight, 
-                                            float              *alt);
+                                            float              *alt,
+                       float       lat,
+                           float       lng);



diff --git a/pred_src/cmake_install.cmake b/pred_src/cmake_install.cmake
index 4e9ac35..e207627 100644
--- a/pred_src/cmake_install.cmake
+++ b/pred_src/cmake_install.cmake
@@ -1,4 +1,4 @@
-# Install script for directory: /var/www/html/habhub/cusf-standalone-predictor/pred_src
+# Install script for directory: /home/daniel/cusf-standalone-predictor-master-mod/pred_src

 # Set the install prefix
 IF(NOT DEFINED CMAKE_INSTALL_PREFIX)
@@ -29,7 +29,7 @@ ENDIF(NOT CMAKE_INSTALL_COMPONENT)

 # Install shared libraries without execute permission?
 IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)
-  SET(CMAKE_INSTALL_SO_NO_EXE "0")
+  SET(CMAKE_INSTALL_SO_NO_EXE "1")
 ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE)

 IF(CMAKE_INSTALL_COMPONENT)
@@ -38,7 +38,7 @@ ELSE(CMAKE_INSTALL_COMPONENT)
   SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt")
 ENDIF(CMAKE_INSTALL_COMPONENT)

-FILE(WRITE "/var/www/html/habhub/cusf-standalone-predictor/pred_src/${CMAKE_INSTALL_MANIFEST}" "")
+FILE(WRITE "/home/daniel/cusf-standalone-predictor-master-mod/pred_src/${CMAKE_INSTALL_MANIFEST}" "")
 FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES})
-  FILE(APPEND "/var/www/html/habhub/cusf-standalone-predictor/pred_src/${CMAKE_INSTALL_MANIFEST}" "${file}\n")
+  FILE(APPEND "/home/daniel/cusf-standalone-predictor-master-mod/pred_src/${CMAKE_INSTALL_MANIFEST}" "${file}\n")
 ENDFOREACH(file)
diff --git a/pred_src/elev/HGTList.csv b/pred_src/elev/HGTList.csv
new file mode 100644
index 0000000..dda758b
--- /dev/null
+++ b/pred_src/elev/HGTList.csv
@@ -0,0 +1,14450 @@
+Africa/N00E006.hgt.zip
+Africa/N00E009.hgt.zip

[snip]

+South_America/S53W075.hgt.zip
+South_America/S53W076.hgt.zip
diff --git a/pred_src/elev/elev.c b/pred_src/elev/elev.c
new file mode 100644
index 0000000..4de8572
--- /dev/null
+++ b/pred_src/elev/elev.c
@@ -0,0 +1,285 @@
+// --------------------------------------------------------------
[snip]
+}
diff --git a/pred_src/elev/elev.h b/pred_src/elev/elev.h
new file mode 100644
index 0000000..a4e0746
--- /dev/null
+++ b/pred_src/elev/elev.h
@@ -0,0 +1,22 @@
+// --------------------------------------------------------------
+// CU Spaceflight Landing Prediction
+// Copyright (c) CU Spaceflight 2013, All Rights Reserved
+//
+// Written by Daniel Kunzler
+//
+// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
+// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
+// PARTICULAR PURPOSE.
+// --------------------------------------------------------------
+
+#ifndef __ELEV_H__
+#define __ELEV_H__
+
+int get_elevation(float lat, float lng);
+int readHgt(FILE *, unsigned int r, unsigned int c);
+static size_t write_data(void *ptr, size_t size, size_t nmemb, void *stream);
+void get_file(char* url, char* file_name);
+int uncomp(char* archivepath, char* filename, char* filePathToSave);
+
+#endif
diff --git a/pred_src/elev/miniz.c b/pred_src/elev/miniz.c
new file mode 100644
index 0000000..5856b7c
--- /dev/null
+++ b/pred_src/elev/miniz.c
@@ -0,0 +1,4834 @@
+/* miniz.c v1.14 - public domain deflate/inflate, zlib-subset, ZIP reading/writing/appending, PNG writing
+   See "unlicense" statement at the end of this file.

[snip]

+
+  For more information, please refer to <http://unlicense.org/>
+*/
diff --git a/pred_src/pred.c b/pred_src/pred.c
index 1089a1d..b6a05b7 100644
--- a/pred_src/pred.c
+++ b/pred_src/pred.c
@@ -149,7 +149,7 @@ int main(int argc, const char *argv[]) {
         }

         if(!scenario) {
-            fprintf(stderr, "ERROR: could not parse scanario file.\n");
+            fprintf(stderr, "ERROR: could not parse scenario file.\n");
             exit(1);
         }

diff --git a/pred_src/run_model.c b/pred_src/run_model.c
index 401d029..54fcf57 100644
--- a/pred_src/run_model.c
+++ b/pred_src/run_model.c
@@ -74,7 +74,7 @@ _advance_one_timestep(wind_file_cache_t* cache,
         model_state_t* state = &(states[i]);

         if(!altitude_model_get_altitude(state->alt_model, 
-                                        timestamp - initial_timestamp, &state->alt))
+                                        timestamp - initial_timestamp, &state->alt, state->lat, state->lng))
             return 0; // alt < 0; finished

         if(!get_wind(cache, state->lat, state->lng, state->alt, timestamp, 

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant