File AccessAnalyzer.hpp¶
File List > analysis > AccessAnalyzer.hpp
Go to the documentation of this file
#pragma once
#include <memory>
#include <vector>
#include <gtl/btree.hpp>
#include <astro/astro.fwd.hpp>
#include <astro/frames/CartesianVector.hpp>
#include <astro/frames/frames.hpp>
#include <astro/time/Date.hpp>
#include <units/units.hpp>
#include <utilities/ProgressBar.hpp>
#include <trace/analysis/PositionCache.hpp>
#include <trace/analysis/SpatialIndex.hpp>
#include <trace/platforms/sensors/Sensor.hpp>
#include <trace/risesets/AccessArray.hpp>
#include <trace/risesets/RiseSetArray.hpp>
#include <trace/trace.fwd.hpp>
#include <trace/types/typedefs.hpp>
namespace astrea {
namespace trace {
template <typename T>
concept HasSize = requires(T t) {
{ t.size() } -> std::convertible_to<std::size_t>;
};
template <typename T>
concept HasSubscriptOperator = requires(T t) {
{ &t[0] } -> std::convertible_to<std::shared_ptr<astro::PayloadPlatform<Sensor>>>;
};
template <typename T>
concept IsPlatformContainer = HasSize<T> && HasSubscriptOperator<T>;
using EciRadiusVec = astro::RadiusVector<astro::frames::earth::icrf>;
using EcefRadiusVec = astro::RadiusVector<astro::frames::earth::earth_fixed>;
using DateVector = std::vector<astro::Date>;
using ViewerConstellation = astro::Constellation<Viewer>;
using ViewerRefVec = std::vector<std::shared_ptr<Viewer>>;
using GroundStationRefVec = std::vector<std::shared_ptr<GroundStation>>;
using GroundPointRefVec = std::vector<std::shared_ptr<GroundPoint>>;
using PairVec = std::vector<std::pair<std::size_t, std::size_t>>;
class AccessAnalyzer {
public:
AccessAnalyzer(const Time& resolution, const astro::Date& startDate, const astro::Date& endDate, const astro::AstrodynamicsSystem& sys, const bool printProgress = false) :
_resolution(resolution),
_startDate(startDate),
_endDate(endDate),
_sys(&sys),
_printProgress(printProgress)
{
create_date_vector();
}
~AccessAnalyzer() = default;
AccessArray find_internal_accesses(ViewerConstellation& constel, const bool clearPositionCache = true);
AccessArray find_accesses(ViewerConstellation& constel, GroundArchitecture& grounds, const bool includeInternalAccesses = false);
AccessArray find_accesses(ViewerConstellation& constel, Grid& grid, const bool includeInternalAccesses = false);
private:
Time _resolution;
astro::Date _startDate;
astro::Date _endDate;
const astro::AstrodynamicsSystem* _sys;
DateVector _dates;
PositionCache _positionCache;
bool _printProgress;
// This isn't doing anything currently, but I'm not convinced it's a terrible idea to speed up the pre-checks by
// binning the ground points using the spatial index and only checking the corners for very dense grids.
// SpatialIndex _spatialIndex; //!< Spatial index for ground points
void create_date_vector();
bool is_central_body_occulting(const EcefRadiusVec& position1, const EcefRadiusVec& position2, const bool atmosphereBlocks) const;
RiseSetArray find_platform_to_platform_accesses(
std::shared_ptr<astro::PayloadPlatform<Sensor>> platform1,
std::shared_ptr<astro::PayloadPlatform<Sensor>> platform2,
const bool twoWay = false
) const;
RiseSetArray
find_platform_to_ground_point_accesses(std::shared_ptr<astro::PayloadPlatform<Sensor>> platform, const std::shared_ptr<GroundPoint> groundPoint) const;
RiseSetArray find_sensor_accesses(
const std::vector<AccessInfo>& accessInfo,
const Sensor& sensor1,
const std::optional<Sensor> sensor2 = std::nullopt,
const bool twoWay = false
) const;
bool can_objects_ever_access_each_other(const std::size_t& id1, const std::size_t& id2, const bool atmosphereBlocks) const;
ViewerRefVec cache_viewers(ViewerConstellation& constel);
GroundStationRefVec cache_ground_points(GroundArchitecture& grounds);
GroundPointRefVec cache_ground_points(Grid& grid);
std::vector<AccessInfo> build_access_info(const std::size_t& id1, const std::size_t& id2) const;
PairVec filter_impossible_pairs(const ViewerRefVec& viewers) const;
template <typename T, typename U>
requires requires(T t) { t.get_id(); } && requires(U u) { u.get_id(); }
PairVec filter_impossible_pairs(const std::vector<std::shared_ptr<T>>& objects1, const std::vector<std::shared_ptr<U>>& objects2) const
{
if (_printProgress) { std::cout << "\tFiltering impossible sat-to-ground pairs..." << std::flush; }
constexpr bool atmosphereBlocks = !(std::is_base_of_v<GroundPoint, T> || std::is_base_of_v<GroundPoint, U>);
PairVec validPairs;
for (std::size_t ii = 0; ii < objects1.size(); ++ii) {
for (std::size_t jj = 0; jj < objects2.size(); ++jj) {
if (can_objects_ever_access_each_other(objects1[ii]->get_id(), objects2[jj]->get_id(), atmosphereBlocks)) {
validPairs.emplace_back(ii, jj);
}
}
}
if (_printProgress) {
std::cout << " kept " << validPairs.size() << " / " << (objects1.size() * objects2.size()) << " pairs ("
<< (100.0 * validPairs.size() / (objects1.size() * objects2.size())) << "%)" << std::endl;
}
return validPairs;
}
};
} // namespace trace
} // namespace astrea