spectrum: Precompute sincos of cluster angles

This commit is contained in:
Gabriel Ferreira
2024-03-08 12:27:44 +01:00
parent 6c0fbb74df
commit 6ae8b54e52
3 changed files with 37 additions and 27 deletions

View File

@@ -138,6 +138,12 @@ class MatrixBasedChannelModel : public Object
*/
Double2DVector m_angle;
/**
* Sin/cos of cluster angle angle[direction][n], where direction = 0(AOA), 1(ZOA), 2(AOD),
* 3(ZOD) in degree.
*/
std::vector<std::vector<std::pair<double, double>>> m_cachedAngleSincos;
/**
* Alpha term per cluster as described in 3GPP TR 37.885 v15.3.0, Sec. 6.2.3
* for calculating doppler.

View File

@@ -42,6 +42,9 @@ NS_LOG_COMPONENT_DEFINE("ThreeGppChannelModel");
NS_OBJECT_ENSURE_REGISTERED(ThreeGppChannelModel);
/// Conversion factor: degrees to radians
static constexpr double DEG2RAD = M_PI / 180.0;
/// The ray offset angles within a cluster, given for rms angle spread normalized to 1.
/// (Table 7.5-3)
static const double offSetAlpha[20] = {
@@ -1784,6 +1787,20 @@ ThreeGppChannelModel::GenerateChannelParameters(const Ptr<const ChannelCondition
channelParams->m_angle.push_back(clusterAod);
channelParams->m_angle.push_back(clusterZod);
// Precompute angles sincos
channelParams->m_cachedAngleSincos.resize(channelParams->m_angle.size());
for (size_t direction = 0; direction < channelParams->m_angle.size(); direction++)
{
channelParams->m_cachedAngleSincos[direction].resize(
channelParams->m_angle[direction].size());
for (size_t cluster = 0; cluster < channelParams->m_angle[direction].size(); cluster++)
{
channelParams->m_cachedAngleSincos[direction][cluster] = {
sin(channelParams->m_angle[direction][cluster] * DEG2RAD),
cos(channelParams->m_angle[direction][cluster] * DEG2RAD)};
}
}
// Compute alpha and D as described in 3GPP TR 37.885 v15.3.0, Sec. 6.2.3
// These terms account for an additional Doppler contribution due to the
// presence of moving objects in the surrounding environment, such as in

View File

@@ -237,31 +237,19 @@ ThreeGppSpectrumPropagationLossModel::CalcBeamformingGain(
NS_ASSERT(numCluster <= longTerm->GetNumPages());
// check if channelParams structure is generated in direction s-to-u or u-to-s
bool isSameDirection = (channelParams->m_nodeIds == channelMatrix->m_nodeIds);
MatrixBasedChannelModel::DoubleVector zoa;
MatrixBasedChannelModel::DoubleVector zod;
MatrixBasedChannelModel::DoubleVector aoa;
MatrixBasedChannelModel::DoubleVector aod;
bool isSameDir = (channelParams->m_nodeIds == channelMatrix->m_nodeIds);
// if channel params is generated in the same direction in which we
// generate the channel matrix, angles and zenith of departure and arrival are ok,
// just set them to corresponding variable that will be used for the generation
// of channel matrix, otherwise we need to flip angles and zeniths of departure and arrival
if (isSameDirection)
{
zoa = channelParams->m_angle[MatrixBasedChannelModel::ZOA_INDEX];
zod = channelParams->m_angle[MatrixBasedChannelModel::ZOD_INDEX];
aoa = channelParams->m_angle[MatrixBasedChannelModel::AOA_INDEX];
aod = channelParams->m_angle[MatrixBasedChannelModel::AOD_INDEX];
}
else
{
zod = channelParams->m_angle[MatrixBasedChannelModel::ZOA_INDEX];
zoa = channelParams->m_angle[MatrixBasedChannelModel::ZOD_INDEX];
aod = channelParams->m_angle[MatrixBasedChannelModel::AOA_INDEX];
aoa = channelParams->m_angle[MatrixBasedChannelModel::AOD_INDEX];
}
using DPV = std::vector<std::pair<double, double>>;
using MBCM = MatrixBasedChannelModel;
const auto& cachedAngleSincos = channelParams->m_cachedAngleSincos;
const DPV& zoa = cachedAngleSincos[isSameDir ? MBCM::ZOA_INDEX : MBCM::ZOD_INDEX];
const DPV& zod = cachedAngleSincos[isSameDir ? MBCM::ZOD_INDEX : MBCM::ZOA_INDEX];
const DPV& aoa = cachedAngleSincos[isSameDir ? MBCM::AOA_INDEX : MBCM::AOD_INDEX];
const DPV& aod = cachedAngleSincos[isSameDir ? MBCM::AOD_INDEX : MBCM::AOA_INDEX];
for (size_t cIndex = 0; cIndex < numCluster; cIndex++)
{
@@ -281,13 +269,12 @@ ThreeGppSpectrumPropagationLossModel::CalcBeamformingGain(
// cluster angle angle[direction][n], where direction = 0(aoa), 1(zoa).
double tempDoppler =
factor * ((sin(zoa[cIndex] * M_PI / 180) * cos(aoa[cIndex] * M_PI / 180) * uSpeed.x +
sin(zoa[cIndex] * M_PI / 180) * sin(aoa[cIndex] * M_PI / 180) * uSpeed.y +
cos(zoa[cIndex] * M_PI / 180) * uSpeed.z) +
(sin(zod[cIndex] * M_PI / 180) * cos(aod[cIndex] * M_PI / 180) * sSpeed.x +
sin(zod[cIndex] * M_PI / 180) * sin(aod[cIndex] * M_PI / 180) * sSpeed.y +
cos(zod[cIndex] * M_PI / 180) * sSpeed.z) +
2 * alpha * D);
factor *
((zoa[cIndex].first * aoa[cIndex].second * uSpeed.x +
zoa[cIndex].first * aoa[cIndex].first * uSpeed.y + zoa[cIndex].second * uSpeed.z) +
(zod[cIndex].first * aod[cIndex].second * sSpeed.x +
zod[cIndex].first * aod[cIndex].first * sSpeed.y + zod[cIndex].second * sSpeed.z) +
2 * alpha * D);
doppler[cIndex] = std::complex<double>(cos(tempDoppler), sin(tempDoppler));
}