removed structs, simple calc

This commit is contained in:
Daniel Grimm 2024-04-27 04:37:27 +02:00 committed by Blyron
parent b3f0dbea66
commit 441372b369
3 changed files with 22 additions and 273 deletions

View File

@ -274,6 +274,16 @@ void PathLossModel::EstimatePathStateAndVehicleObstacles(AActor *OtherActor,
}
}
double PathLossModel::CalcVehicleLoss(const double d1, const double d2, const double h)
{
double V = h * sqrt(2.0 * (d1 + d2) / (lambda * d1 * d2));
if (V >= -0.78) {
double T = std::pow(V - 0.1, 2) + 1.0;
return 6.9 + 20.0 * log10(sqrt(T + 1.0) + V - 0.1);
}
return 0.0;
}
double PathLossModel::CalculateNLOSvLoss(const FVector Source,
const FVector Destination,
const double TxHeight,
@ -281,7 +291,6 @@ double PathLossModel::CalculateNLOSvLoss(const FVector Source,
const double RxDistance3d,
std::vector<FVector> &vehicle_obstacles)
{
double vehicle_blockage_loss = 0.0;
// convert all positions to meters
FVector pos_tx = Source;
@ -293,21 +302,20 @@ double PathLossModel::CalculateNLOSvLoss(const FVector Source,
pos_rx.X /= 100.0f;
pos_rx.Y /= 100.0f;
pos_rx.Z = RxHeight;
const double distTxRx{sqrt(std::pow(pos_rx.X - pos_tx.X, 2) + std::pow(pos_rx.Y - pos_tx.Y, 2))}; /*< ground distance */
DiffractionObstacle Tx{0.0, pos_tx.Z};
DiffractionObstacle Rx{distTxRx, pos_rx.Z};
auto obsTop = buildTopObstacles(vehicle_obstacles, pos_tx, pos_rx);
if (!obsTop.empty())
double max_loss = 0.0;
for(auto veh_it = vehicle_obstacles.begin(); veh_it != vehicle_obstacles.end(); veh_it++)
{
obsTop.push_front(Tx);
obsTop.push_back(Rx);
auto path = computeMultipleKnifeEdge(obsTop);
vehicle_blockage_loss = path.attenuation;
double dist_tx_veh = sqrt(std::pow(veh_it->X - pos_tx.X, 2) + std::pow(veh_it->Y - pos_tx.Y, 2));
double dist_veh_rx = sqrt(std::pow(pos_rx.X - veh_it->X, 2) + std::pow(pos_rx.Y - veh_it->Y, 2));
double cur_loss = CalcVehicleLoss(dist_tx_veh,dist_veh_rx,veh_it->Z);
if(cur_loss >= max_loss)
{
max_loss = cur_loss;
}
}
return vehicle_blockage_loss;
return max_loss;
}
void PathLossModel::SetPathLossModel(const EPathLossModel path_loss_model)

View File

@ -32,22 +32,6 @@ enum EScenario
Urban
};
struct DiffractionObstacle
{
DiffractionObstacle(double distTx, double height);
// meter
double d; // distance to transmitter
double h; // height of obstacle
};
struct DiffractionPath
{
DiffractionPath();
double attenuation;
double d; // meter
};
class PathLossModel
{
public:
@ -69,12 +53,8 @@ public:
void SetPathLossModel(const EPathLossModel path_loss_model);
private:
// multiple knife edge diffraction for NLOSv
double computeVehiclePathLoss(const FVector &pos_tx, const FVector &pos_rx, const double reference_z, std::vector<FVector> &vehicle_obstacles);
double computeSimpleKnifeEdge(double heightTx, double heightRx, double heightObs, double distTxRx, double distTxObs);
DiffractionPath computeMultipleKnifeEdge(const std::list<DiffractionObstacle> &obs);
std::list<DiffractionObstacle> buildTopObstacles(const std::vector<FVector> &vehicles, const FVector &pos_tx, const FVector &pos_rx);
// diffraction for NLOSv
double CalcVehicleLoss(const double d1, const double d2, const double h);
// powers
float CalculateReceivedPower(AActor *OtherActor,
const float OtherTransmitPower,

View File

@ -1,239 +0,0 @@
// Copyright (c) 2024 Institut fuer Technik der Informationsverarbeitung (ITIV) at the
// Karlsruhe Institute of Technology
//
// This work is licensed under the terms of the MIT license.
// For a copy, see <https://opensource.org/licenses/MIT>.
#pragma once
#include <cmath>
#include <limits>
#include <vector>
#include <list>
#include "PathLossModel.h"
namespace
{
auto compareDistance = [](const DiffractionObstacle &a, const DiffractionObstacle &b)
{ return a.d < b.d; };
auto compareHeight = [](const DiffractionObstacle &a, const DiffractionObstacle &b)
{ return a.h < b.h; };
using ObstacleIterator = std::list<DiffractionObstacle>::const_iterator;
ObstacleIterator findMainObstacle(ObstacleIterator, ObstacleIterator);
ObstacleIterator findSecondaryObstacle(ObstacleIterator, ObstacleIterator);
} // namespace
DiffractionObstacle::DiffractionObstacle(double distTx, double height) : d(distTx), h(height)
{
}
DiffractionPath::DiffractionPath() : attenuation(0.0), d(0.0)
{
}
double PathLossModel::computeSimpleKnifeEdge(double heightTx, double heightRx, double heightObs, double distTxRx, double distTxObs)
{
// following calculations are similar to equation 29 of ITU-R P.526-13:
// v = sqrt(2d/lambda * alpha1 * alpha2)
//
// with sinus approximation for small angles:
// alpha1 =~ sin alpha1 = h / d1
// alpha2 =~ sin alpha2 = h / d2
//
// v = sqrt(2d / lambda * h / d1 * h / d2) = sqrt(2) * h / sqrt(lambda * d1 * d2 / d)
//
// with d1 = distTxObs, d2 = distRxObs, d = distTxRx,
// distance between Rx and obstacle
const double distRxObs = distTxRx - distTxObs;
// signed height relative to the line connecting Tx and Rx at obstacle position
const double obsHeightTxRxLine = (heightRx - heightTx) / distTxRx * distTxObs + heightTx;
const double h = heightObs - obsHeightTxRxLine;
// calculate the Fresnel ray
const double r = sqrt(lambda * distTxObs * distRxObs / distTxRx);
static const double root_two = sqrt(2.0);
const double v = root_two * h / r;
double loss = 0.0;
if (v > -0.78)
{
// approximation of Fresnel-Kirchoff loss given by ITU-R P.526, equation 31 (result in dB):
// J(v) = 6.9 + 20 log(sqrt((v - 01)^2 + 1) + v - 0.1)
loss = 6.9 + 20.0 * log10(sqrt(std::pow(v - 0.1, 2) + 1.0) + v - 0.1);
}
return loss;
}
DiffractionPath PathLossModel::computeMultipleKnifeEdge(const std::list<DiffractionObstacle> &obs)
{
DiffractionPath path;
// determine main and secondary obstacles
std::vector<ObstacleIterator> mainObs;
mainObs.push_back(obs.begin()); // Tx
for (ObstacleIterator it = obs.begin(); it != obs.end();)
{
it = findMainObstacle(it, obs.end());
if (it != obs.end())
{
mainObs.push_back(it);
}
}
// NOTE: Rx is added by loop as last main obstacle
struct SecondaryObstacle
{
SecondaryObstacle(ObstacleIterator tx, ObstacleIterator obs, ObstacleIterator rx) : tx(tx), obstacle(obs), rx(rx) {}
ObstacleIterator tx;
ObstacleIterator obstacle;
ObstacleIterator rx;
};
std::vector<SecondaryObstacle> secObs;
std::vector<double> mainObsDistances;
for (std::size_t i = 0, j = 1; j < mainObs.size(); ++i, ++j)
{
const double d = mainObs[j]->d - mainObs[i]->d;
path.d += sqrt(std::pow(d, 2) + std::pow(mainObs[j]->h - mainObs[i]->h, 2));
mainObsDistances.push_back(d);
const auto delta = std::distance(mainObs[i], mainObs[j]);
if (delta == 2)
{
// single other obstacle between two main obstacles
secObs.emplace_back(mainObs[i], std::next(mainObs[i]), mainObs[j]);
}
else if (delta > 2)
{
secObs.emplace_back(mainObs[i], findSecondaryObstacle(mainObs[i], mainObs[j]), mainObs[j]);
}
}
// attenuation due to main obstacles
double attMainObs = 0.0;
for (std::size_t i = 0; i < mainObs.size() - 2; ++i)
{
const double distTxObs = mainObsDistances[i];
const double distTxRx = distTxObs + mainObsDistances[i + 1];
attMainObs += computeSimpleKnifeEdge(mainObs[i]->h, mainObs[i + 2]->h, mainObs[i + 1]->h, distTxRx, distTxObs);
}
// attenuation due to secondary obstacles
double attSecObs = 0.0;
for (const SecondaryObstacle &sec : secObs)
{
const double distTxRx = sec.rx->d - sec.tx->d;
const double distTxObs = sec.obstacle->d - sec.tx->d;
attSecObs += computeSimpleKnifeEdge(sec.tx->h, sec.rx->h, sec.obstacle->h, distTxRx, distTxObs);
}
// correction factor C (see eq. 46 in ITU-R P.526-13)
double C = mainObs.back()->d - mainObs.front()->d; // distance between Tx and Rx
for (double d : mainObsDistances)
{
C *= d;
}
double pairwiseDistProduct = 1.0;
for (std::size_t i = 1; i < mainObsDistances.size(); ++i)
{
pairwiseDistProduct *= mainObsDistances[i - 1] + mainObsDistances[i];
}
C /= mainObsDistances.front() * mainObsDistances.back() * pairwiseDistProduct;
path.attenuation = attMainObs + attSecObs - 10.0 * log10(C);
return path;
}
std::list<DiffractionObstacle> PathLossModel::buildTopObstacles(const std::vector<FVector> &vehicles, const FVector &pos_tx, const FVector &pos_rx)
{
std::list<DiffractionObstacle> diffTop;
const double vx = pos_rx.X - pos_tx.X;
const double vy = pos_rx.Y - pos_tx.Y;
for (auto vehicle : vehicles)
{
const double midpoint_x = vehicle.X;
const double midpoint_y = vehicle.Y;
const double k = (midpoint_x * vx - vy * pos_tx.Y + vy * midpoint_y - pos_tx.X * vx) / (std::pow(vx, 2) + std::pow(vy, 2));
if (k < 0.0 || k > 1.0)
continue; /*< skip points beyond the ends of TxRx line segment */
const double d = k * sqrt(std::pow(vx, 2) + std::pow(vy, 2));
diffTop.emplace_back(d, vehicle.Z);
}
diffTop.sort(compareDistance);
return diffTop;
}
namespace
{
ObstacleIterator findMainObstacle(ObstacleIterator begin, ObstacleIterator end)
{
ObstacleIterator mainIterator = end;
double mainAngle = -std::numeric_limits<double>::infinity();
if (begin != end)
{
for (ObstacleIterator it = std::next(begin); it != end; ++it)
{
double angle = (it->h - begin->h) / (it->d - begin->d);
if (angle > mainAngle)
{
mainIterator = it;
mainAngle = angle;
}
}
}
return mainIterator;
}
ObstacleIterator findSecondaryObstacle(ObstacleIterator first, ObstacleIterator last)
{
ObstacleIterator secIterator = last;
double secHeightGap{std::numeric_limits<double>::infinity()};
const double distFirstLast = last->d - first->d;
const double heightFirstLast = last->h - first->h;
const auto offset = first->h * last->d - first->d * last->h;
for (ObstacleIterator it = std::next(first); it != last; ++it)
{
const double heightGap = ((it->d * heightFirstLast + offset) / distFirstLast) - it->h;
if (heightGap < secHeightGap)
{
secIterator = it;
secHeightGap = heightGap;
}
}
return secIterator;
}
} // namespace
// statistical model from ETSI TR 103 257-1 V1.1.1 (2019-05)
double PathLossModel::MakeVehicleBlockageLoss(double TxHeight, double RxHeight, double obj_height, double obj_distance)
{
// according to ETSI, stochastic method
if (TxHeight > obj_height && RxHeight > obj_height)
{
// no blocking if higher than obj
return 0.0;
}
else if (TxHeight < obj_height && RxHeight < obj_height)
{
// worst case: obj is higher than both tx and rx
float mean = 9.0f + fmax(0.0f, 15.0f * log10(obj_distance) - 41.0f);
return mRandomEngine->GetNormalDistribution(mean, 4.5f);
}
else
{
// something in between
float mean = 5.0f + fmax(0.0f, 15.0f * log10(obj_distance) - 41.0f);
return mRandomEngine->GetNormalDistribution(mean, 4.0f);
}
}