diff --git a/LICENCE b/LICENSE similarity index 95% rename from LICENCE rename to LICENSE index 56f236e4826bbedfaf44299979f39d415849ae43..b116e5cef78f9ca371bd4bb287945d5fe6e4fe7c 100644 --- a/LICENCE +++ b/LICENSE @@ -26,7 +26,7 @@ the implied warranties of merchantability and fitness for a particular purpose. The software and accompanying documentation, if any, provided hereunder is provided “as is”. JuPedSim has no obligation to provide maintenance, support, updates, enhancements, or modifications. -Forschungszentrum J ̈ulich GmbH makes no warranty, expressed or implied, +Forschungszentrum Julich GmbH makes no warranty, expressed or implied, to users of JuPedSim, and accepts no responsibility for its use. Users of JuPedSim assume sole responsibility for determining the appropriateness of its use; and for any actions taken or not taken as a result of analyses performed using this tool. diff --git a/Simulation.cpp b/Simulation.cpp index e74df80a344b54b4901c1711c8c1cc3b00e80b6d..05a6fd6af08de7488cd0ee98d060bcf0884b8920 100644 --- a/Simulation.cpp +++ b/Simulation.cpp @@ -292,15 +292,15 @@ int Simulation::RunSimulation() // update the positions _operationalModel->ComputeNextTimeStep(t, _deltaT, _building.get()); - // update the routes and locations - //Update(); + //update the routes and locations UpdateRoutesAndLocations(); //update the events - _em->Update_Events(t, _deltaT); + _em->Update_Events(t); + //_em->ProcessEvent(); //other updates - //someone might have leave the building + //someone might have left the building _nPeds = _building->GetAllPedestrians().size(); //update the linked cells diff --git a/events/EventManager.cpp b/events/EventManager.cpp index 1ee9c5bcfbdb2ca5a6befa3823326e3c8f5111af..7ea361c4bf3799934cc35782d766be6f22ea8aaf 100644 --- a/events/EventManager.cpp +++ b/events/EventManager.cpp @@ -30,10 +30,13 @@ #include <cstdio> #include <cstdlib> #include <iostream> +#include <algorithm> #include <fstream> #include <vector> #include <math.h> #include <stdio.h> +#include "../pedestrian/Pedestrian.h" +#include "../mpi/LCGrid.h" #include "../geometry/Building.h" #include "../geometry/SubRoom.h" #include "../geometry/Transition.h" @@ -43,6 +46,13 @@ #include "../IO/IODispatcher.h" #include "../routing/RoutingEngine.h" #include "../pedestrian/Pedestrian.h" +#include "../routing/GlobalRouter.h" +#include "../routing/QuickestPathRouter.h" +#include "../routing/GraphRouter.h" +#include "../routing/MeshRouter.h" +#include "../routing/DummyRouter.h" +#include "../routing/SafestPathRouter.h" +#include "../routing/CognitiveMapRouter.h" #include "EventManager.h" using namespace std; @@ -59,34 +69,26 @@ EventManager::EventManager(Building *_b) _event_types = vector<string>(); _event_states = vector<string>(); _event_ids = vector<int>(); - _projectFilename = ""; _building = _b; _eventCounter = 0; _dynamic = false; _file = fopen("../events/events.txt", "r"); _lastUpdateTime = 0; - _deltaT = 0; - this->SetProjectFilename(_building->GetProjectFilename()); - this->SetProjectRootDir(_building->GetProjectRootDir()); + //_deltaT = 0; + _projectFilename=_building->GetProjectFilename(); + _projectRootDir=_building->GetProjectRootDir(); + + _file = fopen("../events/events.txt", "r"); if (!_file) { - Log->Write( - "INFO:\tFiles 'events.txt' missing. Realtime interaction with the simulation not possible."); + Log->Write("INFO:\tFiles 'events.txt' missing. " + "Realtime interaction with the simulation not possible."); } else { - Log->Write( - "INFO:\tFile 'events.txt' will be monitored for new events."); + Log->Write("INFO:\tFile 'events.txt' will be monitored for new events."); _dynamic = true; } -} - -void EventManager::SetProjectFilename(const std::string &filename) -{ - _projectFilename = filename; -} - -void EventManager::SetProjectRootDir(const std::string &filename) -{ - _projectRootDir = filename; + //save the first graph + CreateRoutingEngine(_b, true); } bool EventManager::ReadEventsXml() @@ -143,27 +145,18 @@ bool EventManager::ReadEventsXml() _event_states.push_back(e->Attribute("state")); _event_ids.push_back(atoi(e->Attribute("id"))); } - Log->Write("INFO: \tEvents were initialized\n"); + Log->Write("INFO: \tEvents were initialized"); return true; } + void EventManager::ListEvents() { - if (_event_times.size() == 0) { - //this notification was already printed ealier - //Log->Write("INFO: \tNo events in the events.xml"); - } else { - char buf[10], buf2[10]; - for (unsigned int i = 0; i < _event_times.size(); i++) { - sprintf(buf, "%f", _event_times[i]); - sprintf(buf2, "%d", _event_ids[i]); - Log->Write( - "INFO: \tAfter " + string(buf) + " sec: " - + _event_types[i] + " " + string(buf2) + " " - + _event_states[i]); - } + for (unsigned int i = 0; i < _event_times.size(); i++) + { + Log->Write("INFO: \tAfter %.2f sec, %s door %d", _event_times[i], + _event_states[i].c_str(), _event_ids[i]); } - } void EventManager::ReadEventsTxt(double time) @@ -176,7 +169,7 @@ void EventManager::ReadEventsTxt(double time) Log->Write("WARNING: \tCould not read the event file"); return; } - if (cstring[0] != '#') { // keine Kommentarzeile + if (cstring[0] != '#') {// skip comments lines++; if (lines > _eventCounter) { Log->Write("INFO:\tEvent: after %f sec: ", time); @@ -191,7 +184,175 @@ void EventManager::ReadEventsTxt(double time) Update **********/ -void EventManager::Update_Events(double time, double d) +bool EventManager::UpdateAgentKnowledge(Building* _b) +{ +#pragma omp parallel + for(auto&& ped:_b->GetAllPedestrians()) + { + for (auto&& door: _b->GetAllTransitions()) + { + if(door.second->DistTo(ped->GetPos())<0.2) //TODO: put 0.c metre in macro + { + //actualize the information about the newly closed door + if(door.second->IsOpen()==false) + ped->AddKnownClosedDoor(door.first, Pedestrian::GetGlobalTime()); + } + } + } + + for(auto&& ped1:_b->GetAllPedestrians()) + { + vector<Pedestrian*> neighbourhood; + _b->GetGrid()->GetNeighbourhood(ped1,neighbourhood); + for(auto&& ped2:neighbourhood) + { + if( (ped1->GetPos()-ped2->GetPos()).Norm()<J_EPS_INFO_DIST) + { + //maybe same room and subroom ? + //if(_b->IsVisible(ped1->GetPos(),ped2->GetPos())) + MergeKnowledge(ped1, ped2); + } + } + } + + //update the routers based on the configurations + //#pragma omp parallel + for(auto&& ped:_b->GetAllPedestrians()) + { + if(UpdateRoute(ped)==false) + { + //Clear the memory and attempt to reroute + //this can happen if all doors are known to be closed + ped->ClearKnowledge(); + if(UpdateRoute(ped)==false) + { + Log->Write("ERROR: \t cannot reroute the pedestrian. unknown problem"); + //return false; + exit(EXIT_FAILURE); + } + } + } + return true; +} + +bool EventManager::UpdateRoute(Pedestrian* ped) +{ + //create the key as string. + //map are sorted by default + string key=""; + for(auto&& knowledge:ped->GetKnownledge()) + { + int door=knowledge.first; + if(key.empty()) + key.append(std::to_string(door)); + else + key.append(":"+std::to_string(door)); + } + + //get the router engine corresponding to the actual configuration + bool status=true; + if (_eventEngineStorage.count(key)>0) + { + RoutingEngine* engine=_eventEngineStorage[key]; + //retrieve the old strategy + RoutingStrategy strategy=ped->GetRouter()->GetStrategy(); + //retrieve the new router + Router*rout =engine->GetRouter(strategy); + //check for validity + ped->SetRouter(rout); + //overwrite/update the pedestrian router + if(!rout) status= false; + } + else + { + Log->Write("ERROR: \t unknown configuration %s", key.c_str()); + Log->Write("ERROR: \t [%d] router available", _eventEngineStorage.size()); + status= false; + } + return status; +} + +void EventManager::MergeKnowledge(Pedestrian* p1, Pedestrian* p2) +{ + const map<int, NavLineState>& old_info1=p1->GetKnownledge(); + const map<int, NavLineState>& old_info2=p2->GetKnownledge(); + map<int, NavLineState> merge_info; + //map<int, double> merge_info; + + //collect the most recent knowledge + for (auto&& info1 : old_info1) + { + merge_info[info1.first] = info1.second; + } + + for (auto&& info2:old_info2) + { + //update infos according to a newest time + if(merge_info.count(info2.first)>0) + { + if(info2.second.GetTime()>merge_info[info2.first].GetTime()) + { + merge_info[info2.first]=info2.second; + } + } + else //just add + { + merge_info[info2.first]=info2.second; + } + } + + //synchronize the knowledge + p1->ClearKnowledge(); + p2->ClearKnowledge(); + for (auto&& info : merge_info) + { + p1->AddKnownClosedDoor(info.first,info.second.GetTime()); + p2->AddKnownClosedDoor(info.first,info.second.GetTime()); + } +} + +void EventManager::ProcessEvent() +{ + //const vector<Pedestrian*>& _allPeds = _building->GetAllPedestrians(); + + if (_event_times.size() == 0) return; + + int current_time = Pedestrian::GetGlobalTime(); + + if ( (current_time != _lastUpdateTime) && + ((current_time % UPDATE_FREQUENCY) == 0)) + { + //update knowledge about closed doors + //share the information between the pedestrians + UpdateAgentKnowledge(_building); + + //actualize based on the new knowledge + _lastUpdateTime = current_time; + //cout<<"updating..."<<currentTime<<endl<<endl; + } + + //update the building state + // the time is needed as double + double current_time_d = Pedestrian::GetGlobalTime(); + for (unsigned int i = 0; i < _event_times.size(); i++) + { + if (fabs(_event_times[i] - current_time_d) < J_EPS_EVENT) { + //Event with current time stamp detected + Log->Write("INFO:\tEvent: after %f sec: ", current_time_d); + if (_event_states[i].compare("close") == 0) { + CloseDoor(_event_ids[i]); + } else { + OpenDoor(_event_ids[i]); + } + } + } + + if (_dynamic) + ReadEventsTxt(current_time); +} + + +void EventManager::Update_Events(double time ) { //1. pruefen ob in _event_times der zeitstempel time zu finden ist. Wenn ja zu 2. sonst zu 3. //2. Event aus _event_times und _event_values verarbeiten (Tuere schliessen/oeffnen, neues Routing) @@ -199,51 +360,47 @@ void EventManager::Update_Events(double time, double d) //3. .txt Datei auf neue Zeilen pruefen. Wenn es neue gibt diese Events verarbeiten ( Tuere schliessen/oeffnen, // neues Routing) ansonsten fertig - _deltaT = d; + //_deltaT = d; const vector<Pedestrian*>& _allPeds = _building->GetAllPedestrians(); //zuerst muss geprueft werden, ob die Peds, die die neuen Infos schon haben sie an andere Peds weiter- //leiten muessen (wenn diese sich in der naechsten Umgebung befinden) - int currentTime = _allPeds[0]->GetGlobalTime(); - if (currentTime != _lastUpdateTime) - if ((currentTime % UPDATE_FREQUENCY) == 0) { - - for (unsigned int p1 = 0; p1 < _allPeds.size(); p1++) { - Pedestrian* ped1 = _allPeds[p1]; - if (ped1->GetNewEventFlag()) { - int rID = ped1->GetRoomID(); - int srID = ped1->GetSubRoomID(); - - for (unsigned int p2 = 0; p2 < _allPeds.size(); p2++) { - Pedestrian* ped2 = _allPeds[p2]; - //same room and subroom - if (rID == ped2->GetRoomID() - && srID == ped2->GetSubRoomID()) { - if (!ped2->GetNewEventFlag() - && ped2->GetReroutingTime() - > 2.0) { - //wenn der Pedestrian die neuen Infos noch nicht hat und eine Reroutingtime von > 2 Sekunden hat, pruefen ob er nah genug ist - Point pos1 = ped1->GetPos(); - Point pos2 = ped2->GetPos(); - double distX = pos1.GetX() - - pos2.GetX(); - double distY = pos1.GetY() - - pos2.GetY(); - double dist = sqrt( - distX * distX - + distY * distY); - if (dist <= J_EPS_INFO_DIST) { // wenn er nah genug (weniger als 2m) ist, Info weitergeben (Reroutetime auf 2 Sek) - //ped->RerouteIn(2.0); - ped2->RerouteIn(0.0); - } + //int currentTime = _allPeds[0]->GetGlobalTime(); + int currentTime = Pedestrian::GetGlobalTime(); + + + if ( (currentTime != _lastUpdateTime) && + ((currentTime % UPDATE_FREQUENCY) == 0)) + { + for (unsigned int p1 = 0; p1 < _allPeds.size(); p1++) { + Pedestrian* ped1 = _allPeds[p1]; + if (ped1->GetNewEventFlag()) { + int rID = ped1->GetRoomID(); + int srID = ped1->GetSubRoomID(); + + for (unsigned int p2 = 0; p2 < _allPeds.size(); p2++) { + Pedestrian* ped2 = _allPeds[p2]; + //same room and subroom + if (rID == ped2->GetRoomID() + && srID == ped2->GetSubRoomID()) { + if (!ped2->GetNewEventFlag() + && ped2->GetReroutingTime() + > 2.0) { + //wenn der Pedestrian die neuen Infos noch nicht hat und eine Reroutingtime von > 2 Sekunden hat, pruefen ob er nah genug ist + double dist= (ped1->GetPos()-ped2->GetPos()).Norm(); + + if (dist <= J_EPS_INFO_DIST) { // wenn er nah genug (weniger als 2m) ist, Info weitergeben (Reroutetime auf 2 Sek) + //ped->RerouteIn(2.0); + ped2->RerouteIn(0.0); } } } } } - _lastUpdateTime = currentTime; - //cout<<"updating..."<<currentTime<<endl<<endl; } + _lastUpdateTime = currentTime; + //cout<<"updating..."<<currentTime<<endl<<endl; + } //dann muss die Reroutingzeit der Peds, die die neuen Infos noch nicht haben, aktualisiert werden: for (unsigned int p1 = 0; p1 < _allPeds.size(); p1++) { @@ -259,7 +416,7 @@ void EventManager::Update_Events(double time, double d) //Events finden for (unsigned int i = 0; i < _event_times.size(); i++) { if (fabs(_event_times[i] - time) < J_EPS_EVENT) { - //Event findet statt + //Event with current time stamp detected Log->Write("INFO:\tEvent: after %f sec: ", time); if (_event_states[i].compare("close") == 0) { CloseDoor(_event_ids[i]); @@ -268,18 +425,18 @@ void EventManager::Update_Events(double time, double d) } } } + if (_dynamic) ReadEventsTxt(time); } /*************** - Eventhandling + Event handling **************/ //close the door if it was open and relaunch the routing procedure void EventManager::CloseDoor(int id) { - Transition *t = _building->GetTransition(id); if (t->IsOpen()) { t->Close(); @@ -306,49 +463,37 @@ void EventManager::OpenDoor(int id) void EventManager::ChangeRouting(int id, const std::string& state) { - RoutingEngine* routingEngine = _building->GetRoutingEngine(); - routingEngine->Init(_building); - //_building->InitPhiAllPeds(_deltaT); - const vector<Pedestrian*>& _allPedestrians = - _building->GetAllPedestrians(); - unsigned int nSize = _allPedestrians.size(); //Pedestrians sollen, damit es realitaetsnaeher wird, je nachdem wo sie stehen erst spaeter(abh. von der //Entfernung zur Tuer) merken, dass sich Tueren aendern. Oder sie bekommen die Info von anderen Pedestrians Transition *t = _building->GetTransition(id); //Abstand der aktuellen Position des Pedestrians zur entsprechenden Tuer: Tuer als Linie sehen und mit //DistTo(ped.GetPos()) den Abstand messen. Reroutezeit dann aus Entfernung und Geschwindigkeit berechnen. - Line* l = new Line(t->GetPoint1(), t->GetPoint2()); - for (unsigned int p = 0; p < nSize; ++p) { + + for(auto&& ped:_building->GetAllPedestrians()) + { //if(_allPedestrians[p]->GetExitIndex()==t->GetUniqueID()){ - _allPedestrians[p]->SetNewEventFlag(false); - double dist = l->DistTo(_allPedestrians[p]->GetPos()); - Point v = _allPedestrians[p]->GetV(); - double norm = sqrt((v.GetX() * v.GetX()) + (v.GetY() * v.GetY())); + ped->SetNewEventFlag(false); + double dist = t->DistTo(ped->GetPos()); + const Point& v = ped->GetV(); + double norm = v.Norm(); if (norm == 0.0) { norm = 0.01; } double time = dist / norm; if (time < 1.0) { - _allPedestrians[p]->ClearMentalMap(); - _allPedestrians[p]->ResetRerouting(); - _allPedestrians[p]->SetNewEventFlag(true); + ped->ClearMentalMap(); + ped->ResetRerouting(); + ped->SetNewEventFlag(true); } else { - _allPedestrians[p]->RerouteIn(time); + ped->RerouteIn(time); } - //if(dist>0.0&&dist<0.5){ - // _allPedestrians[p]->ClearMentalMap(); - //} - //else if(dist>=0.5&&dist<3.0){ - // _allPedestrians[p]->RerouteIn(1.0); - //} - //else{ - // _allPedestrians[p]->RerouteIn(2.0); - //} - //} - //else{ - // _allPedestrians[p]->ClearMentalMap(); - //} + } + + //Create and save a graph corresponding to the actual state of the building. + if(CreateRoutingEngine(_building)==false) + { + Log->Write("ERROR: \tcannot create a routing engine with the new event"); } } @@ -381,3 +526,116 @@ void EventManager::GetEvent(char* c) OpenDoor(atoi(id.c_str())); } } + +bool EventManager::CreateRoutingEngine(Building* _b, int first_engine) +{ + std::vector<int> closed_doors; + + for(auto&& t:_b->GetAllTransitions()) + { + if(t.second->IsOpen()==false) + closed_doors.push_back(t.second->GetID()); + } + std::sort(closed_doors.begin(), closed_doors.end()); + + //create the key as string. + string key=""; + for(int door:closed_doors) + { + if(key.empty()) + key.append(std::to_string(door)); + else + key.append(":"+std::to_string(door)); + } + + //the first (default) engine was created in the simulation + // collect the defined routers + if(first_engine) + { + RoutingEngine* engine=_b->GetRoutingEngine(); + _eventEngineStorage[key]=engine; + + for(auto&& rout: engine->GetAvailableRouters()) + { + _availableRouters.push_back(rout->GetStrategy()); + } + Log->Write("INFO: \tAdding a new routing Engine with the key: "+key+"\n"); + return true; + } + + // the engine was not created + // create a new one with the actual configuration + if (_eventEngineStorage.count(key)==0) + { + //std::shared_ptr<RoutingEngine> engine = std::shared_ptr<RoutingEngine>(new RoutingEngine()); + //engine.get()->Init(_b); + //_eventEngineStorage[key]=engine.get(); + + //populate the engine with the routers defined in the ini file + //and initialize + RoutingEngine* engine= new RoutingEngine(); + for(auto&& rout:_availableRouters) + { + engine->AddRouter(CreateRouter(rout)); + } + + if(engine->Init(_b)==false) + return false; + + //save the configuration + _eventEngineStorage[key]=engine; + Log->Write("INFO: \tAdding a new routing Engine with the key: "+key+"\n"); + } + else + { + Log->Write("INFO: \tA routing already exits with the key: "+key+"\n"); + } + + return true; +} + +Router * EventManager::CreateRouter(const RoutingStrategy& strategy) +{ + Router * rout=NULL; + + switch(strategy) + { + case ROUTING_LOCAL_SHORTEST: + rout = new GlobalRouter(ROUTING_LOCAL_SHORTEST, ROUTING_LOCAL_SHORTEST); + break; + + case ROUTING_GLOBAL_SHORTEST: + rout = new GlobalRouter(ROUTING_GLOBAL_SHORTEST, ROUTING_GLOBAL_SHORTEST); + break; + + case ROUTING_QUICKEST: + rout = new QuickestPathRouter(ROUTING_QUICKEST, ROUTING_QUICKEST); + break; + + case ROUTING_DYNAMIC: + rout = new GraphRouter(ROUTING_DYNAMIC, ROUTING_DYNAMIC); + break; + + case ROUTING_NAV_MESH: + rout = new MeshRouter(ROUTING_NAV_MESH, ROUTING_NAV_MESH); + break; + + case ROUTING_DUMMY: + rout = new DummyRouter(ROUTING_DUMMY, ROUTING_DUMMY); + break; + + case ROUTING_SAFEST: + rout = new SafestPathRouter(ROUTING_SAFEST, ROUTING_SAFEST); + break; + + case ROUTING_COGNITIVEMAP: + rout = new CognitiveMapRouter(ROUTING_COGNITIVEMAP, ROUTING_COGNITIVEMAP); + break; + + default: + Log->Write("ERROR: \twrong value for routing strategy [%d]!!!\n", strategy ); + break; + + } + return rout; +} diff --git a/events/EventManager.h b/events/EventManager.h index 7d8266a4227a303ce92f885aff1a7c4a6aaa27d3..876ca0fd9c42606b7bdfff6f7a5ab7c92e5dc9a7 100644 --- a/events/EventManager.h +++ b/events/EventManager.h @@ -29,6 +29,10 @@ #include <string> class Building; +class Router; +class GlobalRouter; +class QuickestPathRouter; +class RoutingEngine; extern OutputHandler* Log; @@ -42,22 +46,83 @@ private: std::string _projectFilename; std::string _projectRootDir; Building *_building; - double _deltaT; FILE *_file; bool _dynamic; int _eventCounter; long int _lastUpdateTime; + //save the router corresponding to the actual state of the building + std::map<std::string, RoutingEngine*> _eventEngineStorage; + //save the available routers defined in the simulation + std::vector<RoutingStrategy> _availableRouters; + +private: + /** + * collect the close doors and generate a new graph + * @param _building + */ + bool CreateRoutingEngine(Building* _b, int first_engine=false); + + /** + * Create a router corresponding to the given strategy + * @param strategy + * @return a router/NULL for invalid strategies + */ + Router * CreateRouter(const RoutingStrategy& strategy); + + /** + * Update the knowledge about closed doors. + * Each pedestrian who is xx metres from a closed door, + * will save that information + * @param _b, the building object + */ + bool UpdateAgentKnowledge(Building* _b); + + /** + * Merge the knowledge of the two pedestrians. + * The information with the newest timestamp + * is always accepted with a probability of one. + * @param p1, first pedestrian + * @param p2, second pedestrian + */ + void MergeKnowledge(Pedestrian* p1, Pedestrian* p2); + + /** + * Update the pedestrian route based on the new information + * @param p1 + * @return + */ + bool UpdateRoute(Pedestrian* p1); public: - //constructor + ///constructor EventManager(Building *_b); - void SetProjectFilename(const std::string &filename); - void SetProjectRootDir(const std::string &filename); + + /** + * Read and parse the events + * @return false if an error occured + */ bool ReadEventsXml(); + + /** + * Print the parsed events + */ void ListEvents(); + + /** + * Read and parse events from a text file + * @param time + */ void ReadEventsTxt(double time); - //Update - void Update_Events(double time, double d); + + /** + * Process the events at runtime + * @param time + */ + void Update_Events(double time); + + //process the event using the current time stamp + //from the pedestrian class + void ProcessEvent(); //Eventhandling void CloseDoor(int id); void OpenDoor(int id); diff --git a/geometry/Building.cpp b/geometry/Building.cpp index 71d092458d205339a9fb21bc376ff3e6783ad039..cb0344b6dc9f1c415be666e50116765e539bf7eb 100644 --- a/geometry/Building.cpp +++ b/geometry/Building.cpp @@ -699,7 +699,7 @@ void Building::AddHline(Hline* line) // check if the lines are identical Hline* ori= _hLines[line->GetID()]; if(ori->operator ==(*line)) { - Log->Write("INFO: Skipping identical hlines with ID [%d]",line->GetID()); + Log->Write("INFO: \tSkipping identical hlines with ID [%d]",line->GetID()); return; } else { Log->Write( @@ -869,7 +869,7 @@ bool Building::IsVisible(Line* l1, Line* l2, bool considerHlines) return true; } -bool Building::ped_is_visible(const Point& p1, const Point& p2, bool considerHlines) +bool Building::IsVisible(const Point& p1, const Point& p2, bool considerHlines) { for (unsigned int i = 0; i < _rooms.size(); i++) { Room* room = _rooms[i]; diff --git a/geometry/Building.h b/geometry/Building.h index d653a2b1229c78bda4fc381bead88ebb5cf8c1d0..89a975d9a55ab38c7856a11a8d1d42487a3fc90f 100644 --- a/geometry/Building.h +++ b/geometry/Building.h @@ -133,7 +133,7 @@ public: * Alls walls and transitions and crossings are used in this check. * The use of hlines is optional, because they are not real, can be considered transparent */ - bool ped_is_visible(const Point& p1, const Point& p2, bool considerHlines=false); + bool IsVisible(const Point& p1, const Point& p2, bool considerHlines=false); /** * @return a crossing or a transition matching the given caption. diff --git a/inputfiles/events/events.xml b/inputfiles/events/events.xml index 0047ee1d24116854fa723ce6a26def1c0434965a..319d54044b78698d37495e6f77aa723901415a33 100644 --- a/inputfiles/events/events.xml +++ b/inputfiles/events/events.xml @@ -1,12 +1,11 @@ <?xml version="1.0" encoding="UTF-8" standalone="yes"?> -<JPScore project="JPS-Project" version="0.5" -xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" -xsi:noNamespaceSchemaLocation="../../xsd/jps_events.xsd"> - <events> - <event time="1" type="door" state="close" id="8" caption="left_exit" /> - <event time="10" type="door" state="open" id="8" caption="left_exit" /> - <event time="25" type="door" state="close" id="4" caption="main_exit" /> - <event time="40" type="door" state="open" id="4" caption="main_exit" /> - </events> +<JPScore project="JPS-Project" version="0.5" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../xsd/jps_events.xsd"> + <events> + <event time="1" type="door" state="close" id="8" caption="left_exit" /> + <event time="10" type="door" state="open" id="8" caption="left_exit" /> + <event time="25" type="door" state="close" id="4" caption="main_exit" /> + <event time="40" type="door" state="open" id="4" caption="main_exit" /> + <event time="70" type="door" state="close" id="8" caption="main_exit" /> + </events> </JPScore> \ No newline at end of file diff --git a/math/GCFMModel.cpp b/math/GCFMModel.cpp index 5aba59f41f3bb333628cc583f01f7b5970352809..42a23af4bf13bd15b985cad0c930896b7d4cb803 100644 --- a/math/GCFMModel.cpp +++ b/math/GCFMModel.cpp @@ -163,7 +163,7 @@ void GCFMModel::ComputeNextTimeStep(double current, double deltaT, Building* bui Pedestrian* ped1 = neighbours[i]; Point p1 = ped->GetPos(); Point p2 = ped1->GetPos(); - bool ped_is_visible = building->ped_is_visible(p1, p2, false); + bool ped_is_visible = building->IsVisible(p1, p2, false); if (!ped_is_visible) continue; // if(debugPed == ped->GetID()) diff --git a/math/GompertzModel.cpp b/math/GompertzModel.cpp index fed816a12e4372832ca2419a1d2e1a61a4770ee9..b6a113959a4e0bdb63b21b6767dd3f9ad98453ea 100644 --- a/math/GompertzModel.cpp +++ b/math/GompertzModel.cpp @@ -201,7 +201,7 @@ void GompertzModel::ComputeNextTimeStep(double current, double deltaT, Building* //if they are in the same subroom Point p1 = ped->GetPos(); Point p2 = ped1->GetPos(); - bool isVisible = building->ped_is_visible(p1, p2, false); + bool isVisible = building->IsVisible(p1, p2, false); if (!isVisible) continue; // if(debugPed == ped->GetID()) diff --git a/pedestrian/Pedestrian.cpp b/pedestrian/Pedestrian.cpp index a517a7adfd5a55fc71cb5476a7aaa2410fd26d11..a4b6b6b2c1c99ae078381ba717ba67db7c30bc44 100644 --- a/pedestrian/Pedestrian.cpp +++ b/pedestrian/Pedestrian.cpp @@ -73,8 +73,9 @@ Pedestrian::Pedestrian() _lastPosition = Point(0,0); _lastCellPosition = -1; _recordingTime = 20; //seconds - _knownDoors = map<int, NavLineState>(); - _height = 160; + // _knownDoors = map<int, NavLineState>(); + _knownDoors.clear(); + _height = 170; _age = 30; _gender = "male"; _trip = vector<int> (); @@ -82,7 +83,8 @@ Pedestrian::Pedestrian() _spotlight = false; _V0UpStairs=0.0; _V0DownStairs=0.0; - _DistToBlockade=0.0; + _distToBlockade=0.0; + _routingStrategy=ROUTING_GLOBAL_SHORTEST; } @@ -243,6 +245,11 @@ int Pedestrian::GetUniqueRoomID() const return _roomID * 1000 + _subRoomID; } +RoutingStrategy Pedestrian::GetRoutingStrategy() const +{ + return _routingStrategy; +} + // returns the exit Id corresponding to the // unique subroom identifier @@ -286,12 +293,14 @@ void Pedestrian::ClearMentalMap() _exitIndex = -1; } -void Pedestrian::AddKnownClosedDoor(int door) +void Pedestrian::AddKnownClosedDoor(int door, double time) { - if(_knownDoors.find(door) == _knownDoors.end()) { - _knownDoors[door].close(GetGlobalTime()); - } - return; + // if(_knownDoors.find(door) == _knownDoors.end()) { + // _knownDoors[door].close(GetGlobalTime()); + // } + // return; + if(time==0) time=_globalTime; + _knownDoors[door].SetState(true,time); } int Pedestrian::DoorKnowledgeCount() const @@ -314,11 +323,22 @@ set<int> Pedestrian::GetKnownClosedDoors() return doors_closed; } +//TODO: remove map<int, NavLineState> * Pedestrian::GetKnownDoors() { return & _knownDoors; } +void Pedestrian::ClearKnowledge() +{ + _knownDoors.clear(); +} + +const map<int, NavLineState>& Pedestrian::GetKnownledge() const +{ + return _knownDoors; +} + void Pedestrian::MergeKnownClosedDoors( map<int, NavLineState> * input) { map<int, NavLineState>::iterator it; @@ -444,7 +464,7 @@ const Point& Pedestrian::GetV0(const Point& target) //new_v0 = delta.NormalizedMolified(); new_v0 = delta.Normalized(); // -------------------------------------- Handover new target - t = _newOrientationDelay++ *_deltaT/(1.0+1000* _DistToBlockade); + t = _newOrientationDelay++ *_deltaT/(1.0+1000* _distToBlockade); _V0 = _V0 + (new_v0 - _V0)*( 1 - exp(-t/_tau) ); #if DEBUG @@ -452,7 +472,7 @@ const Point& Pedestrian::GetV0(const Point& target) printf("Goal Line=[%f, %f]-[%f, %f]\n", _navLine->GetPoint1().GetX(), _navLine->GetPoint1().GetY(), _navLine->GetPoint2().GetX(), _navLine->GetPoint2().GetY()); printf("Ped=%d, sub=%d, room=%d pos=[%f, %f], target=[%f, %f]\n", _id, _subRoomID, _roomID, pos.GetX(), pos.GetY(), target.GetX(), target.GetY()); printf("Ped=%d : BEFORE new_v0=%f %f norm = %f\n", _id, new_v0.GetX(), new_v0.GetY(), new_v0.Norm()); - printf("ped=%d: t=%f, _newOrientationFlag=%d, neworientationDelay=%d, _DistToBlockade=%f\n", _id,t, _newOrientationFlag, _newOrientationDelay, _DistToBlockade); + printf("ped=%d: t=%f, _newOrientationFlag=%d, neworientationDelay=%d, _DistToBlockade=%f\n", _id,t, _newOrientationFlag, _newOrientationDelay, _distToBlockade); printf("_v0=[%f, %f] norm = %f\n", _V0.GetX(), _V0.GetY(), _V0.Norm()); } // getc(stdin); @@ -485,7 +505,7 @@ double Pedestrian::GetTimeInJam() const void Pedestrian::SetSmoothTurning() { - _newOrientationDelay = 0; + _newOrientationDelay = 0; } @@ -536,42 +556,42 @@ bool Pedestrian::IsReadyForRerouting() double Pedestrian::GetReroutingTime() { - return _timeBeforeRerouting; + return _timeBeforeRerouting; } bool Pedestrian::GetNewEventFlag() { - return _newEventFlag; + return _newEventFlag; } bool Pedestrian::GetNewOrientationFlag() { - return _newOrientationFlag; + return _newOrientationFlag; } void Pedestrian::SetDistToBlockade(double dist) { - _DistToBlockade = dist; + _distToBlockade = dist; } double Pedestrian::GetDistToBlockade() { - return _DistToBlockade; + return _distToBlockade; } - + void Pedestrian::SetNewOrientationFlag(bool flag) { - _newOrientationFlag=flag; + _newOrientationFlag=flag; } void Pedestrian::SetNewEventFlag(bool flag) { - _newEventFlag=flag; + _newEventFlag=flag; } double Pedestrian::GetAge() const { - return _age; + return _age; } void Pedestrian::SetAge(double age) @@ -626,9 +646,9 @@ double Pedestrian::GetRecordingTime() const } double Pedestrian::GetMeanVelOverRecTime() const { - //just few position were saved - if (_lastPositions.size()<2) return _ellipse.GetV().Norm(); - return fabs ( (_lastPositions.back()-_lastPositions.front()).Norm() / _recordingTime ); + //just few position were saved + if (_lastPositions.size()<2) return _ellipse.GetV().Norm(); + return fabs ( (_lastPositions.back()-_lastPositions.front()).Norm() / _recordingTime ); } double Pedestrian::GetDistanceToNextTarget() const @@ -684,7 +704,7 @@ void Pedestrian::Dump(int ID, int pa) switch (pa) { - case 0: { + case 0: printf(">> Room/Subroom [%d / %d]\n", _roomID, _subRoomID); printf(">> Destination [ %d ]\n", _exitIndex); printf(">> Final Destination [ %d ]\n", _desiredFinalDestination); @@ -693,17 +713,14 @@ void Pedestrian::Dump(int ID, int pa) printf(">> Velocity [%0.2f, %0.2f] Norm = [%0.2f]\n", GetV().GetX(), GetV().GetY(), GetV().Norm()); if(GetExitLine()) { printf(">> ExitLine: (%0.2f, %0.2f) -- (%0.2f, %0.2f)\n", GetExitLine()->GetPoint1().GetX(), GetExitLine()->GetPoint1().GetY(), - GetExitLine()->GetPoint2().GetX(), GetExitLine()->GetPoint2().GetY()); + GetExitLine()->GetPoint2().GetX(), GetExitLine()->GetPoint2().GetY()); printf(">> dist: %f\n", GetExitLine()->DistTo(GetPos())); } printf(">> smooth rotating: %s \n", (_newOrientationDelay > 0) ? "yes" : "no"); printf(">> mental map"); - map<int, int>::iterator iter; - for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { - printf("\t room / destination [%d, %d]\n", iter->first, iter->second); - } - } - break; + for(auto&& item: _mentalMap) + printf("\t room / destination [%d, %d]\n", item.first, item.second); + break; case 1: printf(">> Position [%f, %f]\n", GetPos().GetX(), GetPos().GetY()); @@ -724,14 +741,20 @@ void Pedestrian::Dump(int ID, int pa) case 5: printf(">> Destination [ %d ]\n", _exitIndex); break; - case 6: { //Mental Map + + case 6: //Mental Map printf(">> mental map"); - map<int, int>::iterator iter; - for (iter = _mentalMap.begin(); iter != _mentalMap.end(); iter++) { - printf("\t room / destination [%d, %d]", iter->first, iter->second); - } - } - break; + for(auto&& item: _mentalMap) + printf("\t room / destination [%d, %d]", item.first, item.second); + break; + + case 7: + for(auto&& item:_knownDoors) + printf("\t door [%d] closed since [%lf] sec\n", item.first, item.second.GetTime()); + break; + + default: + break; } fflush(stdout); @@ -756,6 +779,7 @@ double Pedestrian::GetGlobalTime() void Pedestrian::SetRouter(Router* router) { _router=router; + _routingStrategy=router->GetStrategy(); } Router* Pedestrian::GetRouter() const diff --git a/pedestrian/Pedestrian.h b/pedestrian/Pedestrian.h index 6e3af85f2eba30dd896e73f45dd1d1b492b94c06..1aed43cc37a0475c498f12355c33ce141d1c264f 100644 --- a/pedestrian/Pedestrian.h +++ b/pedestrian/Pedestrian.h @@ -45,9 +45,9 @@ class NavLine; class Router; -class Pedestrian { +class Pedestrian +{ private: - //generic parameters, independent from models int _id; //starting with 1 int _exitIndex; // current exit @@ -85,15 +85,11 @@ private: Point _lastPosition; int _lastCellPosition; - /** - * A set with UniqueIDs of closed crossings, - * transitions or hlines (hlines doesnt make that much sense, - * just that they are removed from the routing graph) - */ + ///state of doors with time stamps std::map<int, NavLineState> _knownDoors; - - double _DistToBlockade=0; // distance to nearest obstacle that blocks the sight of ped. + /// distance to nearest obstacle that blocks the sight of ped. + double _distToBlockade; //routing parameters /// new orientation after 10 seconds double _reroutingThreshold; @@ -109,6 +105,8 @@ private: std::queue <Point> _lastPositions; /// store the last velocities std::queue <Point> _lastVelocites; + /// routing strategy followed + RoutingStrategy _routingStrategy; int _newOrientationDelay; //2 seconds, in steps @@ -183,6 +181,7 @@ public: const Point& GetV0() const; const Point& GetV0(const Point& target); void InitV0(const Point& target); + /** * the desired speed is the projection of the speed on the horizontal plane. * @return the norm of the desired speed. @@ -198,12 +197,20 @@ public: void ClearMentalMap(); // erase the peds memory // functions for known closed Doors (needed for the Graphrouting and Rerouting) - void AddKnownClosedDoor(int door); + void AddKnownClosedDoor(int door, double time=0);//TODo: refactor and remove =0 std::set<int> GetKnownClosedDoors(); void MergeKnownClosedDoors(std::map<int, NavLineState> * input); std::map<int, NavLineState> * GetKnownDoors(); int DoorKnowledgeCount() const; + // needed for information sharing + const std::map<int, NavLineState>& GetKnownledge() const; + + /** + * clear all information related to the knowledge about closed doors + */ + void ClearKnowledge(); + RoutingStrategy GetRoutingStrategy() const; int GetUniqueRoomID() const; int GetNextDestination(); int GetLastDestination(); diff --git a/routing/GlobalRouter.cpp b/routing/GlobalRouter.cpp index ca3583b18fbaaf1992058e3c2d9e7bfc2573996a..7fb4d5ee8a69949913d2f6930b4327e617c6da54 100644 --- a/routing/GlobalRouter.cpp +++ b/routing/GlobalRouter.cpp @@ -296,7 +296,7 @@ bool GlobalRouter::Init(Building* building) if (nav1->operator ==(*nav2)) continue; - if (building->ped_is_visible(nav1->GetCentre(), nav2->GetCentre(), true)) { + if (building->IsVisible(nav1->GetCentre(), nav2->GetCentre(), true)) { int to_door = _map_id_to_index[nav2->GetUniqueID()]; _distMatrix[from_door][to_door] = penalty*(nav1->GetCentre() - nav2->GetCentre()).Norm(); diff --git a/routing/RoutingEngine.cpp b/routing/RoutingEngine.cpp index c0688cd5870ead2150b869de4119b55f0c7e835d..d28d56c4fb77d7a6ec4225191679148c366c1ac2 100644 --- a/routing/RoutingEngine.cpp +++ b/routing/RoutingEngine.cpp @@ -69,7 +69,7 @@ void RoutingEngine::AddRouter(Router* router) _routersCollection.push_back(router); } -const vector<string> RoutingEngine::GetTrip(int index) const +const vector<string>& RoutingEngine::GetTrip(int index) const { if ((index >= 0) && (index < (int) _tripsCollection.size())) return _tripsCollection[index]; @@ -82,23 +82,31 @@ const vector<string> RoutingEngine::GetTrip(int index) const } } +const std::vector<Router*> RoutingEngine::GetAvailableRouters() const +{ + return _routersCollection; +} + + Router* RoutingEngine::GetRouter(RoutingStrategy strategy) const { - for(unsigned int r=0; r<_routersCollection.size(); r++) { - if(_routersCollection[r]->GetStrategy()==strategy) - return _routersCollection[r]; + for(Router* router:_routersCollection) + { + if(router->GetStrategy()==strategy) + return router; } - //Log->Write("ERROR: \t Could not Find any router with ID: [%d].",strategy); - //exit(EXIT_FAILURE); + Log->Write("ERROR: \t Could not Find any router with Strategy: [%d].",strategy); return (Router*) NULL; } Router* RoutingEngine::GetRouter(int id) const { - for(unsigned int r=0; r<_routersCollection.size(); r++) { - if(_routersCollection[r]->GetID()==id) - return _routersCollection[r]; + for(Router* router:_routersCollection) + { + if(router->GetID()==id) + return router; } + Log->Write("ERROR: \t Could not Find any router with ID: [%d].",id); return (Router*) NULL; } diff --git a/routing/RoutingEngine.h b/routing/RoutingEngine.h index 0e3891371d0e118bdf427863209da77f31752ce2..8905cd2e7da928a166e7d61b355c19d6d2d40fbb 100644 --- a/routing/RoutingEngine.h +++ b/routing/RoutingEngine.h @@ -64,11 +64,16 @@ public: /** * Return a trip/route with the particular id - * FIXME referenz? - * @param id - * @return + * @param id, the trip id + * @return the corresponding trip + */ + const std::vector<std::string>& GetTrip(int id) const; + + /** + * @return all available routers + * */ - const std::vector<std::string> GetTrip(int id) const; + const std::vector<Router*> GetAvailableRouters() const; /** * Find the next destination using the appropriate router from @@ -89,6 +94,8 @@ public: /** * Return the router with the specified id + * TODO: Remove this method + * Should prefer etRouter(RoutingStrategy strategy) */ Router* GetRouter(int id) const; diff --git a/routing/graph/NavLineState.cpp b/routing/graph/NavLineState.cpp index fd1201c21b20ddc1db81ff291d6ecaaef03d01dc..63ceda775d622afef877a5d3e6e2b2f52c27a6fb 100644 --- a/routing/graph/NavLineState.cpp +++ b/routing/graph/NavLineState.cpp @@ -82,3 +82,24 @@ void NavLineState::print() { std::cout << open << " - "<< timeFirstSeen << " - " << timeOfInformation << std::endl; } + +void NavLineState::SetState(bool is_closed, double time) +{ + _isClosed=is_closed; + _time=time; +} + +bool NavLineState::GetState() const +{ + return _isClosed; +} + +int NavLineState::GetQuality() const +{ + return _quality; +} + +int NavLineState::GetTime() const +{ + return _time; +} diff --git a/routing/graph/NavLineState.h b/routing/graph/NavLineState.h index cced43dde3869a43943a93b0d524a0c536fa3b74..57f90e25e27953720d06844cb45f11ad775e758f 100644 --- a/routing/graph/NavLineState.h +++ b/routing/graph/NavLineState.h @@ -25,18 +25,17 @@ * **/ - #ifndef NAVLINESTATE_H_ #define NAVLINESTATE_H_ - #include <time.h> #include <iostream> //time between a pedestrian got the information and uses the information #define INFO_OFFSET 1.5 -class NavLineState { +class NavLineState +{ public: NavLineState(); @@ -48,11 +47,23 @@ public: bool mergeDoor(NavLineState & orig, double time); void print(); + void SetState(bool is_closed, double time); + bool GetState() const; + int GetQuality() const; + int GetTime() const; + private: bool open; // aka state int timeFirstSeen; // number of clocks till the door was seen changed the first time int timeOfInformation; // number of clocks when i got the information. should be set to zero after a period of time is over (to + // information quality in [0..1]. 1 is very reliable information + int _quality; // + // last time the state was recorded. + int _time; + // state 0=open, 1=close + bool _isClosed; + }; #endif /* ROUTINGGRAPHSTORAGE_H_ */