Commit 95fe27eb authored by Pascal Palenda's avatar Pascal Palenda
Browse files

Merge develop into ma2020_palenda

parents 49b6ae44 a8b26e0b
......@@ -42,7 +42,7 @@ if( NOT DEFINED ITA_SIMULATION_SCHEDULER_ART_MODULE )
endif( )
if( NOT DEFINED ITA_SIMULATION_SCHEDULER_WITH_PROFILER )
set( ITA_SIMULATION_SCHEDULER_WITH_PROFILER ON CACHE BOOL "Build with profiler" )
set( ITA_SIMULATION_SCHEDULER_WITH_PROFILER OFF CACHE BOOL "Build with profiler" )
endif( )
if( ITA_SIMULATION_SCHEDULER_WITH_PROFILER )
......
......@@ -10,9 +10,7 @@
//#include <type_traits>
// simulation scheduler includes
#include <ITA/SimulationScheduler/update_scene.h>
#include <ITA/SimulationScheduler/OutdoorAcoustics/outdoor_simulator_interface.h>
#include <ITA/SimulationScheduler/OutdoorAcoustics/outdoor_simulation_result.h>
// ART includes
#include <ITAGeo/Atmosphere/StratifiedAtmosphere.h>
......@@ -33,58 +31,58 @@ namespace ITA
* This Simulator uses a single Atmosphere::EigenraySearch::Engine instance.
* The simulation is run synchronous/blocking. Thus, only one simulation can be run at the same time.
*/
class ITA_SIMULATION_SCHEDULER_API CSimulator : public OutdoorAcoustics::ISimulatorInterface
class ITA_SIMULATION_SCHEDULER_API CARTSimulator : public OutdoorAcoustics::ISimulatorInterface
{
public:
//! \brief Raven status types
enum class SimulatorStatus
//! \brief Configuration class for a outdoor acoustics simulator.
struct ITA_SIMULATION_SCHEDULER_API ARTSimulatorConfig : public ISimulatorInterface::SimulatorConfig
{
uninitialized, ///< Simulator is uninitialized.
idle, ///< Raven instance is running but no geometry is loaded.
sceneLoaded, ///< Raven instance is running and a geometry is loaded.
filterEngineLoaded ///< Raven initialized the filter engine.
inline explicit ARTSimulatorConfig() {};
VistaPropertyList Store() const override;
void Load(const VistaPropertyList& oProperties) override;
CoordinateSystem eClientCoordinateSystem = CoordinateSystem::Cartesian; //!< 0 = Cartesian, 1 = OpenGL
std::string sJsonAtmosphere = ""; //!< Either JSON formatted string or path to atmosphere JSON file.
};
CSimulator ( );
CARTSimulator( const ARTSimulatorConfig& oConfig );
CARTSimulator(const CARTSimulator& other) = delete;
CARTSimulator(CARTSimulator&& other) = delete;
CARTSimulator& operator=(const CARTSimulator& other) = delete;
CARTSimulator& operator=(CARTSimulator&& other) = delete;
CSimulator(const CSimulator& other) = delete;
CSimulator(CSimulator&& other) = delete;
CSimulator& operator=(const CSimulator& other) = delete;
CSimulator& operator=(CSimulator&& other) = delete;
static std::unique_ptr<ISimulatorInterface> Create( std::shared_ptr< const ISimulatorInterface::SimulatorConfig > );
//! \brief Reset the simulator.
void Reset ( ) override;
inline void Reset() override { };
//! \brief Simulate the given task.
std::unique_ptr<COutdoorSimulationResult> Compute ( std::unique_ptr<CUpdateScene> pSceneUpdate ) override;
inline std::string GetType() override
static std::string GetType()
{
return "ARTSimulator";
};
private:
//! \brief RT Eigenray-Engine instance.
static VistaVector3D OpenGLToCart(const VistaVector3D& v3In);
static VistaVector3D CartToOpenGL(const VistaVector3D& v3In);
private:
//! \brief Coordinate system used by client (e.g. VA)
CoordinateSystem m_eClientCoordinateSystem;
//! \brief ART Eigenray-Engine instance.
EigenraySearch::CEngine m_oEngine;
//! \brief Stratified atmosphere
CStratifiedAtmosphere m_oAtmosphere;
std::unique_ptr<CUpdateScene> m_pSceneUpdate;
//! \brief Current status of the simulator.
SimulatorStatus m_eStatus;
//! \brief Initialise the raven instance.
//! The simulator is idle afterwards.
void Init ( );
};
inline bool operator<(const CSimulator::SimulatorStatus& lhs, const CSimulator::SimulatorStatus& rhs)
{
return std::underlying_type_t<CSimulator::SimulatorStatus>(lhs) < std::underlying_type_t<CSimulator::SimulatorStatus>(rhs);
};
} // namespace ART
......
......@@ -14,6 +14,9 @@
#include <VistaBase/VistaVector3D.h>
#include <VistaAspects/VistaSerializable.h>
// STD
#include <string.h>
namespace ITA
{
namespace SimulationScheduler
......@@ -28,9 +31,17 @@ namespace ITA
struct ITA_SIMULATION_SCHEDULER_API COutdoorSimulationResult : public CSimulationResult
{
struct CPathProperty : public IVistaSerializable
struct ITA_SIMULATION_SCHEDULER_API CPathProperty : public IVistaSerializable
{
double dPropagationDelay;
inline CPathProperty()
{
oGeoAttenuationSpectrum.SetIdentity();
oAirAttenuationSpectrum.SetIdentity();
};
std::string sID;
double dPropagationDelay; //!< Delay in seconds
double dSpreadingLoss; //!< Wave type specific spreading loss factor
int iReflectionOrder = 0;
......
......@@ -7,8 +7,10 @@
// std includes
#include <string>
#include <memory>
#include <functional>
// simulation scheduler includes
#include <ITA/SimulationScheduler/config_interface.h>
#include <ITA/SimulationScheduler/update_scene.h>
#include <ITA/SimulationScheduler/OutdoorAcoustics/outdoor_simulation_result.h>
......@@ -26,14 +28,75 @@ namespace ITA
class ITA_SIMULATION_SCHEDULER_API ISimulatorInterface
{
public:
//! \brief Reset the simulator.
//! \brief Configuration class for a outdoor acoustics simulator.
struct ITA_SIMULATION_SCHEDULER_API SimulatorConfig : public IConfig
{
explicit SimulatorConfig();
explicit SimulatorConfig(const std::string& sType);
SimulatorConfig(const SimulatorConfig& other);
SimulatorConfig& operator=(const SimulatorConfig& other);
VistaPropertyList Store() const override;
void Load(const VistaPropertyList& oProperties) override;
const std::string& sSimulatorType;
private:
std::string m_sSimulatorType;
};
//! \brief Reset the outdoor acoustics simulator.
virtual void Reset() = 0;
//! \brief Simulate the given task.
virtual std::unique_ptr<COutdoorSimulationResult> Compute(std::unique_ptr<CUpdateScene> pSceneUpdate) = 0;
//! \brief Returns the type of the simulator
virtual std::string GetType() = 0;
//! Static methods to be implemented by derived simulators for factory purposes
//static std::unique_ptr<ISimulatorInterface> Create(const std::shared_ptr <ISimulatorInterface::SimulatorConfig>&);
//static std::string GetType();
};
///
/// \brief Factory class for outdoor acoustic simulators.
///
/// This class implements an extensible factory for outdoor acoustic simulators.
/// After a type of simulator is registered with its IWorkerInterface::createWorker, it can be created using this factory.
/// \todo Add a way to get the correct config from the type. The factory already knows of all possible workers.
///
class ITA_SIMULATION_SCHEDULER_API CSimulatorFactory
{
public:
//! \brief The function signature for a create function.
typedef std::function<std::unique_ptr<ISimulatorInterface>(const std::shared_ptr<ISimulatorInterface::SimulatorConfig>&)> CreateCallback;
//! \brief The function signature for a config create function.
typedef std::function<std::shared_ptr<ISimulatorInterface::SimulatorConfig>()> ConfigCreateCallback;
//! \brief Register a type of simulator to the factory.
static void RegisterSimulator(const std::string& type, CreateCallback createFunction, ConfigCreateCallback configCreateFunction);
//! \brief Unregister a type of simulator from the factory.
static void UnregisterSimulator(const std::string& type);
//! \brief Factory method for simulators.
//! \param pConfig the configuration for the worker.
//! \param pParent the parent scheduler.
//! \return a pointer to the created worker.
static std::unique_ptr<ISimulatorInterface> CreateSimulator(const std::shared_ptr<ISimulatorInterface::SimulatorConfig>& pConfig);
//! \brief Factory method for corresponding configs.
//! \param sType the configuration for the filter.
//! \return a pointer to the created filter config.
static std::shared_ptr<ISimulatorInterface::SimulatorConfig> CreateConfig(const std::string& sType);
private:
//! \brief Map containing all creation functions.
static std::map < std::string, std::pair<CreateCallback, ConfigCreateCallback> > m_mRegisteredSimulatorTypes;
};
} // namespace OutdoorAcoustics
......
......@@ -10,6 +10,7 @@
// simulation scheduler includes
#include <ITA/SimulationScheduler/worker_interface.h>
#include <ITA/SimulationScheduler/config_interface.h>
#include <ITA/SimulationScheduler/update_scene.h>
#include <ITA/SimulationScheduler/OutdoorAcoustics/outdoor_simulator_interface.h>
......@@ -35,7 +36,7 @@ namespace ITA
{
public:
//! \brief Configuration class for a raven thread worker.
//! \brief Configuration class for a outdoor acoustics thread worker.
struct ITA_SIMULATION_SCHEDULER_API WorkerThreadConfig : public IWorkerInterface::WorkerConfig
{
explicit WorkerThreadConfig();
......@@ -44,9 +45,7 @@ namespace ITA
VistaPropertyList Store() const override;
void Load(const VistaPropertyList& oProperties) override;
const std::string& sSimulatorType;
private:
std::string m_sSimulatorType;
std::shared_ptr<ISimulatorInterface::SimulatorConfig> pSimulatorConfig;
};
//! \brief Constructor for CWorkerThread.
......@@ -112,11 +111,11 @@ namespace ITA
* \note This function is primarily for testing.
* However, it could also be useful in the long run.
*/
//void SetSimulator ( std::unique_ptr<ISimulatorInterface> pSimulator );
void SetSimulator ( std::unique_ptr<ISimulatorInterface> pSimulator );
private:
//! \brief Pointer to simulator interface for outdoor scenarios
std::unique_ptr<ISimulatorInterface> m_oSimulator;
std::unique_ptr<ISimulatorInterface> m_pSimulator;
//! \brief If busy, this holds a pointer to the scene update to be simulated
std::unique_ptr<CUpdateScene> m_pUpdate = nullptr;
......
......@@ -30,6 +30,9 @@ namespace ITA
///
SourceReceiverPair sourceReceiverPair = SourceReceiverPair ( );
//! \brief Time stamp of the scene update that lead to this result
double dTimeStamp = -1;
///
/// \brief Serialize the object.
/// \param pSerializer the IVistaSerializer to use.
......
......@@ -20,6 +20,12 @@ namespace ITA
const C3DObject* receiver;
} SourceReceiverPair;
enum class CoordinateSystem
{
Cartesian,
OpenGL
};
namespace RoomAcoustics
{
///
......
......@@ -39,6 +39,13 @@ namespace ITA
///
CUpdateScene ( ) = default;
///
/// \brief Constructs a scene update giving a timestamp from an external clock
///
/// Source and receiver are nullptrs.
///
explicit CUpdateScene( double dTimeStamp );
///
/// \brief Copy constructor.
/// \note This also copies the timestamp to keep the creation time of the original update.
......
......@@ -2,11 +2,24 @@
#include <ITA/SimulationScheduler/OutdoorAcoustics/ART/art_simulator.h>
#include <ITA/SimulationScheduler/Profiler/profiler.h>
//#include <ITA/SimulationScheduler/Utils/utils.h>
#include <ITA/SimulationScheduler/Utils/data_type_utils.h>
#include "../../configuration_keys.h"
//#include "ITALog.h"
// ITAGeo
#include <ITAGeo/Utils/JSON/Atmosphere.h>
#include <ITAPropagationModels/Atmosphere/AirAttenuation.h>
// ITA Base
#include <ITAFileSystemUtils.h>
#include <ITAException.h>
// STD
#include <ostream>
using namespace ITAPropagationPathSim::AtmosphericRayTracing;
using namespace ITAPropagationModels::Atmosphere;
namespace ITA
{
namespace SimulationScheduler
......@@ -15,54 +28,138 @@ namespace ITA
{
namespace ART
{
//#define RAVENSIMULATOR_REQUIRE_UNINITIALISED { if( operator<(m_eStatus, SimulatorStatus::uninitialized) ) ITA_EXCEPT1( MODAL_EXCEPTION, "Uninitialized mode required for this method, use Reset() prior to this call" ); };
//#define RAVENSIMULATOR_REQUIRE_IDLE { if( operator<(m_eStatus , SimulatorStatus::idle) ) ITA_EXCEPT1( MODAL_EXCEPTION, "Idle mode required for this method, use Reset() and Init() prior to this call" ); };
//#define RAVENSIMULATOR_REQUIRE_SCENE { if( operator<(m_eStatus , SimulatorStatus::sceneLoaded) ) ITA_EXCEPT1( MODAL_EXCEPTION, "Loaded scene required for this method, use LoadScene() prior to this call" ); };
//#define RAVENSIMULATOR_REQUIRE_FILTER_ENGINE { if( operator<(m_eStatus , SimulatorStatus::filterEngineLoaded) ) ITA_EXCEPT1( MODAL_EXCEPTION, "Loaded filter engine required for this method, probably an error in LoadScene() occured" ); };
//------CONFIG------
#pragma region CONFIG
VistaPropertyList CARTSimulator::ARTSimulatorConfig::Store() const
{
auto oProperties = ISimulatorInterface::SimulatorConfig::Store();
oProperties.SetValue(CLIENT_COORDINATE_SYSTEM_KEY, AsInteger(eClientCoordinateSystem));
oProperties.SetValue(STRATIFIED_ATMOSPHERE_KEY, sJsonAtmosphere);
return oProperties;
}
void CARTSimulator::ARTSimulatorConfig::Load(const VistaPropertyList& oProperties)
{
ISimulatorInterface::SimulatorConfig::Load(oProperties);
eClientCoordinateSystem = static_cast<CoordinateSystem>(oProperties.GetValue <int>(CLIENT_COORDINATE_SYSTEM_KEY));
if (oProperties.HasProperty(STRATIFIED_ATMOSPHERE_KEY))
oProperties.GetValue(STRATIFIED_ATMOSPHERE_KEY, sJsonAtmosphere);
else
sJsonAtmosphere = "";
}
const int g_iMaxNumSources = 1;
const int g_iMaxNumReceivers = 1;
#pragma endregion
CSimulator::CSimulator ( )
: m_eStatus ( SimulatorStatus::uninitialized )
{
//m_pRavenMasterController = std::make_unique<R_MasterController> ( );
//m_pRavenMasterController->m_currentConfig_General.applicationMode = NET_MODE;
//------SIMULATOR------
#pragma region SIMULATOR
Init ( ); // Danach: IDLE
CARTSimulator::CARTSimulator(const ARTSimulatorConfig& oConfig)
{
m_eClientCoordinateSystem = oConfig.eClientCoordinateSystem;
if (oConfig.sJsonAtmosphere.empty())
std::cout << "ART Simulator: Atmosphere undefined, using default atmosphere." << std::endl;
else
{
try
{
// Assume file if contains path separator and no {
if (oConfig.sJsonAtmosphere.find(PATH_SEPARATOR) != std::string::npos && oConfig.sJsonAtmosphere.find("{") == std::string::npos)
ITAGeo::Utils::JSON::Import(m_oAtmosphere, oConfig.sJsonAtmosphere);
// Assume JSON formatted string
else
ITAGeo::Utils::JSON::Decode(m_oAtmosphere, oConfig.sJsonAtmosphere);
}
catch (const ITAException& err)
{
throw err;
}
catch ( ... )
{
ITA_EXCEPT_INVALID_PARAMETER( "ART Simulator: Unhandled error while loading atmosphere." );
}
}
m_oEngine.eigenraySettings.rayTracing.maxReflectionOrder = 1; //Always expect exactly 2 eigenrays
}
void CSimulator::Reset ( )
std::unique_ptr<ISimulatorInterface> CARTSimulator::Create( std::shared_ptr< const ISimulatorInterface::SimulatorConfig > pConfig )
{
PROFILER_EVENT_COUNT ( "Reset" );
Init ( );
}
std::shared_ptr< const ARTSimulatorConfig > pConfigGenericShared = std::dynamic_pointer_cast< const ARTSimulatorConfig >( pConfig );
if (!pConfigGenericShared)
ITA_EXCEPT_INVALID_PARAMETER("Pointer to oinvalid config given.");
const ARTSimulatorConfig& oConf( *pConfigGenericShared );
return std::make_unique<CARTSimulator>( oConf );
}
std::unique_ptr<COutdoorSimulationResult> CSimulator::Compute ( std::unique_ptr<CUpdateScene> pUpdateScene )
std::unique_ptr<COutdoorSimulationResult> CARTSimulator::Compute ( std::unique_ptr<CUpdateScene> pUpdateScene )
{
PROFILER_FUNCTION ( );
PROFILER_FUNCTION();
m_pSceneUpdate = std::move( pUpdateScene );
const SourceReceiverPair oSRPair = m_pSceneUpdate->GetSourceReceiverPair();
VistaVector3D v3SourcePos = oSRPair.source->GetPosition();
VistaVector3D v3ReceiverPos = oSRPair.receiver->GetPosition();
if (m_eClientCoordinateSystem == CoordinateSystem::OpenGL)
{
v3SourcePos = OpenGLToCart(v3SourcePos);
v3ReceiverPos = OpenGLToCart(v3ReceiverPos);
}
PROFILER_SECTION ( "Adapt Scene" );
// Simulate
PROFILER_SECTION( "Finding Eigenrays" );
std::vector< std::shared_ptr< CRay > > vpEigenrays = m_oEngine.Run( m_oAtmosphere, v3SourcePos, v3ReceiverPos );
PROFILER_END_SECTION( );
PROFILER_END_SECTION ( );
if (vpEigenrays.size() != 2)
ITA_EXCEPT_INVALID_PARAMETER( std::string( "Expected 2 eigenrays but found " + std::to_string(vpEigenrays.size()) + ".") );
// Simulate
PROFILER_SECTION("Eigenrays to OutdoorSimulationResult");
auto pResult = std::make_unique< COutdoorSimulationResult>();
pResult->sourceReceiverPair = oSRPair;
pResult->iReferenceID = m_pSceneUpdate->GetReferenceID();
pResult->dTimeStamp = m_pSceneUpdate->GetTimeStamp();
pResult->voPathProperties.resize( vpEigenrays.size() );
for (int idx = 0; idx < vpEigenrays.size(); idx++)
{
pResult->voPathProperties[idx].sID = std::to_string( idx );
pResult->voPathProperties[idx].dPropagationDelay = vpEigenrays[idx]->LastTimeStamp();
pResult->voPathProperties[idx].dSpreadingLoss = vpEigenrays[idx]->SpreadingLoss();
pResult->voPathProperties[idx].iReflectionOrder = vpEigenrays[idx]->ReflectionOrder();
pResult->voPathProperties[idx].iDiffractionOrder = 0; //No diffraction
pResult->voPathProperties[idx].oAirAttenuationSpectrum = ITAPropagationModels::Atmosphere::AirAttenuationSpectrum(*vpEigenrays[idx], m_oAtmosphere);
//pResult->voPathProperties[idx].oGeoAttenuationSpectrum = ...; //Default is identity. To be changed in future. Probably reading data from config.
pResult->voPathProperties[idx].v3SourceWaveFrontNormal = vpEigenrays[idx]->InitialDirection();
pResult->voPathProperties[idx].v3ReceiverWaveFrontNormal = vpEigenrays[idx]->LastWavefrontNormal();
if (m_eClientCoordinateSystem == CoordinateSystem::OpenGL)
{
pResult->voPathProperties[idx].v3SourceWaveFrontNormal = CartToOpenGL(pResult->voPathProperties[idx].v3SourceWaveFrontNormal);
pResult->voPathProperties[idx].v3ReceiverWaveFrontNormal = CartToOpenGL(pResult->voPathProperties[idx].v3ReceiverWaveFrontNormal);
}
}
PROFILER_END_SECTION();
return std::move(pResult);
}
void CSimulator::Init ( )
VistaVector3D CARTSimulator::OpenGLToCart(const VistaVector3D& v3In)
{
PROFILER_FUNCTION ( );
//m_oEigenrayEngine; //TODO INIT
m_eStatus = SimulatorStatus::idle;
return VistaVector3D( v3In[Vista::X], -v3In[Vista::Z], v3In[Vista::Y] );
}
VistaVector3D CARTSimulator::CartToOpenGL(const VistaVector3D& v3In)
{
return VistaVector3D( v3In[Vista::X], v3In[Vista::Z], -v3In[Vista::Y] );
}
#pragma endregion
} // namespace ART
} // namespace OutdoorAcoustics
} // namespace SimulationScheduler
......
......@@ -11,6 +11,7 @@ endif()
set( DirFiles
outdoor_simulation_result.cpp
outdoor_worker_thread.cpp
outdoor_simulator_interface.cpp
)
set( DirFiles_SourceGroup "${RelativeSourceGroup}" )
......
......@@ -12,10 +12,14 @@
using namespace ITA::SimulationScheduler;
using namespace ITA::SimulationScheduler::OutdoorAcoustics;
const int MAX_PATHID_STRING_LENGTH = 10000;
int COutdoorSimulationResult::CPathProperty::Serialize(IVistaSerializer& pSerializer) const
{
int returnVal = 0;
returnVal += pSerializer.WriteString(sID);
returnVal += pSerializer.WriteDouble(dPropagationDelay);
returnVal += pSerializer.WriteDouble(dSpreadingLoss);
returnVal += pSerializer.WriteInt32(iReflectionOrder);
......@@ -34,6 +38,8 @@ int COutdoorSimulationResult::CPathProperty::DeSerialize(IVistaDeSerializer& pDe
{
int returnVal = 0;
returnVal += pDeserializer.ReadString(sID, MAX_PATHID_STRING_LENGTH);
returnVal += pDeserializer.ReadDouble(dPropagationDelay);
returnVal += pDeserializer.ReadDouble(dSpreadingLoss);
returnVal += pDeserializer.ReadInt32(iReflectionOrder);
......@@ -65,7 +71,8 @@ int COutdoorSimulationResult::DeSerialize(IVistaDeSerializer& pDeserializer)
int iNumPaths;
returnVal += pDeserializer.ReadInt32(iNumPaths);
assert(iNumPaths >= 0, "Number of path properties must be >= 0.");
if (iNumPaths < 0)
ITA_EXCEPT_INVALID_PARAMETER("Number of path properties must be >= 0.");
voPathProperties.resize(iNumPaths);
for(CPathProperty& oPathProp : voPathProperties)
......
// Header include
#include <ITA/SimulationScheduler/OutdoorAcoustics/outdoor_simulator_interface.h>
// simulation scheduler includes
#include "../configuration_keys.h"
#ifdef WITH_ART
#include <ITA/SimulationScheduler/OutdoorAcoustics/ART/art_simulator.h>
#endif
namespace ITA
{
namespace SimulationScheduler
{
namespace OutdoorAcoustics
{
//-------CONFIG-------
//--------------------
#pragma region CONFIG
ISimulatorInterface::SimulatorConfig::SimulatorConfig() : SimulatorConfig( "Unknown" )
{
}
ISimulatorInterface::SimulatorConfig::SimulatorConfig(const std::string & sType)
: m_sSimulatorType(sType)
, sSimulatorType(m_sSimulatorType)
{}
ISimulatorInterface::SimulatorConfig::SimulatorConfig(const SimulatorConfig & other)
: SimulatorConfig(sSimulatorType)
{}
ISimulatorInterface::SimulatorConfig& ISimulatorInterface::SimulatorConfig::operator=(const SimulatorConfig& other)
{
if (this == &other)
return *this;
IConfig::operator =(other);