EventManager.cpp 11.9 KB
Newer Older
1
#include "EventManager.h"
2 3 4

using namespace std;

5 6 7 8
/*******************
 Konstruktoren
 ******************/

Ulrich Kemloh's avatar
Ulrich Kemloh committed
9 10
#define UPDATE_FREQUENCY 1 // in seconds

Ulrich Kemloh's avatar
Ulrich Kemloh committed
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
EventManager::EventManager(Building *_b)
{
     _event_times = vector<double>();
     _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());
     if (!_file) {
          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.");
          _dynamic = true;
     }
34
}
35

36 37 38
/*******************
 Dateien einlesen
 ******************/
Ulrich Kemloh's avatar
Ulrich Kemloh committed
39 40 41
void EventManager::SetProjectFilename(const std::string &filename)
{
     _projectFilename = filename;
42
}
43

Ulrich Kemloh's avatar
Ulrich Kemloh committed
44 45 46
void EventManager::SetProjectRootDir(const std::string &filename)
{
     _projectRootDir = filename;
47 48
}

Ulrich Kemloh's avatar
Ulrich Kemloh committed
49 50
void EventManager::ReadEventsXml()
{
51
     Log->Write("INFO: \tLooking for pre-defined events in other files");
Ulrich Kemloh's avatar
Ulrich Kemloh committed
52 53
     //get the geometry filename from the project file
     TiXmlDocument doc(_projectFilename);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
54
     if (!doc.LoadFile()) {
Ulrich Kemloh's avatar
Ulrich Kemloh committed
55 56 57 58 59 60
          Log->Write("ERROR: \t%s", doc.ErrorDesc());
          Log->Write("ERROR: \t could not parse the project file.");
          exit(EXIT_FAILURE);
     }

     TiXmlElement* xMainNode = doc.RootElement();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
61 62 63 64 65 66
     string eventfile = "";
     if (xMainNode->FirstChild("events")) {
          eventfile = _projectRootDir
                    + xMainNode->FirstChild("events")->FirstChild()->Value();
          Log->Write("INFO: \tevents <" + eventfile + ">");
     } else {
Ulrich Kemloh's avatar
Ulrich Kemloh committed
67 68 69 70 71 72
          Log->Write("INFO: \tNo events found");
          return;
     }

     Log->Write("INFO: \tParsing the event file");
     TiXmlDocument docEvent(eventfile);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
73 74
     if (!docEvent.LoadFile()) {
          Log->Write("ERROR: \t%s", docEvent.ErrorDesc());
Ulrich Kemloh's avatar
Ulrich Kemloh committed
75 76 77 78 79
          Log->Write("ERROR: \t could not parse the event file.");
          return;
     }

     TiXmlElement* xRootNode = docEvent.RootElement();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
80
     if (!xRootNode) {
Ulrich Kemloh's avatar
Ulrich Kemloh committed
81 82 83 84
          Log->Write("ERROR:\tRoot element does not exist.");
          exit(EXIT_FAILURE);
     }

Ulrich Kemloh's avatar
Ulrich Kemloh committed
85
     if (xRootNode->ValueStr() != "JPScore") {
Ulrich Kemloh's avatar
Ulrich Kemloh committed
86 87 88 89 90
          Log->Write("ERROR:\tRoot element value is not 'JPScore'.");
          exit(EXIT_FAILURE);
     }

     TiXmlNode* xEvents = xRootNode->FirstChild("events");
Ulrich Kemloh's avatar
Ulrich Kemloh committed
91
     if (!xEvents) {
Ulrich Kemloh's avatar
Ulrich Kemloh committed
92 93 94 95
          Log->Write("ERROR:\tNo events found.");
          exit(EXIT_FAILURE);
     }

Ulrich Kemloh's avatar
Ulrich Kemloh committed
96 97
     for (TiXmlElement* e = xEvents->FirstChildElement("event"); e;
               e = e->NextSiblingElement("event")) {
Ulrich Kemloh's avatar
Ulrich Kemloh committed
98 99 100 101 102 103
          _event_times.push_back(atoi(e->Attribute("time")));
          _event_types.push_back(e->Attribute("type"));
          _event_states.push_back(e->Attribute("state"));
          _event_ids.push_back(atoi(e->Attribute("id")));
     }
     Log->Write("INFO: \tEvents were read\n");
104 105
}

Ulrich Kemloh's avatar
Ulrich Kemloh committed
106
void EventManager::ListEvents()
107
{
Ulrich Kemloh's avatar
Ulrich Kemloh committed
108 109 110 111 112 113 114 115 116 117 118 119 120 121
     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]);
          }
     }
122 123 124

}

Ulrich Kemloh's avatar
Ulrich Kemloh committed
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
void EventManager::ReadEventsTxt(double time)
{
     rewind(_file);
     char cstring[256];
     int lines = 0;
     do {
          if (fgets(cstring, 30, _file) == NULL) {
               Log->Write("WARNING: \tCould not read the event file");
               return;
          }
          if (cstring[0] != '#') {        // keine Kommentarzeile
               lines++;
               if (lines > _eventCounter) {
                    Log->Write("INFO:\tEvent: after %f sec: ", time);
                    GetEvent(cstring);
                    _eventCounter++;
               }
          }
     } while (feof(_file) == 0);
144 145
}

146 147 148 149
/***********
 Update
 **********/

Ulrich Kemloh's avatar
Ulrich Kemloh committed
150 151
void EventManager::Update_Events(double time, double d)
{
Ulrich Kemloh's avatar
Ulrich Kemloh committed
152 153 154 155 156 157
     //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)
     //   Dann pruefen, ob eine neue Zeile in der .txt Datei steht
     //3. .txt Datei auf neue Zeilen pruefen. Wenn es neue gibt diese Events verarbeiten ( Tuere schliessen/oeffnen,
     //   neues Routing) ansonsten fertig

Ulrich Kemloh's avatar
Ulrich Kemloh committed
158 159
     _deltaT = d;
     const vector<Pedestrian*>& _allPeds = _building->GetAllPedestrians();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
160 161 162

     //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)
163
     int currentTime = _allPeds[0]->GetGlobalTime();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
164 165
     if (currentTime != _lastUpdateTime)
          if ((currentTime % UPDATE_FREQUENCY) == 0) {
166

Ulrich Kemloh's avatar
Ulrich Kemloh committed
167
               for (unsigned int p1 = 0; p1 < _allPeds.size(); p1++) {
168
                    Pedestrian* ped1 = _allPeds[p1];
Ulrich Kemloh's avatar
Ulrich Kemloh committed
169
                    if (ped1->GetNewEventFlag()) {
170 171 172
                         int rID = ped1->GetRoomID();
                         int srID = ped1->GetSubRoomID();

Ulrich Kemloh's avatar
Ulrich Kemloh committed
173
                         for (unsigned int p2 = 0; p2 < _allPeds.size(); p2++) {
174 175
                              Pedestrian* ped2 = _allPeds[p2];
                              //same room and subroom
Ulrich Kemloh's avatar
Ulrich Kemloh committed
176 177 178 179 180
                              if (rID == ped2->GetRoomID()
                                        && srID == ped2->GetSubRoomID()) {
                                   if (!ped2->GetNewEventFlag()
                                             && ped2->GetReroutingTime()
                                                       > 2.0) {
181 182 183
                                        //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();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
184 185 186 187 188 189 190 191
                                        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)
192 193 194
                                             //ped->RerouteIn(2.0);
                                             ped2->RerouteIn(0.0);
                                        }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
195 196 197
                                   }
                              }
                         }
198
                    }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
199
               }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
200
               _lastUpdateTime = currentTime;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
201 202 203 204
               //cout<<"updating..."<<currentTime<<endl<<endl;
          }

     //dann muss die Reroutingzeit der Peds, die die neuen Infos noch nicht haben, aktualisiert werden:
Ulrich Kemloh's avatar
Ulrich Kemloh committed
205
     for (unsigned int p1 = 0; p1 < _allPeds.size(); p1++) {
206 207
          Pedestrian* ped1 = _allPeds[p1];
          ped1->UpdateReroutingTime();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
208
          if (ped1->IsReadyForRerouting()) {
209 210 211
               ped1->ClearMentalMap();
               ped1->ResetRerouting();
               ped1->SetNewEventFlag(true);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
212 213 214 215
          }
     }

     //Events finden
Ulrich Kemloh's avatar
Ulrich Kemloh committed
216 217
     for (unsigned int i = 0; i < _event_times.size(); i++) {
          if (fabs(_event_times[i] - time) < J_EPS_EVENT) {
Ulrich Kemloh's avatar
Ulrich Kemloh committed
218
               //Event findet statt
Ulrich Kemloh's avatar
Ulrich Kemloh committed
219 220 221 222 223
               Log->Write("INFO:\tEvent: after %f sec: ", time);
               if (_event_states[i].compare("close") == 0) {
                    CloseDoor(_event_ids[i]);
               } else {
                    OpenDoor(_event_ids[i]);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
224 225 226
               }
          }
     }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
227 228
     if (_dynamic)
          ReadEventsTxt(time);
229 230 231 232 233
}

/***************
 Eventhandling
 **************/
Ulrich Kemloh's avatar
Ulrich Kemloh committed
234 235 236 237 238 239 240 241 242 243 244
void EventManager::CloseDoor(int id)
{
     //pruefen ob entsprechende Tuer schon zu ist, wenn nicht dann schliessen und neues Routing berechnen
     Transition *t = _building->GetTransition(id);
     if (t->IsOpen()) {
          t->Close();
          Log->Write("\tDoor %d closed.", id);
          ChangeRouting(id, "close");
     } else {
          Log->Write("Door %d is already close yet.", id);
     }
245 246 247

}

Ulrich Kemloh's avatar
Ulrich Kemloh committed
248 249 250 251 252 253 254 255 256 257 258
void EventManager::OpenDoor(int id)
{
     //pruefen ob entsprechende Tuer schon offen ist, wenn nicht dann oeffnen und neues Routing berechnen
     Transition *t = _building->GetTransition(id);
     if (!t->IsOpen()) {
          t->Open();
          Log->Write("\tDoor %d opened.", id);
          ChangeRouting(id, "open");
     } else {
          Log->Write("Door %d is already open yet.", id);
     }
259 260
}

Ulrich Kemloh's avatar
Ulrich Kemloh committed
261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293
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) {
          //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()));
          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);
          } else {
               _allPedestrians[p]->RerouteIn(time);
          }
          //if(dist>0.0&&dist<0.5){
294
          // _allPedestrians[p]->ClearMentalMap();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
295 296
          //}
          //else if(dist>=0.5&&dist<3.0){
297
          // _allPedestrians[p]->RerouteIn(1.0);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
298 299
          //}
          //else{
300
          // _allPedestrians[p]->RerouteIn(2.0);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
301 302 303
          //}
          //}
          //else{
304
          //  _allPedestrians[p]->ClearMentalMap();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
305 306
          //}
     }
307 308
}

Ulrich Kemloh's avatar
Ulrich Kemloh committed
309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337
void EventManager::GetEvent(char* c)
{
     int split = 0;
     string type = "";
     string id = "";
     string state = "";
     for (int i = 0; i < 20; i++) {
          if (!c[i]) {
               break;
          } else if (c[i] == ' ') {
               split++;
          } else if (c[i] == '\n') {

          } else {
               if (split == 0) {
                    type += c[i];
               } else if (split == 1) {
                    id += c[i];
               } else if (split == 2) {
                    state += c[i];
               }
          }

     }
     if (state.compare("close") == 0) {
          CloseDoor(atoi(id.c_str()));
     } else {
          OpenDoor(atoi(id.c_str()));
     }
338
}