Plane earth model and MODIS landcover clutter

This commit is contained in:
root
2016-09-01 21:40:56 +01:00
parent 12e22c1f22
commit 3b2362c72f
12 changed files with 209 additions and 12 deletions

View File

@@ -1,5 +1,8 @@
SIGNAL SERVER CHANGELOG SIGNAL SERVER CHANGELOG
2.9 - 01 September 2016
MODIS Landcover support in ASCII Grid format. Works for 1200/3600 SRTM only.
2.82 - 15 July 2016 2.82 - 15 July 2016
Fixed bug in SUI model which was making it over optimistic. Fixed bug in SUI model which was making it over optimistic.

View File

@@ -8,7 +8,7 @@ LIBS = -lm -lpthread
VPATH = models VPATH = models
objects = main.o cost.o ecc33.o ericsson.o fspl.o hata.o itwom3.0.o \ objects = main.o cost.o ecc33.o ericsson.o fspl.o hata.o itwom3.0.o \
los.o sui.o inputs.o outputs.o los.o sui.o pel.o inputs.o outputs.o
GCC_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 1) GCC_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 1)
GCC_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 2) GCC_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 2)
@@ -43,10 +43,10 @@ main.o: main.cc common.h inputs.hh outputs.hh itwom3.0.hh los.hh
inputs.o: inputs.cc common.h main.hh inputs.o: inputs.cc common.h main.hh
outputs.o: outputs.cc common.h inputs.hh main.hh cost.hh ecc33.hh ericsson.hh \ outputs.o: outputs.cc common.h inputs.hh main.hh cost.hh ecc33.hh ericsson.hh \
fspl.hh hata.hh itwom3.0.hh sui.hh fspl.hh hata.hh itwom3.0.hh sui.hh pel.hh
los.o: los.cc common.h main.hh cost.hh ecc33.hh ericsson.hh fspl.hh hata.hh \ los.o: los.cc common.h main.hh cost.hh ecc33.hh ericsson.hh fspl.hh hata.hh \
itwom3.0.hh sui.hh itwom3.0.hh sui.hh pel.hh
.PHONY: clean .PHONY: clean
clean: clean:

125
inputs.cc
View File

@@ -6,6 +6,131 @@
#include "common.h" #include "common.h"
#include "main.hh" #include "main.hh"
int loadClutter(char *filename, double radius, struct site tx)
{
/* This function reads a MODIS 17-class clutter file in ASCII Grid format.
The nominal heights it applies to each value, eg. 5 (Mixed forest) = 15m are
taken from ITU-R P.452-11.
It doesn't have it's own matrix, instead it boosts the DEM matrix like point clutter
AddElevation(lat, lon, height);
If tiles are standard 2880 x 3840 then cellsize is constant at 0.004166
*/
int x, y, z, clh, result, h, w;
double xll, yll, xur, yur, cellsize, cellsize2, xOffset, yOffset, lat, lon, i, j;
char line[50000];
char * pch;
FILE *fd;
fd = fopen(filename, "rb");
if (fd != NULL) {
if (fgets(line, 19, fd) != NULL) {
pch = strtok (line," ");
pch = strtok (NULL, " ");
w = atoi(pch);
}
if (fgets(line, 19, fd) != NULL) {
//pch = strtok (line," ");
//pch = strtok (NULL, " ");
h = atoi(pch);
}
if(w==2880 && h==3840){
cellsize=0.004167;
cellsize2 = cellsize * 2;
}else{
return 0; // can't work with this yet
}
if (debug) {
fprintf(stdout, "\nLoading clutter file \"%s\" %d x %d...\n", filename, w,h);
fflush(stdout);
}
if (fgets(line, 25, fd) != NULL) {
sscanf(pch, "%lf", &xll);
}
fgets(line, 25, fd);
if (fgets(line, 25, fd) != NULL) {
sscanf(pch, "%lf", &yll);
}
if (debug) {
fprintf(stdout, "\nxll %.2f yll %.2f\n", xll, yll);
fflush(stdout);
}
fgets(line, 25, fd); // cellsize
//loop over matrix
for (y = h; y > 0; y--) {
x = 0;
if (fgets(line, 100000, fd) != NULL) {
pch = strtok(line, " ");
while (pch != NULL && x < w) {
z = atoi(pch);
// Apply ITU-R P.452-11
// Treat classes 0, 9, 10, 11, 15, 16 as water, (Water, savanna, grassland, wetland, snow, barren)
clh = 0;
// evergreen, evergreen, urban
if(z == 1 || z == 2 || z == 13)
clh = 20;
// deciduous, deciduous, mixed
if(z==3 || z==4 || z==5)
clh = 15;
if(z==6)
clh = 4;
if(z==7 || z==12 || z==14)
clh = 2;
if(clh>1){
clh/=2; // Because heights are deliberately conservative
xOffset=x*cellsize; // 12 deg wide
yOffset=y*cellsize; // 16 deg high
// make all longitudes positive
if(xll+xOffset>0){
lon=360-(xll+xOffset);
}else{
lon=(xll+xOffset)*-1;
}
lat = yll+yOffset;
// bounding box
if(lat > tx.lat - radius && lat < tx.lat + radius && lon > tx.lon - radius && lon < tx.lon + radius){
// 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);
// Create rectangle of dimensions cellsize x cellsize
for(i=cellsize*-1; i < cellsize; i=i+0.0005){
for(j=cellsize*-1; j < cellsize; j=j+0.0005){
AddElevation(lat+i,lon+j,clh);
}
}
}
}
}
x++;
pch = strtok(NULL, " ");
}//while
} else {
fprintf(stdout, "Clutter error @ x %d y %d\n", x, y);
}//if
}//for
}
fclose(fd);
return 0;
}
void readLIDAR(FILE *fd, int hoffset, int voffset, int h, int w, int indx, void readLIDAR(FILE *fd, int hoffset, int voffset, int h, int w, int indx,
double n, double e, double s, double west) double n, double e, double s, double west)
{ {

View File

@@ -12,5 +12,6 @@ void LoadDBMColors(struct site xmtr);
void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat); void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat);
void LoadUDT(char *filename); void LoadUDT(char *filename);
int loadLIDAR(char *filename); int loadLIDAR(char *filename);
int loadClutter(char *filename, double radius, struct site tx);
#endif /* _INPUTS_HH_ */ #endif /* _INPUTS_HH_ */

36
main.cc
View File

@@ -1,4 +1,4 @@
double version = 2.82; double version = 2.9;
/****************************************************************************\ /****************************************************************************\
* Signal Server: Radio propagation simulator by Alex Farrant QCVS, 2E0TDW * * Signal Server: Radio propagation simulator by Alex Farrant QCVS, 2E0TDW *
****************************************************************************** ******************************************************************************
@@ -33,6 +33,7 @@ double version = 2.82;
#include "outputs.hh" #include "outputs.hh"
#include "models/itwom3.0.hh" #include "models/itwom3.0.hh"
#include "models/los.hh" #include "models/los.hh"
#include "models/pel.hh"
int MAXPAGES = 64; int MAXPAGES = 64;
int ARRAYSIZE = 76810;//76810; int ARRAYSIZE = 76810;//76810;
@@ -1011,7 +1012,7 @@ int main(int argc, char *argv[])
unsigned char LRmap = 0, txsites = 0, topomap = 0, geo = 0, kml = unsigned char LRmap = 0, txsites = 0, topomap = 0, geo = 0, kml =
0, area_mode = 0, max_txsites, ngs = 0; 0, area_mode = 0, max_txsites, ngs = 0;
char mapfile[255], udt_file[255], ano_filename[255], lidar_tiles[512]; char mapfile[255], udt_file[255], ano_filename[255], lidar_tiles[512], clutter_file[255];
double altitude = 0.0, altitudeLR = 0.0, tx_range = 0.0, double altitude = 0.0, altitudeLR = 0.0, tx_range = 0.0,
rx_range = 0.0, deg_range = 0.0, deg_limit = 0.0, deg_range_lon; rx_range = 0.0, deg_range = 0.0, deg_limit = 0.0, deg_range_lon;
@@ -1040,7 +1041,8 @@ int main(int argc, char *argv[])
fprintf(stdout, "Data:\n"); fprintf(stdout, "Data:\n");
fprintf(stdout, " -sdf Directory containing SRTM derived .sdf DEM tiles\n"); fprintf(stdout, " -sdf Directory containing SRTM derived .sdf DEM tiles\n");
fprintf(stdout, " -lid ASCII grid tile (LIDAR) with dimensions and resolution defined in header\n"); fprintf(stdout, " -lid ASCII grid tile (LIDAR) with dimensions and resolution defined in header\n");
fprintf(stdout, " -udt User defined CSV clutter file\n"); fprintf(stdout, " -udt User defined point clutter as decimal co-ordinates: 'latitude,longitude,height'\n");
fprintf(stdout, " -clt MODIS 17-class wide area clutter in ASCII grid format\n");
fprintf(stdout, "Input:\n"); fprintf(stdout, "Input:\n");
fprintf(stdout, " -lat Tx Latitude (decimal degrees) -70/+70\n"); fprintf(stdout, " -lat Tx Latitude (decimal degrees) -70/+70\n");
fprintf(stdout, " -lon Tx Longitude (decimal degrees) -180/+180\n"); fprintf(stdout, " -lon Tx Longitude (decimal degrees) -180/+180\n");
@@ -1052,7 +1054,7 @@ int main(int argc, char *argv[])
fprintf(stdout, " -rxh Rx Height(s) (optional. Default=0.1)\n"); fprintf(stdout, " -rxh Rx Height(s) (optional. Default=0.1)\n");
fprintf(stdout, " -rxg Rx gain dBi (optional for text report)\n"); fprintf(stdout, " -rxg Rx gain dBi (optional for text report)\n");
fprintf(stdout, " -hp Horizontal Polarisation (default=vertical)\n"); fprintf(stdout, " -hp Horizontal Polarisation (default=vertical)\n");
fprintf(stdout, " -gc Ground clutter (feet/meters)\n"); fprintf(stdout, " -gc Random ground clutter (feet/meters)\n");
fprintf(stdout, " -m Metric units of measurement\n"); fprintf(stdout, " -m Metric units of measurement\n");
fprintf(stdout, " -te Terrain code 1-6 (optional)\n"); fprintf(stdout, " -te Terrain code 1-6 (optional)\n");
fprintf(stdout, " -terdic Terrain dielectric value 2-80 (optional)\n"); fprintf(stdout, " -terdic Terrain dielectric value 2-80 (optional)\n");
@@ -1065,7 +1067,7 @@ int main(int argc, char *argv[])
fprintf(stdout, " -R Radius (miles/kilometers)\n"); fprintf(stdout, " -R Radius (miles/kilometers)\n");
fprintf(stdout, " -res Pixels per tile. 300/600/1200/3600 (Optional. LIDAR res is within the tile)\n"); fprintf(stdout, " -res Pixels per tile. 300/600/1200/3600 (Optional. LIDAR res is within the tile)\n");
fprintf(stdout, " -pm Propagation model. 1: ITM, 2: LOS, 3: Hata, 4: ECC33,\n"); fprintf(stdout, " -pm Propagation model. 1: ITM, 2: LOS, 3: Hata, 4: ECC33,\n");
fprintf(stdout, " 5: SUI, 6: COST-Hata, 7: FSPL, 8: ITWOM, 9: Ericsson\n"); fprintf(stdout, " 5: SUI, 6: COST-Hata, 7: FSPL, 8: ITWOM, 9: Ericsson, 10: Plane earth\n");
fprintf(stdout, " -pe Propagation model mode: 1=Urban,2=Suburban,3=Rural\n"); fprintf(stdout, " -pe Propagation model mode: 1=Urban,2=Suburban,3=Rural\n");
fprintf(stdout, " -ked Knife edge diffraction (Already on for ITM)\n"); fprintf(stdout, " -ked Knife edge diffraction (Already on for ITM)\n");
fprintf(stdout, "Debugging:\n"); fprintf(stdout, "Debugging:\n");
@@ -1082,8 +1084,8 @@ int main(int argc, char *argv[])
/* /*
* If we're not called as signalserverLIDAR we can allocate various * If we're not called as signalserverLIDAR we can allocate various
* memory now. For LIDAR stuff we need to wait until we've pasred * memory now. For LIDAR we need to wait until we've parsed
* the headers in the .asc file to know how much memory to allocate. * the headers in the .asc file to know how much memory to allocate...
*/ */
if (!lidar) if (!lidar)
do_allocs(); do_allocs();
@@ -1096,6 +1098,7 @@ int main(int argc, char *argv[])
metric = 0; metric = 0;
string[0] = 0; string[0] = 0;
mapfile[0] = 0; mapfile[0] = 0;
clutter_file[0] = 0;
clutter = 0.0; clutter = 0.0;
forced_erp = -1.0; forced_erp = -1.0;
forced_freq = 0.0; forced_freq = 0.0;
@@ -1162,6 +1165,14 @@ int main(int argc, char *argv[])
} }
} }
if (strcmp(argv[x], "-clt") == 0) {
z = x + 1;
if (z <= y && argv[z][0] && argv[z][0] != '-') {
strncpy(clutter_file, argv[z], 253);
}
}
if (strcmp(argv[x], "-o") == 0) { if (strcmp(argv[x], "-o") == 0) {
z = x + 1; z = x + 1;
@@ -1606,7 +1617,9 @@ int main(int argc, char *argv[])
} }
}else{ }else{
// DEM first
LoadTopoData(max_lon, min_lon, max_lat, min_lat); LoadTopoData(max_lon, min_lon, max_lat, min_lat);
if (area_mode || topomap) { if (area_mode || topomap) {
for (z = 0; z < txsites && z < max_txsites; z++) { for (z = 0; z < txsites && z < max_txsites; z++) {
/* "Ball park" estimates used to load any additional /* "Ball park" estimates used to load any additional
@@ -1704,6 +1717,15 @@ int main(int argc, char *argv[])
// User defined clutter file // User defined clutter file
LoadUDT(udt_file); LoadUDT(udt_file);
// Enrich with Clutter
if(strlen(clutter_file) > 1){
/*
Clutter tiles cover 16 x 12 degs but we only need a fraction of that area.
Limit by max_range / miles per degree (at equator)
*/
loadClutter(clutter_file,max_range/45,tx_site[0]);
}
if (ppa == 0) { if (ppa == 0) {
if (propmodel == 2) { if (propmodel == 2) {
PlotLOSMap(tx_site[0], altitudeLR, ano_filename, use_threads); PlotLOSMap(tx_site[0], altitudeLR, ano_filename, use_threads);

View File

@@ -5,3 +5,5 @@ Finding a reputable paper to source these models from took a while. There was
lots of bad copy-paste out there. A good paper: lots of bad copy-paste out there. A good paper:
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
Plane earth loss model taken from "Antennas and Propagation for Wireless systems" by Simon Saunders

View File

@@ -9,6 +9,7 @@
#include "hata.hh" #include "hata.hh"
#include "itwom3.0.hh" #include "itwom3.0.hh"
#include "sui.hh" #include "sui.hh"
#include "pel.hh"
#include <pthread.h> #include <pthread.h>
#define NUM_SECTIONS 4 #define NUM_SECTIONS 4
@@ -467,7 +468,7 @@ void PlotPropPath(struct site source, struct site destination,
METERS_PER_FOOT), dkm, pmenv); METERS_PER_FOOT), dkm, pmenv);
break; break;
case 4: case 4:
// COST231-HATA // ECC33
loss = loss =
ECC33pathLoss(LR.frq_mhz, txelev, ECC33pathLoss(LR.frq_mhz, txelev,
path.elevation[y] + path.elevation[y] +
@@ -484,6 +485,7 @@ void PlotPropPath(struct site source, struct site destination,
METERS_PER_FOOT), dkm, pmenv); METERS_PER_FOOT), dkm, pmenv);
break; break;
case 6: case 6:
// COST231-Hata
loss = loss =
COST231pathLoss(LR.frq_mhz, txelev, COST231pathLoss(LR.frq_mhz, txelev,
path.elevation[y] + path.elevation[y] +
@@ -517,6 +519,11 @@ void PlotPropPath(struct site source, struct site destination,
pmenv); pmenv);
break; break;
case 10:
// Plane earth
loss = PlaneEarthLoss(dkm, txelev, path.elevation[y] + (destination.alt * METERS_PER_FOOT));
break;
default: default:
point_to_point_ITM(source.alt * METERS_PER_FOOT, point_to_point_ITM(source.alt * METERS_PER_FOOT,
destination.alt * destination.alt *
@@ -529,7 +536,7 @@ void PlotPropPath(struct site source, struct site destination,
loss, strmode, errnum); loss, strmode, errnum);
} }
if (knifeedge == 1) { if (knifeedge == 1) {
diffloss = diffloss =
ked(LR.frq_mhz, ked(LR.frq_mhz,

29
models/pel.cc Normal file
View File

@@ -0,0 +1,29 @@
/*****************************************************************************
* Plane Earth Path Loss model for Signal Server by Alex Farrant *
* Taken from "Antennas and Propagation for wireless communication systems" *
* ISBN 978-0-470-84879-1 *
* 10 August 2016 *
* This program is free software; you can redistribute it and/or modify it *
* under the terms of the GNU General Public License as published by the *
* Free Software Foundation; either version 2 of the License or any later *
* version. *
* *
* This program is distributed in the hope that it will useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License *
* for more details. *
* */
#include <math.h>
double PlaneEarthLoss(float d, float TxH, float RxH)
{
/*
Plane Earth Loss model
Frequency: N/A
Distance (km): Any
*/
// Plane earth loss is independent of frequency.
double dbloss = 40*log10(d) + 20*log10(TxH) + 20*log10(RxH);
return dbloss;
}

6
models/pel.hh Normal file
View File

@@ -0,0 +1,6 @@
#ifndef _PEL_HH_
#define _PEL_HH_
double PlaneEarthLoss(float d, float TxH, float RxH);
#endif /* _PEL_HH_ */

BIN
signalserver Executable file

Binary file not shown.

1
signalserverHD Symbolic link
View File

@@ -0,0 +1 @@
signalserver

1
signalserverLIDAR Symbolic link
View File

@@ -0,0 +1 @@
signalserver