EMANE  1.2.1
gainmanager.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013-2014 - Adjacent Link LLC, Bridgewater, New Jersey
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * * Neither the name of Adjacent Link LLC nor the names of its
16  * contributors may be used to endorse or promote products derived
17  * from this software without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  */
32 
33 #include "gainmanager.h"
34 #include "antennaprofilemanifest.h"
35 #include "positionutils.h"
37 #include "logservice.h"
38 #include "locationinfoformatter.h"
39 #include "positionneuformatter.h"
40 
42  nemId_{nemId},
43  pLocalPattern_{},
44  pLocalBlockage_{},
45  localAntennaPlacement_{},
46  dLocalAntennaAzimuthDegrees_{},
47  dLocalAntennaElevationDegrees_{},
48  bHasLocalAntennaProfile_{false}{}
49 
51 {
52  for(const auto & antennaProfile : antennaProfiles)
53  {
54  const auto ret =
55  AntennaProfileManifest::instance()->getProfileInfo(antennaProfile.getAntennaProfileId());
56 
57  // do we have the profile
58  if(ret.second)
59  {
60  if(nemId_ == antennaProfile.getNEMId())
61  {
62  pLocalPattern_ = std::get<0>(ret.first);
63  pLocalBlockage_ = std::get<1>(ret.first);
64  localAntennaPlacement_ = std::get<2>(ret.first);
65  dLocalAntennaAzimuthDegrees_ = antennaProfile.getAntennaAzimuthDegrees();
66  dLocalAntennaElevationDegrees_ = antennaProfile.getAntennaElevationDegrees();
67  bHasLocalAntennaProfile_ = true;
68  }
69  else
70  {
71  antennaProfileStore_[antennaProfile.getNEMId()] = antennaProfile;
72  }
73  }
74  else
75  {
76  throw makeException<AntennaProfileException>("NEM %hu: unknown antenna profile %hu",
77  nemId_,
78  antennaProfile);
79  }
80  }
81 }
82 
83 
84 std::pair<double,EMANE::GainManager::GainStatus>
86  const LocationInfo & locationPairInfo,
87  const std::pair<double, bool> & optionalRxFixedGaindBi,
88  const std::pair<double, bool> & optionalTxFixedGaindBi) const
89 {
90  double dRxAntennaGaindBi{optionalRxFixedGaindBi.first};
91  double dTxAntennaGaindBi{optionalTxFixedGaindBi.first};
92  double dRxAntennaBlockagedBi{};
93  double dTxAntennaBlockagedBi{};
94 
95  double dDistanceMeters{};
96  PositionNEU antennaPlacement{};
97 
100  LocationInfoFormatter(locationPairInfo),
101  "PHYI %03hu GainManager::%s src: %hu rx fixed gain %lf (%s) tx fixed gain %lf (%s)",
102  nemId_,
103  __func__,
104  transmitterId,
105  dRxAntennaGaindBi,
106  optionalRxFixedGaindBi.second ? "yes" : "no",
107  dTxAntennaGaindBi,
108  optionalTxFixedGaindBi.second ? "yes" : "no");
109 
110  if(!optionalTxFixedGaindBi.second)
111  {
112  AntennaProfileStore::const_iterator remoteAntennaProfileIter;
113 
114  if(!locationPairInfo)
115  {
117  }
118 
119  if((remoteAntennaProfileIter = antennaProfileStore_.find(transmitterId)) == antennaProfileStore_.end())
120  {
122  }
123 
124  // retrieve remote transmitter antenna profile id and pointing info
125  auto ret =
126  AntennaProfileManifest::instance()->getProfileInfo(remoteAntennaProfileIter->second.getAntennaProfileId());
127 
128  // we have the profile info
129  if(ret.second)
130  {
131  // get the antenna pattern and optional blockage and antenna placement
132  AntennaPattern * pRemotePattern{std::get<0>(ret.first)};
133  AntennaPattern * pRemoteBlockage{std::get<1>(ret.first)};
134  antennaPlacement = std::get<2>(ret.first);
135 
136  // calculate the direction: azimuth, elvation and distance
137  auto direction =
138  Utils::calculateDirection(locationPairInfo.getRemotePOV(),
139  antennaPlacement,
140  locationPairInfo.getLocalPOV(),
141  localAntennaPlacement_);
142 
143  dDistanceMeters = std::get<2>(direction);
144 
145  // adjust the direction azimuth and elvation based on the antenna pointing azimuth and elvation
146  auto lookupAngles =
147  Utils::calculateLookupAngles(std::get<0>(direction),
148  remoteAntennaProfileIter->second.getAntennaAzimuthDegrees(),
149  std::get<1>(direction),
150  remoteAntennaProfileIter->second.getAntennaElevationDegrees());
151 
152  // get the remote transmitter antenna gain
153  dTxAntennaGaindBi = pRemotePattern->getGain(std::round(lookupAngles.first),
154  std::round(lookupAngles.second));
155 
156  // get the blocakage, if specified
157  // Note: no adjustment is necessary to the direction azimuth and elvation
158  if(pRemoteBlockage)
159  {
160  dTxAntennaBlockagedBi = pRemoteBlockage->getGain(std::round(std::get<0>(direction)),
161  std::round(std::get<1>(direction)));
162  }
163 
165  DEBUG_LEVEL,
166  [this,&antennaPlacement]()
167  {
168  Strings strings;
169 
170  strings.push_back("remote antenna");
171  strings.splice(strings.end(),PositionNEUFormatter(antennaPlacement)());
172 
173  strings.push_back("local antenna");
174  strings.splice(strings.end(),PositionNEUFormatter(localAntennaPlacement_)());
175 
176  return strings;
177  },
178  "PHYI %03hu GainManager::%s remote calc tx antenna gain: %lf tx antenna"
179  " blockage: %lf direction az: %lf el: %lf dist: %lf remote antenna az: %lf el: %lf"
180  " lookup bearing: %lf lookup el: %lf",
181  nemId_,
182  __func__,
183  dTxAntennaGaindBi,
184  dTxAntennaBlockagedBi,
185  std::get<0>(direction),
186  std::get<1>(direction),
187  std::get<2>(direction),
188  remoteAntennaProfileIter->second.getAntennaAzimuthDegrees(),
189  remoteAntennaProfileIter->second.getAntennaElevationDegrees(),
190  lookupAngles.first,
191  lookupAngles.second);
192  }
193  else
194  {
195  // profile info is missing
197  }
198  }
199 
200  if(!optionalRxFixedGaindBi.second)
201  {
202  if(!locationPairInfo)
203  {
205  }
206 
207  if(!bHasLocalAntennaProfile_)
208  {
210  }
211 
212  // calculate the direction: azimuth, elvation and distance
213  auto direction =
214  Utils::calculateDirection(locationPairInfo.getLocalPOV(),
215  localAntennaPlacement_,
216  locationPairInfo.getRemotePOV(),
217  antennaPlacement);
218 
219  // adjust the direction azimuth and elvation based on the antenna pointing azimuth and elvation
220  auto lookupAngles =
221  Utils::calculateLookupAngles(std::get<0>(direction),
222  dLocalAntennaAzimuthDegrees_,
223  std::get<1>(direction),
224  dLocalAntennaElevationDegrees_);
225 
226  // get the local receiver antenna gain
227  dRxAntennaGaindBi =
228  pLocalPattern_->getGain(std::round(lookupAngles.first),
229  std::round(lookupAngles.second));
230 
231  // get the blocakage, if specified
232  // Note: no adjustment is necessary to the direction azimuth and elvation
233  if(pLocalBlockage_)
234  {
235  dRxAntennaBlockagedBi =
236  pLocalBlockage_->getGain(std::round(std::get<0>(direction)),
237  std::round(std::get<1>(direction)));
238  }
239 
241  DEBUG_LEVEL,
242  [this,&antennaPlacement]()
243  {
244  Strings strings;
245 
246  strings.push_back("local antenna");
247  strings.splice(strings.end(),PositionNEUFormatter(localAntennaPlacement_)());
248 
249  strings.push_back("remote antenna");
250  strings.splice(strings.end(),PositionNEUFormatter(antennaPlacement)());
251 
252  return strings;
253  },
254  "PHYI %03hu GainManager::%s local calc rx antenna gain: %lf rx antenna"
255  " blockage: %lf direction az: %lf el: %lf dist: %lf local antenna az: %lf el: %lf"
256  " lookup bearing: %lf lookup el: %lf",
257  nemId_,
258  __func__,
259  dRxAntennaGaindBi,
260  dRxAntennaBlockagedBi,
261  std::get<0>(direction),
262  std::get<1>(direction),
263  std::get<2>(direction),
264  dLocalAntennaAzimuthDegrees_,
265  dLocalAntennaElevationDegrees_,
266  lookupAngles.first,
267  lookupAngles.second);
268 
269 
270  }
271 
272  const auto & localPosition = locationPairInfo.getLocalPOV().getPosition();
273  const auto & remotePosition = locationPairInfo.getRemotePOV().getPosition();
274 
275  // check if antennas are below the horizon
276  if(!locationPairInfo == false &&
277  dDistanceMeters > 10 &&
278  Utils::checkHorizon(localPosition.getAltitudeMeters() +
279  localAntennaPlacement_.getUpMeters(),
280  remotePosition.getAltitudeMeters() +
281  antennaPlacement.getUpMeters(),
282  dDistanceMeters) == false)
283  {
284  // below horizon use minimal gain
285  return {0,GainStatus::ERROR_HORIZON};
286  }
287 
288  double dCombinedGaindBi{dRxAntennaGaindBi + dRxAntennaBlockagedBi + dTxAntennaGaindBi + dTxAntennaBlockagedBi};
289 
291  DEBUG_LEVEL,
292  "PHYI %03hu GainManager::%s combined gain: %lf",
293  nemId_,
294  __func__,
295  dCombinedGaindBi);
296 
297  return {dCombinedGaindBi, GainStatus::SUCCESS};
298 }
std::tuple< double, double, double > calculateDirection(const PositionOrientationVelocity &localLocationInfo, const PositionNEU &localAntennaPositionNEU, const PositionOrientationVelocity &remoteLocationInfo, const PositionNEU &remoteAntennaPositionNEU)
Definition: positionutils.h:49
Callable formatter object for PositioNEU instances.
std::pair< double, GainStatus > determineGain(NEMId transmitterId, const LocationInfo &locationPairInfo, const std::pair< double, bool > &optionalRxFixedGaindBi, const std::pair< double, bool > &optionalTxFixedGaindBi) const
Definition: gainmanager.cc:85
#define LOGGER_VERBOSE_LOGGING(logger, level, fmt, args...)
GainManager(NEMId nemId)
Definition: gainmanager.cc:41
std::pair< double, double > calculateLookupAngles(double dAzReference, double dAzPointing, double dElReference, double dElPointing)
#define LOGGER_VERBOSE_LOGGING_FN_VARGS(logger, level, fn, fmt, args...)
double getGain(std::int16_t iBearing, std::int16_t iElevation) const
std::uint16_t NEMId
Definition: types.h:52
std::list< std::string > Strings
Definition: types.h:66
const PositionOrientationVelocity & getRemotePOV() const
const PositionOrientationVelocity & getLocalPOV() const
double getUpMeters() const
Definition: positionneu.inl:60
void update(const Events::AntennaProfiles &antennaProfiles)
Definition: gainmanager.cc:50
bool checkHorizon(const double dHeightMeters1, const double dHeightMeters2, const double dDistanceMeters)
static AntennaProfileManifest * instance()
Definition: singleton.h:56
std::list< AntennaProfile > AntennaProfiles
std::pair< std::tuple< AntennaPattern *, AntennaPattern *, PositionNEU >, bool > getProfileInfo(AntennaProfileId antennaProfileId) const