Mobile Station Post-processing (RunMS) in Urban Scenarios
Detailed Description
This is an example of how to carry out mobile station post-processing, with the WinProp API, in an urban scenario. The full example is distributed with the installation.#include <stdio.h> #include <string> #include <iostream> #include "outdoor_propagation_runms.h" #ifndef API_DATA_FOLDER #define API_DATA_FOLDER "../../api/winprop/data/" #endif // !API_DATA_FOLDER int main(int argc, char** argv) { int Error = 0; WinProp_ParaMain GeneralParameters; WinProp_Antenna Antenna; WinProp_Callback Callback; WinProp_ResultTrajectoryList WinPropResultTrajectories; WinProp_Propagation_Results OutputResults; // Set up input trajectory int NrWinPropTrajectories = 1; WinProp_Trajectory* WinPropTrajectories = nullptr; WinPropTrajectories = (WinProp_Trajectory*)malloc(sizeof(WinProp_Trajectory) * NrWinPropTrajectories); if (WinPropTrajectories != nullptr) { WinProp_Structure_Init_Trajectory(&WinPropTrajectories[0]); WinPropTrajectories[0].Id = 1; WinPropTrajectories[0].PointSize = 5.0; WinPropTrajectories[0].samplingResolution = 1.0; WinPropTrajectories[0].NrPoints = 9; WinPropTrajectories[0].Points = (WinProp_Trajectory_Point*)malloc(sizeof(WinProp_Trajectory_Point) * WinPropTrajectories[0].NrPoints); if (WinPropTrajectories[0].Points != nullptr) { for (int i = 0; i < WinPropTrajectories[0].NrPoints; i++) WinProp_Structure_Init_TrajectoryPoint(&WinPropTrajectories[0].Points[i]); WinPropTrajectories[0].Points[0].location.x = 476101.49; WinPropTrajectories[0].Points[0].location.y = 552413.58; WinPropTrajectories[0].Points[0].location.z = 1.5; WinPropTrajectories[0].Points[1].location.x = 476597.37; WinPropTrajectories[0].Points[1].location.y = 552604.19; WinPropTrajectories[0].Points[1].location.z = 1.5; WinPropTrajectories[0].Points[2].location.x = 476607.80; WinPropTrajectories[0].Points[2].location.y = 552620.57; WinPropTrajectories[0].Points[2].location.z = 1.5; WinPropTrajectories[0].Points[3].location.x = 476391.13; WinPropTrajectories[0].Points[3].location.y = 553024.13; WinPropTrajectories[0].Points[3].location.z = 1.5; WinPropTrajectories[0].Points[4].location.x = 476333.05; WinPropTrajectories[0].Points[4].location.y = 553030.83; WinPropTrajectories[0].Points[4].location.z = 1.5; WinPropTrajectories[0].Points[5].location.x = 476201.26; WinPropTrajectories[0].Points[5].location.y = 552888.62; WinPropTrajectories[0].Points[5].location.z = 1.5; WinPropTrajectories[0].Points[6].location.x = 475830.47; WinPropTrajectories[0].Points[6].location.y = 552670.46; WinPropTrajectories[0].Points[6].location.z = 1.5; WinPropTrajectories[0].Points[7].location.x = 475810.36; WinPropTrajectories[0].Points[7].location.y = 552624.29; WinPropTrajectories[0].Points[7].location.z = 1.5; WinPropTrajectories[0].Points[8].location.x = 476082.88; WinPropTrajectories[0].Points[8].location.y = 552423.26; WinPropTrajectories[0].Points[8].location.z = 1.5; } } // name of .odb database without extension const char* my_odb_database = API_DATA_FOLDER "outdoor/Frankfurt"; /* ------------------------ Initialisation of parameters ----------------------*/ WinProp_Structure_Init_ParameterMain(&GeneralParameters); WinProp_Structure_Init_Antenna(&Antenna); WinProp_Structure_Init_Callback(&Callback); WinProp_Structure_Init_ResultTrajectoryList(&WinPropResultTrajectories); WinProp_Structure_Init_Propagation_Results(&OutputResults); /*---------------- Definition of scenario -------------------------------------*/ /* Definition of general parameters. */ GeneralParameters.ScenarioMode = SCENARIOMODE_URBAN; // Urban prediction GeneralParameters.PredictionModelUrban = PREDMODEL_UDP; // Use Dominant Path Model /* Definition of prediction trajectory. */ GeneralParameters.UrbanLowerLeftX = 475800.0; GeneralParameters.UrbanLowerLeftY = 552400.0; GeneralParameters.UrbanUpperRightX = 476620.0; GeneralParameters.UrbanUpperRightY = 553040.0; /* Copy coordinates to prediction area of second model (not yet used) */ GeneralParameters.RuralLowerLeftX = GeneralParameters.UrbanLowerLeftX; GeneralParameters.RuralLowerLeftY = GeneralParameters.UrbanLowerLeftY; GeneralParameters.RuralUpperRightX = GeneralParameters.UrbanUpperRightX; GeneralParameters.RuralUpperRightY = GeneralParameters.UrbanUpperRightY; double PredictionHeight = 1.5; /* Size of matrix with results. */ GeneralParameters.Resolution = 5.0; // Resolution in meter GeneralParameters.NrLayers = 1; // Number of prediction heights GeneralParameters.PredictionHeights = &PredictionHeight; // Prediction height in meter /* Building vector data and topography. */ GeneralParameters.BuildingsMode = BUILDINGSMODE_BINARY; // load a .opb database (urban) sprintf(GeneralParameters.BuildingsName, "%s", my_odb_database); // Vector database in WinProp format /*--------------------------- Definition of antenna ---------------------------*/ /* Position and configuration. */ Antenna.Id = 1; Antenna.SiteId = 1; Antenna.Longitude_X = 476079.78; Antenna.Latitude_Y = 552495.05; Antenna.Height = 25.0; Antenna.Power = 40.0; // Power in dBm Antenna.Frequency = 2000.0; // Frequency in MHz char AntennaName[500]; sprintf(AntennaName, "%s", "Antenna 1"); Antenna.Name = AntennaName; /* Definition of outputs to be computed and written in WinProp format. */ GeneralParameters.OutputResults = &OutputResults; OutputResults.ResultPath = API_DATA_FOLDER "output/OutdoorRunPRO"; // Output data directory OutputResults.FieldStrength = 1; OutputResults.PathLoss = 1; OutputResults.StatusLOS = 1; OutputResults.RayFilePropPaths = 1; OutputResults.StrFilePropPaths = 1; /*-------------------------- Callbacks ----------------------------------------*/ Callback.Percentage = CallbackProgress; Callback.Message = CallbackMessage; Callback.Error = CallbackError; /*----------------------- Compute outdoor prediction --------------------------*/ Error = OutdoorPlugIn_ComputeTrajectories( &Antenna, &GeneralParameters, NULL, NULL, WinPropTrajectories, NrWinPropTrajectories, &Callback, &WinPropResultTrajectories); /*----------------------- Do something with results ---------------------------*/ if (Error == 0) { write_ascii(&WinPropResultTrajectories, API_DATA_FOLDER "output/OutdoorRunPRO.txt"); } else { /* Error during prediction. Print error message. */ CallbackError(GeneralParameters.ErrorMessageMain, Error); } /*----------------------- Rx antenna superposition (RunMS) --------------------*/ // Create project WinProp_SuperposeMS superposeMS; /* Definition of antenna pattern. */ WinProp_Pattern WinPropPattern; WinProp_Structure_Init_Pattern(&WinPropPattern); WinPropPattern.Mode = PATTERN_MODE_FILE; // Load pattern from file char PatternFileName[500]; sprintf(PatternFileName, "%s", API_DATA_FOLDER "antennas/Antenna.apb"); // Pattern file (including extension) WinPropPattern.Filename = PatternFileName; // Setup tx array WINPROP_MS_ARRAY_TYPE txArrayAPI = WINPROP_MS_ARRAY_SINGLE_ANTENNA; WINPROP_MS_POLARIZATION_TYPE pol = WINPROP_MS_POLARIZATION_VERTICAL; if (Error == 0) Error = superposeMS.setArray(false, txArrayAPI, 1, 0.f, 0.f, 0.f, 0); if (Error == 0) // Changing the azimuth from north over east in RunPRO to east over north orientation, 90deg // tilt is equal to horizontal orientation. Error = superposeMS.setArrayElement( false, 0, nullptr, nullptr, (float)(-Antenna.Azimuth + 90. + 360.), (float)(Antenna.Downtilt + 90.), pol, { 0., 0., 0. }); // Setup rx array WINPROP_MS_ARRAY_TYPE rxArrayAPI = WINPROP_MS_ARRAY_SINGLE_ANTENNA; if (Error == 0) Error = superposeMS.setArray(true, rxArrayAPI, 1 /*rxArray.nbrElements*/, 0.f /*rxArray.arrayAzimuth*/, 0.f /*rxArray.spacingHorizontal*/, 0.f /*rxArray.radius*/, false /*rxArray.antCoupling != 0*/); if (Error == 0) // azimuth with east over north orientation, in case of trajectories 0deg means 90deg right // from driving direction, using 180deg here to point the Rx antenna towards the Tx 90deg tilt // is equal to horizontal orientation. Error = superposeMS.setArrayElement( true, 0, &WinPropPattern, nullptr, 180.f/*azimuth*/, 90.f/*tilt*/, pol, { 0., 0., 0. }/*offset*/); if (Error == 0) Error = superposeMS.setPropagationTrajectories( 0, Antenna, WinPropTrajectories, NrWinPropTrajectories, WinPropResultTrajectories); // Set computation parameter WinProp_MS_Para msPara; WinProp_Structure_Init_MS_Para(&msPara); // Enable ouputs WinProp_MS_AdditionalResults msAdditionalResult; WinProp_Structure_Init_MS_AdditionalResults(&msAdditionalResult); sprintf(msAdditionalResult.outputPath, "%s%s", API_DATA_FOLDER, "output/OutdoorRunMS"); if (Error == 0) Error = superposeMS.compute(msPara, &msAdditionalResult, &Callback); /*----------------------------- Free memory -----------------------------------*/ WinProp_Structure_Free_ResultTrajectoryList(&WinPropResultTrajectories); if (WinPropTrajectories != nullptr) { if (WinPropTrajectories->Points != nullptr) free(WinPropTrajectories->Points); free(WinPropTrajectories); } return 0; } int _STD_CALL CallbackMessage(const char * Text) { if (Text == nullptr) return 0; std::cout << "\n" << Text; return(0); } int _STD_CALL CallbackError(const char * Text, int Error) { if (Text == nullptr) return 0; std::cout << "\n"; #ifdef __LINUX std::cout << "\033[31m" << "Error (" << Error << "): "; // highlight error in red color #else HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); SetConsoleTextAttribute(hConsole, FOREGROUND_RED); std::cout << "Error (" << Error << "): "; #endif // __LINUX std::cout << Text; #ifdef __LINUX std::cout << "\033[0m"; // highlight error in red color #else SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN); #endif // __LINUX return 0; } int _STD_CALL CallbackProgress(int value, const char* text) { char Line[200]; sprintf(Line, "\n%d%% %s", value, text); std::cout << Line; return(0); } void write_ascii(const WinProp_ResultTrajectoryList* Result, const char* Filename) { FILE* OutputFile = fopen(Filename, "w"); if (OutputFile) { /* Loop all pixels. */ for (int x = 0; x < Result->NrTrajectories; x++) { for (int y = 0; y < Result->trajectories[x].ResultPoints.NrResultPoints; y++) { /* Compute real coordinates. */ double Coordinate_X = Result->trajectories[x].ResultPoints.ResultPoints[y].Location.x; double Coordinate_Y = Result->trajectories[x].ResultPoints.ResultPoints[y].Location.y; double Coordinate_Z = Result->trajectories[x].ResultPoints.ResultPoints[y].Location.z; double ResultValue = Result->trajectories[x].ResultPoints.ResultPoints[y].ResultValue; /* Check if pixel was computed or not */ if (ResultValue > -1000) fprintf(OutputFile, "%.2f\t%.2f\t%.2f\t%.2f\n", Coordinate_X, Coordinate_Y, Coordinate_Z, ResultValue); } } /* Close file. */ fclose(OutputFile); } else printf("\nCould not open the File: %s for writing.\n", Filename); }