Simulation.cpp 46.1 KB
Newer Older
1
/**
Weichen's avatar
Weichen committed
2 3
 * \file        Simulation.cpp
 * \date        Dec 15, 2010
Mohcine Chraibi's avatar
Mohcine Chraibi committed
4
 * \version     v0.8.1
5
 * \copyright   <2009-2015> Forschungszentrum Jülich GmbH. All rights reserved.
6
 *
Weichen's avatar
Weichen committed
7
 * \section License
8 9 10
 * This file is part of JuPedSim.
 *
 * JuPedSim is free software: you can redistribute it and/or modify
11
 * it under the terms of the GNU Lesser General Public License as published by
12 13 14 15 16 17 18 19
 * 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.
 *
20
 * You should have received a copy of the GNU Lesser General Public License
Weichen's avatar
Weichen committed
21
 * along with JuPedSim. If not, see <http://www.gnu.org/licenses/>.
22
 *
23
 * \section Description
24 25 26 27
 * The Simulation class represents a simulation of pedestrians
 * based on a certain model in a specific scenario. A simulation is defined by
 * various parameters and functions.
 *
Weichen's avatar
Weichen committed
28 29 30
 *
 **/

Ulrich Kemloh's avatar
Ulrich Kemloh committed
31
#include "Simulation.h"
Mohcine Chraibi's avatar
Mohcine Chraibi committed
32
#include "IO/progress_bar.hpp"
33
#include "routing/ff_router/ffRouter.h"
Ulrich Kemloh's avatar
Ulrich Kemloh committed
34 35
#include "math/GCFMModel.h"
#include "math/GompertzModel.h"
Arne Graf's avatar
Arne Graf committed
36
#include "math/GradientModel.h"
37
#include "pedestrian/AgentsQueue.h"
38
#include "pedestrian/AgentsSourcesManager.h"
39 40
#include "geometry/WaitingArea.h"

41
#ifdef _OPENMP
GrgrLmml's avatar
GrgrLmml committed
42

43 44 45 46
#else
#define omp_get_thread_num() 0
#define omp_get_max_threads()  1
#endif
47
namespace fs = std::filesystem;
48
using namespace std;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
49

50
OutputHandler* Log;
51
Trajectories* outputTXT;
52 53 54 55 56
// todo: add these variables to class simulation
std::map<std::string, std::shared_ptr<TrainType> > TrainTypes;
std::map<int, std::shared_ptr<TrainTimeTable> >  TrainTimeTables;
std::map<int, double> trainOutflow;
//--------
Arne Graf's avatar
Arne Graf committed
57
Simulation::Simulation(Configuration* args)
GrgrLmml's avatar
GrgrLmml committed
58
        :_config(args)
59
{
60 61
     _countTraj = 0;
     _maxFileSize = 10; // MB
GrgrLmml's avatar
GrgrLmml committed
62 63 64 65 66 67 68 69 70 71
    _nPeds = 0;
    _seed = 8091983;
    _deltaT = 0;
    _building = nullptr;
    //_direction = NULL;
    _operationalModel = nullptr;
    _solver = nullptr;
    _iod = new IODispatcher();
    _fps = 1;
    _em = nullptr;
72
    _gotSources = false;
73
    _trainConstraints = false;
74
    _maxSimTime = 100;
GrgrLmml's avatar
GrgrLmml committed
75
//     _config = args;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
76 77
}

78 79
Simulation::~Simulation()
{
GrgrLmml's avatar
GrgrLmml committed
80 81 82
    delete _solver;
    delete _iod;
    delete _em;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
83 84
}

85
long Simulation::GetPedsNumber() const
86
{
GrgrLmml's avatar
GrgrLmml committed
87
    return _nPeds;
Ulrich Kemloh's avatar
Ulrich Kemloh committed
88 89
}

GrgrLmml's avatar
GrgrLmml committed
90
bool Simulation::InitArgs()
91
{
GrgrLmml's avatar
GrgrLmml committed
92 93 94 95
    char tmp[CLENGTH];
    string s = "Parameter:\n";

    switch (_config->GetLog()) {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
96 97
    case 0: {

GrgrLmml's avatar
GrgrLmml committed
98
        break;
Mohcine Chraibi's avatar
Mohcine Chraibi committed
99 100
    }
    case 1: {
GrgrLmml's avatar
GrgrLmml committed
101 102 103 104
        if (Log)
            delete Log;
        Log = new STDIOHandler();
        break;
Mohcine Chraibi's avatar
Mohcine Chraibi committed
105
    }
GrgrLmml's avatar
GrgrLmml committed
106 107
    case 2: {
        char name[CLENGTH] = "";
Mohcine Chraibi's avatar
Mohcine Chraibi committed
108
        sprintf(name, "%s.txt", _config->GetErrorLogFile().c_str());
GrgrLmml's avatar
GrgrLmml committed
109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
        if (Log)
            delete Log;
        Log = new FileHandler(name);
    }
        break;
    default:
        printf("Wrong option for Logfile!\n\n");
        return false;
    }

    if (_config->GetPort()!=-1) {
        switch (_config->GetFileFormat()) {
        case FORMAT_XML_PLAIN_WITH_MESH:
        case FORMAT_XML_PLAIN: {
            OutputHandler* travisto = new SocketHandler(_config->GetHostname(),
                    _config->GetPort());
Mohcine Chraibi's avatar
Mohcine Chraibi committed
125
            Trajectories* output = new TrajectoriesJPSV05();
GrgrLmml's avatar
GrgrLmml committed
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154
            output->SetOutputHandler(travisto);
            _iod->AddIO(output);
            break;
        }
        case FORMAT_XML_BIN: {
            Log->Write(
                    "INFO: \tFormat xml-bin not yet supported in streaming\n");
            //exit(0);
            break;
        }
        case FORMAT_PLAIN: {
            Log->Write(
                    "INFO: \tFormat plain not yet supported in streaming\n");
            return false;
        }
        case FORMAT_VTK: {
            Log->Write(
                    "INFO: \tFormat vtk not yet supported in streaming\n");
            return false;
        }
        default: {
            return false;
        }
        }

        s.append("\tonline streaming enabled \n");
    }

    if (!_config->GetTrajectoriesFile().empty()) {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
155 156 157 158 159 160 161 162 163 164
         fs::path p(_config->GetTrajectoriesFile());
         fs::path curr_abs_path = fs::current_path();
         fs::path rel_path = _config->GetTrajectoriesFile();
         fs::path combined = (curr_abs_path /= rel_path);
         std::string traj = combined.string();
         _config->SetTrajectoriesFile(combined);
         if(!fs::exists(traj))
              fs::create_directories(combined.parent_path());


GrgrLmml's avatar
GrgrLmml committed
165 166 167
        switch (_config->GetFileFormat()) {
        case FORMAT_XML_PLAIN: {
            OutputHandler* tofile = new FileHandler(
Mohcine Chraibi's avatar
Mohcine Chraibi committed
168
                    traj.c_str());
GrgrLmml's avatar
GrgrLmml committed
169 170 171 172 173 174
            Trajectories* output = new TrajectoriesJPSV05();
            output->SetOutputHandler(tofile);
            _iod->AddIO(output);
            break;
        }
        case FORMAT_PLAIN: {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
175 176 177



GrgrLmml's avatar
GrgrLmml committed
178
            OutputHandler* file = new FileHandler(
Mohcine Chraibi's avatar
Mohcine Chraibi committed
179
                 traj.c_str());
180 181 182
            outputTXT = new TrajectoriesFLAT();
            outputTXT->SetOutputHandler(file);
            _iod->AddIO(outputTXT);
GrgrLmml's avatar
GrgrLmml committed
183 184 185 186 187
            break;
        }
        case FORMAT_VTK: {
            Log->Write("INFO: \tFormat vtk not yet supported\n");
            OutputHandler* file = new FileHandler(
Mohcine Chraibi's avatar
Mohcine Chraibi committed
188
                    (traj+".vtk").c_str());
GrgrLmml's avatar
GrgrLmml committed
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
            Trajectories* output = new TrajectoriesVTK();
            output->SetOutputHandler(file);
            _iod->AddIO(output);
            break;
        }

        case FORMAT_XML_PLAIN_WITH_MESH: {
            //OutputHandler* tofile = new FileHandler(args->GetTrajectoriesFile().c_str());
            //if(_iod) delete _iod;
            //_iod = new TrajectoriesXML_MESH();
            //_iod->AddIO(tofile);
            break;
        }
        case FORMAT_XML_BIN: {
            // OutputHandler* travisto = new SocketHandler(args->GetHostname(), args->GetPort());
            // Trajectories* output= new TrajectoriesJPSV06();
            // output->SetOutputHandler(travisto);
            // _iod->AddIO(output);
            break;
        }
        default: {
            break;
        }
        }
    }

    _operationalModel = _config->GetModel();
    s.append(_operationalModel->GetDescription());

    // ODE solver which is never used!
    auto solver = _config->GetSolver();
    sprintf(tmp, "\tODE Solver: %d\n", solver);
    s.append(tmp);

    sprintf(tmp, "\tnCPU: %d\n", _config->GetMaxOpenMPThreads());
    s.append(tmp);
    sprintf(tmp, "\tt_max: %f\n", _config->GetTmax());
    s.append(tmp);
    _deltaT = _config->Getdt();
228
    _maxSimTime = _config->GetTmax();
GrgrLmml's avatar
GrgrLmml committed
229 230 231 232 233 234 235 236 237 238 239 240 241
    sprintf(tmp, "\tdt: %f\n", _deltaT);
    _periodic = _config->IsPeriodic();
    sprintf(tmp, "\t periodic: %d\n", _periodic);
    s.append(tmp);

    _fps = _config->GetFps();
    sprintf(tmp, "\tfps: %f\n", _fps);
    s.append(tmp);
    //Log->Write(s.c_str());

    _routingEngine = _config->GetRoutingEngine();
    auto distributor = std::unique_ptr<PedDistributor>(new PedDistributor(_config));
    // IMPORTANT: do not change the order in the following..
242
    _building = std::shared_ptr<Building>(new Building(_config, *distributor));
GrgrLmml's avatar
GrgrLmml committed
243 244 245

    // Initialize the agents sources that have been collected in the pedestrians distributor
    _agentSrcManager.SetBuilding(_building.get());
246
    _agentSrcManager.SetMaxSimTime(GetMaxSimTime());
Mohcine Chraibi's avatar
Mohcine Chraibi committed
247
    _gotSources = (bool) distributor->GetAgentsSources().size(); // did we have any sources? false if no sources
Mohcine Chraibi's avatar
Mohcine Chraibi committed
248
    std::cout << "\nGot " << _gotSources  << " sources"<< std::endl ;
249

GrgrLmml's avatar
GrgrLmml committed
250 251
    for (const auto& src: distributor->GetAgentsSources()) {
        _agentSrcManager.AddSource(src);
252
        src->Dump();
GrgrLmml's avatar
GrgrLmml committed
253 254 255 256
    }



257

GrgrLmml's avatar
GrgrLmml committed
258 259 260 261 262 263 264
    //perform customs initialisation, like computing the phi for the gcfm
    //this should be called after the routing engine has been initialised
    // because a direction is needed for this initialisation.
    Log->Write("INFO:\t Init Operational Model starting ...");
    if (!_operationalModel->Init(_building.get()))
        return false;
    Log->Write("INFO:\t Init Operational Model done");
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
    Log->Write("Got %d Train Types", _building->GetTrainTypes().size());
    for(auto&& TT: _building->GetTrainTypes())
    {
          Log->Write("INFO\ttype         : %s",TT.second->type.c_str());
          Log->Write("INFO\tMax          : %d",TT.second->nmax);
          Log->Write("INFO\tnumber doors : %d\n",TT.second->doors.size());
    }
    if(_building->GetTrainTimeTables().size())
         Log->Write("INFO:\tGot %d Train Time Tables",_building->GetTrainTimeTables().size());
    else
         Log->Write("WARNING:\tGot %d Train Time Tables",_building->GetTrainTimeTables().size());
    for(auto&& TT: _building->GetTrainTimeTables())
    {
          Log->Write("INFO\tid           : %d",TT.second->id);
          Log->Write("INFO\ttype         : %s",TT.second->type.c_str());
          Log->Write("INFO\troom id      : %d",TT.second->rid);
          Log->Write("INFO\ttin          : %.2f%",TT.second->tin);
          Log->Write("INFO\ttout         : %.2f",TT.second->tout);
          Log->Write("INFO\ttrack start  : (%.2f, %.2f)",TT.second->pstart._x,TT.second->pstart._y);
          Log->Write("INFO\ttrack end    : (%.2f, %.2f)",TT.second->pend._x,TT.second->pend._y);
          Log->Write("INFO\ttrain start  : (%.2f, %.2f)",TT.second->tstart._x, TT.second->tstart._y);
          Log->Write("INFO\ttrain end    : (%.2f, %.2f)\n",TT.second->tend._x, TT.second->tend._y);
    }
    //@todo: these variables are global
    TrainTypes = _building->GetTrainTypes();
    TrainTimeTables = _building->GetTrainTimeTables();
    _trainConstraints = (bool) TrainTimeTables.size();
f.mack's avatar
f.mack committed
292

293
    //-----
f.mack's avatar
f.mack committed
294 295 296 297 298
    // Give the DirectionStrategy the chance to perform some initialization.
    // This should be done after the initialization of the operationalModel
    // because then, invalid pedestrians have been deleted and FindExit()
    // has been called.

GrgrLmml's avatar
GrgrLmml committed
299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321
    //other initializations
    for (auto&& ped: _building->GetAllPedestrians()) {
        ped->Setdt(_deltaT);
    }
    _nPeds = _building->GetAllPedestrians().size();
    //_building->WriteToErrorLog();
    Log->Write("INFO:\t nPeds %d received", _nPeds);
    //get the seed
    _seed = _config->GetSeed();

    //size of the cells/GCFM/Gompertz
    if (_config->GetDistEffMaxPed()>_config->GetLinkedCellSize()) {
        Log->Write(
                "ERROR: the linked-cell size [%f] should be bigger than the force range [%f]",
                _config->GetLinkedCellSize(), _config->GetDistEffMaxPed());
        return false;
    }

    //read and initialize events
    _em = new EventManager(_building.get(), _config->GetSeed());
    if (!_em->ReadEventsXml()) {
        Log->Write("ERROR: \tCould not initialize events handling");
    }
322 323 324 325 326
     if (!_em->ReadSchedule()) {
          Log->Write("ERROR: \tCould not initialize schedule handling");
     }

     _em->ListEvents();
GrgrLmml's avatar
GrgrLmml committed
327 328 329 330 331 332 333 334

    //_building->SaveGeometry("test.sav.xml");

    //if(_building->SanityCheck()==false)
    //     return false;

    //everything went fine
    return true;
335
}
336

337
double Simulation::RunStandardSimulation(double maxSimTime)
338
{
GrgrLmml's avatar
GrgrLmml committed
339 340 341
    RunHeader(_nPeds+_agentSrcManager.GetMaxAgentNumber());
    double t = RunBody(maxSimTime);
    RunFooter();
342
    return t;
343
}
344

345
void Simulation::UpdateRoutesAndLocations()
346
{
347 348
     //pedestrians to be deleted
     //you should better create this in the constructor and allocate it once.
349 350
     set<Pedestrian*> pedsToRemove;
//     pedsToRemove.reserve(500); //just reserve some space
351 352

     // collect all pedestrians in the simulation.
353 354
     const vector<Pedestrian*>& allPeds = _building->GetAllPedestrians();
     const map<int, Goal*>& goals = _building->GetAllGoals();
Oliver Schmidts's avatar
Oliver Schmidts committed
355
     auto allRooms = _building->GetAllRooms();
356

357 358 359 360 361 362
//    for (signed int p = 0; p < allPeds.size(); ++p) {
//        Pedestrian* ped = allPeds[p];
//
//        std::cout << "FinalDestination of [" << ped->GetID() << "] in (" << ped->GetRoomID() << ", " << ped->GetSubRoomID() << "/" <<  ped->GetSubRoomUID() << "): " << ped->GetFinalDestination() << std::endl;
//    }

Oliver Schmidts's avatar
Oliver Schmidts committed
363
#pragma omp parallel for shared(pedsToRemove, allRooms)
Ozaq's avatar
Ozaq committed
364
     for (size_t p = 0; p < allPeds.size(); ++p) {
Oliver Schmidts's avatar
Oliver Schmidts committed
365 366 367
          auto ped = allPeds[p];
          Room* room = _building->GetRoom(ped->GetRoomID());
          SubRoom* sub0 = room->GetSubRoom(ped->GetSubRoomID());
368

Oliver Schmidts's avatar
Oliver Schmidts committed
369 370
          //set the new room if needed
          if ((ped->GetFinalDestination() == FINAL_DEST_OUT)
371
              && (room->GetCaption() == "outside")) { //TODO Hier aendern fuer inside goals?
f.mack's avatar
f.mack committed
372
#pragma omp critical(Simulation_Update_pedsToRemove)
373
               pedsToRemove.insert(ped);
Oliver Schmidts's avatar
Oliver Schmidts committed
374
          } else if ((ped->GetFinalDestination() != FINAL_DEST_OUT)
GrgrLmml's avatar
GrgrLmml committed
375
                    && (goals.at(ped->GetFinalDestination())->Contains(
376
                              ped->GetPos()))&& (goals.at(ped->GetFinalDestination())->GetIsFinalGoal())) {
f.mack's avatar
f.mack committed
377
#pragma omp critical(Simulation_Update_pedsToRemove)
378
               pedsToRemove.insert(ped);
Oliver Schmidts's avatar
Oliver Schmidts committed
379
          }
GrgrLmml's avatar
GrgrLmml committed
380

Oliver Schmidts's avatar
Oliver Schmidts committed
381 382 383 384 385
          // reposition in the case the pedestrians "accidently left the room" not via the intended exit.
          // That may happen if the forces are too high for instance
          // the ped is removed from the simulation, if it could not be reassigned
          else if (!sub0->IsInSubRoom(ped))
          {
386

Oliver Schmidts's avatar
Oliver Schmidts committed
387 388 389 390
               bool assigned = false;
               std::function<void(const Pedestrian&)> f = std::bind(&Simulation::UpdateFlowAtDoors, this, std::placeholders::_1);
               assigned = ped->Relocate(f);
               //this will delete agents, that are pushed outside (maybe even if inside obstacles??)
391

Oliver Schmidts's avatar
Oliver Schmidts committed
392
               if (!assigned) {
f.mack's avatar
f.mack committed
393
#pragma omp critical(Simulation_Update_pedsToRemove)
394
                       pedsToRemove.insert(ped); //the agent left the old room
GrgrLmml's avatar
GrgrLmml committed
395
                    //actualize the eggress time for that room
f.mack's avatar
f.mack committed
396
#pragma omp critical(SetEgressTime)
GrgrLmml's avatar
GrgrLmml committed
397 398
                    allRooms.at(ped->GetRoomID())->SetEgressTime(ped->GetGlobalTime());

399 400
               }
          }
Mohcine Chraibi's avatar
Mohcine Chraibi committed
401 402 403
          // actualize routes for sources
          if(_gotSources)
               ped->FindRoute();
Oliver Schmidts's avatar
Oliver Schmidts committed
404
          //finally actualize the route
405
          if ( !_gotSources && ped->FindRoute() == -1 && !_trainConstraints) {
Oliver Schmidts's avatar
Oliver Schmidts committed
406
               //a destination could not be found for that pedestrian
407 408
               Log->Write("ERROR: \tCould not find a route for pedestrian %d in room %d and subroom %d",
                         ped->GetID(), ped->GetRoomID(), ped->GetSubRoomID());
Mohcine Chraibi's avatar
Mohcine Chraibi committed
409
               //ped->FindRoute(); //debug only, plz remove
Arne Graf's avatar
Arne Graf committed
410 411
               std::function<void(const Pedestrian&)> f = std::bind(&Simulation::UpdateFlowAtDoors, this, std::placeholders::_1);
               ped->Relocate(f);
Oliver Schmidts's avatar
Oliver Schmidts committed
412
               //exit(EXIT_FAILURE);
f.mack's avatar
f.mack committed
413
#pragma omp critical(Simulation_Update_pedsToRemove)
414
               {
Mohcine Chraibi's avatar
Mohcine Chraibi committed
415
                    pedsToRemove.insert(ped);
416 417
                    Log->incrementDeletedAgents();
               }
Oliver Schmidts's avatar
Oliver Schmidts committed
418 419
          }
     }
GrgrLmml's avatar
GrgrLmml committed
420

421

Ulrich Kemloh's avatar
Ulrich Kemloh committed
422
#ifdef _USE_PROTOCOL_BUFFER
423 424
     if (_hybridSimManager)
     {
Arne Graf's avatar
Arne Graf committed
425
          AgentsQueueOut::Add(pedsToRemove);    //this should be critical region (and it is)
426 427
     }
     else
Ulrich Kemloh's avatar
Ulrich Kemloh committed
428
#endif
GrgrLmml's avatar
GrgrLmml committed
429
    {
430

GrgrLmml's avatar
GrgrLmml committed
431
        // remove the pedestrians that have left the building
432 433 434
        for (auto p : pedsToRemove){
            UpdateFlowAtDoors(*p);
            _building->DeletePedestrian(p);
GrgrLmml's avatar
GrgrLmml committed
435
        }
Arne Graf's avatar
Arne Graf committed
436
        pedsToRemove.clear();
GrgrLmml's avatar
GrgrLmml committed
437 438 439 440 441 442 443 444
    }

    //    temporary fix for the safest path router
    //    if (dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1)))
    //    {
    //         SafestPathRouter* spr = dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1));
    //         spr->ComputeAndUpdateDestinations(_allPedestians);
    //    }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
445
}
446

Mohcine Chraibi's avatar
Mohcine Chraibi committed
447
void Simulation::PrintStatistics(double simTime)
448
{
Mohcine Chraibi's avatar
Mohcine Chraibi committed
449
    Log->Write("\nRooms Egress. Simulation Time: %.2f", simTime);
GrgrLmml's avatar
GrgrLmml committed
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468
    Log->Write("==================");
    Log->Write("id\tcaption\tegress time (s)");

    for (const auto& it:_building->GetAllRooms()) {
        auto&& room = it.second;
        if (room->GetCaption()!="outside")
            Log->Write("%d\t%s\t%.2f", room->GetID(), room->GetCaption().c_str(), room->GetEgressTime());
    }

    Log->Write("\nUsage of Exits");
    Log->Write("==========");
    for (const auto& itr : _building->GetAllTransitions()) {
        Transition* goal = itr.second;
        if (goal->GetDoorUsage()) {
            Log->Write(
                    "\nExit ID [%d] used by [%d] pedestrians. Last passing time [%0.2f] s",
                    goal->GetID(), goal->GetDoorUsage(),
                    goal->GetLastPassingTime());

Mohcine Chraibi's avatar
Mohcine Chraibi committed
469 470 471
            fs::path p(_config->GetOriginalTrajectoriesFile());

            string statsfile = "flow_exit_id_"+to_string(goal->GetID())+"_"+p.stem().string()+".txt";
472 473 474
            if(goal->GetOutflowRate() <  (std::numeric_limits<double>::max)())
            {
                 char tmp[50];
Mohcine Chraibi's avatar
Mohcine Chraibi committed
475 476
                 sprintf(tmp, "%.2f_", goal->GetOutflowRate());
                 statsfile = "flow_exit_id_"+to_string(goal->GetID())+"_rate_"+tmp+p.stem().string()+".txt";
477
            }
GrgrLmml's avatar
GrgrLmml committed
478
            Log->Write("More Information in the file: %s", statsfile.c_str());
479 480 481 482 483 484 485 486 487
            {
                 auto statOutput = new FileHandler(statsfile.c_str());
                 statOutput->Write("#Simulation time: %.2f", simTime);
                 statOutput->Write("#Flow at exit "+goal->GetCaption()+"( ID "+to_string(goal->GetID())+" )");
                 statOutput->Write("#Time (s)  cummulative number of agents \n");
                 statOutput->Write(goal->GetFlowCurve());
                 statOutput->FileHandler::~FileHandler();
            }

GrgrLmml's avatar
GrgrLmml committed
488 489
        }
    }
490 491 492 493

        Log->Write("\nUsage of Crossings");
        Log->Write("==========");
        for (const auto& itr : _building->GetAllCrossings()) {
494 495 496 497 498 499 500 501 502 503 504 505 506
             Crossing* goal = itr.second;
             if (goal->GetDoorUsage()) {
                  Log->Write(
                       "\nCrossing ID [%d] in Room ID [%d] used by [%d] pedestrians. Last passing time [%0.2f] s",
                       goal->GetID(), itr.first/1000, goal->GetDoorUsage(),
                       goal->GetLastPassingTime());

                  string statsfile = "flow_crossing_id_"
                       + to_string(itr.first/1000) + "_" + to_string(itr.first % 1000) +".dat";
                  Log->Write("More Information in the file: %s", statsfile.c_str());
                  auto output = new FileHandler(statsfile.c_str());
                  output->Write("#Simulation time: %.2f", simTime);
                  output->Write("#Flow at crossing " + goal->GetCaption() + "( ID " + to_string(goal->GetID())
507
                                + " ) in Room ( ID "+ to_string(itr.first / 1000) + " )");
508 509 510
                  output->Write("#Time (s)  cummulative number of agents \n");
                  output->Write(goal->GetFlowCurve());
             }
511 512
        }

GrgrLmml's avatar
GrgrLmml committed
513
    Log->Write("\n");
Ulrich Kemloh's avatar
Ulrich Kemloh committed
514 515
}

516 517
void Simulation::RunHeader(long nPed)
{
GrgrLmml's avatar
GrgrLmml committed
518 519
    // writing the header
    if (nPed==-1) nPed = _nPeds;
520 521
    _iod->WriteHeader(nPed, _fps, _building.get(), _seed, 0);// first trajectory
                                                             // count = 0
GrgrLmml's avatar
GrgrLmml committed
522
    _iod->WriteGeometry(_building.get());
Mohcine Chraibi's avatar
Mohcine Chraibi committed
523 524
    if( _gotSources)
         _iod->WriteSources( GetAgentSrcManager().GetSources());
525

GrgrLmml's avatar
GrgrLmml committed
526 527 528
    int writeInterval = (int) ((1./_fps)/_deltaT+0.5);
    writeInterval = (writeInterval<=0) ? 1 : writeInterval; // mustn't be <= 0
    int firstframe = (Pedestrian::GetGlobalTime()/_deltaT)/writeInterval;
529

GrgrLmml's avatar
GrgrLmml committed
530 531 532 533
    _iod->WriteFrame(firstframe, _building.get());
    //first initialisation needed by the linked-cells
    UpdateRoutesAndLocations();
    ProcessAgentsQueue();
534
}
Ulrich Kemloh's avatar
Ulrich Kemloh committed
535

536
double Simulation::RunBody(double maxSimTime)
537
{
GrgrLmml's avatar
GrgrLmml committed
538 539 540 541 542 543 544
    //needed to control the execution time PART 1
    //in the case you want to run in no faster than realtime
    //time_t starttime, endtime;
    //time(&starttime);

    //take the current time from the pedestrian
    double t = Pedestrian::GetGlobalTime();
545 546 547 548
    fs::path TrajectoryName(_config->GetTrajectoriesFile());// in case we
                                                                // may need to
                                                                // generate
                                                                // several small files
GrgrLmml's avatar
GrgrLmml committed
549 550 551
    //frame number. This function can be called many times,
    static int frameNr = (int) (1+t/_deltaT); // Frame Number

552 553 554 555
    //##########
    //PROBLEMATIC: time when frame should be printed out
    // possibly skipped when using the following lines
    // NEEDS TO BE FIXED!
GrgrLmml's avatar
GrgrLmml committed
556 557
    int writeInterval = (int) ((1./_fps)/_deltaT+0.5);
    writeInterval = (writeInterval<=0) ? 1 : writeInterval; // mustn't be <= 0
558
    // ##########
GrgrLmml's avatar
GrgrLmml committed
559 560 561 562 563 564

    //process the queue for incoming pedestrians
    //important since the number of peds is used
    //to break the main simulation loop
    ProcessAgentsQueue();
    _nPeds = _building->GetAllPedestrians().size();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
565
    std::cout << "\n";
Mohcine Chraibi's avatar
Mohcine Chraibi committed
566
    std::string description = "Evacutation ";
Mohcine Chraibi's avatar
Mohcine Chraibi committed
567 568 569 570 571 572 573
    ProgressBar *bar = new ProgressBar(_nPeds, description);
    // bar->SetFrequencyUpdate(10);
#ifdef _WINDOWS
    bar->SetStyle("|","-");
#else
    bar->SetStyle("\u2588", "-"); //for linux
#endif
GrgrLmml's avatar
GrgrLmml committed
574 575
    int initialnPeds = _nPeds;
    // main program loop
576
    while ((_nPeds || (!_agentSrcManager.IsCompleted()&& _gotSources) ) && t<maxSimTime) {
GrgrLmml's avatar
GrgrLmml committed
577
        t = 0+(frameNr-1)*_deltaT;
578 579
        // Handle train traffic: coorect geometry
        bool geometryChanged= TrainTraffic();
580

581
        //process the queue for incoming pedestrians
GrgrLmml's avatar
GrgrLmml committed
582 583 584 585 586 587 588 589 590 591 592 593
        ProcessAgentsQueue();

        if (t>Pedestrian::GetMinPremovementTime()) {
            //update the linked cells
            _building->UpdateGrid();

            // update the positions
            _operationalModel->ComputeNextTimeStep(t, _deltaT, _building.get(), _periodic);

            //update the events
            _em->ProcessEvent();

594 595
            //here we could place router-tasks (calc new maps) that can use multiple cores AND we have 't'
            //update quickestRouter
596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614
            if(geometryChanged)
            {
                 // debug
                 fs::path f("tmp_"+std::to_string(t)+"_"+_config->GetGeometryFile());
                 std::string filename = f.string();
                 std::cout << "\nUpdate geometry. New  geometry --> " << filename.c_str() << "\n";

                 std::cout<< KGRN << "Enter correctGeometry: Building Has " << _building->GetAllTransitions().size() << " Transitions\n" << RESET;
                 _building->SaveGeometry(filename);
                 //
                 double _deltaH = _building->GetConfig()->get_deltaH();
                 double _wallAvoidDistance = _building->GetConfig()->get_wall_avoid_distance();
                 bool _useWallAvoidance = _building->GetConfig()->get_use_wall_avoidance();

                 if(auto dirlocff = dynamic_cast<DirectionLocalFloorfield*>(_building->GetConfig()->get_dirStrategy())){
                      Log->Write("INFO:\t Init DirectionLOCALFloorfield starting ...");
                      dirlocff->Init(_building.get(), _deltaH, _wallAvoidDistance, _useWallAvoidance);
                      Log->Write("INFO:\t Init DirectionLOCALFloorfield done");
                 }
615
                }
616 617 618 619 620 621 622
            else{ // quickest needs update even if NeedsUpdate() is false
                 FFRouter* ffrouter = dynamic_cast<FFRouter*>(_routingEngine.get()->GetRouter(ROUTING_FF_QUICKEST));
                 if(ffrouter != nullptr)
                      if (ffrouter->MustReInit()) {
                           ffrouter->ReInit();
                           ffrouter->SetRecalc(t);
                      }
623
            }
624

tobias schroedter's avatar
tobias schroedter committed
625 626
            // here the used routers are update, when needed due to external changes
            if (_routingEngine->NeedsUpdate()){
627
                 std::cout << KBLU << " Init router in simulation\n" << RESET;
628 629 630
                 _routingEngine->UpdateRouter();
            }

GrgrLmml's avatar
GrgrLmml committed
631 632 633 634 635 636 637 638 639 640 641 642 643
            //update the routes and locations
            UpdateRoutesAndLocations();

            //other updates
            //someone might have left the building
            _nPeds = _building->GetAllPedestrians().size();
        }

        // update the global time
        Pedestrian::SetGlobalTime(t);

        // write the trajectories
        if (0==frameNr%writeInterval) {
644 645
              _iod->WriteFrame(frameNr/writeInterval, _building.get());
              WriteTrajectories(TrajectoryName.stem().string());
GrgrLmml's avatar
GrgrLmml committed
646
        }
Mohcine Chraibi's avatar
Mohcine Chraibi committed
647 648

        if(!_gotSources && !_periodic && _config->print_prog_bar())
Arne Graf's avatar
Arne Graf committed
649 650 651
              // Log->ProgressBar(initialnPeds, initialnPeds-_nPeds, t);
              bar->Progressed(initialnPeds-_nPeds);
        else
Mohcine Chraibi's avatar
No  
Mohcine Chraibi committed
652 653 654
             if ((!_gotSources) &&
                 ((frameNr < 100 &&  frameNr % 10 == 0) ||
                  (frameNr > 100 &&  frameNr % 100 == 0)))
Mohcine Chraibi's avatar
Mohcine Chraibi committed
655
                  printf("time: %6.2f (%4.0f)  | Agents: %6ld / %d [%4.1f%%]\n",  t , maxSimTime, _nPeds, initialnPeds, (double)(initialnPeds-_nPeds)/initialnPeds*100);
Arne Graf's avatar
Arne Graf committed
656

Mohcine Chraibi's avatar
Mohcine Chraibi committed
657

GrgrLmml's avatar
GrgrLmml committed
658 659 660 661 662 663
        // needed to control the execution time PART 2
        // time(&endtime);
        // double timeToWait=t-difftime(endtime, starttime);
        // clock_t goal = timeToWait*1000 + clock();
        // while (goal > clock());
        ++frameNr;
Mohcine Chraibi's avatar
Mohcine Chraibi committed
664 665 666

        //Trigger JPSfire Toxicity Analysis
        //only executed every 3 seconds
Mohcine Chraibi's avatar
Mohcine Chraibi committed
667
        #ifdef JPSFIRE
Mohcine Chraibi's avatar
Mohcine Chraibi committed
668 669 670 671 672
        if( fmod(Pedestrian::GetGlobalTime(), 3) == 0 ) {
            for (auto&& ped: _building->GetAllPedestrians()) {
                ped->ConductToxicityAnalysis();
            }
        }
Mohcine Chraibi's avatar
Mohcine Chraibi committed
673
        #endif
674

675 676 677 678 679 680
        //init train trainOutfloww
        for (auto tab : TrainTimeTables)
        {
              trainOutflow[tab.first] = 0;
        }
        // regulate flow
681 682 683 684 685
        for (auto& itr: _building->GetAllTransitions())
        {
             Transition* Trans = itr.second;
             if(Trans->IsTempClose())
             {
qiancheng xu's avatar
qiancheng xu committed
686 687
                  if ((Trans->GetMaxDoorUsage() != (std::numeric_limits<int>::max)()) ||
                    (Trans->GetOutflowRate() != (std::numeric_limits<double>::max)()) ){
688 689 690
                        Trans->UpdateClosingTime( _deltaT);
                        if(Trans->GetClosingTime() <= _deltaT){
                             Trans->changeTemporaryState();
691
                      }
692
                  }// normal transition
693
             }
694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712
             //-----------
             // regulate train doorusage
             std::string transType = Trans->GetType();
             if (Trans->IsOpen() && transType.rfind("Train", 0) == 0)
             {
                   std::vector<std::string> strs;
                   boost::split(strs, transType, boost::is_any_of("_"),boost::token_compress_on);
                   int id = atoi(strs[1].c_str());
                   std::string type = Trans->GetCaption();
                   trainOutflow[id] += Trans->GetDoorUsage();
                   if(trainOutflow[id] >= TrainTypes[type]->nmax)
                   {
                        std::cout << "INFO:\tclosing train door "<<  transType.c_str() << " at "<<  Pedestrian::GetGlobalTime() << " capacity " <<  TrainTypes[type]->nmax<< "\n";
                         Log->Write("INFO:\tclosing train door %s at t=%.2f. Flow = %.2f (Train Capacity %d)", transType.c_str(), Pedestrian::GetGlobalTime(), trainOutflow[id], TrainTypes[type]->nmax);
                         Trans->Close();
                   }
             }
             //-----------
        }// Transitions
Mohcine Chraibi's avatar
Mohcine Chraibi committed
713 714
        if(frameNr % 1000 == 0)
        {
715 716
              Log->Write("INFO:\tUpdate door statistics at t=%.2f", t);
              PrintStatistics(t);
Mohcine Chraibi's avatar
Mohcine Chraibi committed
717
        }
718
    }// while time
719
    return t;
720
}
721 722 723 724 725
bool Simulation::WriteTrajectories(std::string trajectoryName)
{
      if(_config-> GetFileFormat() == FORMAT_PLAIN)
      {
            fs::path p = _config->GetTrajectoriesFile();
Mohcine Chraibi's avatar
Mohcine Chraibi committed
726
            fs::path parent = p.parent_path();
727 728 729 730 731 732 733
            int sf = fs::file_size(p);
            if(sf>_maxFileSize*1024*1024)
            {
                  std::string extention = p.extension().string();
                  this->incrementCountTraj();
                  char tmp_traj_name[100];
                  sprintf(tmp_traj_name,"%s_%.4d_%s", trajectoryName.c_str(), _countTraj, extention.c_str());
Mohcine Chraibi's avatar
Mohcine Chraibi committed
734 735
                  fs::path abs_traj_name = parent/ fs::path(tmp_traj_name);
                  _config->SetTrajectoriesFile(abs_traj_name.string());
736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004
                  Log->Write("INFO:\tNew trajectory file <%s>", tmp_traj_name);
                  OutputHandler* file = new FileHandler(_config->GetTrajectoriesFile().c_str());
                  outputTXT->SetOutputHandler(file);

//_config->GetProjectRootDir()+"_1_"+_config->GetTrajectoriesFile());
                  // _config->SetTrajectoriesFile(name);
                  _iod->WriteHeader(_nPeds, _fps, _building.get(), _seed, _countTraj);
                  // _iod->WriteGeometry(_building.get());
            }
      }
      return true;
}
//      |             |
//      *-------------* <---door
//      |             |
//      |             |
//      |             |
//      |             |
//      |             |
//*-----x-------------x--------* <- wall
//      |             |


/*
 * in this function this happens:
* remove walls
* add walls
* add doors
* set _routingEngine->setNeedUpdate(true);
*/
bool Simulation::correctGeometry(std::shared_ptr<Building> building, std::shared_ptr<TrainTimeTable> tab)
{
     //auto platforms = building->GetPlatforms();
     int trainId = tab->id;
     std::string trainType = tab->type;
     Point TrackStart = tab->pstart;
     Point TrainStart = tab->tstart;
     Point TrackEnd = tab->pend;
     SubRoom * subroom;
     int room_id, subroom_id;
     auto mytrack = building->GetTrackWalls(TrackStart, TrackEnd, room_id, subroom_id);
     Room* room = building->GetRoom(room_id);
     subroom = room->GetSubRoom(subroom_id);
     if(subroom == nullptr)
     {
          Log->Write("ERROR:\t Simulation::correctGeometry got wrong room_id|subroom_id (%d|%d). TrainId %d", room_id, subroom_id, trainId);
          exit(EXIT_FAILURE);
     }
     static int transition_id = 10000; // randomly high number

     std::cout << "enter with train " << trainType.c_str() << "\n";
     std::cout<< KBLU << "Enter correctGeometry: Building Has " << building->GetAllTransitions().size() << " Transitions\n" << RESET;
     std::cout << "room: " << room_id << " subroom_id " << subroom_id << "\n" ;

      if(mytrack.empty() || subroom == nullptr)
            return false;


      auto train = building->GetTrainTypes().at(trainType);
      auto doors = train->doors;
      for(auto && d: doors)
      {
           auto newX  = d.GetPoint1()._x + TrainStart._x + TrackStart._x;
           auto newY  = d.GetPoint1()._y + TrainStart._y + TrackStart._y;
           d.SetPoint1(Point(newX, newY));
           newX  = d.GetPoint2()._x + TrainStart._x + TrackStart._x;
           newY  = d.GetPoint2()._y + TrainStart._y + TrackStart._y;
           d.SetPoint2(Point(newX, newY));
      }
      for(auto d: doors)
      {
           Log->Write("Train %s %d. Transformed coordinates of doors: %s -- %s", trainType.c_str(), trainId, d.GetPoint1().toString().c_str(), d.GetPoint2().toString().c_str());
      }

      // std::vector<std::pair<PointWall, pointWall > >
      auto pws = building->GetIntersectionPoints(doors, mytrack);
      if(pws.empty())
           std::cout << KRED << "simulation::correctGeometry: pws are empty. Something went south with train doors\n" << RESET;

      auto walls = subroom->GetAllWalls();
      //---
      for(auto pw: pws)
      {
            auto pw1 = pw.first;
            auto pw2 = pw.second;
            auto p1 = pw1.first;
            auto w1 = pw1.second;
            auto p2 = pw2.first;
            auto w2 = pw2.second;
            // std::cout << "p1 " << p1.toString() << ", wall: " << w1.toString() << "\n";
            // std::cout << "p2 " << p2.toString() << ", wall: " << w2.toString() << "\n";
            // std::cout << "------\n";
            // case 1
            Point P;
            if(w1 == w2)
            {
                  std::cout << "EQUAL\n";
                  Transition* e = new Transition();
                  e->SetID(transition_id++);
                  e->SetCaption(trainType);
                  e->SetPoint1(p1);
                  e->SetPoint2(p2);
                  std::string transType = "Train_"+std::to_string(tab->id)+"_"+std::to_string(tab->tin)+"_"+std::to_string(tab->tout);
                  e->SetType(transType);
                  room->AddTransitionID(e->GetUniqueID());// danger area
                  e->SetRoom1(room);
                  e->SetSubRoom1(subroom);
                  subroom->AddTransition(e);// danger area
                  building->AddTransition(e);// danger area
                  /* std::cout << KRED << "Trans added: " << e->toString() << "\n" << RESET; */

                  /* std::cout<< KGRN << "Transition added. Building Has " << building->GetAllTransitions().size() << " Transitions\n" << RESET; */
                  double dist_pt1 = (w1.GetPoint1() - e->GetPoint1()).NormSquare();
                  double dist_pt2 = (w1.GetPoint1() - e->GetPoint2()).NormSquare();
                  Point A, B;

                  if(dist_pt1<dist_pt2)
                  {
                        A = e->GetPoint1();
                        B = e->GetPoint2();
                  }
                  else
                  {
                        A = e->GetPoint2();
                        B = e->GetPoint1();
                  }

                  Wall NewWall(w1.GetPoint1(), A);
                  Wall NewWall1(w1.GetPoint2(), B);
                  NewWall.SetType(w1.GetType());
                  NewWall1.SetType(w1.GetType());

                  // add new lines to be controled against overlap with exits
                  if(NewWall.GetLength() > J_EPS_DIST)
                  {
                       building->TempAddedWalls[trainId].push_back(NewWall);
                       subroom->AddWall(NewWall);
                  }

                  else
                       std::cout << KRED << ">> WALL did not add: " << NewWall.toString() << "\n" << RESET ;

                  if(NewWall1.GetLength() > J_EPS_DIST)
                  {
                       building->TempAddedWalls[trainId].push_back(NewWall1);
                       subroom->AddWall(NewWall1);
                  }
                  else
                       std::cout << KRED << ">> WALL did not add: " << NewWall1.toString() << "\n" << RESET ;

                  building->TempAddedDoors[trainId].push_back(*e);
                  building->TempRemovedWalls[trainId].push_back(w1);

                  subroom->RemoveWall(w1);


                  /* std::cout << KRED << "WALL added " << NewWall1.toString() << "\n" << RESET ; */
                  /* std::cout << KRED << "WALL removed " << w1.toString() << "\n" << RESET ; */
                  /* getc(stdin); */

                  //room->AddTransitionID(e->GetUniqueID());
            }
            else if(w1.ShareCommonPointWith(w2, P))
            {

                  std::cout << "ONE POINT COMON\n";
                  //------------ transition --------
                  Transition* e = new Transition();
                  e->SetID(transition_id++);
                  e->SetCaption(trainType);
                  e->SetPoint1(p1);
                  e->SetPoint2(p2);
                  std::string transType = "Train_"+std::to_string(tab->id)+"_"+std::to_string(tab->tin)+"_"+std::to_string(tab->tout);
                  e->SetType(transType);
                  room->AddTransitionID(e->GetUniqueID());// danger area
                  e->SetRoom1(room);
                  e->SetSubRoom1(subroom);

                  subroom->AddTransition(e);// danger area
                  building->AddTransition(e);// danger area
                  //--------------------------------
                  Point N, M;
                  if(w1.GetPoint1()==P)
                        N = w1.GetPoint2();
                  else
                        N = w1.GetPoint1();

                  if(w2.GetPoint1()==P)
                        M = w2.GetPoint2();
                  else
                        M = w2.GetPoint1();

                  Wall NewWall(N, p1);
                  Wall NewWall1(M, p2);
                  NewWall.SetType(w1.GetType());
                  NewWall1.SetType(w2.GetType());
                  // changes to building
                  building->TempAddedWalls[trainId].push_back(NewWall);
                  building->TempAddedWalls[trainId].push_back(NewWall1);
                  building->TempAddedDoors[trainId].push_back(*e);
                  building->TempRemovedWalls[trainId].push_back(w1);
                  building->TempRemovedWalls[trainId].push_back(w2);
                  subroom->AddWall(NewWall);
                  subroom->AddWall(NewWall1);
                  subroom->RemoveWall(w1);
                  subroom->RemoveWall(w2);
                  /* std::cout << KRED << ". WALL added " << NewWall.toString() << "\n" << RESET ; */
                  /* std::cout << KRED << "WALL added " << NewWall1.toString() << "\n" << RESET ; */
                  /* std::cout << KRED << "WALL removed " << w1.toString() << "\n" << RESET ; */
                  /* std::cout << KRED << "WALL removed " << w2.toString() << "\n" << RESET ; */
                  /* getc(stdin); */
            }
            else // disjoint
            {
                  std::cout << "DISJOINT\n";
                                    //------------ transition --------
                  Transition* e = new Transition();
                  e->SetID(transition_id++);
                  e->SetCaption(trainType);
                  e->SetPoint1(p1);
                  e->SetPoint2(p2);
                  std::string transType = "Train_"+std::to_string(tab->id)+"_"+std::to_string(tab->tin)+"_"+std::to_string(tab->tout);
                  e->SetType(transType);
                  room->AddTransitionID(e->GetUniqueID());// danger area
                  e->SetRoom1(room);
                  e->SetSubRoom1(subroom);

                  subroom->AddTransition(e);// danger area
                  building->AddTransition(e);// danger area
                  //--------------------------------
                  // find points on w1 and w2 between p1 and p2
                  // (A, B)
                  Point A, B;
                  if(e->isBetween(w1.GetPoint1()))
                        A = w1.GetPoint2();
                  else
                        A = w1.GetPoint1();

                  if(e->isBetween(w2.GetPoint1()))
                        B = w2.GetPoint2();
                  else
                        B = w2.GetPoint1();

                  Wall NewWall(A, p1);
                  Wall NewWall1(B, p2);
                  NewWall.SetType(w1.GetType());
                  NewWall1.SetType(w2.GetType());
                  // remove walls between
                  for(auto wall: mytrack)
                  {
                       if(e->isBetween(wall.GetPoint1()) || e->isBetween(wall.GetPoint2()))
                        {
                             building->TempRemovedWalls[trainId].push_back(wall);
                             subroom->RemoveWall(wall);
                        }
                  }
                  // changes to building
                  building->TempAddedWalls[trainId].push_back(NewWall);
                  building->TempAddedWalls[trainId].push_back(NewWall1);
                  building->TempAddedDoors[trainId].push_back(*e);
                  subroom->AddWall(NewWall);
                  subroom->AddWall(NewWall1);

                  // remove walls w1 and w2
            }
      }
      _routingEngine->setNeedUpdate(true);
     return true;
}
1005 1006
void Simulation::RunFooter()
{
GrgrLmml's avatar
GrgrLmml committed
1007 1008
    // writing the footer
    _iod->WriteFooter();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
1009 1010
}

1011
void Simulation::ProcessAgentsQueue()
1012
{
1013

1014 1015 1016 1017
     /* std::cout << "Call Simulation::ProcessAgentsQueue() at: " << Pedestrian::GetGlobalTime() << std::endl; */
     /* std::cout << KRED << " SIMULATION building " << _building << " size "  << _building->GetAllPedestrians().size() << "\n" << RESET; */
           /* for(auto pp: _building->GetAllPedestrians()) */
     /*           std::cout<< KBLU << "BUL: Simulation: " << pp->GetPos()._x << ", " << pp->GetPos()._y << RESET << std::endl; */
1018

GrgrLmml's avatar
GrgrLmml committed
1019 1020
    //incoming pedestrians
    vector<Pedestrian*> peds;
1021 1022
    //  std::cout << ">>> peds " << peds.size() << RESET<< std::endl;

GrgrLmml's avatar
GrgrLmml committed
1023
    AgentsQueueIn::GetandClear(peds);
1024
    //std::cout << "SIMULATION BEFORE BOOL = " <<  _agentSrcManager.IsBuildingUpdated() << " peds size " << peds.size() << "\n" ;
1025

1026 1027
    //_agentSrcManager.SetBuildingUpdated(true);
    /* std::cout << "SIMULATION AFTER BOOL = " <<  _agentSrcManager.IsBuildingUpdated() << "\n" ; */
1028

GrgrLmml's avatar
GrgrLmml committed
1029
    for (auto&& ped: peds) {
1030
            /* std::cout << "Add to building : " << ped->GetPos()._x << ", " << ped->GetPos()._y << " t: "<< Pedestrian::GetGlobalTime() << std::endl; */
GrgrLmml's avatar
GrgrLmml committed
1031 1032
        _building->AddPedestrian(ped);
    }
tobias schroedter's avatar
tobias schroedter committed
1033
    _building->UpdateGrid();
1034 1035 1036 1037
    //  for(auto pp: _building->GetAllPedestrians())
    //         std::cout<< KBLU << "BUL: Simulation: " << pp->GetPos()._x << ", " << pp->GetPos()._y  << " t: "<< Pedestrian::GetGlobalTime() <<RESET << std::endl;


1038
    /* std::cout << "LEAVE Simulation::ProcessAgentsQueue() with " << " size "  << _building->GetAllPedestrians().size() << "\n" << RESET; */
Ulrich Kemloh's avatar
Ulrich Kemloh committed
1039
}
Ulrich Kemloh's avatar
Ulrich Kemloh committed
1040

1041
void Simulation::UpdateDoorticks() const {
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
//    int softstateDecay = 1;
//    //Softstate of _lastTickTime is valid for X seconds as in (X/_deltaT); here it is 2s
//    auto& allCross = _building->GetAllCrossings();
//    for (auto& crossPair : allCross) {
//        crossPair.second->_refresh1 += 1;
//        crossPair.second->_refresh2 += 1;
//        if (crossPair.second->_refresh1 > (softstateDecay/_deltaT)) {
//            crossPair.second->_lastTickTime1 = 0;
//            crossPair.second->_refresh1 = 0;
//        }
//        if (crossPair.second->_refresh2 > (softstateDecay/_deltaT)) {
//            crossPair.second->_lastTickTime2 = 0;
//            crossPair.second->_refresh2 = 0;
//        }
//    }
//
//    auto& allTrans = _building->GetAllTransitions();
//    for (auto& transPair : allTrans) {
//        transPair.second->_refresh1 += 1;
//        transPair.second->_refresh2 += 1;
//        if (transPair.second->_refresh1 > (softstateDecay/_deltaT)) {
//            transPair.second->_lastTickTime1 = 0;
//            transPair.second->_refresh1 = 0;
//        }
//        if (transPair.second->_refresh2 > (softstateDecay/_deltaT)) {
//            transPair.second->_lastTickTime2 = 0;
//            transPair.second->_refresh2 = 0;
//        }
//    }
1071 1072
};

Ulrich Kemloh's avatar
Ulrich Kemloh committed
1073 1074
void Simulation::UpdateFlowAtDoors(const Pedestrian& ped) const
{
GrgrLmml's avatar
GrgrLmml committed
1075 1076 1077 1078
    if (_config->ShowStatistics()) {
        Transition* trans = _building->GetTransitionByUID(ped.GetExitIndex());
        if (trans) {
            //check if the pedestrian left the door correctly
Arne Graf's avatar
Arne Graf committed
1079
            if (trans->DistTo(ped.GetPos())>0.5) {
GrgrLmml's avatar
GrgrLmml committed
1080 1081 1082
                Log->Write("WARNING:\t pedestrian [%d] left room/subroom [%d/%d] in an unusual way. Please check",
                        ped.GetID(), ped.GetRoomID(), ped.GetSubRoomID());
                Log->Write("       :\t distance to last door (%d | %d) is %f. That should be smaller.",
Arne Graf's avatar
Arne Graf committed
1083 1084
                        trans->GetUniqueID(), ped.GetExitIndex(),
                        trans->DistTo(ped.GetPos()));
GrgrLmml's avatar
GrgrLmml committed
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099
                Log->Write("       :\t correcting the door statistics");
                //ped.Dump(ped.GetID());

                //checking the history and picking the nearest previous destination
                double biggest = 0.3;
                bool success = false;
                for (const auto& dest:ped.GetLastDestinations()) {
                    if (dest!=-1) {
                        Transition* trans_tmp = _building->GetTransitionByUID(dest);
                        if (trans_tmp && trans_tmp->DistTo(ped.GetPos())<biggest) {
                            biggest = trans_tmp->DistTo(ped.GetPos());
                            trans = trans_tmp;
                            Log->Write("       :\t Best match found at door %d", dest);
                            success = true;//at least one door was found
                        }
1100
                    }
GrgrLmml's avatar
GrgrLmml committed
1101 1102 1103 1104 1105 1106 1107
                }

                if (!success) {
                    Log->Write("WARNING       :\t correcting the door statistics");
                    return; //todo we need to check if the ped is in a subroom neighboring the target. If so, no problems!
                }
            }
1108
//#pragma omp critical
1109
            bool regulateFlow = trans->GetOutflowRate() <  (std::numeric_limits<double>::max)();
1110

1111 1112
            trans->IncreaseDoorUsage(1, ped.GetGlobalTime());
            trans->IncreasePartialDoorUsage(1);
1113 1114 1115 1116 1117 1118 1119 1120 1121

            if(regulateFlow)
            {
                 // when <dn> agents pass <trans>, we start evaluating the flow
                 // .. and maybe close the <trans>
                 if( trans->GetPartialDoorUsage() ==  trans->GetDN() ) {
                      trans->regulateFlow(Pedestrian::GetGlobalTime());
                      trans->ResetPartialDoorUsage();
                 }
1122
            }
1123

GrgrLmml's avatar
GrgrLmml committed
1124
        }
1125

1126 1127 1128
        Crossing* cross = _building->GetCrossingByUID(ped.GetExitIndex());
        if (cross) {
             cross->IncreaseDoorUsage(1, ped.GetGlobalTime());
GrgrLmml's avatar
GrgrLmml committed
1129 1130
        }
    }
Ulrich Kemloh's avatar
Ulrich Kemloh committed
1131 1132
}

1133 1134 1135 1136 1137
void Simulation::incrementCountTraj()
{
      _countTraj++;
}

1138
AgentsSourcesManager& Simulation::GetAgentSrcManager()
1139
{
GrgrLmml's avatar
GrgrLmml committed
1140
    return _agentSrcManager;
1141
}
Ulrich Kemloh's avatar
Ulrich Kemloh committed
1142 1143 1144

Building* Simulation::GetBuilding()
{
GrgrLmml's avatar
GrgrLmml committed
1145
    return _building.get();
Ulrich Kemloh's avatar
Ulrich Kemloh committed
1146
}
1147 1148 1149 1150

int Simulation::GetMaxSimTime() const{
      return _maxSimTime;
}
1151 1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192
// return true is changes are made to the geometry
bool Simulation::TrainTraffic()
{
     bool trainHere = false;
     bool trainLeave = false;
     std::string trainType = "";
     Point trackStart, trackEnd;
     int trainId = 0;
     auto now = Pedestrian::GetGlobalTime();
     for(auto && tab: TrainTimeTables)
     {
          trainType = tab.second->type;
          trainId = tab.second->id;
          trackStart = tab.second->pstart;
          trackEnd = tab.second->pend;
          if(!tab.second->arrival && (now >= tab.second->tin) && (now <= tab.second->tout))
          {
               trainHere = true;
               TrainTimeTables.at(trainId)->arrival = true;
               std::cout << KRED << "Arrival: TRAIN " << trainType << " at time: " << now << "\n" << RESET;
               correctGeometry(_building, tab.second);

          }
          else if(tab.second->arrival && now >= tab.second->tout)
          {
               std::cout <<KGRN << "Departure: TRAIN " << trainType << " at time: " << now  << "\n" << RESET;
               _building->resetGeometry(tab.second);
               trainLeave = true;
               TrainTimeTables.at(trainId)->arrival = false;

          }
     }
     if(trainHere || trainLeave)
     {
          return true;
     }

     /* std::cout<< KRED << "Check: Building Has " << _building->GetAllTransitions().size() << " Transitions\n" << RESET; */

     return false;

}