forked from ExternalVendorCode/Signal-Server
Plane earth model and MODIS landcover clutter
This commit is contained in:
@@ -1,5 +1,8 @@
|
||||
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
|
||||
Fixed bug in SUI model which was making it over optimistic.
|
||||
|
||||
|
6
Makefile
6
Makefile
@@ -8,7 +8,7 @@ LIBS = -lm -lpthread
|
||||
|
||||
VPATH = models
|
||||
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_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
|
||||
|
||||
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 \
|
||||
itwom3.0.hh sui.hh
|
||||
itwom3.0.hh sui.hh pel.hh
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
|
125
inputs.cc
125
inputs.cc
@@ -6,6 +6,131 @@
|
||||
#include "common.h"
|
||||
#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,
|
||||
double n, double e, double s, double west)
|
||||
{
|
||||
|
@@ -12,5 +12,6 @@ void LoadDBMColors(struct site xmtr);
|
||||
void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat);
|
||||
void LoadUDT(char *filename);
|
||||
int loadLIDAR(char *filename);
|
||||
int loadClutter(char *filename, double radius, struct site tx);
|
||||
|
||||
#endif /* _INPUTS_HH_ */
|
||||
|
36
main.cc
36
main.cc
@@ -1,4 +1,4 @@
|
||||
double version = 2.82;
|
||||
double version = 2.9;
|
||||
/****************************************************************************\
|
||||
* Signal Server: Radio propagation simulator by Alex Farrant QCVS, 2E0TDW *
|
||||
******************************************************************************
|
||||
@@ -33,6 +33,7 @@ double version = 2.82;
|
||||
#include "outputs.hh"
|
||||
#include "models/itwom3.0.hh"
|
||||
#include "models/los.hh"
|
||||
#include "models/pel.hh"
|
||||
|
||||
int MAXPAGES = 64;
|
||||
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 =
|
||||
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,
|
||||
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, " -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, " -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, " -lat Tx Latitude (decimal degrees) -70/+70\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, " -rxg Rx gain dBi (optional for text report)\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, " -te Terrain code 1-6 (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, " -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, " 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, " -ked Knife edge diffraction (Already on for ITM)\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
|
||||
* memory now. For LIDAR stuff we need to wait until we've pasred
|
||||
* the headers in the .asc file to know how much memory to allocate.
|
||||
* 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...
|
||||
*/
|
||||
if (!lidar)
|
||||
do_allocs();
|
||||
@@ -1096,6 +1098,7 @@ int main(int argc, char *argv[])
|
||||
metric = 0;
|
||||
string[0] = 0;
|
||||
mapfile[0] = 0;
|
||||
clutter_file[0] = 0;
|
||||
clutter = 0.0;
|
||||
forced_erp = -1.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) {
|
||||
z = x + 1;
|
||||
|
||||
@@ -1606,7 +1617,9 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
}else{
|
||||
// DEM first
|
||||
LoadTopoData(max_lon, min_lon, max_lat, min_lat);
|
||||
|
||||
if (area_mode || topomap) {
|
||||
for (z = 0; z < txsites && z < max_txsites; z++) {
|
||||
/* "Ball park" estimates used to load any additional
|
||||
@@ -1704,6 +1717,15 @@ int main(int argc, char *argv[])
|
||||
// User defined clutter 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 (propmodel == 2) {
|
||||
PlotLOSMap(tx_site[0], altitudeLR, ano_filename, use_threads);
|
||||
|
@@ -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:
|
||||
|
||||
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
|
||||
|
@@ -9,6 +9,7 @@
|
||||
#include "hata.hh"
|
||||
#include "itwom3.0.hh"
|
||||
#include "sui.hh"
|
||||
#include "pel.hh"
|
||||
#include <pthread.h>
|
||||
|
||||
#define NUM_SECTIONS 4
|
||||
@@ -467,7 +468,7 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
METERS_PER_FOOT), dkm, pmenv);
|
||||
break;
|
||||
case 4:
|
||||
// COST231-HATA
|
||||
// ECC33
|
||||
loss =
|
||||
ECC33pathLoss(LR.frq_mhz, txelev,
|
||||
path.elevation[y] +
|
||||
@@ -484,6 +485,7 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
METERS_PER_FOOT), dkm, pmenv);
|
||||
break;
|
||||
case 6:
|
||||
// COST231-Hata
|
||||
loss =
|
||||
COST231pathLoss(LR.frq_mhz, txelev,
|
||||
path.elevation[y] +
|
||||
@@ -517,6 +519,11 @@ void PlotPropPath(struct site source, struct site destination,
|
||||
pmenv);
|
||||
break;
|
||||
|
||||
case 10:
|
||||
// Plane earth
|
||||
loss = PlaneEarthLoss(dkm, txelev, path.elevation[y] + (destination.alt * METERS_PER_FOOT));
|
||||
break;
|
||||
|
||||
default:
|
||||
point_to_point_ITM(source.alt * METERS_PER_FOOT,
|
||||
destination.alt *
|
||||
|
29
models/pel.cc
Normal file
29
models/pel.cc
Normal 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
6
models/pel.hh
Normal 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
BIN
signalserver
Executable file
Binary file not shown.
1
signalserverHD
Symbolic link
1
signalserverHD
Symbolic link
@@ -0,0 +1 @@
|
||||
signalserver
|
1
signalserverLIDAR
Symbolic link
1
signalserverLIDAR
Symbolic link
@@ -0,0 +1 @@
|
||||
signalserver
|
Reference in New Issue
Block a user