diff --git a/CMakeLists.txt b/CMakeLists.txt index 5b44a8de88987fb9de25dbafa1eb936634613b0a..f58b3197965f59f8745ef8b7c0c9a976ed4e2432 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -320,7 +320,7 @@ math/VelocityModel.cpp math/OperationalModel.cpp math/GCVMModel.cpp math/SimplestModel.cpp - +math/AGCVMModel.cpp mpi/LCGrid.cpp pedestrian/Ellipse.cpp @@ -550,7 +550,7 @@ math/VelocityModel.h math/OperationalModel.h math/GCVMModel.h math/SimplestModel.h - +math/AGCVMModel.h events/EventManager.h events/Event.h diff --git a/IO/IniFileParser.cpp b/IO/IniFileParser.cpp index 42e47576647441ac13c78ef99c501b3d6bf74616..e716bdc37977066e3f7a1655f177771487da9fb0 100644 --- a/IO/IniFileParser.cpp +++ b/IO/IniFileParser.cpp @@ -41,6 +41,7 @@ #include "../math/VelocityModel.h" #include "../math/GCVMModel.h" #include "../math/SimplestModel.h" +#include "../math/AGCVMModel.h" #include "../routing/global_shortest/GlobalRouter.h" #include "../routing/quickest/QuickestPathRouter.h" #include "../routing/smoke_router/SmokeRouter.h" @@ -557,10 +558,21 @@ bool IniFileParser::Parse(std::string iniFile) //only parsing one model break; } + if ((_model == MODEL_AGCVM) && (model_id == MODEL_AGCVM)) { + if (modelName != "agcvm") { + Log->Write("ERROR: \t mismatch model ID and description. Did you mean agcvm?"); + return false; + } + if (!ParseGCVMModel(xModel, xMainNode)) + return false; + parsingModelSuccessful = true; + //only parsing one model + break; + } } if (!parsingModelSuccessful) { - Log->Write("ERROR: \tWrong model id [%d]. Choose 1 (GCFM), 2 (Gompertz), 3 (Tordeux2015), 5 (Krausz), 6 (GCVM) or 7 (Simplest)", _model); + Log->Write("ERROR: \tWrong model id [%d]. Choose 1 (GCFM), 2 (Gompertz), 3 (Tordeux2015), 5 (Krausz), 6 (GCVM), 7 (Simplest), 8 (AGCVM)", _model); Log->Write("ERROR: \tPlease make sure that all models are specified in the operational_models section"); Log->Write("ERROR: \tand make sure to use the same ID in the agent section"); return false; @@ -1290,6 +1302,12 @@ void IniFileParser::ParseAgentParameters(TiXmlElement* operativModel, TiXmlNode* _config->SetDistEffMaxPed(max_Eb + _config->GetTs()*agentParameters->GetV0()); _config->SetDistEffMaxWall(_config->GetDistEffMaxPed()); } + + if (_model == 8) { // AGCVM + double max_Eb = 2 * agentParameters->GetBmax(); + _config->SetDistEffMaxPed(max_Eb + _config->GetTs()*agentParameters->GetV0()); + _config->SetDistEffMaxWall(_config->GetDistEffMaxPed()); + } } } } @@ -2000,7 +2018,7 @@ bool IniFileParser::ParseGCVMModel(TiXmlElement* xGCVM, TiXmlElement* xMainNode) if (xModelPara->FirstChild("GCVM")) { if (!xModelPara->FirstChildElement("GCVM")->Attribute("using")) - _config->SetGCVMUsing(0); + _config->SetGCVMUsing(1); else { string GCVMUsing = xModelPara->FirstChildElement("GCVM")->Attribute("using"); _config->SetGCVMUsing(atoi(GCVMUsing.c_str())); @@ -2177,13 +2195,145 @@ bool IniFileParser::ParseSimplestModel(TiXmlElement* xSimplest, TiXmlElement* xM Log->Write("INFO: \twaiting_time Tw=%0.2f",_config->GetWaitingTime()); } + if (xModelPara->FirstChild("clogging_area")) { + + if (!xModelPara->FirstChildElement("clogging_area")->Attribute("size")) + _config->SetAreaSize(1); // default value + else { + string AreaSize = xModelPara->FirstChildElement("clogging_area")->Attribute("size"); + _config->SetAreaSize(atof(AreaSize.c_str())); + } + Log->Write("INFO: \tclogging_area size=%0.2f", _config->GetAreaSize()); + } + //Parsing the agent parameters TiXmlNode* xAgentDistri = xMainNode->FirstChild("agents")->FirstChild("agents_distribution"); ParseAgentParameters(xSimplest, xAgentDistri); _config->SetModel(std::shared_ptr<OperationalModel>(new SimplestModel(_exit_strategy, _config->GetaPed(), _config->GetDPed(), _config->GetaWall(), - _config->GetDWall(), _config->GetTs(), _config->GetTd(), _config->GetUpdate(), _config->GetWaitingTime(), _config->GetSubmodelDirection(), _config->GetSubmodelSpeed(), _config->GetGCVMUsing()))); + _config->GetDWall(), _config->GetTs(), _config->GetTd(), _config->GetUpdate(), _config->GetWaitingTime(), _config->GetAreaSize(), _config->GetSubmodelDirection(), _config->GetSubmodelSpeed(), _config->GetGCVMUsing()))); + + return true; +} + +bool IniFileParser::ParseAGCVMModel(TiXmlElement* xGCVM, TiXmlElement* xMainNode) +{ + //parsing the model parameters + Log->Write("\nINFO:\tUsing AGCVM model"); + Log->Write("INFO:\tParsing the model parameters"); + + TiXmlNode* xModelPara = xGCVM->FirstChild("model_parameters"); + + if (!xModelPara) { + Log->Write("ERROR: \t !!!! Changes in the operational model section !!!"); + Log->Write("ERROR: \t !!!! The new version is in inputfiles/ship_msw/ini_ship3.xml !!!"); + return false; + } + + // For convenience. This moved to the header as it is not model specific + if (xModelPara->FirstChild("tmax")) { + Log->Write("ERROR: \tthe maximal simulation time section moved to the header!!!"); + Log->Write("ERROR: \t\t <max_sim_time> </max_sim_time>\n"); + return false; + } + + //solver + if (!ParseNodeToSolver(*xModelPara)) + return false; + + //stepsize + if (!ParseStepSize(*xModelPara)) + return false; + + //exit crossing strategy + if (!ParseStrategyNodeToObject(*xModelPara)) + return false; + + //linked-cells + if (!ParseLinkedCells(*xModelPara)) + return false; + + //periodic + if (!ParsePeriodic(*xModelPara)) + return false; + + //force_ped + if (xModelPara->FirstChild("force_ped")) { + + if (!xModelPara->FirstChildElement("force_ped")->Attribute("a")) + _config->SetaPed(3.0); // default value + else { + string a = xModelPara->FirstChildElement("force_ped")->Attribute("a"); + _config->SetaPed(atof(a.c_str())); + } + + if (!xModelPara->FirstChildElement("force_ped")->Attribute("D")) + _config->SetDPed(0.1); // default value in [m] + else { + string D = xModelPara->FirstChildElement("force_ped")->Attribute("D"); + _config->SetDPed(atof(D.c_str())); + } + Log->Write("INFO: \tfrep_ped a=%0.2f, D=%0.2f", _config->GetaPed(), _config->GetDPed()); + + } + //force_wall + if (xModelPara->FirstChild("force_wall")) { + + if (!xModelPara->FirstChildElement("force_wall")->Attribute("a")) + _config->SetaWall(6.0); // default value + else { + string a = xModelPara->FirstChildElement("force_wall")->Attribute("a"); + _config->SetaWall(atof(a.c_str())); + } + + if (!xModelPara->FirstChildElement("force_wall")->Attribute("D")) + _config->SetDWall(0.05); // default value in [m] + else { + string D = xModelPara->FirstChildElement("force_wall")->Attribute("D"); + _config->SetDWall(atof(D.c_str())); + } + Log->Write("INFO: \tfrep_wall a=%0.2f, D=%0.2f", _config->GetaWall(), _config->GetDWall()); + } + + //time parameters + if (xModelPara->FirstChild("time_parameters")) { + + if (!xModelPara->FirstChildElement("time_parameters")->Attribute("Ts")) + _config->SetTs(0.5); // default value + else { + string Ts = xModelPara->FirstChildElement("time_parameters")->Attribute("Ts"); + _config->SetTs(atof(Ts.c_str())); + } + + if (!xModelPara->FirstChildElement("time_parameters")->Attribute("Td")) + _config->SetTd(0.3); // default value in [m] + else { + string Td = xModelPara->FirstChildElement("time_parameters")->Attribute("Td"); + _config->SetTd(atof(Td.c_str())); + } + Log->Write("INFO: \ttime_parameters Ts=%0.2f, Td=%0.2f", _config->GetTs(), _config->GetTd()); + + if (xModelPara->FirstChild("GCVM")) { + if (!xModelPara->FirstChildElement("GCVM")->Attribute("using")) + _config->SetGCVMUsing(1); + else { + string GCVMUsing = xModelPara->FirstChildElement("GCVM")->Attribute("using"); + _config->SetGCVMUsing(atoi(GCVMUsing.c_str())); + } + _config->GetGCVMUsing() == 1 ? + Log->Write("INFO:\tUsing GCVM model") : + Log->Write("INFO:\tUsing CVM model"); + } + + + } + //Parsing the agent parameters + TiXmlNode* xAgentDistri = xMainNode->FirstChild("agents")->FirstChild("agents_distribution"); + ParseAgentParameters(xGCVM, xAgentDistri); + _config->SetModel(std::shared_ptr<OperationalModel>(new GCVMModel(_exit_strategy, _config->GetaPed(), + _config->GetDPed(), _config->GetaWall(), + _config->GetDWall(), _config->GetTs(), _config->GetTd(), _config->GetGCVMUsing()))); return true; } \ No newline at end of file diff --git a/IO/IniFileParser.h b/IO/IniFileParser.h index 98216579f462d0ca9e18f9c471ec2693b5bb6068..0a81d9c007d28076f880839fd6fa0a16696be532 100644 --- a/IO/IniFileParser.h +++ b/IO/IniFileParser.h @@ -65,6 +65,8 @@ private: bool ParseGCVMModel(TiXmlElement* xGCVM, TiXmlElement* xMain); bool ParseSimplestModel(TiXmlElement* xSimplest, TiXmlElement* xMain); + + bool ParseAGCVMModel(TiXmlElement* xGCVM, TiXmlElement* xMain); #ifdef AIROUTER bool ParseAIOpts(TiXmlNode* routingNode); #endif diff --git a/Simulation.cpp b/Simulation.cpp index bd9e48bd0d21dc9cfefc9e787da5d0a35a05bba1..7e60e48ab33a431de31ec8e914107f467aa4d099 100644 --- a/Simulation.cpp +++ b/Simulation.cpp @@ -36,6 +36,7 @@ #include "math/GradientModel.h" #include "math/GCVMModel.h" #include "math/SimplestModel.h" +#include "math/AGCVMModel.h" #include "pedestrian/AgentsQueue.h" #include "pedestrian/AgentsSourcesManager.h" #include "geometry/WaitingArea.h" diff --git a/general/Configuration.h b/general/Configuration.h index d11bc5d89f1753436a4006796e76737214cb0fa2..e3965ec1ce747e417888b3b1078a3c7ca3e507d3 100644 --- a/general/Configuration.h +++ b/general/Configuration.h @@ -104,6 +104,7 @@ public: _SubmodelDirection = 0; _SubmodelSpeed = 0; _GCVMUsing = 0; + _AreaSize = 1; // ---------------- _hostname = "localhost"; @@ -381,7 +382,11 @@ public: void SetGCVMUsing(int gu) { _GCVMUsing=gu; }; - int GetGCVMUsing() const { return _GCVMUsing; } + int GetGCVMUsing() const { return _GCVMUsing; }; + + void SetAreaSize(double as) { _AreaSize = as; }; + + double GetAreaSize() const { return _AreaSize; }; #ifdef _JPS_AS_A_SERVICE @@ -456,6 +461,7 @@ private: int _SubmodelDirection; int _SubmodelSpeed; int _GCVMUsing; + double _AreaSize; //ff router quickest double _recalc_interval; diff --git a/general/Macros.h b/general/Macros.h index b080cda5c401135634153782a13c40a224914de5..0e57067e15da5916d439688b99b6e25ffad536ef 100644 --- a/general/Macros.h +++ b/general/Macros.h @@ -144,7 +144,8 @@ enum OperativModels { MODEL_GRADIENT, MODEL_KRAUSZ, MODEL_GCVM, - MODEL_SIMPLEST + MODEL_SIMPLEST, + MODEL_AGCVM // MODEL_ORCA, // MODEL_CFM, // MODEL_GNM diff --git a/math/AGCVMModel.cpp b/math/AGCVMModel.cpp new file mode 100644 index 0000000000000000000000000000000000000000..1622874d8e0a3f01b585b93d3955a973c014f114 --- /dev/null +++ b/math/AGCVMModel.cpp @@ -0,0 +1,902 @@ +/** +* \file AGCVM.cpp +* \date Jun 26, 2019 +* \version v0.8 +* \copyright <2009-2015> Forschungszentrum Jülich GmbH. All rights reserved. +* +* \section License +* This file is part of JuPedSim. +* +* JuPedSim is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* any later version. +* +* JuPedSim is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. +* +* \section Description +* Implementation of first-order model +* Anticipation generalized collision-free velocity model: Qiancheng (8) +* +* +**/ + +# define NOMINMAX +#include "../pedestrian/Pedestrian.h" +//#include "../routing/DirectionStrategy.h" +#include "../mpi/LCGrid.h" +#include "../geometry/Wall.h" +#include "../geometry/SubRoom.h" + + +#include "AGCVMModel.h" +#ifdef _OPENMP +#include <omp.h> +#else +#define omp_get_thread_num() 0 +#define omp_get_max_threads() 1 +#endif + +double xRight_agcvm = 26.0; +double xLeft_agcvm = 0.0; +double cutoff_agcvm = 2.0; + +//------------------------------- + +using std::vector; +using std::string; + +AGCVMModel::AGCVMModel(std::shared_ptr<DirectionStrategy> dir, double aped, double Dped, + double awall, double Dwall, double Ts, double Td, int GCVM) +{ + _direction = dir; + // Force_rep_PED Parameter + _aPed = aped; + _DPed = Dped; + // Force_rep_WALL Parameter + _aWall = awall; + _DWall = Dwall; + // GCVM Parameter + _Ts = Ts; // Speed module + _Td = Td; // Direction module + _GCVMUsing = GCVM; // If using GCVM +} + + +AGCVMModel::~AGCVMModel() +{ + +} + +bool AGCVMModel::Init(Building* building) +{ + + if (auto dirff = dynamic_cast<DirectionFloorfield*>(_direction.get())) { + Log->Write("INFO:\t Init DirectionFloorfield starting ..."); + double _deltaH = building->GetConfig()->get_deltaH(); + double _wallAvoidDistance = building->GetConfig()->get_wall_avoid_distance(); + bool _useWallAvoidance = building->GetConfig()->get_use_wall_avoidance(); + dirff->Init(building, _deltaH, _wallAvoidDistance, _useWallAvoidance); + Log->Write("INFO:\t Init DirectionFloorfield done"); + } + + if (auto dirlocff = dynamic_cast<DirectionLocalFloorfield*>(_direction.get())) { + Log->Write("INFO:\t Init DirectionLOCALFloorfield starting ..."); + double _deltaH = building->GetConfig()->get_deltaH(); + double _wallAvoidDistance = building->GetConfig()->get_wall_avoid_distance(); + bool _useWallAvoidance = building->GetConfig()->get_use_wall_avoidance(); + dirlocff->Init(building, _deltaH, _wallAvoidDistance, _useWallAvoidance); + Log->Write("INFO:\t Init DirectionLOCALFloorfield done"); + } + + if (auto dirsublocff = dynamic_cast<DirectionSubLocalFloorfield*>(_direction.get())) { + Log->Write("INFO:\t Init DirectionSubLOCALFloorfield starting ..."); + double _deltaH = building->GetConfig()->get_deltaH(); + double _wallAvoidDistance = building->GetConfig()->get_wall_avoid_distance(); + bool _useWallAvoidance = building->GetConfig()->get_use_wall_avoidance(); + dirsublocff->Init(building, _deltaH, _wallAvoidDistance, _useWallAvoidance); + Log->Write("INFO:\t Init DirectionSubLOCALFloorfield done"); + } + + const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); + size_t peds_size = allPeds.size(); + for (unsigned int p = 0; p < peds_size; p++) + { + Pedestrian* ped = allPeds[p]; + double cosPhi, sinPhi; + //a destination could not be found for that pedestrian + if (ped->FindRoute() == -1) { + Log->Write( + "ERROR:\tGCVMModel::Init() cannot initialise route. ped %d is deleted in Room %d %d.\n", ped->GetID(), ped->GetRoomID(), ped->GetSubRoomID()); + building->DeletePedestrian(ped); + p--; + peds_size--; + continue; + } + + + + + Point target = ped->GetExitLine()->ShortestPoint(ped->GetPos()); + Point d = target - ped->GetPos(); + double dist = d.Norm(); + if (dist != 0.0) { + cosPhi = d._x / dist; + sinPhi = d._y / dist; + } + else { + Log->Write( + "ERROR: \tallPeds::Init() cannot initialise phi! " + "dist to target is 0\n"); + return false; + } + + ped->InitV0(target); + + JEllipse E = ped->GetEllipse(); + E.SetCosPhi(cosPhi); + E.SetSinPhi(sinPhi); + ped->SetEllipse(E); + } + return true; +} + +void AGCVMModel::ComputeNextTimeStep(double current, double deltaT, Building* building, int periodic) +{ + // collect all pedestrians in the simulation. + const vector< Pedestrian* >& allPeds = building->GetAllPedestrians(); + vector<Pedestrian*> pedsToRemove; + pedsToRemove.reserve(500); + unsigned long nSize; + nSize = allPeds.size(); + int nThreads = omp_get_max_threads(); + nThreads = 1; //debug only, I have to use other pedestrian's information + int partSize; + partSize = ((int)nSize > nThreads) ? (int)(nSize / nThreads) : (int)nSize; + if (partSize == (int)nSize) + nThreads = 1; // not worthy to parallelize + +#pragma omp parallel default(shared) num_threads(nThreads) + { + vector< Point > result_acc = vector<Point >(); + result_acc.reserve(nSize); + vector< Point > result_dir = vector<Point >(); + result_dir.reserve(nSize); + vector< my_pair > spacings = vector<my_pair >(); + spacings.reserve(nSize); // larger than needed + const int threadID = omp_get_thread_num(); + + int start = threadID * partSize; + int end; + end = (threadID < nThreads - 1) ? (threadID + 1) * partSize - 1 : (int)(nSize - 1); + for (int p = start; p <= end; ++p) { + Pedestrian* ped = allPeds[p]; + Room* room = building->GetRoom(ped->GetRoomID()); + SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID()); + Point repPed = Point(0, 0); + vector<Pedestrian*> neighbours; + building->GetGrid()->GetNeighbourhood(ped, neighbours); + Point inid_direction = e0(ped, room); + + //using a new method calculate the influence of pedestrian (the value of influence id decided by distance and the direction is vertical with desired direction) + Point inf_direction;// left side of pedestrian + inf_direction._x = -inid_direction._y; + inf_direction._y = inid_direction._x; + inf_direction = inf_direction.Normalized(); + //-------------------------------------------------------------------------------------------------------------------------------------------------------------- + + int size = (int)neighbours.size(); + for (int i = 0; i < size; i++) + { + Pedestrian* ped1 = neighbours[i]; + //if they are in the same subroom + Point p1 = ped->GetPos(); + Point p2 = ped1->GetPos(); + Point ep12 = p2 - p1; + + //Deciding the influence direction-------------------------------------------------------------------- + double result1 = inid_direction.CrossProduct(ep12); + Point zero = Point(0, 0); + if (bool equal = almostEqual(result1, 0, 0.00001))//if neighbour is in front or behind pedestrian + { + int random = rand() % 1000;//choose one direciton bu random + if (random < 500)//when random is larger than 50, influence's direction is right, otherwise is left + { + inf_direction = zero - inf_direction; + } + } + else + { + double result2 = inid_direction.CrossProduct(inf_direction); + if (result1*result2 > 0)//is ep12 and inf_direction in the same side of inid_direction, change the direction of inf_direction + { + inf_direction = zero - inf_direction; + } + } + + //subrooms to consider when looking for neighbour for the 3d visibility + vector<SubRoom*> emptyVector; + emptyVector.push_back(subroom); + emptyVector.push_back(building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID())); + bool isVisible = building->IsVisible(p1, p2, emptyVector, false); + if (!isVisible) + { + continue; + } + if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) { + if (GetGCVMU() == 1) + { + repPed += inf_direction * ForceRepPed(ped, ped1, inid_direction, periodic).Norm();//new method + } + else + { + repPed += ForceRepPed(ped, ped1, inid_direction, periodic);//original method + } + } + else { + // or in neighbour subrooms + SubRoom* sb2 = building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID()); + if (subroom->IsDirectlyConnectedWith(sb2)) { + if (GetGCVMU() == 1) + { + repPed += inf_direction * ForceRepPed(ped, ped1, inid_direction, periodic).Norm();//new method + } + else + { + repPed += ForceRepPed(ped, ped1, inid_direction, periodic);//original method + } + } + } + } //for i + + // Calculating influence of walls------------------------------------------------------------------------- + Point repWall = ForceRepRoom(allPeds[p], subroom, inid_direction); + + //Caluculating desired direcition---------------------------------------------------------------------------------------------- + Point d_direction; + d_direction = inid_direction + repPed + repWall;//new method + + //Calculating the actual direction of pedestrian at next timestep------------------------------------------------------------------ + Point a_direction; + a_direction._x = ped->GetEllipse().GetCosPhi(); + a_direction._y = ped->GetEllipse().GetSinPhi(); + double angle_tau = _Td; + + //case 1 (vector) + Point angle_v = (d_direction.Normalized()-a_direction)/ angle_tau; + Point direction = a_direction + angle_v * deltaT; + + //When the angle between desired mocing direction and actual direction is bigger than 90 degree. turning to the desired moving direction directly. + if (d_direction.ScalarProduct(a_direction) < 0) { + direction = d_direction; + } + + if (GetGCVMU() == 0) { + direction = d_direction;//original method + } + result_dir.push_back(direction); + //------------------------------------------------------------------------------------------------------------------------------------ + + + //Calculating spacing in front ------------------------------------------------------------------------------------------------------- + for (int i = 0; i < size; i++) { + Pedestrian* ped1 = neighbours[i]; + // calculate spacing + if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) { + spacings.push_back(GetSpacing(ped, ped1, direction, periodic)); + } + else { + // or in neighbour subrooms + SubRoom* sb2 = building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID()); + if (subroom->IsDirectlyConnectedWith(sb2)) { + spacings.push_back(GetSpacing(ped, ped1, direction, periodic)); + } + } + }//for i + //------------------------------------------------------------------------------------------------------------------------------------ + + // Calculate min spacing, and save all spacing=0 to vector relation-------------------------------------------------------------------- + std::sort(spacings.begin(), spacings.end(), sort_pred_agcvm()); + double spacing = spacings.size() == 0 ? 100 : spacings[0].first; + double first_ID = spacings.size() == 0 ? -1 : spacings[0].second; + double sec_spacing = spacings.size() <= 1 ? 100 : spacings[1].first; + + // add this part to avoid pedestrian cross the wall directly + spacing = spacing > GetSpacingRoom(ped, subroom, direction) ? GetSpacingRoom(ped, subroom, direction) : spacing; + Point speed; + speed = direction.NormalizedMolified() *OptimalSpeed(ped, spacing); + result_acc.push_back(speed); + spacings.clear(); //clear for ped p + //----------------------------------------------------------------------------------------------------------------------------------------- + } // for p + + +#pragma omp barrier + // update + for (int p = start; p <= end; ++p) { + Pedestrian* ped = allPeds[p]; + + Point v_neu = result_acc[p - start]; + Point dir_neu = result_dir[p - start]; + Point pos_neu = ped->GetPos() + v_neu * deltaT; + //Jam is based on the current velocity + if (v_neu.Norm() >= ped->GetV0Norm()*0.5) { + ped->ResetTimeInJam(); + } + else { + ped->UpdateTimeInJam(); + } + //calculate ellipse orientation + double normdir = dir_neu.Norm(); + double cosPhi = dir_neu._x / normdir; + double sinPhi = dir_neu._y / normdir; + JEllipse e = ped->GetEllipse(); + e.SetCosPhi(cosPhi); + e.SetSinPhi(sinPhi); + ped->SetEllipse(e); + + ped->SetV(v_neu); + if (periodic) { + if ((ped->GetPos()._x < xRight_agcvm)&&(pos_neu._x>=xRight_agcvm)) { + ped->SetPos(Point(pos_neu._x - (xRight_agcvm - xLeft_agcvm), pos_neu._y)); + } + else if ((ped->GetPos()._x > xLeft_agcvm) && (pos_neu._x <= xLeft_agcvm)) { + ped->SetPos(Point(pos_neu._x + (xRight_agcvm - xLeft_agcvm), pos_neu._y)); + } + else { + ped->SetPos(pos_neu); + } + } + else { + ped->SetPos(pos_neu); + } + } + }//end parallel + + // remove the pedestrians that have left the building + for (unsigned int p = 0; p<pedsToRemove.size(); p++) { + building->DeletePedestrian(pedsToRemove[p]); + } + pedsToRemove.clear(); +} + +Point AGCVMModel::e0(Pedestrian* ped, Room* room) const +{ + const Point target = _direction->GetTarget(room, ped); // target is where the ped wants to be after the next timestep + Point desired_direction; + const Point pos = ped->GetPos(); + double dist = ped->GetExitLine()->DistTo(pos); + // check if the molified version works + Point lastE0 = ped->GetLastE0(); + ped->SetLastE0(target - pos); + + if ((dynamic_cast<DirectionFloorfield*>(_direction.get())) || + (dynamic_cast<DirectionLocalFloorfield*>(_direction.get())) || + (dynamic_cast<DirectionSubLocalFloorfield*>(_direction.get()))) { + if (dist > 50 * J_EPS_GOAL) { + desired_direction = target - pos; //ped->GetV0(target); + } + else { + desired_direction = lastE0; + ped->SetLastE0(lastE0); //keep old vector (revert set operation done 9 lines above) + } + } + else if (dist > J_EPS_GOAL) { + desired_direction = ped->GetV0(target); + } + else { + ped->SetSmoothTurning(); + desired_direction = ped->GetV0(); + } + //test result + //fprintf(stderr,"\n %d %f %f %f %f",ped->GetID(),ped->GetPos()._x,ped->GetPos()._y,target._x,target._y); + //test result + return desired_direction; +} + + +double AGCVMModel::OptimalSpeed(Pedestrian* ped, double spacing) const +{ + double v0 = ped->GetV0Norm(); + double T = _Ts; + double speed = (spacing) / T; + speed = (speed>0) ? speed : 0; + speed = (speed<v0) ? speed : v0; + return speed; +} + +// return spacing and id of the nearest pedestrian +my_pair AGCVMModel::GetSpacing(Pedestrian* ped1, Pedestrian* ped2, Point ei, int periodic) const +{ + double x1 = ped1->GetPos()._x; + double x2_real = ped2->GetPos()._x; + double y2 = ped2->GetPos()._y; + Point ped2_current = ped2->GetPos(); + + if (periodic) { + if ((xRight_agcvm - x1) + (x2_real - xLeft_agcvm) <= cutoff_agcvm) { + double x2_periodic = x2_real + xRight_agcvm - xLeft_agcvm; + ped2->SetPos(Point(x2_periodic, y2)); + } + if ((x1 - xLeft_agcvm) + (xRight_agcvm - x2_real) <= cutoff_agcvm) { + double x2_periodic = xLeft_agcvm - xRight_agcvm + x2_real; + ped2->SetPos(Point(x2_periodic, y2)); + } + } + + Point distp12 = ped2->GetPos() - ped1->GetPos(); // inversed sign + double Distance = distp12.Norm(); + Point ep12; + if (Distance >= J_EPS) { + ep12 = distp12.Normalized(); + } + else { + //printf("ERROR: \tin VelocityModel::forcePedPed() ep12 can not be calculated!!!\n"); + Log->Write("WARNING: \tin VelocityModel::GetSPacing() ep12 can not be calculated!!!\n"); + Log->Write("\t\t Pedestrians are too near to each other (%f).", Distance); + exit(EXIT_FAILURE); + } + //calculate effective distance + JEllipse eped1 = ped1->GetEllipse(); + JEllipse eped2 = ped2->GetEllipse(); + double dist; + double eff_dist = eped1.EffectiveDistanceToEllipse(eped2, &dist); + + double condition1 = ei.ScalarProduct(ep12); // < e_i , e_ij > should be positive + if (condition1 < 0) { + ped2->SetPos(ped2_current); + return my_pair(FLT_MAX, -1); + } + //When condition1==0,should no influence on velocity + bool parallel = almostEqual(condition1, 0.0, J_EPS); + if (parallel) + { + ped2->SetPos(ped2_current); + return my_pair(FLT_MAX, -1); + } + //Judge conllision + //Obtain parameters + double a1 = ped1->GetLargerAxis(); + Point v = ped1->GetV(); + double b1 = ped1->GetSmallerAxis(); + + //Avoid block B(drill,small tricks)----------------------------------------------------- + /* + if (fabs(v._x) < J_EPS && fabs(v._y) < J_EPS) // v==0 + { + const Point& pos = ped1->GetPos(); + double distGoal = ped1->GetExitLine()->DistToSquare(pos); + if (distGoal < 0.2) + { + b1 = 0.1; + b1 = ped1->GetEllipse().GetBmin(); + } + } + */ + //----------------------------------------------------------------------------------- + + double a2 = ped2->GetLargerAxis(); + double b2 = ped2->GetSmallerAxis(); + double x2 = ped2->GetPos()._x; + double y1 = ped1->GetPos()._y; + double cosphi1 = ei.Normalized()._x; + double sinphi1 = ei.Normalized()._y; + double cosphi2 = ped2->GetEllipse().GetCosPhi(); + double sinphi2 = ped2->GetEllipse().GetSinPhi(); + //Judge the position of the center of ped2 + double d1 = -sinphi1 * (x2 - x1) + cosphi1 * (y2 - y1) + b1; + double d2 = -sinphi1 * (x2 - x1) + cosphi1 * (y2 - y1) - b1; + if (d1*d2 <= 0) { + //if the center between two lines, collision + ped2->SetPos(ped2_current); + return my_pair(eff_dist, ped2->GetID()); + } + //If the center not between two lines, Judge if ped2 contact with two lines + Point D; + D._x = cosphi1; + D._y = sinphi1; + Point De; + De._x = cosphi1 * cosphi2 + sinphi1 * sinphi2; + De._y = sinphi1 * cosphi2 - sinphi2 * cosphi1; + Point Ne; + Ne._x = -De._y; + Ne._y = De._x; + Point A1; + A1._x = x1 + b1 * sinphi1; + A1._y = y1 - b1 * cosphi1; + Point A2; + A2._x = x1 - b1 * sinphi1; + A2._y = y1 + b1 * cosphi1; + //Transfer A1 and A2 to ped2 coordinate + //Point A1e = ((A1._x - x2)*cosphi2 + (A1._y - y2)*sinphi2, (A1._y - y2)*cosphi2 - (A1._x - x2)*sinphi2); + Point A1e = A1.TransformToEllipseCoordinates(ped2->GetPos(), cosphi2, sinphi2); + //Point A2e = ((A2._x - x2)*cosphi2 + (A2._y - y2)*sinphi2, (A2._y - y2)*cosphi2 - (A2._x - x2)*sinphi2); + Point A2e = A2.TransformToEllipseCoordinates(ped2->GetPos(), cosphi2, sinphi2); + // Judge if the direction of De is right (ellipse2 coordinate) + double J1 = Ne.ScalarProduct(A1e); + double J2 = Ne.ScalarProduct(A2e); + Point De1 = (J1 >= 0) ? De * (-1, -1) : De; + Point De2 = (J2 >= 0) ? De * (-1, -1) : De; + //Calculate point R (ellipse2 coordinate) + Point Ne1; + Ne1._x = -De1._y; + Ne1._y = De1._x; + Point Ne2; + Ne2._x = -De2._y; + Ne2._y = De2._x; + Point Te1; + Te1._x = De1._y / b2; + Te1._y = -De1._x / a2; + Point Te2; + Te2._x = De2._y / b2; + Te2._y = -De2._x / a2; + Point Te1n = Te1.Normalized(); + Point Te2n = Te2.Normalized(); + Point Re1; + Re1._x = a2 * Te1n._x; + Re1._y = b2 * Te1n._y; + Point Re2; + Re2._x = a2 * Te2n._x; + Re2._y = b2 * Te2n._y; + //Transfer R to global coordinate + /* + Point R1 = (Re1._x*cosphi2 - Re1._y*sinphi2 + x2, Re1._y*cosphi2 + Re1._x*sinphi2 + y2); + Point R1 = Re1.TransformToCartesianCoordinates(ped2->GetPos(), cosphi2, sinphi2); + Point R2 = (Re2._x*cosphi2 - Re2._y*sinphi2 + x2, Re2._y*cosphi2 + Re2._x*sinphi2 + y2); + Point R2 = Re2.TransformToCartesianCoordinates(ped2->GetPos(), cosphi2, sinphi2); + */ + //Calculate distance between point R and line + double Dis1 = Ne1.ScalarProduct(Re1) - Ne1.ScalarProduct(A1e); + double Dis2 = Ne2.ScalarProduct(Re2) - Ne2.ScalarProduct(A2e); + + //Judge if the line contact with ellipse2 + ped2->SetPos(ped2_current); + if (Dis1 >= 0 && Dis2 >= 0) + return my_pair(FLT_MAX, -1); + else + { + return my_pair(eff_dist, ped2->GetID()); + } +} +Point AGCVMModel::ForceRepPed(Pedestrian* ped1, Pedestrian* ped2, Point e0, int periodic) const +{ + Point F_rep(0.0, 0.0); + // x- and y-coordinate of the distance between p1 and p2 + + double x_j = ped2->GetPos()._x; + double y_j = ped2->GetPos()._y; + + if (periodic) { + double x = ped1->GetPos()._x; + if ((xRight_agcvm - x) + (x_j - xLeft_agcvm) <= cutoff_agcvm) { + double x2_periodic = x_j + xRight_agcvm - xLeft_agcvm; + ped2->SetPos(Point(x2_periodic, y_j)); + } + if ((x - xLeft_agcvm) + (xRight_agcvm - x_j) <= cutoff_agcvm) { + double x2_periodic = xLeft_agcvm - xRight_agcvm + x_j; + ped2->SetPos(Point(x2_periodic, y_j)); + } + } + + Point distp12 = ped2->GetPos() - ped1->GetPos(); + double Distance = distp12.Norm(); + Point ep12; // x- and y-coordinate of the normalized vector between p1 and p2 + double R_ij; + + if (Distance >= J_EPS) { + ep12 = distp12.Normalized(); + } + else { + //printf("ERROR: \tin VelocityModel::forcePedPed() ep12 can not be calculated!!!\n"); + Log->Write(KRED "\nWARNING: \tin VelocityModel::forcePedPed() ep12 can not be calculated!!!" RESET); + Log->Write("\t\t Pedestrians are too near to each other (dist=%f).", Distance); + Log->Write("\t\t Maybe the value of <a> in force_ped should be increased. Going to exit.\n"); + printf("ped1 %d ped2 %d\n", ped1->GetID(), ped2->GetID()); + printf("ped1 at (%f, %f), ped2 at (%f, %f)\n", ped1->GetPos()._x, ped1->GetPos()._y, ped2->GetPos()._x, ped2->GetPos()._y); + exit(EXIT_FAILURE); + } + Point ei; + JEllipse Eped1 = ped1->GetEllipse(); + ei._x = Eped1.GetCosPhi(); + ei._y = Eped1.GetSinPhi(); + + //Version area----------------------------------- + double condition1 = e0.ScalarProduct(ep12); // < e_i , e_ij > should be positive + double condition2 = ei.ScalarProduct(ep12); + if (GetGCVMU() == 0)//all + { + condition1 = 1; + condition2 = 1; + } + //----------------------------------------------- + + //rule:pedestrian's direction only influenced by pedestrian in version area + if (condition1 > 0 || condition2 > 0) + { + double dist; + JEllipse Eped2 = ped2->GetEllipse(); + dist = Eped1.EffectiveDistanceToEllipse(Eped2, &dist); + dist = dist > 0 ? dist : 0; + R_ij = -_aPed * exp((-dist) / _DPed); + F_rep = ep12 * R_ij; + } + ped2->SetPos(Point(x_j, y_j)); + return F_rep; +}//END Velocity:ForceRepPed() + +Point AGCVMModel::ForceRepRoom(Pedestrian* ped, SubRoom* subroom, Point e0) const +{ + Point f(0., 0.); + const Point& centroid = subroom->GetCentroid(); + bool inside = subroom->IsInSubRoom(centroid); + //first the walls + for (const auto & wall : subroom->GetAllWalls()) + { + f += ForceRepWall(ped, wall, centroid, inside, e0); + } + + //then the obstacles + for (const auto & obst : subroom->GetAllObstacles()) + { + if (obst->Contains(ped->GetPos())) + { + Log->Write("ERROR:\t Agent [%d] is trapped in obstacle in room/subroom [%d/%d]", ped->GetID(), subroom->GetRoomID(), subroom->GetSubRoomID()); + exit(EXIT_FAILURE); + } + else + for (const auto & wall : obst->GetAllWalls()) + { + f += ForceRepWall(ped, wall, centroid, inside, e0); + } + } + + // and finally the closed doors + for (const auto & goal : subroom->GetAllTransitions()) + { + if (!goal->IsOpen()) + { + f += ForceRepWall(ped, *(static_cast<Line*>(goal)), centroid, inside, e0); + } + int uid1 = goal->GetUniqueID(); + int uid2 = ped->GetExitIndex(); + // ignore my transition consider closed doors + //closed doors are considered as wall + //door is open, but it's not my door (has influence) + /* + if((uid1 != uid2) && (goal->IsOpen()==true )) + { + f += ForceRepWall(ped,*(static_cast<Line*>(goal)), centroid, inside, e0, pdesire); + } + */ + } + return f; +} + +Point AGCVMModel::ForceRepWall(Pedestrian* ped, const Line& w, const Point& centroid, bool inside, Point e0) const +{ + Point F_wrep = Point(0.0, 0.0); + Point pt = w.ShortestPoint(ped->GetPos()); + Point dist = pt - ped->GetPos(); // x- and y-coordinate of the distance between ped and p + const double EPS = 0.000; // molified see Koester2013 + double Distance = dist.Norm() + EPS; // distance between the centre of ped and point p + //double vn = w.NormalComp(ped->GetV()); //normal component of the velocity on the wall + Point e_iw; // x- and y-coordinate of the normalized vector between ped and pt + //double K_iw; + double R_iw; + double min_distance_to_wall = 0.001; // 10 cm + if (Distance > min_distance_to_wall) { + e_iw = dist / Distance; + } + else { + Log->Write("WARNING:\t Velocity: forceRepWall() ped %d [%f, %f] is too near to the wall [%f, %f]-[%f, %f] (dist=%f)", ped->GetID(), ped->GetPos()._y, ped->GetPos()._y, w.GetPoint1()._x, w.GetPoint1()._y, w.GetPoint2()._x, w.GetPoint2()._y, Distance); + Point new_dist = centroid - ped->GetPos(); + new_dist = new_dist / new_dist.Norm(); + //printf("new distance = (%f, %f) inside=%d\n", new_dist._x, new_dist._y, inside); + e_iw = (inside ? new_dist * -1 : new_dist); + } + + //rules-------------------------------------- + + //rule: wall in behind has no influence + Point pt1 = w.GetPoint1(); + Point pt2 = w.GetPoint2(); + Point dist_pt1 = pt1 - ped->GetPos(); + Point dist_pt2 = pt2 - ped->GetPos(); + Point e_iw1 = dist_pt1 / dist_pt1.Norm(); + Point e_iw2 = dist_pt2 / dist_pt2.Norm(); + Point ei; + JEllipse Eped1 = ped->GetEllipse(); + ei._x = Eped1.GetCosPhi(); + ei._y = Eped1.GetSinPhi(); + //version area---------------------------------- + double result_e01 = e0.ScalarProduct(e_iw1); + double result_e02 = e0.ScalarProduct(e_iw2); + double result_ei1 = ei.ScalarProduct(e_iw1); + double result_ei2 = ei.ScalarProduct(e_iw2); + //---------------------------------------------- + if (GetGCVMU() == 0)//all + { + result_e01 = 1; + result_e02 = 1; + result_ei1 = 1; + result_ei2 = 1; + } + if (result_e01 < 0 && result_e02 < 0 && result_ei1 < 0 && result_ei1 < 0) + { + return F_wrep; + } + + // using new method calculate influence direciton---------------------------------------- + Point inf_direction;// left side f pedestrian + inf_direction._x = -e0._y; + inf_direction._y = e0._x; + inf_direction = inf_direction.Normalized(); + double result1 = e0.CrossProduct(e_iw); + double result2 = e0.CrossProduct(inf_direction); + if (bool equal = almostEqual(result1, 0, 0.00001))//Is there any possible that desired direction towards the wall? + { + //double alpha = ped->GetAlpha(); + Point zero = Point(0.0, 0.0); + int random = rand() % 1000;//choose one direciton by random + if (random > 500)//when random is larger than 50, influence's direction is right, otherwise is left + { + inf_direction = zero - inf_direction; + } + } + else + { + double result2 = e0.CrossProduct(inf_direction); + Point zero = Point(0.0, 0.0); + if (result1*result2 < 0) + { + inf_direction = zero - inf_direction; + } + } + //----------------------------------------------------------------------------------------- + + //use effective distance to calculate ForceRepWall + double effdis = Eped1.EffectiveDistanceToLine(w); + effdis = effdis > 0 ? effdis : 0; + R_iw = -_aWall * exp((-effdis) / _DWall); + if (GetGCVMU() == 1) + { + F_wrep = inf_direction * R_iw;//new method + } + else + { + F_wrep = e_iw * R_iw;//original method + } + return F_wrep; +} + +double AGCVMModel::GetSpacingRoom(Pedestrian* ped, SubRoom* subroom, Point ei) const +{ + double spacing = FLT_MAX; + double distance = FLT_MAX; + //first the walls + for (const auto & wall : subroom->GetAllWalls()) + { + distance = GetSpacingWall(ped, wall, ei); + spacing = spacing > distance ? distance : spacing; + } + //then the obstacles + for (const auto & obst : subroom->GetAllObstacles()) + { + for (const auto & wall : obst->GetAllWalls()) + { + distance = GetSpacingWall(ped, wall, ei); + spacing = spacing > distance ? distance : spacing; + } + } + //and finally the closed doors + for (const auto & goal : subroom->GetAllTransitions()) + { + if (!goal->IsOpen()) + { + distance = GetSpacingWall(ped, *(static_cast<Line*>(goal)), ei); + spacing = spacing > distance ? distance : spacing; + } + int uid1 = goal->GetUniqueID(); + int uid2 = ped->GetExitIndex(); + //door is open, bur not my door + if ((uid1 != uid2) && (goal->IsOpen() == true)) + { + distance = GetSpacingWall(ped, *(static_cast<Line*>(goal)), ei); + spacing = spacing > distance ? distance : spacing; + } + } + return spacing; + +} + +double AGCVMModel::GetSpacingWall(Pedestrian* ped, const Line& l, Point ei) const +{ + double spacing = FLT_MAX; + Point pp = ped->GetPos(); + Point pt = l.ShortestPoint(ped->GetPos()); + Point p1 = l.GetPoint1(); + Point p2 = l.GetPoint2(); + Point dist = pt - pp; + Point ei_vertical; + ei_vertical._x = -ei.Normalized()._y; + ei_vertical._y = ei.Normalized()._x; + double b = ped->GetSmallerAxis(); + Point A1 = pp + ei_vertical * b; + Point A2 = pp - ei_vertical * b; + Point p1_A1 = p1 - A1; + Point p2_A1 = p2 - A1; + Point p12 = p1 - p2; + double A1_result1 = ei.CrossProduct(p1_A1); + double A1_result2 = ei.CrossProduct(p2_A1); + double result3 = ei.ScalarProduct(dist); + Point p1_A2 = p1 - A2; + Point p2_A2 = p2 - A2; + double A2_result1 = ei.CrossProduct(p1_A2); + double A2_result2 = ei.CrossProduct(p2_A2); + if (result3 <= 0) + { + return spacing; + } + if (A1_result1*A1_result2 > 0 && A2_result1*A2_result2 > 0 && A1_result1*A2_result1 > 0 && A1_result2*A2_result2 > 0) + { + return spacing; + } + double effdis = ped->GetEllipse().EffectiveDistanceToLine(l); + double cosangle = dist.ScalarProduct(ei) / (dist.Norm()*ei.Norm()); + if (cosangle < 0.00001) + { + return spacing; + } + spacing = effdis / cosangle; + return spacing; +} + +string AGCVMModel::GetDescription() +{ + string rueck; + char tmp[CLENGTH]; + + sprintf(tmp, "\t\ta: \t\tPed: %f \tWall: %f\n", _aPed, _aWall); + rueck.append(tmp); + sprintf(tmp, "\t\tD: \t\tPed: %f \tWall: %f\n", _DPed, _DWall); + rueck.append(tmp); + return rueck; +} + +std::shared_ptr<DirectionStrategy> AGCVMModel::GetDirection() const +{ + return _direction; +} + + +double AGCVMModel::GetaPed() const +{ + return _aPed; +} + +double AGCVMModel::GetDPed() const +{ + return _DPed; +} + + +double AGCVMModel::GetaWall() const +{ + return _aWall; +} + +double AGCVMModel::GetDWall() const +{ + return _DWall; +} + +int AGCVMModel::GetGCVMU() const +{ + return _GCVMUsing; +} diff --git a/math/AGCVMModel.h b/math/AGCVMModel.h new file mode 100644 index 0000000000000000000000000000000000000000..adfea0e8cecf64d4e672c14b2762b6b756e1e25d --- /dev/null +++ b/math/AGCVMModel.h @@ -0,0 +1,189 @@ +/** +* \file AGCVM.h +* \date Jun 26, 2019 +* \version v0.8 +* \copyright <2009-2015> Forschungszentrum Jülich GmbH. All rights reserved. +* +* \section License +* This file is part of JuPedSim. +* +* JuPedSim is free software: you can redistribute it and/or modify +* it under the terms of the GNU Lesser General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* any later version. +* +* JuPedSim is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU Lesser General Public License +* along with JuPedSim. If not, see <http://www.gnu.org/licenses/>. +* +* \section Description +* Implementation of first-order model +* Anticipation generalized collision-free velocity model: Qiancheng (8) +* +* +**/ + + +#ifndef AGCVMMODEL_H_ +#define AGCVMMODEL_H_ + +#include <vector> + +#include "../geometry/Building.h" +#include "OperationalModel.h" + +typedef std::pair<double, double> my_pair; +// sort with respect to first element (ascending). +// In case of equality sort with respect to second element (descending) + +struct sort_pred_agcvm +{ + bool operator () (const my_pair& left, const my_pair& right) + { + return (left.first == right.first) ? + (left.second > right.second) : + (left.first < right.first); + } +}; + + + +//forward declaration +class Pedestrian; +class DirectionStrategy; + + +class AGCVMModel : public OperationalModel { +private: + + /// Modellparameter + double _aPed; + double _DPed; + + double _aWall; + double _DWall; + + double _Ts; + double _Td; + + int _GCVMUsing=1;// Keep it for incase + + double OptimalSpeed(Pedestrian* ped, double spacing) const; + + /** + * The desired direction of pedestrian + * + * @param ped: Pointer to Pedestrians + * @param room: Pointer to room + * + * @return Point + */ + Point e0(Pedestrian *ped, Room* room) const; + /** + * Get the spacing between ped1 and ped2 + * + * @param ped1 Pointer to Pedestrian: First pedestrian + * @param ped2 Pointer to Pedestrian: Second pedestrian + * @param ei the direction of pedestrian. + * + * @return Point + */ + my_pair GetSpacing(Pedestrian* ped1, Pedestrian* ped2, Point ei, int periodic) const; + /** + * Repulsive force between two pedestrians ped1 and ped2 + * @param ped1 Pointer to Pedestrian: First pedestrian + * @param ped2 Pointer to Pedestrian: Second pedestrian + * + * @return Point + */ + Point ForceRepPed(Pedestrian* ped1, Pedestrian* ped2, Point e0, int periodic) const; + /** + * Repulsive force acting on pedestrian <ped> from the walls in + * <subroom>. The sum of all repulsive forces of the walls in <subroom> is calculated + * @see ForceRepWall + * @param ped Pointer to Pedestrian + * @param subroom Pointer to SubRoom + * + * @return Point + */ + Point ForceRepRoom(Pedestrian* ped, SubRoom* subroom, Point e0) const; + /** + * Repulsive force between pedestrian <ped> and wall <l> + * + * @param ped Pointer to Pedestrian + * @param l reference to Wall + * + * @return Point + */ + Point ForceRepWall(Pedestrian* ped, const Line& l, const Point& centroid, bool inside, Point e0) const; + double GetSpacingRoom(Pedestrian* ped, SubRoom* subroom, Point ei) const; + double GetSpacingWall(Pedestrian* ped, const Line& l, Point ei) const; + +public: + + AGCVMModel(std::shared_ptr<DirectionStrategy> dir, double aped, double Dped, + double awall, double Dwall, double Ts, double Td, int GCVM); + virtual ~AGCVMModel(void); + + + std::shared_ptr<DirectionStrategy> GetDirection() const; + + /** + * ToDO: What is this parameter doing? + * + * @return double + * + */ + double GetaPed() const; + + /** + * ToDO: What is this parameter doing? + * + * @return double + */ + double GetDPed() const; + + /** + * ToDO: What is this parameter doing? + * + * @return double + */ + double GetaWall() const; + + /** + * ToDO: What is this parameter doing? + * + * @return double + */ + double GetDWall() const; + + /** + * @return all model parameters in a nicely formatted string + */ + virtual std::string GetDescription(); + + /** + * initialize the phi angle + * @param building + */ + virtual bool Init(Building* building); + + /** + * Compute the next simulation step + * Solve the differential equations and update the positions and velocities + * @param current the actual time + * @param deltaT the next timestep + * @param building the geometry object + * @param periodic: used in some utests for periodic scenarios (very specific) + */ + virtual void ComputeNextTimeStep(double current, double deltaT, Building* building, int periodic); + + int GetGCVMU() const; +}; + + +#endif diff --git a/math/SimplestModel.cpp b/math/SimplestModel.cpp index bcf54952a7d3f5346031b8817df02c34122c651d..65fdba942ef17aa1f8628fb00395f0cf7ac11d6a 100644 --- a/math/SimplestModel.cpp +++ b/math/SimplestModel.cpp @@ -61,7 +61,7 @@ using std::vector; using std::string; SimplestModel::SimplestModel(std::shared_ptr<DirectionStrategy> dir, double aped, double Dped, - double awall, double Dwall, double Ts, double Td, int Parallel, double waitingTime, int sDirection, int sSpeed, int GCVMU) + double awall, double Dwall, double Ts, double Td, int Parallel, double waitingTime, double areasize, int sDirection, int sSpeed, int GCVMU) { _direction = dir; // Force_rep_PED Parameter @@ -77,6 +77,7 @@ SimplestModel::SimplestModel(std::shared_ptr<DirectionStrategy> dir, double aped _SubmodelDirection = sDirection; _SubmodelSpeed = sSpeed; _GCVMUsing = GCVMU; + _AreaSize = areasize; } @@ -326,7 +327,7 @@ void SimplestModel::ComputeNextTimeStep(double current, double deltaT, Building* my_pair relation = my_pair(ped->GetID(), first_ID); const Point& pos = ped->GetPos(); double distGoal = ped->GetExitLine()->DistTo(pos); - double DRange=1; + double DRange=GetAreaSize(); if (UDirection==0||distGoal<DRange) { relations.push_back(relation); @@ -1121,4 +1122,9 @@ int SimplestModel::GetSSpeed() const int SimplestModel::GetGCVMU() const { return _GCVMUsing; +} + +double SimplestModel::GetAreaSize() const +{ + return _AreaSize; } \ No newline at end of file diff --git a/math/SimplestModel.h b/math/SimplestModel.h index 999d696b02eef001f21046a650aa8f455460d611..94126507177eef59e009b4723355cadf5728a354 100644 --- a/math/SimplestModel.h +++ b/math/SimplestModel.h @@ -73,6 +73,7 @@ private: int _Parallel; double _WaitingTime; + double _AreaSize; int _SubmodelDirection; int _SubmodelSpeed; @@ -133,7 +134,7 @@ private: public: SimplestModel(std::shared_ptr<DirectionStrategy> dir, double aped, double Dped, - double awall, double Dwall, double Ts, double Td, int Parallel, double waitingTime, int sDirection, int sSpeed, int GCVMU); + double awall, double Dwall, double Ts, double Td, int Parallel, double waitingTime, double areasize, int sDirection, int sSpeed, int GCVMU); virtual ~SimplestModel(void); @@ -198,6 +199,8 @@ public: int GetSSpeed() const; int GetGCVMU() const; + + double GetAreaSize() const; };