forked from ExternalVendorCode/Signal-Server
2.5 - Major refactor
This commit is contained in:
32
.txt
32
.txt
@@ -1,32 +0,0 @@
|
||||
|
||||
--==[ Path Profile Analysis ]==--
|
||||
|
||||
Transmitter site: Tx
|
||||
Site location: 50.0000 North / 350.0000 West
|
||||
Ground elevation: 0.00 meters AMSL
|
||||
Antenna height: 30.00 meters AGL / 30.00 meters AMSL
|
||||
Distance to Rx: 5.00 kilometers
|
||||
Azimuth to Rx: 89.97 degrees
|
||||
Depression angle to Rx: -0.3433 degrees
|
||||
Receiver site: Rx
|
||||
Site location: 50.0000 North / 349.9300 West
|
||||
Ground elevation: 0.00 meters AMSL
|
||||
Antenna height: 2.00 meters AGL / 2.00 meters AMSL
|
||||
Distance to Tx: 5.00 kilometers
|
||||
Azimuth to Tx: 270.03 degrees
|
||||
Elevation angle to Tx: +0.2984 degrees
|
||||
Longley-Rice path calculation parameters used in this analysis:
|
||||
|
||||
Earth's Dielectric Constant: 15.000
|
||||
Earth's Conductivity: 0.005 Siemens/meter
|
||||
Atmospheric Bending Constant (N-units): 301.000 ppm
|
||||
Frequency: 5900.000 MHz
|
||||
Radio Climate: 5 (Continental Temperate)
|
||||
Polarisation: 1 (Vertical)
|
||||
Fraction of Situations: 50.0%
|
||||
Fraction of Time: 50.0%
|
||||
|
||||
|
||||
|
||||
Summary for the link between Tx and Rx:
|
||||
|
@@ -1,4 +1,10 @@
|
||||
SIGNAL SERVER CHANGE LOG
|
||||
SIGNAL SERVER CHANGELOG
|
||||
|
||||
2.5 - 27 May 2015
|
||||
Code refactored by Andrew Clayton / ac000 with header files
|
||||
New Makefile with c / c++ multi mode compilation
|
||||
Single executable now with run time switch for HD mode
|
||||
Models separated into directory
|
||||
|
||||
2.44 - 25 Mar 2015
|
||||
Improved PPA text report to list other prop models
|
||||
|
51
Makefile
Normal file
51
Makefile
Normal file
@@ -0,0 +1,51 @@
|
||||
SHELL = /bin/sh
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -Wall -O3 -s -ffast-amth
|
||||
CXXFLAGS = -Wall -O3 -s -ffast-math
|
||||
LIBS = -lm
|
||||
|
||||
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
|
||||
|
||||
GCC_MAJOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 1)
|
||||
GCC_MINOR := $(shell $(CXX) -dumpversion 2>&1 | cut -d . -f 2)
|
||||
GCC_VER_OK := $(shell test $(GCC_MAJOR) -ge 4 && \
|
||||
test $(GCC_MINOR) -ge 7 && \
|
||||
echo 1)
|
||||
|
||||
ifneq "$(GCC_VER_OK)" "1"
|
||||
error:
|
||||
@echo "Requires GCC version >= 4.7"
|
||||
@exit
|
||||
endif
|
||||
|
||||
%.o : %.cc
|
||||
@echo -e " CXX\t$@"
|
||||
@$ $(CXX) $(CXXFLAGS) -c $<
|
||||
|
||||
%.o : %.c
|
||||
@echo -e " CC\t$@"
|
||||
@$ $(CC) $(CFLAGS) -c $<
|
||||
|
||||
signalserver: $(objects)
|
||||
@echo -e " LNK\t$@"
|
||||
@$(CXX) $(objects) -o $@ ${LIBS}
|
||||
@echo -e " SYMLNK\tsignalserverHD -> $@"
|
||||
@ln -sf $@ signalserverHD
|
||||
|
||||
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
|
||||
|
||||
los.o: los.cc common.h main.hh cost.hh ecc33.hh ericsson.hh fspl.hh hata.hh \
|
||||
itwom3.0.hh sui.hh
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
rm -f $(objects) signalserver signalserverHD
|
10
README.md
10
README.md
@@ -20,15 +20,7 @@
|
||||
* *
|
||||
\****************************************************************************/
|
||||
|
||||
/*
|
||||
REQUIRES GCC >= 4.7
|
||||
90m mode
|
||||
g++ -Wall -Ofast -s -lm itwom3.0.cpp models.cpp main.cpp -o signalserver
|
||||
30m HD mode
|
||||
g++ -Wall -Ofast -s -lm itwom3.0.cpp models.cpp main.cpp -DHD -o signalserverHD
|
||||
*/
|
||||
|
||||
-- Signal Server 2.41 --
|
||||
-- Signal Server 2.5 --
|
||||
Compiled for 64 tiles at 1200 pixels/degree
|
||||
|
||||
-d Directory containing .sdf tiles
|
||||
|
18
_curvature
18
_curvature
@@ -1,18 +0,0 @@
|
||||
0.000 -10.000
|
||||
0.057 -11.490
|
||||
0.114 -12.981
|
||||
0.172 -14.473
|
||||
0.229 -15.965
|
||||
0.286 -17.457
|
||||
0.343 -18.950
|
||||
0.401 -20.444
|
||||
0.458 -21.938
|
||||
0.515 -23.432
|
||||
0.572 -24.927
|
||||
0.630 -26.423
|
||||
0.687 -27.919
|
||||
0.744 -29.415
|
||||
0.801 -30.913
|
||||
0.858 -32.410
|
||||
0.916 -33.908
|
||||
0.973 -35.407
|
19
_fresnel
19
_fresnel
@@ -1,19 +0,0 @@
|
||||
0.000 -0.000
|
||||
0.057 -4.240
|
||||
0.114 -5.811
|
||||
0.172 -6.882
|
||||
0.229 -7.666
|
||||
0.286 -8.245
|
||||
0.343 -8.660
|
||||
0.401 -8.934
|
||||
0.458 -9.081
|
||||
0.515 -9.105
|
||||
0.572 -9.008
|
||||
0.630 -8.786
|
||||
0.687 -8.430
|
||||
0.744 -7.920
|
||||
0.801 -7.226
|
||||
0.858 -6.284
|
||||
0.916 -4.959
|
||||
0.973 -2.736
|
||||
0.996 0.000
|
19
_fresnel60
19
_fresnel60
@@ -1,19 +0,0 @@
|
||||
0.000 -0.000
|
||||
0.057 -2.544
|
||||
0.114 -3.487
|
||||
0.172 -4.129
|
||||
0.229 -4.600
|
||||
0.286 -4.947
|
||||
0.343 -5.196
|
||||
0.401 -5.361
|
||||
0.458 -5.448
|
||||
0.515 -5.463
|
||||
0.572 -5.405
|
||||
0.630 -5.272
|
||||
0.687 -5.058
|
||||
0.744 -4.752
|
||||
0.801 -4.335
|
||||
0.858 -3.771
|
||||
0.916 -2.975
|
||||
0.973 -1.642
|
||||
0.996 0.000
|
19
_reference
19
_reference
@@ -1,19 +0,0 @@
|
||||
0.000 0.000
|
||||
0.057 0.000
|
||||
0.114 0.000
|
||||
0.172 0.000
|
||||
0.229 0.000
|
||||
0.286 0.000
|
||||
0.343 0.000
|
||||
0.401 0.000
|
||||
0.458 0.000
|
||||
0.515 0.000
|
||||
0.572 0.000
|
||||
0.630 0.000
|
||||
0.687 0.000
|
||||
0.744 0.000
|
||||
0.801 0.000
|
||||
0.858 0.000
|
||||
0.916 0.000
|
||||
0.973 0.000
|
||||
0.996 0.000
|
7
build.sh
7
build.sh
@@ -1,7 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
rm -f signalserver
|
||||
rm -f signalserverHD
|
||||
g++ -Wall -O3 -s -lm -fomit-frame-pointer itwom3.0.cpp models.cpp main.cpp -o signalserver
|
||||
g++ -Wall -O3 -s -lm -fomit-frame-pointer itwom3.0.cpp models.cpp main.cpp -DHD -o signalserverHD
|
||||
./signalserver
|
119
common.h
Normal file
119
common.h
Normal file
@@ -0,0 +1,119 @@
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
#define GAMMA 2.5
|
||||
|
||||
#ifndef PI
|
||||
#define PI 3.141592653589793
|
||||
#endif
|
||||
|
||||
#ifndef TWOPI
|
||||
#define TWOPI 6.283185307179586
|
||||
#endif
|
||||
|
||||
#ifndef HALFPI
|
||||
#define HALFPI 1.570796326794896
|
||||
#endif
|
||||
|
||||
#define DEG2RAD 1.74532925199e-02
|
||||
#define EARTHRADIUS 20902230.97
|
||||
#define METERS_PER_MILE 1609.344
|
||||
#define METERS_PER_FOOT 0.3048
|
||||
#define KM_PER_MILE 1.609344
|
||||
#define FOUR_THIRDS 1.3333333333333
|
||||
|
||||
struct dem {
|
||||
int min_north;
|
||||
int max_north;
|
||||
int min_west;
|
||||
int max_west;
|
||||
int max_el;
|
||||
int min_el;
|
||||
short **data;
|
||||
unsigned char **mask;
|
||||
unsigned char **signal;
|
||||
};
|
||||
|
||||
struct site {
|
||||
double lat;
|
||||
double lon;
|
||||
float alt;
|
||||
char name[50];
|
||||
char filename[255];
|
||||
};
|
||||
|
||||
struct path {
|
||||
double *lat;
|
||||
double *lon;
|
||||
double *elevation;
|
||||
double *distance;
|
||||
int length;
|
||||
};
|
||||
|
||||
struct LR {
|
||||
double eps_dielect;
|
||||
double sgm_conductivity;
|
||||
double eno_ns_surfref;
|
||||
double frq_mhz;
|
||||
double conf;
|
||||
double rel;
|
||||
double erp;
|
||||
int radio_climate;
|
||||
int pol;
|
||||
float antenna_pattern[361][1001];
|
||||
};
|
||||
|
||||
struct region {
|
||||
unsigned char color[128][3];
|
||||
int level[128];
|
||||
int levels;
|
||||
};
|
||||
|
||||
extern int MAXPAGES;
|
||||
extern int ARRAYSIZE;
|
||||
extern int IPPD;
|
||||
|
||||
extern int min_north;
|
||||
extern int max_north;
|
||||
extern int min_west;
|
||||
extern int max_west;
|
||||
extern int ippd;
|
||||
extern int mpi;
|
||||
extern int max_elevation;
|
||||
extern int min_elevation;
|
||||
extern int contour_threshold;
|
||||
extern int loops;
|
||||
extern int jgets;
|
||||
|
||||
extern double earthradius;
|
||||
extern double north;
|
||||
extern double east;
|
||||
extern double south;
|
||||
extern double west;
|
||||
extern double max_range;
|
||||
extern double dpp;
|
||||
extern double ppd;
|
||||
extern double fzone_clearance;
|
||||
extern double clutter;
|
||||
extern double dBm;
|
||||
extern double loss;
|
||||
extern double field_strength;
|
||||
extern double *elev;
|
||||
|
||||
extern char string[];
|
||||
extern char sdf_path[];
|
||||
extern char gpsav;
|
||||
|
||||
extern unsigned char got_elevation_pattern;
|
||||
extern unsigned char got_azimuth_pattern;
|
||||
extern unsigned char metric;
|
||||
extern unsigned char dbm;
|
||||
|
||||
extern struct dem *dem;
|
||||
extern struct path path;
|
||||
extern struct LR LR;
|
||||
extern struct region region;
|
||||
|
||||
extern int debug;
|
||||
|
||||
#endif /* _COMMON_H_ */
|
41
cost.cpp
41
cost.cpp
@@ -1,41 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* COST231-HATA MODEL for Signal Server by Alex Farrant *
|
||||
* 30 December 2013 *
|
||||
* 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 <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
double CostHataLinkdB(float f,float h_B, float h_M, float d){
|
||||
/*
|
||||
COST HATA URBAN model
|
||||
Frequency 1500 to 2000MHz
|
||||
h_B = Base station height 30 to 200m
|
||||
h_M = Mobile station height 1 to 10m
|
||||
Distance 1-20km
|
||||
*/
|
||||
|
||||
int C = 0; // 0dB for suburban
|
||||
|
||||
float lh_M = log10(11.75*h_M);
|
||||
float C_H = 3.2*lh_M*lh_M-4.97;
|
||||
|
||||
float logf = log10(f);
|
||||
|
||||
double dbloss = 46.3 + (33.9 * logf) - (13.82 * log10(h_B)) - C_H + (44.9 - 6.55 * log10(h_B)) * log10(d) + C;
|
||||
|
||||
|
||||
return dbloss;
|
||||
}
|
110
hata.cpp
110
hata.cpp
@@ -1,110 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* HATA MODEL for Signal Server by Alex Farrant *
|
||||
* 30 December 2013 *
|
||||
* 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 <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
/* Acute Angle from Rx point to an obstacle of height (opp) and distance (adj) */
|
||||
double incidenceAngle(double opp, double adj){
|
||||
return atan2(opp,adj) * 180 / PI;
|
||||
}
|
||||
|
||||
/*
|
||||
Knife edge diffraction:
|
||||
This custom function adds to the overall path loss based upon the obstacle
|
||||
angle (from receive point) and the frequency. Loss increases with angle and frequency.
|
||||
This is not a recognised formula like Huygens, rather it is a
|
||||
compromise for increased speed which adds a realistic diffraction effect.
|
||||
*/
|
||||
double ked(double freq, double elev[], double rxh, double dkm){
|
||||
double obh,obd,rxobaoi=0,d;
|
||||
|
||||
obh=0; // Obstacle height
|
||||
obd=0; // Obstacle distance
|
||||
|
||||
dkm=dkm*1000; // KM to metres
|
||||
|
||||
// walk along path
|
||||
for(int n=2;n<(dkm/elev[1]);n++){
|
||||
|
||||
d = (n-2)*elev[1]; // no of points * delta = km
|
||||
|
||||
//Find dip(s)
|
||||
if(elev[n]<(obh+20)){
|
||||
|
||||
// Angle from Rx point to obstacle
|
||||
rxobaoi = incidenceAngle((obh-(elev[n]+rxh)),d-obd);
|
||||
} else{
|
||||
// Line of sight or higher
|
||||
rxobaoi=0;
|
||||
}
|
||||
|
||||
//note the highest point
|
||||
if(elev[n]>obh){
|
||||
obh=elev[n];
|
||||
obd=d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(rxobaoi >= 0){
|
||||
return rxobaoi / (300/freq); // Diffraction angle divided by wavelength (m)
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double HataLinkdB(float f,float h_B, float h_M, float d, int mode){
|
||||
/*
|
||||
HATA URBAN model for cellular planning
|
||||
Frequency (MHz) 150 to 1500MHz
|
||||
Base station height 30-200m
|
||||
Mobile station height 1-10m
|
||||
Distance 1-20km
|
||||
|
||||
mode 1 = URBAN
|
||||
mode 2 = SUBURBAN
|
||||
mode 3 = OPEN
|
||||
*/
|
||||
|
||||
float lh_M = log10(11.75*h_M);
|
||||
float C_H = 3.2*lh_M*lh_M-4.97;
|
||||
|
||||
float logf = log10(f);
|
||||
|
||||
float L_u = 69.55 + 26.16*logf - 13.82*log10(h_B) - C_H + (44.9 - 6.55*log10(h_B))*log10(d);
|
||||
|
||||
if(!mode || mode==1){
|
||||
return L_u; //URBAN
|
||||
}
|
||||
|
||||
if(mode==2){ //SUBURBAN
|
||||
float logf_28 = log10(f/28);
|
||||
return L_u - 2*logf_28*logf_28 - 5.4;
|
||||
}
|
||||
|
||||
if(mode==3){ //OPEN
|
||||
return L_u - 4.78*logf*logf + 18.33*logf - 40.94;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
16
inputs.hh
Normal file
16
inputs.hh
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef _INPUTS_HH_
|
||||
#define _INPUTS_HH_
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int LoadSDF_SDF(char *name, int winfiles);
|
||||
char LoadSDF(char *name, int winfiles);
|
||||
void LoadPAT(char *filename);
|
||||
void LoadSignalColors(struct site xmtr);
|
||||
void LoadLossColors(struct site xmtr);
|
||||
void LoadDBMColors(struct site xmtr);
|
||||
void LoadTopoData(int max_lon, int min_lon, int max_lat, int min_lat,
|
||||
int winfiles);
|
||||
void LoadUDT(char *filename);
|
||||
|
||||
#endif /* _INPUTS_HH_ */
|
2863
itwom3.0.cpp
2863
itwom3.0.cpp
File diff suppressed because it is too large
Load Diff
26
main.hh
Normal file
26
main.hh
Normal file
@@ -0,0 +1,26 @@
|
||||
#ifndef _MAIN_HH_
|
||||
#define _MAIN_HH_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int ReduceAngle(double angle);
|
||||
double LonDiff(double lon1, double lon2);
|
||||
int PutMask(double lat, double lon, int value);
|
||||
int OrMask(double lat, double lon, int value);
|
||||
int GetMask(double lat, double lon);
|
||||
int PutSignal(double lat, double lon, unsigned char signal);
|
||||
unsigned char GetSignal(double lat, double lon);
|
||||
double GetElevation(struct site location);
|
||||
int AddElevation(double lat, double lon, double height);
|
||||
double Distance(struct site site1, struct site site2);
|
||||
double Azimuth(struct site source, struct site destination);
|
||||
double ElevationAngle(struct site source, struct site destination);
|
||||
void ReadPath(struct site source, struct site destination);
|
||||
double ElevationAngle2(struct site source, struct site destination, double er);
|
||||
double ReadBearing(char *input);
|
||||
void ObstructionAnalysis(struct site xmtr, struct site rcvr, double f,
|
||||
FILE *outfile);
|
||||
|
||||
#endif /* _MAIN_HH_ */
|
5720
mainHD.cpp
5720
mainHD.cpp
File diff suppressed because it is too large
Load Diff
276
models.cpp
276
models.cpp
@@ -1,276 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* RF propagation models for Signal Server by Alex Farrant, CloudRF.com *
|
||||
* *
|
||||
* 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 <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
/*
|
||||
Whilst every effort has been made to ensure the accuracy of the models, their accuracy is not guaranteed.
|
||||
Finding a reputable paper to source these models from took a while. There was lots of bad copy-pasta out there.
|
||||
A good paper: http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||
*/
|
||||
|
||||
#define PI 3.14159265
|
||||
|
||||
/* Acute Angle from Rx point to an obstacle of height (opp) and distance (adj) */
|
||||
double incidenceAngle(double opp, double adj){
|
||||
return atan2(opp,adj) * 180 / PI;
|
||||
}
|
||||
|
||||
/*
|
||||
Knife edge diffraction:
|
||||
This is based upon a recognised formula like Huygens, but trades thoroughness for increased speed
|
||||
which adds a proportional diffraction effect to obstacles.
|
||||
*/
|
||||
double ked(double freq, double elev[], double rxh, double dkm){
|
||||
double obh,obd,rxobaoi=0,d,dipheight=25;
|
||||
|
||||
obh=0; // Obstacle height
|
||||
obd=0; // Obstacle distance
|
||||
|
||||
dkm=dkm*1000; // KM to metres
|
||||
|
||||
// walk along path
|
||||
for(int n=2;n<(dkm/elev[1]);n++){
|
||||
|
||||
d = (n-2)*elev[1]; // no of points * delta = km
|
||||
|
||||
//Find dip(s)
|
||||
if(elev[n]<(obh+dipheight)){
|
||||
|
||||
// Angle from Rx point to obstacle
|
||||
rxobaoi = incidenceAngle((obh-(elev[n]+rxh)),d-obd);
|
||||
} else{
|
||||
// Line of sight or higher
|
||||
rxobaoi=0;
|
||||
}
|
||||
|
||||
//note the highest point
|
||||
if(elev[n]>obh){
|
||||
obh=elev[n];
|
||||
obd=d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if(rxobaoi >= 0){
|
||||
return rxobaoi / (300/freq); // Diffraction angle divided by wavelength (m)
|
||||
}else{
|
||||
return 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
double HATApathLoss(float f,float TxH, float RxH, float d, int mode){
|
||||
/*
|
||||
HATA model for cellular planning
|
||||
Frequency (MHz) 150 to 1500MHz
|
||||
Base station height 30-200m
|
||||
Mobile station height 1-10m
|
||||
Distance 1-20km
|
||||
modes 1 = URBAN, 2 = SUBURBAN, 3 = OPEN
|
||||
*/
|
||||
|
||||
if(f<150 || f>1500){
|
||||
printf("Error: Hata model frequency range 150-1500MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
float lRxH = log10(11.75*RxH);
|
||||
float C_H = 3.2*lRxH*lRxH-4.97;
|
||||
float logf = log10(f);
|
||||
float L_u = 69.55 + 26.16*logf - 13.82*log10(TxH) - C_H + (44.9 - 6.55*log10(TxH))*log10(d);
|
||||
|
||||
if(!mode || mode==1){
|
||||
return L_u; //URBAN
|
||||
}
|
||||
|
||||
if(mode==2){ //SUBURBAN
|
||||
float logf_28 = log10(f/28);
|
||||
return L_u - 2*logf_28*logf_28 - 5.4;
|
||||
}
|
||||
|
||||
if(mode==3){ //OPEN
|
||||
return L_u - 4.78*logf*logf + 18.33*logf - 40.94;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
double COST231pathLoss(float f,float TxH, float RxH, float d, int mode){
|
||||
/*
|
||||
COST231 extension to HATA model
|
||||
Frequency 1500 to 2000MHz
|
||||
TxH = Base station height 30 to 200m
|
||||
RxH = Mobile station height 1 to 10m
|
||||
Distance 1-20km
|
||||
modes 1 = URBAN, 2 = SUBURBAN, 3 = OPEN
|
||||
http://morse.colorado.edu/~tlen5510/text/classwebch3.html
|
||||
*/
|
||||
if(f<150 || f>2000){
|
||||
printf("Error: COST231 Hata model frequency range 150-2000MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int C = 3; // 3dB for Urban
|
||||
float lRxH = log10(11.75*RxH);
|
||||
float C_H = 3.2*(lRxH*lRxH)-4.97; // Large city (conservative)
|
||||
int c0 = 69.55;
|
||||
int cf = 26.16;
|
||||
if(f>1500){
|
||||
c0=46.3;
|
||||
cf=33.9;
|
||||
}
|
||||
if(mode==2){
|
||||
C = 0; // Medium city (average)
|
||||
C_H = 8.29*(lRxH*lRxH)-1.1;
|
||||
}
|
||||
if(mode==3){
|
||||
C = -3; // Small city (Optimistic)
|
||||
C_H = (1.1*log10(f) - 0.7) * RxH - (1.56 * log10(f)) + 0.8;
|
||||
}
|
||||
float logf = log10(f);
|
||||
double dbloss = c0 + (cf * logf) - (13.82 * log10(TxH)) - C_H + (44.9 - 6.55 * log10(TxH)) * log10(d) + C;
|
||||
return dbloss;
|
||||
}
|
||||
|
||||
double SUIpathLoss(float f,float TxH, float RxH, float d, int mode){
|
||||
/*
|
||||
f = Frequency (MHz)
|
||||
TxH = Transmitter height (m)
|
||||
RxH = Receiver height (m)
|
||||
d = distance (km)
|
||||
mode 1 = Hilly + trees
|
||||
mode 2 = Flat + trees OR hilly + light foliage
|
||||
mode 3 = Flat + light foliage
|
||||
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||
*/
|
||||
d=d*1000; // km to m
|
||||
if(f<1900 || f>11000){
|
||||
printf("Error: SUI model frequency range 1.9-11GHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// Terrain mode A is default
|
||||
double a = 4.6;
|
||||
double b = 0.0075;
|
||||
double c = 12.6;
|
||||
double s = 10.6; // Optional fading value
|
||||
int XhCF = -10.8;
|
||||
|
||||
if(mode==2){
|
||||
a=4.0;
|
||||
b=0.0065;
|
||||
c=17.1;
|
||||
s=6; // average
|
||||
}
|
||||
if(mode==3){
|
||||
a=3.6;
|
||||
b=0.005;
|
||||
c=20;
|
||||
s=3; // Optimistic
|
||||
XhCF = -20;
|
||||
}
|
||||
double d0 = 100;
|
||||
double A = 20 * log10((4*M_PI*d0)/(300/f));
|
||||
double y = (a - b * TxH) + c / TxH;
|
||||
double Xf = 6 * log10(f/2000);
|
||||
double Xh = XhCF * log10(RxH/2);
|
||||
return A + (10*y*log10(d/d0)) + Xf + Xh + s;
|
||||
}
|
||||
|
||||
double ECC33pathLoss(float f,float TxH, float RxH, float d, int mode){
|
||||
|
||||
if(f<700 || f>3500){
|
||||
printf("Error: ECC33 model frequency range 700-3500MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
// MHz to GHz
|
||||
f=f/1000;
|
||||
|
||||
double Gr = 0.759 * RxH - 1.862; // Big city with tall buildings (1)
|
||||
// PL = Afs + Abm - Gb - Gr
|
||||
double Afs = 92.4 + 20 * log10(d) + 20 * log10(f);
|
||||
double Abm = 20.41 + 9.83 * log10(d) + 7.894 * log10(f) + 9.56 * (log10(f) * log10(f));
|
||||
double Gb = log10(TxH/200) * (13.958 + 5.8 * (log10(d) * log10(d)));
|
||||
if(mode>1){ // Medium city (Europe)
|
||||
Gr = (42.57 + 13.7 * log10(f)) * (log10(RxH) - 0.585);
|
||||
}
|
||||
return Afs+Abm-Gb-Gr;
|
||||
}
|
||||
|
||||
double EricssonpathLoss(float f,float TxH, float RxH, float d, int mode){
|
||||
/*
|
||||
http://research.ijcaonline.org/volume84/number7/pxc3892830.pdf
|
||||
AKA Ericsson 9999 model
|
||||
*/
|
||||
// Default is Urban which bizarrely has lowest loss
|
||||
double a0=36.2, a1=30.2, a2=-12, a3=0.1;
|
||||
|
||||
if(f<150 || f>3500){
|
||||
printf("Error: Ericsson9999 model frequency range 150-3500MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if(mode==2){ // Suburban / Med loss
|
||||
a0=43.2;
|
||||
a1=68.93;
|
||||
}
|
||||
if(mode==1){ // "Rural" but has highest loss according to Ericsson.
|
||||
a0=45.95;
|
||||
a1=100.6;
|
||||
}
|
||||
double g1 = (11.75 * RxH) * (11.75 * RxH);
|
||||
double g2 = (44.49 * log10(f)) - 4.78 * ((log10(f) * log10(f)));
|
||||
return a0 + a1 * log10(d) + a2 * log10(TxH) + a3 * log10(TxH) * log10(d) - (3.2 * log10(g1)) + g2;
|
||||
}
|
||||
|
||||
double FSPLpathLoss(float f, float d){
|
||||
/*
|
||||
Free Space Path Loss (ITU-R P.525) model
|
||||
Frequency: Any
|
||||
Distance: Any
|
||||
*/
|
||||
//MHz to GHz
|
||||
f = f / 1000;
|
||||
double dbloss = (20 * log10(d)) + (20 * log10(f)) + 92.45;
|
||||
return dbloss;
|
||||
}
|
||||
/*
|
||||
int main(int argc, char* argv[]){
|
||||
if(argc<5){
|
||||
printf("Need freq,TxH,RxH,dist,terr\n");
|
||||
return 0;
|
||||
}
|
||||
int dis, ter;
|
||||
double frq, TxH, RxH;
|
||||
|
||||
sscanf(argv[1],"%lf",&frq);
|
||||
sscanf(argv[2],"%lf",&TxH);
|
||||
sscanf(argv[3],"%lf",&RxH);
|
||||
sscanf(argv[4],"%d",&dis);
|
||||
sscanf(argv[5],"%d",&ter);
|
||||
// ALL are freq in MHz and distances in metres
|
||||
printf("FSPL: %.2f dB\n",FSPLpathLoss(frq,dis));
|
||||
printf("HATA (%d): %.2f dB\n",ter,HATApathLoss(frq,TxH,RxH,dis,ter));
|
||||
printf("COST-HATA (%d): %.2f dB\n",ter,COST231pathLoss(frq,TxH,RxH,dis,ter));
|
||||
printf("SUI (%d): %.2f dB\n",ter,SUIpathLoss(frq,TxH,RxH,dis,ter));
|
||||
printf("ECC33 (%d): %.2f dB\n",ter,ECC33pathLoss(frq,TxH,RxH,dis,ter));
|
||||
printf("Ericsson (%d): %.2f dB\n",ter,EricssonpathLoss(frq,TxH,RxH,dis,ter));
|
||||
}
|
||||
*/
|
7
models/README
Normal file
7
models/README
Normal file
@@ -0,0 +1,7 @@
|
||||
Whilst every effort has been made to ensure the accuracy of the models, their
|
||||
accuracy is not guaranteed.
|
||||
|
||||
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
|
60
models/cost.cc
Normal file
60
models/cost.cc
Normal file
@@ -0,0 +1,60 @@
|
||||
/*****************************************************************************
|
||||
* COST231-HATA MODEL for Signal Server by Alex Farrant *
|
||||
* 30 December 2013i *
|
||||
* 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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||
{
|
||||
/*
|
||||
COST231 extension to HATA model
|
||||
Frequency 1500 to 2000MHz
|
||||
TxH = Base station height 30 to 200m
|
||||
RxH = Mobile station height 1 to 10m
|
||||
Distance 1-20km
|
||||
modes 1 = URBAN, 2 = SUBURBAN, 3 = OPEN
|
||||
http://morse.colorado.edu/~tlen5510/text/classwebch3.html
|
||||
*/
|
||||
if (f < 150 || f > 2000) {
|
||||
printf
|
||||
("Error: COST231 Hata model frequency range 150-2000MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
int C = 3; // 3dB for Urban
|
||||
float lRxH = log10(11.75 * RxH);
|
||||
float C_H = 3.2 * (lRxH * lRxH) - 4.97; // Large city (conservative)
|
||||
int c0 = 69.55;
|
||||
int cf = 26.16;
|
||||
if (f > 1500) {
|
||||
c0 = 46.3;
|
||||
cf = 33.9;
|
||||
}
|
||||
if (mode == 2) {
|
||||
C = 0; // Medium city (average)
|
||||
C_H = 8.29 * (lRxH * lRxH) - 1.1;
|
||||
}
|
||||
if (mode == 3) {
|
||||
C = -3; // Small city (Optimistic)
|
||||
C_H = (1.1 * log10(f) - 0.7) * RxH - (1.56 * log10(f)) + 0.8;
|
||||
}
|
||||
float logf = log10(f);
|
||||
double dbloss =
|
||||
c0 + (cf * logf) - (13.82 * log10(TxH)) - C_H + (44.9 -
|
||||
6.55 *
|
||||
log10(TxH)) *
|
||||
log10(d) + C;
|
||||
return dbloss;
|
||||
}
|
6
models/cost.hh
Normal file
6
models/cost.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _COST_HH_
|
||||
#define _COST_HH_
|
||||
|
||||
double COST231pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
|
||||
#endif /* _COST_HH_ */
|
26
models/ecc33.cc
Normal file
26
models/ecc33.cc
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||
{
|
||||
|
||||
if (f < 700 || f > 3500) {
|
||||
printf("Error: ECC33 model frequency range 700-3500MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// MHz to GHz
|
||||
f = f / 1000;
|
||||
|
||||
double Gr = 0.759 * RxH - 1.862; // Big city with tall buildings (1)
|
||||
// PL = Afs + Abm - Gb - Gr
|
||||
double Afs = 92.4 + 20 * log10(d) + 20 * log10(f);
|
||||
double Abm =
|
||||
20.41 + 9.83 * log10(d) + 7.894 * log10(f) +
|
||||
9.56 * (log10(f) * log10(f));
|
||||
double Gb = log10(TxH / 200) * (13.958 + 5.8 * (log10(d) * log10(d)));
|
||||
if (mode > 1) { // Medium city (Europe)
|
||||
Gr = (42.57 + 13.7 * log10(f)) * (log10(RxH) - 0.585);
|
||||
}
|
||||
return Afs + Abm - Gb - Gr;
|
||||
}
|
6
models/ecc33.hh
Normal file
6
models/ecc33.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _ECC33_HH_
|
||||
#define _ECC33_HH_
|
||||
|
||||
double ECC33pathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
|
||||
#endif /* _ECC33_HH_ */
|
33
models/ericsson.cc
Normal file
33
models/ericsson.cc
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||
{
|
||||
/*
|
||||
http://research.ijcaonline.org/volume84/number7/pxc3892830.pdf
|
||||
AKA Ericsson 9999 model
|
||||
*/
|
||||
// Default is Urban which bizarrely has lowest loss
|
||||
double a0 = 36.2, a1 = 30.2, a2 = -12, a3 = 0.1;
|
||||
|
||||
if (f < 150 || f > 3500) {
|
||||
printf
|
||||
("Error: Ericsson9999 model frequency range 150-3500MHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
if (mode == 2) { // Suburban / Med loss
|
||||
a0 = 43.2;
|
||||
a1 = 68.93;
|
||||
}
|
||||
if (mode == 1) { // "Rural" but has highest loss according to Ericsson.
|
||||
a0 = 45.95;
|
||||
a1 = 100.6;
|
||||
}
|
||||
double g1 = (11.75 * RxH) * (11.75 * RxH);
|
||||
double g2 = (44.49 * log10(f)) - 4.78 * ((log10(f) * log10(f)));
|
||||
|
||||
return a0 + a1 * log10(d) + a2 * log10(TxH) +
|
||||
a3 * log10(TxH) * log10(d) - (3.2 * log10(g1)) + g2;
|
||||
}
|
6
models/ericsson.hh
Normal file
6
models/ericsson.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _ERICSSON_HH_
|
||||
#define _ERICSSON_HH_
|
||||
|
||||
double EricssonpathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
|
||||
#endif /* _ERICSSON_HH_ */
|
@@ -12,13 +12,10 @@
|
||||
* for more details. *
|
||||
* */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace std;
|
||||
|
||||
double FsplLinkdB(float f, float d){
|
||||
double FSPLpathLoss(float f, float d)
|
||||
{
|
||||
/*
|
||||
Free Space Path Loss model
|
||||
Frequency: Any
|
6
models/fspl.hh
Normal file
6
models/fspl.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _FSPL_HH_
|
||||
#define _FSPL_HH_
|
||||
|
||||
double FSPLpathLoss(float f, float d);
|
||||
|
||||
#endif /* _FSPL_HH_ */
|
56
models/hata.cc
Normal file
56
models/hata.cc
Normal file
@@ -0,0 +1,56 @@
|
||||
/*****************************************************************************
|
||||
* HATA MODEL for Signal Server by Alex Farrant *
|
||||
* 30 December 2013 *
|
||||
* 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 HATApathLoss(float f, float h_B, float h_M, float d, int mode)
|
||||
{
|
||||
/*
|
||||
HATA URBAN model for cellular planning
|
||||
Frequency (MHz) 150 to 1500MHz
|
||||
Base station height 30-200m
|
||||
Mobile station height 1-10m
|
||||
Distance 1-20km
|
||||
|
||||
mode 1 = URBAN
|
||||
mode 2 = SUBURBAN
|
||||
mode 3 = OPEN
|
||||
*/
|
||||
|
||||
float lh_M = log10(11.75 * h_M);
|
||||
float C_H = 3.2 * lh_M * lh_M - 4.97;
|
||||
|
||||
float logf = log10(f);
|
||||
|
||||
float L_u =
|
||||
69.55 + 26.16 * logf - 13.82 * log10(h_B) - C_H + (44.9 -
|
||||
6.55 *
|
||||
log10(h_B)) *
|
||||
log10(d);
|
||||
|
||||
if (!mode || mode == 1) {
|
||||
return L_u; //URBAN
|
||||
}
|
||||
|
||||
if (mode == 2) { //SUBURBAN
|
||||
float logf_28 = log10(f / 28);
|
||||
return L_u - 2 * logf_28 * logf_28 - 5.4;
|
||||
}
|
||||
|
||||
if (mode == 3) { //OPEN
|
||||
return L_u - 4.78 * logf * logf + 18.33 * logf - 40.94;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
6
models/hata.hh
Normal file
6
models/hata.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _HATA_HH_
|
||||
#define _HATA_HH_
|
||||
|
||||
double HATApathLoss(float f, float h_B, float h_M, float d, int mode);
|
||||
|
||||
#endif /* _HATA_HH_ */
|
1574
models/itm.cc
Normal file
1574
models/itm.cc
Normal file
File diff suppressed because it is too large
Load Diff
2963
models/itwom3.0.cc
Normal file
2963
models/itwom3.0.cc
Normal file
File diff suppressed because it is too large
Load Diff
14
models/itwom3.0.hh
Normal file
14
models/itwom3.0.hh
Normal file
@@ -0,0 +1,14 @@
|
||||
#ifndef _ITWOM30_HH_
|
||||
#define _ITWOM30_HH_
|
||||
|
||||
void point_to_point_ITM(double tht_m, double rht_m, double eps_dielect,
|
||||
double sgm_conductivity, double eno_ns_surfref,
|
||||
double frq_mhz, int radio_climate, int pol,
|
||||
double conf, double rel, double &dbloss, char *strmode,
|
||||
int &errnum);
|
||||
void point_to_point(double tht_m, double rht_m, double eps_dielect,
|
||||
double sgm_conductivity, double eno_ns_surfref,
|
||||
double frq_mhz, int radio_climate, int pol, double conf,
|
||||
double rel, double &dbloss, char *strmode, int &errnum);
|
||||
|
||||
#endif /* _ITWOM30_HH_ */
|
864
models/los.cc
Normal file
864
models/los.cc
Normal file
@@ -0,0 +1,864 @@
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "../common.h"
|
||||
#include "../main.hh"
|
||||
#include "cost.hh"
|
||||
#include "ecc33.hh"
|
||||
#include "ericsson.hh"
|
||||
#include "fspl.hh"
|
||||
#include "hata.hh"
|
||||
#include "itwom3.0.hh"
|
||||
#include "sui.hh"
|
||||
|
||||
/*
|
||||
* Acute Angle from Rx point to an obstacle of height (opp) and
|
||||
* distance (adj)
|
||||
*/
|
||||
static double incidenceAngle(double opp, double adj)
|
||||
{
|
||||
return atan2(opp, adj) * 180 / PI;
|
||||
}
|
||||
|
||||
/*
|
||||
* Knife edge diffraction:
|
||||
* This is based upon a recognised formula like Huygens, but trades
|
||||
* thoroughness for increased speed which adds a proportional diffraction
|
||||
* effect to obstacles.
|
||||
*/
|
||||
static double ked(double freq, double rxh, double dkm)
|
||||
{
|
||||
double obh, obd, rxobaoi = 0, d, dipheight = 25;
|
||||
|
||||
obh = 0; // Obstacle height
|
||||
obd = 0; // Obstacle distance
|
||||
|
||||
dkm = dkm * 1000; // KM to metres
|
||||
|
||||
// walk along path
|
||||
for (int n = 2; n < (dkm / elev[1]); n++) {
|
||||
|
||||
d = (n - 2) * elev[1]; // no of points * delta = km
|
||||
|
||||
//Find dip(s)
|
||||
if (elev[n] < (obh + dipheight)) {
|
||||
|
||||
// Angle from Rx point to obstacle
|
||||
rxobaoi =
|
||||
incidenceAngle((obh - (elev[n] + rxh)), d - obd);
|
||||
} else {
|
||||
// Line of sight or higher
|
||||
rxobaoi = 0;
|
||||
}
|
||||
|
||||
//note the highest point
|
||||
if (elev[n] > obh) {
|
||||
obh = elev[n];
|
||||
obd = d;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (rxobaoi >= 0) {
|
||||
return rxobaoi / (300 / freq); // Diffraction angle divided by wavelength (m)
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void PlotLOSPath(struct site source, struct site destination, char mask_value,
|
||||
FILE *fd)
|
||||
{
|
||||
/* This function analyzes the path between the source and
|
||||
destination locations. It determines which points along
|
||||
the path have line-of-sight visibility to the source.
|
||||
Points along with path having line-of-sight visibility
|
||||
to the source at an AGL altitude equal to that of the
|
||||
destination location are stored by setting bit 1 in the
|
||||
mask[][] array, which are displayed in green when PPM
|
||||
maps are later generated by ss. */
|
||||
|
||||
char block;
|
||||
int x, y;
|
||||
register double cos_xmtr_angle, cos_test_angle, test_alt;
|
||||
double distance, rx_alt, tx_alt;
|
||||
|
||||
ReadPath(source, destination);
|
||||
|
||||
for (y = 0; y < path.length; y++) {
|
||||
/* Test this point only if it hasn't been already
|
||||
tested and found to be free of obstructions. */
|
||||
|
||||
if ((GetMask(path.lat[y], path.lon[y]) & mask_value) == 0) {
|
||||
distance = 5280.0 * path.distance[y];
|
||||
tx_alt = earthradius + source.alt + path.elevation[0];
|
||||
rx_alt =
|
||||
earthradius + destination.alt + path.elevation[y];
|
||||
|
||||
/* Calculate the cosine of the elevation of the
|
||||
transmitter as seen at the temp rx point. */
|
||||
|
||||
cos_xmtr_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(tx_alt * tx_alt)) / (2.0 * rx_alt * distance);
|
||||
|
||||
for (x = y, block = 0; x >= 0 && block == 0; x--) {
|
||||
distance =
|
||||
5280.0 * (path.distance[y] -
|
||||
path.distance[x]);
|
||||
test_alt =
|
||||
earthradius + (path.elevation[x] ==
|
||||
0.0 ? path.
|
||||
elevation[x] : path.
|
||||
elevation[x] + clutter);
|
||||
|
||||
cos_test_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(test_alt * test_alt)) / (2.0 * rx_alt *
|
||||
distance);
|
||||
|
||||
/* Compare these two angles to determine if
|
||||
an obstruction exists. Since we're comparing
|
||||
the cosines of these angles rather than
|
||||
the angles themselves, the following "if"
|
||||
statement is reversed from what it would
|
||||
be if the actual angles were compared. */
|
||||
|
||||
if (cos_xmtr_angle >= cos_test_angle)
|
||||
block = 1;
|
||||
}
|
||||
|
||||
if (block == 0)
|
||||
OrMask(path.lat[y], path.lon[y], mask_value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PlotPropPath(struct site source, struct site destination,
|
||||
unsigned char mask_value, FILE * fd, int propmodel,
|
||||
int knifeedge, int pmenv)
|
||||
{
|
||||
|
||||
int x, y, ifs, ofs, errnum;
|
||||
char block = 0, strmode[100];
|
||||
double loss, azimuth, pattern = 0.0,
|
||||
xmtr_alt, dest_alt, xmtr_alt2, dest_alt2,
|
||||
cos_rcvr_angle, cos_test_angle = 0.0, test_alt,
|
||||
elevation = 0.0, distance = 0.0, four_thirds_earth,
|
||||
field_strength = 0.0, rxp, dBm, txelev, dkm, diffloss;
|
||||
struct site temp;
|
||||
|
||||
ReadPath(source, destination);
|
||||
|
||||
four_thirds_earth = FOUR_THIRDS * EARTHRADIUS;
|
||||
|
||||
for (x = 1; x < path.length - 1; x++)
|
||||
elev[x + 2] =
|
||||
(path.elevation[x] ==
|
||||
0.0 ? path.elevation[x] * METERS_PER_FOOT : (clutter +
|
||||
path.
|
||||
elevation[x])
|
||||
* METERS_PER_FOOT);
|
||||
|
||||
/* Copy ending points without clutter */
|
||||
|
||||
elev[2] = path.elevation[0] * METERS_PER_FOOT;
|
||||
txelev = elev[2] + (source.alt * METERS_PER_FOOT);
|
||||
|
||||
elev[path.length + 1] =
|
||||
path.elevation[path.length - 1] * METERS_PER_FOOT;
|
||||
|
||||
/* Since the only energy the Longley-Rice model considers
|
||||
reaching the destination is based on what is scattered
|
||||
or deflected from the first obstruction along the path,
|
||||
we first need to find the location and elevation angle
|
||||
of that first obstruction (if it exists). This is done
|
||||
using a 4/3rds Earth radius to match the model used by
|
||||
Longley-Rice. This information is required for properly
|
||||
integrating the antenna's elevation pattern into the
|
||||
calculation for overall path loss. */
|
||||
|
||||
for (y = 2; (y < (path.length - 1) && path.distance[y] <= max_range);
|
||||
y++) {
|
||||
/* Process this point only if it
|
||||
has not already been processed. */
|
||||
|
||||
if ((GetMask(path.lat[y], path.lon[y]) & 248) !=
|
||||
(mask_value << 3)) {
|
||||
distance = 5280.0 * path.distance[y];
|
||||
xmtr_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;
|
||||
xmtr_alt2 = xmtr_alt * xmtr_alt;
|
||||
|
||||
/* Calculate the cosine of the elevation of
|
||||
the receiver as seen by the transmitter. */
|
||||
|
||||
cos_rcvr_angle =
|
||||
((xmtr_alt2) + (distance * distance) -
|
||||
(dest_alt2)) / (2.0 * xmtr_alt * distance);
|
||||
|
||||
if (cos_rcvr_angle > 1.0)
|
||||
cos_rcvr_angle = 1.0;
|
||||
|
||||
if (cos_rcvr_angle < -1.0)
|
||||
cos_rcvr_angle = -1.0;
|
||||
|
||||
if (got_elevation_pattern || fd != NULL) {
|
||||
/* Determine the elevation angle to the first obstruction
|
||||
along the path IF elevation pattern data is available
|
||||
or an output (.ano) file has been designated. */
|
||||
|
||||
for (x = 2, block = 0; (x < y && block == 0);
|
||||
x++) {
|
||||
distance = 5280.0 * path.distance[x];
|
||||
|
||||
test_alt =
|
||||
four_thirds_earth +
|
||||
(path.elevation[x] ==
|
||||
0.0 ? path.elevation[x] : path.
|
||||
elevation[x] + clutter);
|
||||
|
||||
/* Calculate the cosine of the elevation
|
||||
angle of the terrain (test point)
|
||||
as seen by the transmitter. */
|
||||
|
||||
cos_test_angle =
|
||||
((xmtr_alt2) +
|
||||
(distance * distance) -
|
||||
(test_alt * test_alt)) / (2.0 *
|
||||
xmtr_alt
|
||||
*
|
||||
distance);
|
||||
|
||||
if (cos_test_angle > 1.0)
|
||||
cos_test_angle = 1.0;
|
||||
|
||||
if (cos_test_angle < -1.0)
|
||||
cos_test_angle = -1.0;
|
||||
|
||||
/* Compare these two angles to determine if
|
||||
an obstruction exists. Since we're comparing
|
||||
the cosines of these angles rather than
|
||||
the angles themselves, the sense of the
|
||||
following "if" statement is reversed from
|
||||
what it would be if the angles themselves
|
||||
were compared. */
|
||||
|
||||
if (cos_rcvr_angle >= cos_test_angle)
|
||||
block = 1;
|
||||
}
|
||||
|
||||
if (block)
|
||||
elevation =
|
||||
((acos(cos_test_angle)) / DEG2RAD) -
|
||||
90.0;
|
||||
else
|
||||
elevation =
|
||||
((acos(cos_rcvr_angle)) / DEG2RAD) -
|
||||
90.0;
|
||||
}
|
||||
|
||||
/* Determine attenuation for each point along the
|
||||
path using a prop model starting at y=2 (number_of_points = 1), the
|
||||
shortest distance terrain can play a role in
|
||||
path loss. */
|
||||
|
||||
elev[0] = y - 1; /* (number of points - 1) */
|
||||
|
||||
/* Distance between elevation samples */
|
||||
|
||||
elev[1] =
|
||||
METERS_PER_MILE * (path.distance[y] -
|
||||
path.distance[y - 1]);
|
||||
|
||||
if (path.elevation[y] < 1) {
|
||||
path.elevation[y] = 1;
|
||||
}
|
||||
|
||||
dkm = (elev[1] * elev[0]) / 1000; // km
|
||||
|
||||
switch (propmodel) {
|
||||
case 1:
|
||||
// Longley Rice ITM
|
||||
point_to_point_ITM(source.alt * METERS_PER_FOOT,
|
||||
destination.alt *
|
||||
METERS_PER_FOOT,
|
||||
LR.eps_dielect,
|
||||
LR.sgm_conductivity,
|
||||
LR.eno_ns_surfref,
|
||||
LR.frq_mhz, LR.radio_climate,
|
||||
LR.pol, LR.conf, LR.rel,
|
||||
loss, strmode, errnum);
|
||||
break;
|
||||
case 3:
|
||||
//HATA 1, 2 & 3
|
||||
loss =
|
||||
HATApathLoss(LR.frq_mhz, txelev,
|
||||
path.elevation[y] +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm, pmenv);
|
||||
break;
|
||||
case 4:
|
||||
// COST231-HATA
|
||||
loss =
|
||||
ECC33pathLoss(LR.frq_mhz, txelev,
|
||||
path.elevation[y] +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm,
|
||||
pmenv);
|
||||
break;
|
||||
case 5:
|
||||
// SUI
|
||||
loss =
|
||||
SUIpathLoss(LR.frq_mhz, txelev,
|
||||
path.elevation[y] +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm, pmenv);
|
||||
break;
|
||||
case 6:
|
||||
loss =
|
||||
COST231pathLoss(LR.frq_mhz, txelev,
|
||||
path.elevation[y] +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm,
|
||||
pmenv);
|
||||
break;
|
||||
case 7:
|
||||
// ITU-R P.525 Free space path loss
|
||||
loss = FSPLpathLoss(LR.frq_mhz, dkm);
|
||||
break;
|
||||
case 8:
|
||||
// ITWOM 3.0
|
||||
point_to_point(source.alt * METERS_PER_FOOT,
|
||||
destination.alt *
|
||||
METERS_PER_FOOT, LR.eps_dielect,
|
||||
LR.sgm_conductivity,
|
||||
LR.eno_ns_surfref, LR.frq_mhz,
|
||||
LR.radio_climate, LR.pol,
|
||||
LR.conf, LR.rel, loss, strmode,
|
||||
errnum);
|
||||
break;
|
||||
case 9:
|
||||
// Ericsson
|
||||
loss =
|
||||
EricssonpathLoss(LR.frq_mhz, txelev,
|
||||
path.elevation[y] +
|
||||
(destination.alt *
|
||||
METERS_PER_FOOT), dkm,
|
||||
pmenv);
|
||||
break;
|
||||
|
||||
default:
|
||||
point_to_point_ITM(source.alt * METERS_PER_FOOT,
|
||||
destination.alt *
|
||||
METERS_PER_FOOT,
|
||||
LR.eps_dielect,
|
||||
LR.sgm_conductivity,
|
||||
LR.eno_ns_surfref,
|
||||
LR.frq_mhz, LR.radio_climate,
|
||||
LR.pol, LR.conf, LR.rel,
|
||||
loss, strmode, errnum);
|
||||
|
||||
}
|
||||
|
||||
if (knifeedge == 1) {
|
||||
diffloss =
|
||||
ked(LR.frq_mhz,
|
||||
destination.alt * METERS_PER_FOOT, dkm);
|
||||
loss += (diffloss); // ;)
|
||||
}
|
||||
//Key stage. Link dB for p2p is returned as 'loss'.
|
||||
|
||||
temp.lat = path.lat[y];
|
||||
temp.lon = path.lon[y];
|
||||
|
||||
azimuth = (Azimuth(source, temp));
|
||||
|
||||
if (fd != NULL)
|
||||
fprintf(fd, "%.7f, %.7f, %.3f, %.3f, ",
|
||||
path.lat[y], path.lon[y], azimuth,
|
||||
elevation);
|
||||
|
||||
/* If ERP==0, write path loss to alphanumeric
|
||||
output file. Otherwise, write field strength
|
||||
or received power level (below), as appropriate. */
|
||||
|
||||
if (fd != NULL && LR.erp == 0.0)
|
||||
fprintf(fd, "%.2f", loss);
|
||||
|
||||
/* Integrate the antenna's radiation
|
||||
pattern into the overall path loss. */
|
||||
|
||||
x = (int)rint(10.0 * (10.0 - elevation));
|
||||
|
||||
if (x >= 0 && x <= 1000) {
|
||||
azimuth = rint(azimuth);
|
||||
|
||||
pattern =
|
||||
(double)LR.antenna_pattern[(int)azimuth][x];
|
||||
|
||||
if (pattern != 0.0) {
|
||||
pattern = 20.0 * log10(pattern);
|
||||
loss -= pattern;
|
||||
}
|
||||
}
|
||||
|
||||
if (LR.erp != 0.0) {
|
||||
if (dbm) {
|
||||
/* dBm is based on EIRP (ERP + 2.14) */
|
||||
|
||||
rxp =
|
||||
LR.erp /
|
||||
(pow(10.0, (loss - 2.14) / 10.0));
|
||||
|
||||
dBm = 10.0 * (log10(rxp * 1000.0));
|
||||
|
||||
if (fd != NULL)
|
||||
fprintf(fd, "%.3f", dBm);
|
||||
|
||||
/* Scale roughly between 0 and 255 */
|
||||
|
||||
ifs = 200 + (int)rint(dBm);
|
||||
|
||||
if (ifs < 0)
|
||||
ifs = 0;
|
||||
|
||||
if (ifs > 255)
|
||||
ifs = 255;
|
||||
|
||||
ofs =
|
||||
GetSignal(path.lat[y], path.lon[y]);
|
||||
|
||||
if (ofs > ifs)
|
||||
ifs = ofs;
|
||||
|
||||
PutSignal(path.lat[y], path.lon[y],
|
||||
(unsigned char)ifs);
|
||||
|
||||
}
|
||||
|
||||
else {
|
||||
field_strength =
|
||||
(139.4 +
|
||||
(20.0 * log10(LR.frq_mhz)) -
|
||||
loss) +
|
||||
(10.0 * log10(LR.erp / 1000.0));
|
||||
|
||||
ifs = 100 + (int)rint(field_strength);
|
||||
|
||||
if (ifs < 0)
|
||||
ifs = 0;
|
||||
|
||||
if (ifs > 255)
|
||||
ifs = 255;
|
||||
|
||||
ofs =
|
||||
GetSignal(path.lat[y], path.lon[y]);
|
||||
|
||||
if (ofs > ifs)
|
||||
ifs = ofs;
|
||||
|
||||
PutSignal(path.lat[y], path.lon[y],
|
||||
(unsigned char)ifs);
|
||||
|
||||
if (fd != NULL)
|
||||
fprintf(fd, "%.3f",
|
||||
field_strength);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
if (loss > 255)
|
||||
ifs = 255;
|
||||
else
|
||||
ifs = (int)rint(loss);
|
||||
|
||||
ofs = GetSignal(path.lat[y], path.lon[y]);
|
||||
|
||||
if (ofs < ifs && ofs != 0)
|
||||
ifs = ofs;
|
||||
|
||||
PutSignal(path.lat[y], path.lon[y],
|
||||
(unsigned char)ifs);
|
||||
}
|
||||
|
||||
if (fd != NULL) {
|
||||
if (block)
|
||||
fprintf(fd, " *");
|
||||
|
||||
fprintf(fd, "\n");
|
||||
}
|
||||
|
||||
/* Mark this point as having been analyzed */
|
||||
|
||||
PutMask(path.lat[y], path.lon[y],
|
||||
(GetMask(path.lat[y], path.lon[y]) & 7) +
|
||||
(mask_value << 3));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void PlotLOSMap(struct site source, double altitude, char *plo_filename)
|
||||
{
|
||||
/* This function performs a 360 degree sweep around the
|
||||
transmitter site (source location), and plots the
|
||||
line-of-sight coverage of the transmitter on the ss
|
||||
generated topographic map based on a receiver located
|
||||
at the specified altitude (in feet AGL). Results
|
||||
are stored in memory, and written out in the form
|
||||
of a topographic map when the WritePPM() function
|
||||
is later invoked. */
|
||||
|
||||
int x, y, z;
|
||||
struct site edge;
|
||||
double lat, lon, minwest, maxnorth, th;
|
||||
static unsigned char mask_value = 1;
|
||||
FILE *fd = NULL;
|
||||
|
||||
if (plo_filename[0] != 0)
|
||||
fd = fopen(plo_filename, "wb");
|
||||
|
||||
if (fd != NULL) {
|
||||
fprintf(fd,
|
||||
"%d, %d\t; max_west, min_west\n%d, %d\t; max_north, min_north\n",
|
||||
max_west, min_west, max_north, min_north);
|
||||
}
|
||||
|
||||
th = ppd / loops;
|
||||
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
|
||||
minwest = dpp + (double)min_west;
|
||||
maxnorth = (double)max_north - dpp;
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
|
||||
edge.lat = max_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
}
|
||||
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = maxnorth, x = 0, y = 0; lat >= (double)min_north;
|
||||
y++, lat = maxnorth - (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = min_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
|
||||
}
|
||||
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
|
||||
edge.lat = min_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
|
||||
}
|
||||
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = (double)min_north, x = 0, y = 0; lat < (double)max_north;
|
||||
y++, lat = (double)min_north + (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = max_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotLOSPath(source, edge, mask_value, fd);
|
||||
|
||||
}
|
||||
|
||||
switch (mask_value) {
|
||||
case 1:
|
||||
mask_value = 8;
|
||||
break;
|
||||
|
||||
case 8:
|
||||
mask_value = 16;
|
||||
break;
|
||||
|
||||
case 16:
|
||||
mask_value = 32;
|
||||
}
|
||||
}
|
||||
|
||||
void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||
int propmodel, int knifeedge, int haf, int pmenv)
|
||||
{
|
||||
int y, z, count;
|
||||
struct site edge;
|
||||
double lat, lon, minwest, maxnorth, th;
|
||||
unsigned char x;
|
||||
static unsigned char mask_value = 1;
|
||||
FILE *fd = NULL;
|
||||
|
||||
minwest = dpp + (double)min_west;
|
||||
maxnorth = (double)max_north - dpp;
|
||||
|
||||
count = 0;
|
||||
|
||||
if (LR.erp == 0.0 && debug)
|
||||
fprintf(stdout, "path loss");
|
||||
else {
|
||||
if (debug) {
|
||||
if (dbm)
|
||||
fprintf(stdout, "signal power level");
|
||||
else
|
||||
fprintf(stdout, "field strength");
|
||||
}
|
||||
}
|
||||
if (debug) {
|
||||
fprintf(stdout,
|
||||
" contours of \"%s\"\nout to a radius of %.2f %s with Rx antenna(s) at %.2f %s AGL\n",
|
||||
source.name,
|
||||
metric ? max_range * KM_PER_MILE : max_range,
|
||||
metric ? "kilometers" : "miles",
|
||||
metric ? altitude * METERS_PER_FOOT : altitude,
|
||||
metric ? "meters" : "feet");
|
||||
}
|
||||
|
||||
if (clutter > 0.0 && debug)
|
||||
fprintf(stdout, "\nand %.2f %s of ground clutter",
|
||||
metric ? clutter * METERS_PER_FOOT : clutter,
|
||||
metric ? "meters" : "feet");
|
||||
|
||||
if (debug) {
|
||||
fprintf(stdout, "...\n\n 0%c to 25%c ", 37, 37);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
if (plo_filename[0] != 0)
|
||||
fd = fopen(plo_filename, "wb");
|
||||
|
||||
if (fd != NULL) {
|
||||
fprintf(fd,
|
||||
"%d, %d\t; max_west, min_west\n%d, %d\t; max_north, min_north\n",
|
||||
max_west, min_west, max_north, min_north);
|
||||
}
|
||||
|
||||
th = ppd / loops;
|
||||
|
||||
// Four sections start here
|
||||
|
||||
//S1
|
||||
if (haf == 0 || haf == 1) {
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
|
||||
edge.lat = max_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
|
||||
if (count == z) {
|
||||
count = 0;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//S2
|
||||
if (haf == 0 || haf == 1) {
|
||||
count = 0;
|
||||
if (debug) {
|
||||
fprintf(stdout, "\n25%c to 50%c ", 37, 37);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = maxnorth, x = 0, y = 0; lat >= (double)min_north;
|
||||
y++, lat = maxnorth - (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = min_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
|
||||
if (count == z) {
|
||||
count = 0;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//S3
|
||||
if (haf == 0 || haf == 2) {
|
||||
count = 0;
|
||||
if (debug) {
|
||||
fprintf(stdout, "\n50%c to 75%c ", 37, 37);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
z = (int)(th * ReduceAngle(max_west - min_west));
|
||||
|
||||
for (lon = minwest, x = 0, y = 0;
|
||||
(LonDiff(lon, (double)max_west) <= 0.0);
|
||||
y++, lon = minwest + (dpp * (double)y)) {
|
||||
if (lon >= 360.0)
|
||||
lon -= 360.0;
|
||||
|
||||
edge.lat = min_north;
|
||||
edge.lon = lon;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
if (count == z) {
|
||||
count = 0;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
//S4
|
||||
if (haf == 0 || haf == 2) {
|
||||
count = 0;
|
||||
if (debug) {
|
||||
fprintf(stdout, "\n75%c to 100%c ", 37, 37);
|
||||
fflush(stdout);
|
||||
}
|
||||
z = (int)(th * (double)(max_north - min_north));
|
||||
|
||||
for (lat = (double)min_north, x = 0, y = 0;
|
||||
lat < (double)max_north;
|
||||
y++, lat = (double)min_north + (dpp * (double)y)) {
|
||||
edge.lat = lat;
|
||||
edge.lon = max_west;
|
||||
edge.alt = altitude;
|
||||
|
||||
PlotPropPath(source, edge, mask_value, fd, propmodel,
|
||||
knifeedge, pmenv);
|
||||
count++;
|
||||
|
||||
if (count == z) {
|
||||
|
||||
count = 0;
|
||||
|
||||
if (x == 3)
|
||||
x = 0;
|
||||
else
|
||||
x++;
|
||||
}
|
||||
}
|
||||
|
||||
} //S4
|
||||
|
||||
if (fd != NULL)
|
||||
fclose(fd);
|
||||
|
||||
if (mask_value < 30)
|
||||
mask_value++;
|
||||
}
|
||||
|
||||
void PlotPath(struct site source, struct site destination, char mask_value)
|
||||
{
|
||||
/* This function analyzes the path between the source and
|
||||
destination locations. It determines which points along
|
||||
the path have line-of-sight visibility to the source.
|
||||
Points along with path having line-of-sight visibility
|
||||
to the source at an AGL altitude equal to that of the
|
||||
destination location are stored by setting bit 1 in the
|
||||
mask[][] array, which are displayed in green when PPM
|
||||
maps are later generated by SPLAT!. */
|
||||
|
||||
char block;
|
||||
int x, y;
|
||||
register double cos_xmtr_angle, cos_test_angle, test_alt;
|
||||
double distance, rx_alt, tx_alt;
|
||||
|
||||
ReadPath(source, destination);
|
||||
|
||||
for (y = 0; y < path.length; y++) {
|
||||
/* Test this point only if it hasn't been already
|
||||
tested and found to be free of obstructions. */
|
||||
|
||||
if ((GetMask(path.lat[y], path.lon[y]) & mask_value) == 0) {
|
||||
distance = 5280.0 * path.distance[y];
|
||||
tx_alt = earthradius + source.alt + path.elevation[0];
|
||||
rx_alt =
|
||||
earthradius + destination.alt + path.elevation[y];
|
||||
|
||||
/* Calculate the cosine of the elevation of the
|
||||
transmitter as seen at the temp rx point. */
|
||||
|
||||
cos_xmtr_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(tx_alt * tx_alt)) / (2.0 * rx_alt * distance);
|
||||
|
||||
for (x = y, block = 0; x >= 0 && block == 0; x--) {
|
||||
distance =
|
||||
5280.0 * (path.distance[y] -
|
||||
path.distance[x]);
|
||||
test_alt =
|
||||
earthradius + (path.elevation[x] ==
|
||||
0.0 ? path.
|
||||
elevation[x] : path.
|
||||
elevation[x] + clutter);
|
||||
|
||||
cos_test_angle =
|
||||
((rx_alt * rx_alt) + (distance * distance) -
|
||||
(test_alt * test_alt)) / (2.0 * rx_alt *
|
||||
distance);
|
||||
|
||||
/* Compare these two angles to determine if
|
||||
an obstruction exists. Since we're comparing
|
||||
the cosines of these angles rather than
|
||||
the angles themselves, the following "if"
|
||||
statement is reversed from what it would
|
||||
be if the actual angles were compared. */
|
||||
|
||||
if (cos_xmtr_angle >= cos_test_angle)
|
||||
block = 1;
|
||||
}
|
||||
|
||||
if (block == 0)
|
||||
OrMask(path.lat[y], path.lon[y], mask_value);
|
||||
}
|
||||
}
|
||||
}
|
18
models/los.hh
Normal file
18
models/los.hh
Normal file
@@ -0,0 +1,18 @@
|
||||
#ifndef _LOS_HH_
|
||||
#define _LOS_HH_
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "../common.h"
|
||||
|
||||
void PlotLOSPath(struct site source, struct site destination, char mask_value,
|
||||
FILE *fd);
|
||||
void PlotPropPath(struct site source, struct site destination,
|
||||
unsigned char mask_value, FILE * fd, int propmodel,
|
||||
int knifeedge, int pmenv);
|
||||
void PlotLOSMap(struct site source, double altitude, char *plo_filename);
|
||||
void PlotPropagation(struct site source, double altitude, char *plo_filename,
|
||||
int propmodel, int knifeedge, int haf, int pmenv);
|
||||
void PlotPath(struct site source, struct site destination, char mask_value);
|
||||
|
||||
#endif /* _LOS_HH_ */
|
49
models/sui.cc
Normal file
49
models/sui.cc
Normal file
@@ -0,0 +1,49 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
double SUIpathLoss(float f, float TxH, float RxH, float d, int mode)
|
||||
{
|
||||
/*
|
||||
f = Frequency (MHz)
|
||||
TxH = Transmitter height (m)
|
||||
RxH = Receiver height (m)
|
||||
d = distance (km)
|
||||
mode 1 = Hilly + trees
|
||||
mode 2 = Flat + trees OR hilly + light foliage
|
||||
mode 3 = Flat + light foliage
|
||||
http://www.cl.cam.ac.uk/research/dtg/lce-pub/public/vsa23/VTC05_Empirical.pdf
|
||||
*/
|
||||
d = d * 1000; // km to m
|
||||
if (f < 1900 || f > 11000) {
|
||||
printf("Error: SUI model frequency range 1.9-11GHz\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
// Terrain mode A is default
|
||||
double a = 4.6;
|
||||
double b = 0.0075;
|
||||
double c = 12.6;
|
||||
double s = 10.6; // Optional fading value
|
||||
int XhCF = -10.8;
|
||||
|
||||
if (mode == 2) {
|
||||
a = 4.0;
|
||||
b = 0.0065;
|
||||
c = 17.1;
|
||||
s = 6; // average
|
||||
}
|
||||
if (mode == 3) {
|
||||
a = 3.6;
|
||||
b = 0.005;
|
||||
c = 20;
|
||||
s = 3; // Optimistic
|
||||
XhCF = -20;
|
||||
}
|
||||
double d0 = 100;
|
||||
double A = 20 * log10((4 * M_PI * d0) / (300 / f));
|
||||
double y = (a - b * TxH) + c / TxH;
|
||||
double Xf = 6 * log10(f / 2000);
|
||||
double Xh = XhCF * log10(RxH / 2);
|
||||
|
||||
return A + (10 * y * log10(d / d0)) + Xf + Xh + s;
|
||||
}
|
6
models/sui.hh
Normal file
6
models/sui.hh
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef _SUI_HH_
|
||||
#define _SUI_HH_
|
||||
|
||||
double SUIpathLoss(float f, float TxH, float RxH, float d, int mode);
|
||||
|
||||
#endif /* _SUI_HH_ */
|
1994
outputs.cc
Normal file
1994
outputs.cc
Normal file
File diff suppressed because it is too large
Load Diff
17
outputs.hh
Normal file
17
outputs.hh
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _OUTPUT_HH_
|
||||
#define _OUTPUT_HH_
|
||||
|
||||
void DoPathLoss(char *filename, unsigned char geo, unsigned char kml,
|
||||
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||
void DoSigStr(char *filename, unsigned char geo, unsigned char kml,
|
||||
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||
void DoRxdPwr(char *filename, unsigned char geo, unsigned char kml,
|
||||
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||
void DoLOS(char *filename, unsigned char geo, unsigned char kml,
|
||||
unsigned char ngs, struct site *xmtr, unsigned char txsites);
|
||||
void PathReport(struct site source, struct site destination, char *name,
|
||||
char graph_it, int propmodel, int pmenv);
|
||||
void SeriesData(struct site source, struct site destination, char *name,
|
||||
unsigned char fresnel_plot, unsigned char normalised);
|
||||
|
||||
#endif /* _OUTPUT_HH_ */
|
BIN
signalserver
BIN
signalserver
Binary file not shown.
BIN
signalserverHD
BIN
signalserverHD
Binary file not shown.
9
test.sh
9
test.sh
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
mkdir test
|
||||
RAD=10
|
||||
RAD=5
|
||||
MAXRAD=30
|
||||
FRQ=800
|
||||
ERP=20
|
||||
@@ -11,6 +11,13 @@ while [ $RAD -lt $MAXRAD ]; do
|
||||
convert test/$RAD.ppm test/$RAD.png
|
||||
rm test/$RAD.ppm
|
||||
rm test/$RAD.*cf
|
||||
|
||||
echo "Calculating $FRQ MHz @ $ERP Watts for $RAD km radius (HD mode)..."
|
||||
time ./signalserverHD -m -d /var/SRTM1 -lat 51.47 -lon -1.50 -txh 15 -gc 2 -rxh 2 -m -dbm -rt -120 -R $RAD -erp $ERP -f $FRQ -o test/$RAD.hd -pm 1 -res 3600 -t
|
||||
convert test/$RAD.hd.ppm test/$RAD.hd.png
|
||||
rm test/$RAD.hd.ppm
|
||||
rm test/$RAD.*cf
|
||||
let RAD=RAD+5
|
||||
done
|
||||
|
||||
|
||||
|
BIN
test/10.png
BIN
test/10.png
Binary file not shown.
Before Width: | Height: | Size: 685 KiB |
BIN
test/15.png
BIN
test/15.png
Binary file not shown.
Before Width: | Height: | Size: 673 KiB |
BIN
test/20.png
BIN
test/20.png
Binary file not shown.
Before Width: | Height: | Size: 653 KiB |
BIN
test/25.png
BIN
test/25.png
Binary file not shown.
Before Width: | Height: | Size: 634 KiB |
Reference in New Issue
Block a user