Commit e8bd8ffe authored by Mohcine Chraibi's avatar Mohcine Chraibi

Merge branch '300-tracks-for-trains' into 'develop'

Interface of trains

Closes #300

See merge request !49
parents 02706b98 32795a9e
Pipeline #21759 passed with stages
in 9 minutes and 17 seconds
......@@ -50,6 +50,11 @@ void GeoFileParser::LoadBuilding(Building* building)
Log->Write("ERROR:\t could not load extra traffic information!");
exit(EXIT_FAILURE);
}
if(!LoadTrainInfo(building))
{
Log->Write("ERROR:\t could not load train information!");
exit(EXIT_FAILURE);
}
}
bool GeoFileParser::LoadGeometry(Building* building)
......@@ -199,6 +204,7 @@ bool GeoFileParser::LoadGeometry(Building* building)
for (TiXmlElement* xPolyVertices = xSubRoom->FirstChildElement("polygon"); xPolyVertices;
xPolyVertices = xPolyVertices->NextSiblingElement("polygon")) {
std::string wall_type = xmltoa(xPolyVertices->Attribute("type"), "wall");
for (TiXmlElement* xVertex = xPolyVertices->FirstChildElement(
"vertex");
xVertex && xVertex!=xPolyVertices->LastChild("vertex");
......@@ -208,7 +214,7 @@ bool GeoFileParser::LoadGeometry(Building* building)
double y1 = xmltof(xVertex->Attribute("py"));
double x2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("px"));
double y2 = xmltof(xVertex->NextSiblingElement("vertex")->Attribute("py"));
subroom->AddWall(Wall(Point(x1, y1), Point(x2, y2)));
subroom->AddWall(Wall(Point(x1, y1), Point(x2, y2), wall_type));
//printf("%0.2f %0.2f %0.2f %0.2f\n",x1,y1,x2,y2);
}
......@@ -327,7 +333,7 @@ bool GeoFileParser::LoadGeometry(Building* building)
}
}
else{
Log->Write("INFO:\tNot parsing transition from file %s");
Log->Write("INFO:\tNot parsing transition from file");
}
Log->Write("INFO:\tGot %d transitions", building-> GetAllTransitions().size());
......@@ -464,7 +470,7 @@ bool GeoFileParser::parseDoorNode(TiXmlElement * xDoor, int id, Building* buildi
building->GetTransition(id)->TempClose();
break;
case DoorState::Error:
Log->Write("WARNING:\t Unknown door state: <%s>. open or close. Default: open",
Log->Write("WARNING:\t Unknown door state: <%s>. open, close or temp_close. Default: open",
stateStr.c_str());
building->GetTransition(id)->Open();
break;
......@@ -791,6 +797,220 @@ Goal* GeoFileParser::parseWaitingAreaNode(TiXmlElement * e)
return wa;
}
bool GeoFileParser::LoadTrainInfo(Building* building)
{
Log->Write("--------\nINFO:\tLoading the train info");
TiXmlDocument doc(_configuration->GetProjectFile());
if (!doc.LoadFile()) {
Log->Write("ERROR: \t%s", doc.ErrorDesc());
Log->Write("ERROR: \t could not parse the project file");
return false;
}
TiXmlElement* xRootNode = doc.RootElement();
if (!xRootNode) {
Log->Write("ERROR:\tRoot element does not exist");
return false;
}
if (!xRootNode->FirstChild("train_constraints")) {
Log->Write("WARNING:\tNo train constraints were found. Continue.");
}
bool resTTT = true;
bool resType = true;
if(xRootNode->FirstChild("train_constraints"))
{
resTTT = LoadTrainTimetable(building, xRootNode);
resType = LoadTrainType(building, xRootNode);
}
return (resTTT && resType);
}
bool GeoFileParser::LoadTrainTimetable(Building* building, TiXmlElement * xRootNode)
{
TiXmlNode* xTTTNode = xRootNode->FirstChild("train_constraints")->FirstChild("train_time_table");
std::string TTTFilename;
if(xTTTNode)
{
fs::path p(_configuration->GetProjectRootDir());
TTTFilename = xTTTNode->FirstChild()->ValueStr();
p /= TTTFilename;
TTTFilename = p.string();
Log->Write("INFO:\tTrain Timetable file <%s> will be parsed", TTTFilename.c_str());
}
else return true;
TiXmlDocument docTTT(TTTFilename);
if (!docTTT.LoadFile()) {
Log->Write("ERROR: \t%s", docTTT.ErrorDesc());
Log->Write("ERROR: \t could not parse the train timetable file.");
return false;
}
TiXmlElement* xTTT = docTTT.RootElement();
if (!xTTT) {
Log->Write("ERROR:\tRoot element does not exist in TTT file.");
return false;
}
if (xTTT->ValueStr() != "train_time_table") {
Log->Write("ERROR:\tParsing train timetable file. Root element value is not 'train_time_table'.");
return false;
}
for (TiXmlElement* e = xTTT->FirstChildElement("train"); e;
e = e->NextSiblingElement("train")) {
std::shared_ptr<TrainTimeTable> TTT = parseTrainTimeTableNode(e);
if (TTT) {
building->AddTrainTimeTable(TTT);
}
}
return true;
}
bool GeoFileParser::LoadTrainType(Building* building, TiXmlElement * xRootNode)
{
TiXmlNode* xTTNode = xRootNode->FirstChild("train_constraints")->FirstChild("train_types");
std::string TTFilename;
if(xTTNode)
{
fs::path p(_configuration->GetProjectRootDir());
TTFilename = xTTNode->FirstChild()->ValueStr();
p /= TTFilename;
TTFilename = p.string();
Log->Write("INFO:\tTrain Type file <%s> will be parsed", TTFilename.c_str());
}
else return true;
TiXmlDocument docTT(TTFilename);
if (!docTT.LoadFile()) {
Log->Write("ERROR: \t%s", docTT.ErrorDesc());
Log->Write("ERROR: \t could not parse the train type file.");
return false;
}
TiXmlElement* xTT = docTT.RootElement();
if (!xTT) {
Log->Write("ERROR:\tRoot element does not exist in TT file.");
return false;
}
if (xTT->ValueStr() != "train_type") {
Log->Write("ERROR:\tParsing train type file. Root element value is not 'train_type'.");
return false;
}
for (TiXmlElement* e = xTT->FirstChildElement("train"); e;
e = e->NextSiblingElement("train")) {
std::shared_ptr<TrainType> TT = parseTrainTypeNode(e);
if (TT) {
building->AddTrainType(TT);
}
}
return true;
}
std::shared_ptr<TrainTimeTable> GeoFileParser::parseTrainTimeTableNode(TiXmlElement * e)
{
Log->Write("INFO:\tLoading train time table NODE");
std::string caption = xmltoa(e->Attribute("caption"), "-1");
int id = xmltoi(e->Attribute("id"), -1);
std::string type = xmltoa(e->Attribute("type"), "-1");
int room_id = xmltoi(e->Attribute("room_id"), -1);
int subroom_id = xmltoi(e->Attribute("subroom_id"), -1);
int platform_id = xmltoi(e->Attribute("platform_id"), -1);
float track_start_x = xmltof(e->Attribute("track_start_x"), -1);
float track_start_y = xmltof(e->Attribute("track_start_y"), -1);
float track_end_x = xmltof(e->Attribute("track_end_x"), -1);
float track_end_y = xmltof(e->Attribute("track_end_y"), -1);
float train_start_x = xmltof(e->Attribute("train_start_x"),-1);
float train_start_y = xmltof(e->Attribute("train_start_y"), -1);
float train_end_x = xmltof(e->Attribute("train_end_x"), -1);
float train_end_y = xmltof(e->Attribute("train_end_y"), -1);
float arrival_time = xmltof(e->Attribute("arrival_time"), -1);
float departure_time = xmltof(e->Attribute("departure_time"), -1);
// @todo: check these values for correctness e.g. arrival < departure
Log->Write("INFO:\tTrain time table:");
Log->Write("INFO:\t id: %d", id);
Log->Write("INFO:\t type: %s", type.c_str());
Log->Write("INFO:\t room_id: %d", room_id);
Log->Write("INFO:\t subroom_id: %d", subroom_id);
Log->Write("INFO:\t platform_id: %d", platform_id);
Log->Write("INFO:\t track_start: [%.2f, %.2f]", track_start_x, track_start_y);
Log->Write("INFO:\t track_end: [%.2f, %.2f]", track_end_x, track_end_y);
Log->Write("INFO:\t arrival_time: %.2f", arrival_time);
Log->Write("INFO:\t departure_time: %.2f", departure_time);
Point track_start(track_start_x, track_start_y);
Point track_end(track_end_x, track_end_y);
Point train_start(train_start_x, train_start_y);
Point train_end(train_end_x, train_end_y);
std::shared_ptr<TrainTimeTable> trainTimeTab = std::make_shared<TrainTimeTable>(
TrainTimeTable{
id,
type,
room_id,
subroom_id,
arrival_time,
departure_time,
track_start,
track_end,
train_start,
train_end,
platform_id,
false,
false,
});
return trainTimeTab;
}
std::shared_ptr<TrainType> GeoFileParser::parseTrainTypeNode(TiXmlElement * e)
{
Log->Write("INFO:\tLoading train type");
// int T_id = xmltoi(e->Attribute("id"), -1);
std::string type = xmltoa(e->Attribute("type"), "-1");
int agents_max = xmltoi(e->Attribute("agents_max"), -1);
float length = xmltof(e->Attribute("length"), -1);
// std::shared_ptr<Transition> t = new Transition();
// std::shared_ptr<Transition> doors;
Transition t;
std::vector<Transition> doors;
for (TiXmlElement* xDoor = e->FirstChildElement("door"); xDoor;
xDoor = xDoor->NextSiblingElement("door")) {
int D_id = xmltoi(xDoor->Attribute("id"), -1);
float x1 = xmltof(xDoor->FirstChildElement("vertex")->Attribute("px"), -1);
float y1 = xmltof(xDoor->FirstChildElement("vertex")->Attribute("py"), -1);
float x2 = xmltof(xDoor->LastChild("vertex")->ToElement()->Attribute("px"), -1);
float y2 = xmltof(xDoor->LastChild("vertex")->ToElement()->Attribute("py"), -1);
Point start(x1, y1);
Point end(x2, y2);
float outflow = xmltof(xDoor->Attribute("outflow"), -1);
float dn = xmltoi(xDoor->Attribute("dn"), -1);
t.SetID(D_id);
t.SetCaption(type + std::to_string(D_id));
t.SetPoint1(start);
t.SetPoint2(end);
t.SetOutflowRate(outflow);
t.SetDN(dn);
doors.push_back(t);
}
Log->Write("INFO:\t type: %s", type.c_str());
Log->Write("INFO:\t capacity: %d", agents_max);
Log->Write("INFO:\t number of doors: %d", doors.size());
for(auto d: doors)
{
Log->Write("INFO\t door (%d): %s | %s", d.GetID(), d.GetPoint1().toString().c_str(), d.GetPoint2().toString().c_str());
}
std::shared_ptr<TrainType> Type = std::make_shared<TrainType>(
TrainType{
type,
agents_max,
length,
doors,
});
return Type;
}
GeoFileParser::~GeoFileParser()
{
......
......@@ -44,6 +44,11 @@ public:
Goal* parseGoalNode(TiXmlElement * e);
Transition* parseTransitionNode(TiXmlElement * xTrans, Building * building);
Goal* parseWaitingAreaNode(TiXmlElement * e);
bool LoadTrainInfo(Building* building);
bool LoadTrainTimetable(Building* building, TiXmlElement * xRootNode);
bool LoadTrainType(Building* building, TiXmlElement * xRootNode);
std::shared_ptr<TrainType> parseTrainTypeNode(TiXmlElement * e);
std::shared_ptr<TrainTimeTable> parseTrainTimeTableNode(TiXmlElement * e);
private:
Configuration* _configuration;
......
......@@ -370,16 +370,69 @@ std::string getEventFileName(const std::string & GetProjectFile)
TiXmlNode* xMainNode = doc.RootElement();
string eventfile = "";
if (xMainNode->FirstChild("events_file")) {
ret = xMainNode->FirstChild("events_file")->FirstChild()->Value();
Log->Write("INFO: \tevents <" + eventfile + ">");
ret = xMainNode->FirstChild("events_file")->FirstChild()->ValueStr();
Log->Write("INFO: \tevents <" + ret + ">");
} else {
Log->Write("INFO: \tNo events found");
return ret;
}
return ret;
}
// <train_constraints>
// <train_time_table>ttt.xml</train_time_table>
// <train_types>train_types.xml</train_types>
// </train_constraints>
std::string getTrainTimeTableFileName(const std::string & GetProjectFile)
{
std::string ret="";
TiXmlDocument doc(GetProjectFile);
if (!doc.LoadFile()) {
Log->Write("ERROR: \t%s", doc.ErrorDesc());
Log->Write("ERROR: \tGetTrainTimeTable could not parse the project file");
return ret;
}
TiXmlNode* xMainNode = doc.RootElement();
string tttfile = "";
if (xMainNode->FirstChild("train_constraints")) {
TiXmlNode * xFileNode = xMainNode->FirstChild("train_constraints")->FirstChild("train_time_table");
if(xFileNode)
ret = xFileNode->FirstChild()->ValueStr();
Log->Write("INFO: \ttrain_time_table <" + ret + ">");
} else {
Log->Write("INFO: \tNo events no ttt file found");
return ret;
}
return ret;
}
std::string getTrainTypeFileName(const std::string & GetProjectFile)
{
std::string ret="";
TiXmlDocument doc(GetProjectFile);
if (!doc.LoadFile()) {
Log->Write("ERROR: \t%s", doc.ErrorDesc());
Log->Write("ERROR: \tGetTrainType could not parse the project file");
return ret;
}
TiXmlNode* xMainNode = doc.RootElement();
string tttfile = "";
if (xMainNode->FirstChild("train_constraints")) {
auto xFileNode = xMainNode->FirstChild("train_constraints")->FirstChild("train_types");
if(xFileNode)
ret = xFileNode->FirstChild()->ValueStr();
Log->Write("INFO: \ttrain_types <" + ret + ">");
} else {
Log->Write("INFO: \tNo events no train types file found");
return ret;
}
return ret;
}
std::string getGoalFileName(const std::string & GetProjectFile)
{
std::string ret="";
......@@ -411,6 +464,8 @@ void TrajectoriesFLAT::WriteHeader(long nPeds, double fps, Building* building, i
std::string sourceFileName = getSourceFileName(building->GetProjectFilename());
std::string goalFileName = getGoalFileName(building->GetProjectFilename());
std::string eventFileName = getEventFileName(building->GetProjectFilename());
std::string trainTimeTableFileName = getTrainTimeTableFileName(building->GetProjectFilename());
std::string trainTypeFileName = getTrainTypeFileName(building->GetProjectFilename());
(void) seed; (void) nPeds;
char tmp[100] = "";
sprintf(tmp, "#description: jpscore (%s)", JPSCORE_VERSION);
......@@ -436,6 +491,16 @@ void TrajectoriesFLAT::WriteHeader(long nPeds, double fps, Building* building, i
sprintf(tmp,"#events: %s", eventFileName.c_str());
Write(tmp);
}
if( trainTimeTableFileName != "")
{
sprintf(tmp,"#trainTimeTable: %s", trainTimeTableFileName.c_str());
Write(tmp);
}
if( trainTypeFileName != "")
{
sprintf(tmp,"#trainType: %s", trainTypeFileName.c_str());
Write(tmp);
}
Write("#ID: the agent ID");
Write("#FR: the current frame");
Write("#X,Y,Z: the agents coordinates (in metres)");
......
......@@ -1635,6 +1635,9 @@ bool IniFileParser::ParseStrategyNodeToObject(const TiXmlNode& strategyNode)
};
_config->set_dirStrategy(dynamic_cast<DirectionSubLocalFloorfieldTripsVoronoi*>(_exit_strategy.get()));
break;
case 12:
_exit_strategy = std::shared_ptr<DirectionStrategy>(new DirectionTrain());
break;
default:
_exit_strategy = std::shared_ptr<DirectionStrategy>(new DirectionMinSeperationShorterLine());
......
......@@ -37,8 +37,6 @@
#include "pedestrian/AgentsQueue.h"
#include "pedestrian/AgentsSourcesManager.h"
#include "geometry/WaitingArea.h"
#include <filesystem>
namespace fs = std::filesystem;
#ifdef _OPENMP
......@@ -46,12 +44,16 @@ namespace fs = std::filesystem;
#define omp_get_thread_num() 0
#define omp_get_max_threads() 1
#endif
namespace fs = std::filesystem;
using namespace std;
OutputHandler* Log;
Trajectories* outputTXT;
// 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;
//--------
Simulation::Simulation(Configuration* args)
:_config(args)
{
......@@ -68,6 +70,7 @@ Simulation::Simulation(Configuration* args)
_fps = 1;
_em = nullptr;
_gotSources = false;
_trainConstraints = false;
_maxSimTime = 100;
// _config = args;
}
......@@ -246,7 +249,35 @@ bool Simulation::InitArgs()
if (!_operationalModel->Init(_building.get()))
return false;
Log->Write("INFO:\t Init Operational Model done");
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();
//-----
// 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()
......@@ -324,7 +355,7 @@ void Simulation::UpdateRoutesAndLocations()
//set the new room if needed
if ((ped->GetFinalDestination() == FINAL_DEST_OUT)
&& (room->GetCaption() == "outside")) { //TODO Hier aendern fuer inside goals?
&& (room->GetCaption() == "outside")) { //TODO Hier aendern fuer inside goals?
#pragma omp critical(Simulation_Update_pedsToRemove)
pedsToRemove.insert(ped);
} else if ((ped->GetFinalDestination() != FINAL_DEST_OUT)
......@@ -358,7 +389,7 @@ void Simulation::UpdateRoutesAndLocations()
if(_gotSources)
ped->FindRoute();
//finally actualize the route
if ( !_gotSources && ped->FindRoute() == -1 ) {
if ( !_gotSources && ped->FindRoute() == -1 && !_trainConstraints) {
//a destination could not be found for that pedestrian
Log->Write("ERROR: \tCould not find a route for pedestrian %d in room %d and subroom %d",
ped->GetID(), ped->GetRoomID(), ped->GetSubRoomID());
......@@ -529,6 +560,8 @@ double Simulation::RunBody(double maxSimTime)
// main program loop
while ((_nPeds || (!_agentSrcManager.IsCompleted()&& _gotSources) ) && t<maxSimTime) {
t = 0+(frameNr-1)*_deltaT;
// Handle train traffic: coorect geometry
bool geometryChanged= TrainTraffic();
//process the queue for incoming pedestrians
ProcessAgentsQueue();
......@@ -545,16 +578,38 @@ double Simulation::RunBody(double maxSimTime)
//here we could place router-tasks (calc new maps) that can use multiple cores AND we have 't'
//update quickestRouter
if (_routingEngine.get()->GetRouter(ROUTING_FF_QUICKEST)) {
FFRouter* ffrouter = dynamic_cast<FFRouter*>(_routingEngine.get()->GetRouter(ROUTING_FF_QUICKEST));
if (ffrouter->MustReInit()) {
ffrouter->ReInit();
ffrouter->SetRecalc(t);
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");
}
}
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);
}
}
// here the used routers are update, when needed due to external changes
if (_routingEngine->NeedsUpdate()){
std::cout << KBLU << " Init router in simulation\n" << RESET;
_routingEngine->UpdateRouter();
}
......@@ -571,29 +626,8 @@ double Simulation::RunBody(double maxSimTime)
// write the trajectories
if (0==frameNr%writeInterval) {
_iod->WriteFrame(frameNr/writeInterval, _building.get());
if(_config-> GetFileFormat() == FORMAT_PLAIN)
{
fs::path p = _config->GetTrajectoriesFile();
int sf = fs::file_size(p);
if(sf>_maxFileSize*1024*1024)
{
std::string extention = p.extension().string();
_countTraj++;
char tmp_traj_name[100];
sprintf(tmp_traj_name,"%s_%.4d_%s", TrajectoryName.stem().string().c_str(), _countTraj, extention.c_str());
_config->SetTrajectoriesFile(tmp_traj_name);
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());
}
}
_iod->WriteFrame(frameNr/writeInterval, _building.get());
WriteTrajectories(TrajectoryName.stem().string());
}
if(!_gotSources && !_periodic && _config->print_prog_bar())
......@@ -623,8 +657,12 @@ double Simulation::RunBody(double maxSimTime)
}
#endif
// here open transition that should be closed
// TODO fix, opens door everytime...
//init train trainOutfloww
for (auto tab : TrainTimeTables)
{
trainOutflow[tab.first] = 0;
}
// regulate flow
for (auto& itr: _building->GetAllTransitions())
{
Transition* Trans = itr.second;
......@@ -632,26 +670,323 @@ double Simulation::RunBody(double maxSimTime)
{
if ((Trans->GetMaxDoorUsage() != (std::numeric_limits<int>::max)()) ||
(Trans->GetOutflowRate() != (std::numeric_limits<double>::max)()) ){
// || (Trans->GetOutflowRate() != std::numeric_limits<double>::max)){
Trans->UpdateClosingTime( _deltaT);
if(Trans->GetClosingTime() <= _deltaT){
Trans->changeTemporaryState();
Trans->UpdateClosingTime( _deltaT);
if(Trans->GetClosingTime() <= _deltaT){
Trans->changeTemporaryState();
}
Log-> Write("INFO:\tReset state of door %d, Time=%.2f", Trans->GetID(), Pedestrian::GetGlobalTime());
}
}// normal transition
}
}
//-----------
// 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
if(frameNr % 1000 == 0)
{
Log->Write("INFO:\tUpdate door statistics at t=%.2f", t);
PrintStatistics(t);
Log->Write("INFO:\tUpdate door statistics at t=%.2f", t);
PrintStatistics(t);
}
}// while time
return t;
}