EventManager.cpp 11.1 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 11
#define UPDATE_FREQUENCY 1 // in seconds


12
EventManager::EventManager(Building *_b){
13
    _event_times=vector<double>();
14 15 16
    _event_types=vector<string>();
    _event_states=vector<string>();
    _event_ids=vector<int>();
17
    _projectFilename = "";
18
    _building = _b;
19 20
    _eventCounter=0;
    _dynamic=false;
21
    _file = fopen("../events/events.txt","r");
Ulrich Kemloh's avatar
Ulrich Kemloh committed
22
    _lastUpdateTime=0;
23
    _deltaT=0;
24 25
    this->SetProjectFilename(_building->GetProjectFilename());
    this->SetProjectRootDir(_building->GetProjectRootDir());
26
    if(!_file){
27
        Log->Write("INFO:\tFiles 'events.txt' missing. Realtime interaction with the simulation not possible.");
28 29
    }
    else{
30
        Log->Write("INFO:\tFile 'events.txt' will be monitored for new events.");
31 32
        _dynamic=true;
    }
33
}
34

35 36 37 38 39 40
/*******************
 Dateien einlesen
 ******************/
void EventManager::SetProjectFilename(const std::string &filename){
    _projectFilename=filename;
}
41

42 43 44 45 46
void EventManager::SetProjectRootDir(const std::string &filename){
    _projectRootDir= filename;
}

void EventManager::readEventsXml(){
47
     Log->Write("INFO: \tLooking for pre-defined events in other files");
Ulrich Kemloh's avatar
Ulrich Kemloh committed
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
     //get the geometry filename from the project file
     TiXmlDocument doc(_projectFilename);
     if (!doc.LoadFile()){
          Log->Write("ERROR: \t%s", doc.ErrorDesc());
          Log->Write("ERROR: \t could not parse the project file.");
          exit(EXIT_FAILURE);
     }

     TiXmlElement* xMainNode = doc.RootElement();
     string eventfile="";
     if(xMainNode->FirstChild("events")){
          eventfile=_projectRootDir+xMainNode->FirstChild("events")->FirstChild()->Value();
          Log->Write("INFO: \tevents <"+eventfile+">");
     }
     else
     {
          Log->Write("INFO: \tNo events found");
          return;
     }

     Log->Write("INFO: \tParsing the event file");
     TiXmlDocument docEvent(eventfile);
     if(!docEvent.LoadFile()){
          Log->Write("ERROR: \t%s",docEvent.ErrorDesc());
          Log->Write("ERROR: \t could not parse the event file.");
          return;
     }

     TiXmlElement* xRootNode = docEvent.RootElement();
     if(!xRootNode){
          Log->Write("ERROR:\tRoot element does not exist.");
          exit(EXIT_FAILURE);
     }

     if( xRootNode->ValueStr () != "JPScore" ) {
          Log->Write("ERROR:\tRoot element value is not 'JPScore'.");
          exit(EXIT_FAILURE);
     }

     TiXmlNode* xEvents = xRootNode->FirstChild("events");
     if(!xEvents){
          Log->Write("ERROR:\tNo events found.");
          exit(EXIT_FAILURE);
     }

     for(TiXmlElement* e = xEvents->FirstChildElement("event"); e; e= e->NextSiblingElement("event")){
          _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");
100 101
}

102 103 104 105 106 107 108 109 110 111 112 113 114
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]);
115 116 117 118 119
        }
    }

}

120
void EventManager::readEventsTxt(double time){
121
    rewind(_file);
122 123
    char cstring[256];
    int lines=0;
124
    do{
125 126 127 128 129
        if(fgets(cstring,30,_file)==NULL)
        {
            Log->Write("WARNING: \tCould not read the event file");
            return;
        }
130 131 132 133 134 135 136
        if(cstring[0]!='#'){// keine Kommentarzeile
            lines++;
            if(lines>_eventCounter){
                Log->Write("INFO:\tEvent: after %f sec: ",time);
                getTheEvent(cstring);
                _eventCounter++;
            }
137
        }
138
     }while (feof(_file)==0);
139 140
}

141 142 143 144
/***********
 Update
 **********/

145
void EventManager::Update_Events(double time, double d){
Ulrich Kemloh's avatar
Ulrich Kemloh committed
146 147 148 149 150 151 152
     //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

     _deltaT=d;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
153
     const vector<Pedestrian*>& _allPeds=_building->GetAllPedestrians();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
154 155 156

     //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)
157
     int currentTime = _allPeds[0]->GetGlobalTime();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
158 159
     if(currentTime!=_lastUpdateTime)
          if((currentTime%UPDATE_FREQUENCY)==0) {
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184

               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);
                                        }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
185 186 187
                                   }
                              }
                         }
188
                    }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
189 190 191 192 193 194
               }
               _lastUpdateTime=currentTime;
               //cout<<"updating..."<<currentTime<<endl<<endl;
          }

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

     //Events finden
     for(unsigned int i=0;i<_event_times.size();i++){
          if(fabs(_event_times[i]-time)<J_EPS_EVENT){
               //Event findet statt
               Log->Write("INFO:\tEvent: after %f sec: ",time);
               if(_event_states[i].compare("close")==0){
                    closeDoor(_event_ids[i]);
               }
               else{
                    openDoor(_event_ids[i]);
               }
          }
     }
     if(_dynamic)
          readEventsTxt(time);
221 222 223 224 225 226 227 228 229 230
}

/***************
 Eventhandling
 **************/
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();
231
        Log->Write("\tDoor %d closed.",id);
232
        changeRouting(id,"close");
233
    }
234
    else{
235
        Log->Write("Door %d is already close yet.", id);
236
    }
237 238 239 240 241 242 243 244

}

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();
245
        Log->Write("\tDoor %d opened.",id);
246 247 248
        changeRouting(id,"open");
    }
    else{
249
        Log->Write("Door %d is already open yet.", id);
250 251 252
    }
}

253 254 255
void EventManager::changeRouting(int id, string state){
    RoutingEngine* routingEngine= _building->GetRoutingEngine();
    routingEngine->Init(_building);
256
    //_building->InitPhiAllPeds(_deltaT);
Ulrich Kemloh's avatar
Ulrich Kemloh committed
257
    const vector<Pedestrian*>& _allPedestrians=_building->GetAllPedestrians();
258
    unsigned int nSize = _allPedestrians.size();
259

260 261
    //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
262
    Transition *t = _building->GetTransition(id);
263
    //Abstand der aktuellen Position des Pedestrians zur entsprechenden Tuer: Tuer als Linie sehen und mit
264
    //DistTo(ped.GetPos()) den Abstand messen. Reroutezeit dann aus Entfernung und Geschwindigkeit berechnen.
265
    Line* l = new Line(t->GetPoint1(),t->GetPoint2());
266
    for (unsigned int p = 0; p < nSize; ++p) {
267
        //if(_allPedestrians[p]->GetExitIndex()==t->GetUniqueID()){
268
        _allPedestrians[p]->SetNewEventFlag(false);
269
        double dist = l->DistTo(_allPedestrians[p]->GetPos());
270 271
        Point v = _allPedestrians[p]->GetV();
        double norm =sqrt((v.GetX()*v.GetX())+(v.GetY()*v.GetY()));
272
        if(norm==0.0){
273
            norm=0.01;
274
        }
275 276 277 278
        double time = dist/norm;
        if(time<1.0){
            _allPedestrians[p]->ClearMentalMap();
            _allPedestrians[p]->ResetRerouting();
279
            _allPedestrians[p]->SetNewEventFlag(true);
280 281
        }
        else{
282
            _allPedestrians[p]->RerouteIn(time);
283
        }
284 285 286 287 288 289 290 291 292
        //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);
        //}
293 294 295 296
        //}
        //else{
          //  _allPedestrians[p]->ClearMentalMap();
        //}
297 298 299 300 301 302 303 304 305
    }
}

void EventManager::getTheEvent(char* c){
    int split = 0;
    string type = "";
    string id = "";
    string state = "";
    for(int i=0;i<20;i++){
306
        if(!c[i]){
307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332
            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()));
333
    }
334
}