From e943a28d3c0bf6f59e7429ffeb78b0eaaf5ffc50 Mon Sep 17 00:00:00 2001 From: alex Date: Sun, 19 Mar 2017 19:55:09 +0000 Subject: [PATCH] Path profile Tx height bugfix for some models --- CHANGELOG | 21 +++++++++++++++++ README.md | 2 +- inputs.cc | 9 ++++---- main.cc | 63 +++++++++++++++++++++++++++++++++------------------ models/los.cc | 5 ++-- models/sui.cc | 3 ++- outputs.cc | 29 +++++++++++++----------- 7 files changed, 87 insertions(+), 45 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 4d14a02..1ab7936 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,26 @@ SIGNAL SERVER CHANGELOG +3.03 - 19 March 2017 +Path profile bugfix for some models +Error handling for when prop loss < free space loss + +3.02 - 22 Feb 2017 +Gareth's error handling + +3.01 - 16 Feb 2017 +Image crop (Major performance improvement later on), SUI bugfix, txelev replaced + +3.0 - 02 Feb 2017 +Image rendering library support. Uses third party PNG lib instead of expensive PPM. +Code cleanup by a professional developer. +More errors to stderr + +2.94 - 03 Oct 2016 +Reduced MAXPAGES array for LIDAR to allow for uber large tiles + +2.93 - 30 Sep 2016 +More tiles + 2.92 - 29 September 2016 Overhauled LIDAR functions to read in (more) native format tiles. Replaced 'super tile' code with more scalable multi-tile code: currently limited to 16. diff --git a/README.md b/README.md index 446307e..1c3c20c 100644 --- a/README.md +++ b/README.md @@ -32,7 +32,7 @@ make ## Parameters ``` -Version: Signal Server 2.94 (Built for 64 DEM tiles at 1200 pixels) +Version: Signal Server 3.03 (Built for 100 DEM tiles at 1200 pixels) License: GNU General Public License (GPL) version 2 Radio propagation simulator by Alex Farrant QCVS, 2E0TDW diff --git a/inputs.cc b/inputs.cc index 3cadf59..1f45304 100644 --- a/inputs.cc +++ b/inputs.cc @@ -41,7 +41,7 @@ int loadClutter(char *filename, double radius, struct site tx) if(w==2880 && h==3840){ cellsize=0.004167; - cellsize2 = cellsize * 2; + cellsize2 = cellsize * 3; }else{ return 0; // can't work with this yet } @@ -107,8 +107,7 @@ int loadClutter(char *filename, double radius, struct site tx) // not in near field if((lat > tx.lat+cellsize2 || lat < tx.lat-cellsize2) || (lon > tx.lon + cellsize2 || lon < tx.lon - cellsize2)){ - AddElevation(lat,lon,clh,3); - + AddElevation(lat,lon,clh,2); } } @@ -414,7 +413,7 @@ int LoadSDF_SDF(char *name) if (debug == 1) { fprintf(stderr, - "Loading \"%s\" into page %d...", + "Loading \"%s\" into page %d...\n", path_plus_name, indx + 1); fflush(stderr); } @@ -566,7 +565,7 @@ int LoadSDF(char *name) sscanf(name, "%d:%d:%d:%d", &minlat, &maxlat, &minlon, &maxlon); - + /* Is it already in memory? */ for (indx = 0, found = 0; indx < MAXPAGES && found == 0; indx++) { diff --git a/main.cc b/main.cc index 36af101..3b5be7e 100644 --- a/main.cc +++ b/main.cc @@ -1,4 +1,4 @@ -double version = 3.02; +double version = 3.03; /****************************************************************************\ * Signal Server: Radio propagation simulator by Alex Farrant QCVS, 2E0TDW * ****************************************************************************** @@ -38,9 +38,9 @@ double version = 3.02; #include "models/pel.hh" #include "image.hh" -int MAXPAGES = 64; -int ARRAYSIZE = 76810; +int MAXPAGES = 10*10; int IPPD = 1200; +int ARRAYSIZE = MAXPAGES * IPPD; char string[255], sdf_path[255], udt_file[255], opened = 0, gpsav = 0, ss_name[16], dashes[80]; @@ -53,7 +53,7 @@ double earthradius, max_range = 0.0, forced_erp, dpp, ppd, yppd, int ippd, mpi, max_elevation = -32768, min_elevation = 32768, bzerror, contour_threshold, - pred, pblue, pgreen, ter, multiplier = 256, debug = 0, loops = 64, jgets = + pred, pblue, pgreen, ter, multiplier = 256, debug = 0, loops = 100, jgets = 0, MAXRAD, hottest = 10, height, width; unsigned char got_elevation_pattern, got_azimuth_pattern, metric = 0, dbm = 0; @@ -200,7 +200,6 @@ int OrMask(double lat, double lon, int value) x = (int)rint(ppd * (lat - dem[indx].min_north)); y = mpi - (int)rint(yppd * (LonDiff(dem[indx].max_west, lon))); - if (x >= 0 && x <= mpi && y >= 0 && y <= mpi) found = 1; else @@ -234,7 +233,6 @@ int PutSignal(double lat, double lon, unsigned char signal) int x = 0, y = 0, indx; char found; - if (signal > hottest) // dBm, dBuV hottest = signal; @@ -348,7 +346,7 @@ int AddElevation(double lat, double lon, double height, int size) } } - + return found; } @@ -1710,9 +1708,15 @@ int main(int argc, char *argv[]) if(delta>0){ tx_site[0].lon+=delta; } - + }else{ // DEM first + if(debug){ + fprintf(stderr,"%.4f,%.4f,%.4f,%.4f,%.4f,%.4f\n",max_north,min_west,min_north,max_west,max_lon,min_lon); + } + + max_lon-=3; + if( (result = LoadTopoData(max_lon, min_lon, max_lat, min_lat)) != 0 ){ // This only fails on errors loading SDF tiles fprintf(stderr, "Error loading topo data\n"); @@ -1810,10 +1814,11 @@ int main(int argc, char *argv[]) } ppd=(double)ippd; yppd=ppd; + width = (unsigned)(ippd * ReduceAngle(max_west - min_west)); height = (unsigned)(ippd * ReduceAngle(max_north - min_north)); } - + dpp = 1 / ppd; mpi = ippd-1; @@ -1863,14 +1868,27 @@ int main(int argc, char *argv[]) } } - // CROPPING. croplat assigned in propPathLoss() - max_north=cropLat; // MAX(path.lat[y]) - max_west=cropLon; // MAX(path.lon[y]) - cropLat-=tx_site[0].lat; // angle from tx to edge - cropLon-=tx_site[0].lon; - width=(int)((cropLon*ppd)*2); - height=(int)((cropLat*ppd)*2); - + if(max_range<=100){ + // CROPPING. croplat assigned in propPathLoss() + max_north=cropLat; // MAX(path.lat[y]) + // Edge case #1 - EAST/WEST + if(cropLon>357 && tx_site[0].lon < 3) + cropLon=tx_site[0].lon+3; + // Edge case #2 - EAST/EAST + if(cropLon>359.5 && tx_site[0].lon > 359.5) + cropLon=362; + max_west=cropLon; // MAX(path.lon[y]) + cropLat-=tx_site[0].lat; // angle from tx to edge + cropLon-=tx_site[0].lon; + width=(int)((cropLon*ppd)*2); + height=(int)((cropLat*ppd)*2); + + if(width>3600*10){ + fprintf(stderr,"FATAL BOUNDS! max_west: %.4f cropLat: %.4f cropLon: %.4f longitude: %.5f\n",max_west,cropLat,cropLon,tx_site[0].lon); + return 0; + } + } + // Write bitmap if (LR.erp == 0.0) DoPathLoss(mapfile, geo, kml, ngs, tx_site, @@ -1889,11 +1907,12 @@ int main(int argc, char *argv[]) if (tx_site[0].lon > 0.0){ tx_site[0].lon *= -1; - } + } if (tx_site[0].lon < -180.0){ tx_site[0].lon += 360; - } - if (propmodel == 2) { + } + + if (propmodel == 2 || max_range > 100) { // No croppping because this is LOS fprintf(stderr, "|%.6f", max_north); fprintf(stderr, "|%.6f", east); @@ -1907,7 +1926,7 @@ int main(int argc, char *argv[]) fprintf(stderr, "|%.6f|",tx_site[0].lon-cropLon); } fprintf(stderr, "\n"); - + } else { strncpy(tx_site[0].name, "Tx", 3); @@ -1915,7 +1934,7 @@ int main(int argc, char *argv[]) PlotPath(tx_site[0], tx_site[1], 1); PathReport(tx_site[0], tx_site[1], tx_site[0].filename, 0, propmodel, pmenv, rxGain); - SeriesData(tx_site[1], tx_site[0], tx_site[0].filename, 1, + SeriesData(tx_site[0], tx_site[1], tx_site[0].filename, 1, normalise); } fflush(stderr); diff --git a/models/los.cc b/models/los.cc index f07f624..a5cba82 100644 --- a/models/los.cc +++ b/models/los.cc @@ -336,7 +336,8 @@ void PlotPropPath(struct site source, struct site destination, Longley-Rice. This information is required for properly integrating the antenna's elevation pattern into the calculation for overall path loss. */ - + if(debug) + fprintf(stderr,"four_thirds_earth %.1f source.alt %.1f path.elevation[0] %.1f\n",four_thirds_earth,source.alt,path.elevation[0]); for (y = 2; (y < (path.length - 1) && path.distance[y] <= max_range); y++) { /* Process this point only if it @@ -445,8 +446,6 @@ void PlotPropPath(struct site source, struct site destination, dkm = (elev[1] * elev[0]) / 1000; // km - - switch (propmodel) { case 1: // Longley Rice ITM diff --git a/models/sui.cc b/models/sui.cc index 6ad7657..ef72d2d 100644 --- a/models/sui.cc +++ b/models/sui.cc @@ -45,5 +45,6 @@ double SUIpathLoss(float f, float TxH, float RxH, float d, int mode) double Xf = 6 * log10(f / 2000); double Xh = XhCF * log10(RxH / 2000); - return A + (10 * y * log10(d / d0)) + Xf + Xh + s; + //return A + (10 * y * log10(d / d0)) + Xf + Xh + s; + return A + (10 * y) * (log10(d / d0)) + Xf + Xh + s; } diff --git a/outputs.cc b/outputs.cc index 54c1041..675c6e2 100644 --- a/outputs.cc +++ b/outputs.cc @@ -491,7 +491,7 @@ int DoSigStr(char *filename, unsigned char geo, unsigned char kml, /* We should never get here, but if */ /* we do, display the region as black */ - ADD_PIXEL(&ctx, 0, 0, 0); + ADD_PIXEL(&ctx, 255, 255, 255); } } } @@ -735,7 +735,7 @@ void DoRxdPwr(char *filename, unsigned char geo, unsigned char kml, /* We should never get here, but if */ /* we do, display the region as black */ - ADD_PIXEL(&ctx, 0, 0, 0); + ADD_PIXEL(&ctx, 255, 255, 255); } } } @@ -981,7 +981,7 @@ void DoLOS(char *filename, unsigned char geo, unsigned char kml, /* We should never get here, but if */ /* we do, display the region as black */ - ADD_PIXEL(&ctx, 0, 0, 0); + ADD_PIXEL(&ctx, 255, 255, 255); } } } @@ -1336,10 +1336,9 @@ void PathReport(struct site source, struct site destination, char *name, for (y = 2; y < (path.length - 1); y++) { /* path.length-1 avoids LR error */ distance = 5280.0 * path.distance[y]; - source_alt = - four_thirds_earth + source.alt + path.elevation[0]; - dest_alt = - four_thirds_earth + destination.alt + + + source_alt = four_thirds_earth + source.alt + path.elevation[0]; + dest_alt = four_thirds_earth + destination.alt + path.elevation[y]; dest_alt2 = dest_alt * dest_alt; source_alt2 = source_alt * source_alt; @@ -1414,7 +1413,7 @@ void PathReport(struct site source, struct site destination, char *name, strmode, errnum); */ dkm = (elev[1] * elev[0]) / 1000; // km - + switch (propmodel) { case 1: // Longley Rice ITM @@ -1431,14 +1430,14 @@ void PathReport(struct site source, struct site destination, char *name, case 3: //HATA 1, 2 & 3 loss = - HATApathLoss(LR.frq_mhz, source_alt * METERS_PER_FOOT, + HATApathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT), dkm, pmenv); break; case 4: // COST231-HATA loss = - ECC33pathLoss(LR.frq_mhz, source_alt * METERS_PER_FOOT, + ECC33pathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT), dkm, pmenv); break; @@ -1451,7 +1450,7 @@ void PathReport(struct site source, struct site destination, char *name, break; case 6: loss = - COST231pathLoss(LR.frq_mhz, source_alt * METERS_PER_FOOT, + COST231pathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT), dkm,pmenv); break; @@ -1473,7 +1472,7 @@ void PathReport(struct site source, struct site destination, char *name, case 9: // Ericsson loss = - EricssonpathLoss(LR.frq_mhz, source_alt * METERS_PER_FOOT, + EricssonpathLoss(LR.frq_mhz, source.alt * METERS_PER_FOOT, (path.elevation[y] * METERS_PER_FOOT) + (destination.alt * METERS_PER_FOOT), dkm, @@ -1535,6 +1534,11 @@ void PathReport(struct site source, struct site destination, char *name, free_space_loss); } + if((loss*1.1) < free_space_loss){ + fprintf(stderr,"Model error! Computed loss of %.1fdB is greater than free space loss of %.1fdB. Check your inuts for model %d\n",loss,free_space_loss,propmodel); + return; + } + fprintf(fd2, "Computed path loss: %.2f dB\n", loss); if (free_space_loss != 0.0) @@ -1633,7 +1637,6 @@ void PathReport(struct site source, struct site destination, char *name, } ObstructionAnalysis(source, destination, LR.frq_mhz, fd2); - fclose(fd2); fprintf(stderr,