Open danielrichman opened 11 years ago
// --------------------------------------------------------------
// 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;
}
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,
Daniel Kunzler de S. Carmo daniel@dkcarmo.com 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:
Maybe: