diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2d2fc34e874d20b200a889b9bad1e2639554f618..1d3e86a65b62a6dfae8ac070ed373cf3b92a2c1b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -159,6 +159,7 @@ set( HDR
   src/IO/TraVisToClient.h
   forms/Settings.h
   src/SaxParser.h
+  src/train.h
   src/Debug.h
   src/Frame.h
   src/InteractorStyle.h
diff --git a/src/IO/OutputHandler.cpp b/src/IO/OutputHandler.cpp
index 064c973771c78b59dfe2abce76a9e000222c52c9..669a15d15e311bab57dcd3ffef4d18bd84f189a8 100644
--- a/src/IO/OutputHandler.cpp
+++ b/src/IO/OutputHandler.cpp
@@ -57,8 +57,7 @@ int OutputHandler::GetErrors()
 
 void OutputHandler::Write(const string& str)
 {
-     if (this != NULL)
-          cout << str << endl;
+     cout << str << endl;
 }
 
 void OutputHandler::ProgressBar(double TotalPeds, double NowPeds)
@@ -157,10 +156,10 @@ FileHandler::~FileHandler()
 
 void FileHandler::Write(const string& str)
 {
-    if (this != NULL) {
+    // if (this != NULL) {
         _pfp << str << endl;
         _pfp.flush();
-    }
+    // }
 
     if (str.find("ERROR") != string::npos)
     {
diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp
index 5d489c1b901771775d06c6be115516386f17f812..a4ab9c2d1ccd236f8f424fd52c5e5f4c16fa2af8 100755
--- a/src/MainWindow.cpp
+++ b/src/MainWindow.cpp
@@ -808,8 +808,15 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
     }
 
     SyncData* dataset=NULL;
+
     extern_trajectories_firstSet.clearFrames();
 
+
+    vtkSmartPointer<vtkSphereSource> org = vtkSphereSource::New();
+    org->SetRadius(10);
+    // extern_mysphere = org;
+
+
     switch(groupID) {
     case 1:
         Debug::Messages("handling first set");
@@ -855,6 +862,8 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
     else if(fileName.endsWith(".txt",Qt::CaseInsensitive))
     {
          QString source_file= wd + QDir::separator() + SaxParser::extractSourceFileTXT(fileName);
+         QString ttt_file= wd + QDir::separator() + SaxParser::extractTrainTimeTableFileTXT(fileName);
+         QString tt_file= wd + QDir::separator() + SaxParser::extractTrainTypeFileTXT(fileName);
          QString goal_file=wd + QDir::separator() + SaxParser::extractGoalFileTXT(fileName);
          QFileInfo check_file(source_file);
          if( !(check_file.exists() && check_file.isFile()) )
@@ -864,7 +873,7 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
          else
               Debug::Messages("INFO: MainWindow::addPedestrianGroup: source name: <%s>", source_file.toStdString().c_str());
 
-         check_file = source_file;
+         check_file = goal_file;
          if( !(check_file.exists() && check_file.isFile()) )
         {
              Debug::Messages("WARNING: MainWindow::addPedestrianGroup: goal name: <%s> not found!", goal_file.toStdString().c_str());
@@ -873,6 +882,25 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
               Debug::Messages("INFO: MainWindow::addPedestrianGroup: goal name: <%s>", goal_file.toStdString().c_str());
 
 
+         check_file = ttt_file;
+         if( !(check_file.exists() && check_file.isFile()) )
+        {
+             Debug::Messages("WARNING: MainWindow::addPedestrianGroup: ttt name: <%s> not found!", ttt_file.toStdString().c_str());
+        }
+         else
+              Debug::Messages("INFO: MainWindow::addPedestrianGroup: ttt name: <%s>", ttt_file.toStdString().c_str());
+
+         check_file = tt_file;
+         if( !(check_file.exists() && check_file.isFile()) )
+        {
+             Debug::Messages("WARNING: MainWindow::addPedestrianGroup: tt name: <%s> not found!", tt_file.toStdString().c_str());
+        }
+         else
+              Debug::Messages("INFO: MainWindow::addPedestrianGroup: tt name: <%s>", tt_file.toStdString().c_str());
+
+
+
+
         // ------ parsing sources
         QFile file(source_file);
         QXmlInputSource source(&file);
@@ -881,14 +909,30 @@ bool MainWindow::addPedestrianGroup(int groupID,QString fileName)
         reader.setContentHandler(&handler);
         reader.parse(source);
         file.close();
+        // -----
+        // // ---- parsing goals
+        // -----
         QFile file2(goal_file);
         QXmlInputSource source2(&file2);
         reader.parse(source2);
         file2.close();
-        // -----
-        // // ---- parsing goals
-        // -----
+        // parsing trains
+        // train type
+        std::map<int, std::shared_ptr<TrainTimeTable> > trainTimeTable;
+        std::map<std::string, std::shared_ptr<TrainType> > trainTypes;
+
+        SaxParser::LoadTrainType(tt_file.toStdString(), trainTypes);
+        extern_trainTypes = trainTypes;
+
+        bool ret = SaxParser::LoadTrainTimetable(ttt_file.toStdString(), trainTimeTable);
+        if(!ret) std::cout << "hmmm\n";
+
+        extern_trainTimeTables = trainTimeTable;
+        for(auto tab: trainTimeTable)
+             std::cout << "tab: " << tab.first << "\n";
 
+        for(auto tab: trainTypes)
+             std::cout << "type: " << tab.first << "\n";
 
         if(false==SaxParser::ParseTxtFormat(fileName, dataset,&frameRate))
             return false;
diff --git a/src/SaxParser.cpp b/src/SaxParser.cpp
index 4bc76de705f81d8a1a2a1dc4ac6e5b455421d342..0354f50dec00fa62c50f86a2dcac0db33de89748 100644
--- a/src/SaxParser.cpp
+++ b/src/SaxParser.cpp
@@ -1199,6 +1199,70 @@ QString SaxParser::extractSourceFileTXT(QString &filename)
      return extracted_source_name;
 }
 
+QString SaxParser::extractTrainTypeFileTXT(QString &filename)
+{
+     QString extracted_tt_name="";
+     QFile file(filename);
+     QString line;
+     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+          QTextStream in(&file);
+          while (!in.atEnd()) {
+               //look for a line with
+               line = in.readLine();
+               // std::cout << " >> " <<  line.toStdString().c_str() << endl;
+               if(line.split(":").size()==2)
+               {
+                    if(line.split(":")[0].contains("trainType",Qt::CaseInsensitive))
+                    {
+                         extracted_tt_name = line.split(":")[1].simplified().remove(' ');
+                         break;
+                    }
+               }
+          }// while
+     } // if open
+     if(extracted_tt_name=="")
+     {
+          Debug::Warning("Could not extract trainType file!");
+     }
+
+     else
+          Debug::Messages("Extracted trainType from TXT file <%s>", extracted_tt_name.toStdString().c_str());
+     return extracted_tt_name;
+}
+
+QString SaxParser::extractTrainTimeTableFileTXT(QString &filename)
+{
+     QString extracted_ttt_name="";
+     QFile file(filename);
+     QString line;
+     if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
+          QTextStream in(&file);
+          while (!in.atEnd()) {
+               //look for a line with
+               line = in.readLine();
+               // std::cout << " >> " <<  line.toStdString().c_str() << endl;
+               if(line.split(":").size()==2)
+               {
+                    if(line.split(":")[0].contains("trainTimeTable",Qt::CaseInsensitive))
+                    {
+                         extracted_ttt_name = line.split(":")[1].simplified().remove(' ');
+                         break;
+                    }
+               }
+          }// while
+     } // if open
+     if(extracted_ttt_name=="")
+     {
+          Debug::Warning("Could not extract trainTimeTable file!");
+     }
+
+     else
+          Debug::Messages("Extracted trainTimeTable from TXT file <%s>", extracted_ttt_name.toStdString().c_str());
+     return extracted_ttt_name;
+}
+
+
+
 QString SaxParser::extractGoalFileTXT(QString &filename)
 {
      QString extracted_goal_name="";
@@ -1687,3 +1751,184 @@ void SaxParser::InitHeader(int major, int minor, int patch)
           exit(0);
      }
 }
+
+
+bool SaxParser::LoadTrainTimetable(std::string Filename, std::map<int, std::shared_ptr<TrainTimeTable> > & trainTimeTables)
+{
+     TiXmlDocument docTTT(Filename);
+     if (!docTTT.LoadFile()) {
+          Debug::Messages("ERROR: \t%s", docTTT.ErrorDesc());
+          Debug::Messages("ERROR: \t could not parse the train timetable file.");
+          return false;
+     }
+     TiXmlElement* xTTT = docTTT.RootElement();
+     if (!xTTT) {
+          Debug::Messages("ERROR:\tRoot element does not exist in TTT file.");
+          return false;
+     }
+     if (xTTT->ValueStr() != "train_time_table") {
+          Debug::Messages("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) { // todo: maybe get pointer to train
+               if (trainTimeTables.count(TTT->id)!=0) {
+                    Debug::Messages("WARNING: Duplicate id for train time table found [%d]",TTT->id);
+                    exit(EXIT_FAILURE);
+               }
+               trainTimeTables[TTT->id] = TTT;
+          }
+          else {
+          std:cout << "too bad! \n" ;
+
+          }
+     }
+     return true;
+}
+
+
+bool   SaxParser::LoadTrainType(std::string Filename, std::map<std::string, std::shared_ptr<TrainType> > & trainTypes)
+{
+
+     TiXmlDocument docTT(Filename);
+     if (!docTT.LoadFile()) {
+          Debug::Messages("ERROR: \t%s", docTT.ErrorDesc());
+          Debug::Messages("ERROR: \t could not parse the train type file.");
+          return false;
+     }
+     TiXmlElement* xTT = docTT.RootElement();
+     if (!xTT) {
+          Debug::Messages("ERROR:\tRoot element does not exist in TT file.");
+          return false;
+     }
+     if (xTT->ValueStr() != "train_type") {
+          Debug::Messages("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) {
+               if (trainTypes.count(TT->type)!=0) {
+                    Debug::Messages("WARNING: Duplicate type for train found [%s]",TT->type.c_str());
+               }
+               trainTypes[TT->type] = TT;
+          }
+     }
+     return true;
+
+
+}
+
+
+
+std::shared_ptr<TrainTimeTable> SaxParser::parseTrainTimeTableNode(TiXmlElement * e)
+{
+     Debug::Messages("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
+     Debug::Messages("INFO:\tTrain time table:");
+     Debug::Messages("INFO:\t   id: %d", id);
+     Debug::Messages("INFO:\t   type: %s", type.c_str());
+     Debug::Messages("INFO:\t   room_id: %d", room_id);
+     Debug::Messages("INFO:\t   subroom_id: %d", subroom_id);
+     Debug::Messages("INFO:\t   platform_id: %d", platform_id);
+     Debug::Messages("INFO:\t   track_start: [%.2f, %.2f]", track_start_x, track_start_y);
+     Debug::Messages("INFO:\t   track_end: [%.2f, %.2f]", track_end_x, track_end_y);
+     Debug::Messages("INFO:\t   arrival_time: %.2f", arrival_time);
+     Debug::Messages("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,
+                    vtkSmartPointer<vtkPolyDataMapper>::New(),
+                    vtkSmartPointer<vtkActor>::New(),
+                    vtkSmartPointer<vtkTextActor3D>::New(),
+                    });
+
+     return trainTimeTab;
+}
+
+std::shared_ptr<TrainType> SaxParser::parseTrainTypeNode(TiXmlElement * e)
+{
+     Debug::Messages("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);
+     }
+     Debug::Messages("INFO:\t   type: %s", type.c_str());
+     Debug::Messages("INFO:\t   capacity: %d", agents_max);
+     Debug::Messages("INFO:\t   number of doors: %d", doors.size());
+     for(auto d: doors)
+     {
+          Debug::Messages("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;
+
+}
diff --git a/src/SaxParser.h b/src/SaxParser.h
index 7e104cb8489f872d5e6f2eb1e25cf1a02098188a..bcc5e4558f1c0d1781030f7652cec80089d270cc 100644
--- a/src/SaxParser.h
+++ b/src/SaxParser.h
@@ -35,6 +35,12 @@
 #include <vector>
 #include "SyncData.h"
 #include"geometry/GeometryFactory.h"
+#include "tinyxml/tinyxml.h"
+#include "general/Macros.h"
+
+#include "train.h"
+
+
 
 
 
@@ -90,6 +96,14 @@ public:
 
     /// parse a vtk file
     static bool ParseGradientFieldVTK(QString fileName, GeometryFactory& geoFac);
+     /// Trains
+     static bool LoadTrainTimetable(std::string filename, std::map<int, std::shared_ptr<TrainTimeTable> > & trainTimeTables);
+     static std::shared_ptr<TrainTimeTable> parseTrainTimeTableNode(TiXmlElement * e);
+     static std::shared_ptr<TrainType> parseTrainTypeNode(TiXmlElement * e);
+     static QString extractTrainTypeFileTXT(QString &filename);
+     static QString extractTrainTimeTableFileTXT(QString &filename);
+
+     static bool   LoadTrainType(std::string Filename, std::map<std::string, std::shared_ptr<TrainType> > & trainTypes);
 
 private:
     //clear the mo
diff --git a/src/SyncData.cpp b/src/SyncData.cpp
index 3b6085a5b5bdcea18e6838dc1de71d35b5f2f1e1..d4af0b4ad61e60e8adc7520338591d57ae2455b8 100644
--- a/src/SyncData.cpp
+++ b/src/SyncData.cpp
@@ -138,6 +138,17 @@ Frame* SyncData::getFrame( int i)
 
 }
 
+vtkSmartPointer<vtkSphereSource> SyncData::getTTT()
+{
+     return _ttt;
+}
+
+void SyncData::setTTT(vtkSmartPointer<vtkSphereSource> s)
+{
+     _ttt = s;
+}
+
+
 Frame* SyncData::getNextFrame()
 {
 
@@ -193,8 +204,8 @@ Frame* SyncData::getNextFrame()
 /***
 * This method is for convenience only.
 * The normal way to get the previous frame is:
-* 		1. either set the variable extern_update_step to a negative value;
-* 		2. using the function getFrame(int frameNumber). one may first get
+*               1. either set the variable extern_update_step to a negative value;
+*               2. using the function getFrame(int frameNumber). one may first get
 * the current framecursor position using getFrameCursor()
 */
 //Frame* SyncData::getPreviousFrame()
diff --git a/src/SyncData.h b/src/SyncData.h
index 05ba080f796461e186e8f62937f2a78c00235c27..488109d921f8fa41fe33bdd053622da9df29d088 100644
--- a/src/SyncData.h
+++ b/src/SyncData.h
@@ -42,7 +42,8 @@
 #include <memory>
 #include <vector>
 #include <map>
-
+#include <vtkSmartPointer.h>
+#include <vtkSphereSource.h>
 
 class QObject;
 class QStringList;
@@ -84,6 +85,9 @@ public:
 
     /// return the frame at position i
     Frame* getFrame(int i);
+     vtkSmartPointer<vtkSphereSource> getTTT();
+     void setTTT(vtkSmartPointer<vtkSphereSource> s);
+
 
     /// return a pointer to the next frame
     Frame* getNextFrame();
@@ -166,6 +170,8 @@ private:
     //std::vector<Frame*> _frames;
     std::map <int, Frame*> _frames;
     //std::map<int, std::unique_ptr<Frame> > _frames;
+     vtkSmartPointer<vtkSphereSource> _ttt;
+
 };
 
 #endif /* SYNCDATA_H_ */
diff --git a/src/ThreadVisualisation.cpp b/src/ThreadVisualisation.cpp
index ef079cf1bd4d26fcca5189562dc683b0b29dbe72..6ab70c6394aac62b95ec4884148fc0aae78cabeb 100644
--- a/src/ThreadVisualisation.cpp
+++ b/src/ThreadVisualisation.cpp
@@ -76,7 +76,7 @@
 #include <vtkWindowToImageFilter.h>
 #include <vtkActor.h>
 #include <vtkLightKit.h>
-
+#include <vtkPolyLine.h>
 
 #include "geometry/FacilityGeometry.h"
 #include "geometry/GeometryFactory.h"
@@ -140,7 +140,6 @@ void ThreadVisualisation::slotSetFrameRate(float fps)
 
 void ThreadVisualisation::run()
 {
-//     std::cout << "RUN " << _runningTime << "\n";
     //deactivate the output windows
     vtkObject::GlobalWarningDisplayOff();
 
@@ -180,59 +179,83 @@ void ThreadVisualisation::run()
     //renderer->AddActor(axis);
 
     //add big circle at null point
-    {
-        vtkSphereSource* org = vtkSphereSource::New();
-        org->SetRadius(300);
-
-        vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
-        mapper->SetInputConnection(org->GetOutputPort());
-        org->Delete();
-
-        // create actor
-        vtkActor* actor = vtkActor::New();
-        actor->SetMapper(mapper);
-        mapper->Delete();
-        actor->GetProperty()->SetColor(.90,.90,0.0);
-        actor->Delete();
-        //renderer->AddActor(actor);
-    }
-    //add another big circle at null point
-    {
-        vtkSphereSource* org = vtkSphereSource::New();
-        org->SetRadius(300);
-        //org->SetCenter(50,80,0);
-
-        vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
-        mapper->SetInputConnection(org->GetOutputPort());
-        org->Delete();
-
-        // create actor
-        vtkActor* actor = vtkActor::New();
-        actor->SetMapper(mapper);
-        mapper->Delete();
-        actor->GetProperty()->SetColor(.90,.90,0.0);
-        actor->SetPosition(5000,8000,0);
-        actor->Delete();
-        //renderer->AddActor(actor);
-    }
-
-
-    // Create a real circle, not a sphere
-    {
-        VTK_CREATE(vtkRegularPolygonSource, polygonSource);
-        polygonSource->GeneratePolygonOff();
-        polygonSource->SetNumberOfSides(50);
-        polygonSource->SetRadius(1000);
-        polygonSource->SetCenter(0,0,0);
-        polygonSource->Update();
-
-        VTK_CREATE(vtkPolyDataMapper,mapper);
-        mapper->SetInputConnection(polygonSource->GetOutputPort());
-        VTK_CREATE(vtkActor,actor);
-        actor->GetProperty()->SetColor(180.0/255,180.0/255.0,180.0/255.0);
-        actor->SetMapper(mapper);
-        //renderer->AddActor(actor);
-    }
+    // {
+    //      vtkSphereSource* org = vtkSphereSource::New();
+    //     org->SetRadius(10);
+    //     vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
+    //     mapper->SetInputConnection(org->GetOutputPort());
+    //     org->Delete();
+    //     //------
+    //     // create actor
+    //     vtkActor* actor = vtkActor::New();
+    //     actor->SetMapper(mapper);
+    //     mapper->Delete();
+    //     actor->GetProperty()->SetColor(.1,.10,0.0);
+    //     _renderer->AddActor(actor);
+    //     actor->Delete();
+    //      mysphere;
+    //     //
+    // }
+    // {
+    //     vtkPolyDataMapper* mapper = vtkPolyDataMapper::New();
+    //     mapper->SetInputConnection(extern_mysphere->GetOutputPort());
+    //     //------
+    //     // create actor
+    //     vtkActor* actor = vtkActor::New();
+    //     actor->SetMapper(mapper);
+    //     mapper->Delete();
+    //     actor->GetProperty()->SetColor(.1,.10,0.0);
+    //     _renderer->AddActor(actor);
+    //     actor->Delete();
+    //     //
+    // }
+
+    // {
+    //      // Train
+    //      double p0[3] = {1.0*100, 4.0*100, 0.0};
+    //      double p1[3] = {3.0*100, 4.0*100, 0.0};
+    //      double p2[3] = {3.0*100, 5.0*100, 0.0};
+    //      double p3[3] = {1.0*100, 5.0*100, 0.0};
+    //      double p4[3] = {1.0*100, 4.0*100, 0.0};
+    //      // Create a vtkPoints object and store the points in it
+    //      VTK_CREATE(vtkPoints, points);
+
+    //      points->InsertNextPoint(p0);
+    //      points->InsertNextPoint(p1);
+    //      points->InsertNextPoint(p2);
+    //      points->InsertNextPoint(p3);
+    //      points->InsertNextPoint(p4);
+
+    //      VTK_CREATE(vtkPolyLine, polyLine);
+
+    //      polyLine->GetPointIds()->SetNumberOfIds(5);
+    //      for(unsigned int i = 0; i < 5; i++)
+    //      {
+    //           polyLine->GetPointIds()->SetId(i,i);
+    //      }
+
+    //      // Create a cell array to store the lines in and add the lines to it
+    //      VTK_CREATE(vtkCellArray, cells);
+    //      cells->InsertNextCell(polyLine);
+
+    //      // Create a polydata to store everything in
+    //      VTK_CREATE(vtkPolyData, polyData);
+
+    //      // Add the points to the dataset
+    //      polyData->SetPoints(points);
+
+    //      // Add the lines to the dataset
+    //      polyData->SetLines(cells);
+
+    //      VTK_CREATE(vtkPolyDataMapper, mapper);
+    //      mapper->SetInputData(polyData);
+
+
+    //      VTK_CREATE(vtkActor, actor);
+    //      actor->SetMapper(mapper);
+    //      actor->GetProperty()->SetColor(.1,.10,0.0);
+    //     _renderer->AddActor(actor);
+    // }
 
     // Create the render window
     _renderWindow = vtkRenderWindow::New();
@@ -302,6 +325,10 @@ void ThreadVisualisation::run()
     renderingTimer->setTextActor(_runningTime);
     _renderWinInteractor->AddObserver(vtkCommand::TimerEvent,renderingTimer);
 
+
+
+
+
     //create the necessary connections
     QObject::connect(renderingTimer, SIGNAL(signalRunningTime(unsigned long )),
                      this->parent(), SLOT(slotRunningTime(unsigned long )));
@@ -311,7 +338,6 @@ void ThreadVisualisation::run()
 
     QObject::connect(renderingTimer, SIGNAL(signalRenderingTime(int)),
                      this->parent(), SLOT(slotRenderingTime(int)));
-//    std::cout << "timer " << timer << "\n";
 
     // Create my interactor style
     InteractorStyle* style = InteractorStyle::New();
@@ -586,7 +612,7 @@ void ThreadVisualisation::initGlyphs3D()
         //importer->GetRenderWindow()->GetInteractor()->Start();
 
         ////collect all the elements from the 3ds
-        vtkActorCollection* collection=importer->GetRenderer()->GetActors();
+        vtkActorCollection* collection=importer->GetRenderer()x->GetActors();
         vtkActor *actorCharlie= collection->GetLastActor();
         actorCharlie->InitPathTraversal();
         vtkMapper *mapperCharlie=actorCharlie->GetMapper();
diff --git a/src/ThreadVisualisation.h b/src/ThreadVisualisation.h
index efe0288bc6358a317129bd1aa27883c80b35a820..32560b5e09baa1cd88d8e19393681dd8f025cb10 100644
--- a/src/ThreadVisualisation.h
+++ b/src/ThreadVisualisation.h
@@ -74,6 +74,8 @@ extern  vtkActor* extern_glyphs_pedestrians_actor_2D;
 extern  vtkActor* extern_glyphs_pedestrians_actor_3D;
 
 extern SyncData extern_trajectories_firstSet;
+// extern vtkSmartPointer<vtkSphereSource> extern_mysphere;
+
 
 class ThreadVisualisation :public QThread {
     Q_OBJECT
diff --git a/src/TimerCallback.cpp b/src/TimerCallback.cpp
index 416ed69b1b0344e5edb9bb204444b2e37e61e4d5..e44274b8dca376975fefad119b55259444bea53b 100644
--- a/src/TimerCallback.cpp
+++ b/src/TimerCallback.cpp
@@ -37,7 +37,7 @@
 #include <algorithm>
 #include <cstdlib>
 #include <iostream>
-
+#include <stdio.h>
 
 #ifdef TRAVISTO_FFMPEG
 #ifdef _WIN32
@@ -77,8 +77,14 @@
 #include <vtkLabeledDataMapper.h>
 #include <vtkMath.h>
 
-
-
+#include <vtkPolyLine.h>
+#include <vtkTextProperty.h>
+#include <vtkProperty.h>
+#include <vtkLineSource.h>
+#include <vtkVectorText.h>
+#include <vtkFollower.h>
+#include <vtkLine.h>
+#include <vtkTubeFilter.h>
 
 #include "geometry/FacilityGeometry.h"
 #include "geometry/Point.h"
@@ -92,12 +98,17 @@
 #include "TrailPlotter.h"
 #include "geometry/PointPlotter.h"
 #include "TimerCallback.h"
+#include <vtkTextActor3D.h>
+
 
 #define VTK_CREATE(type, name) \
     vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
 
 using namespace std;
 
+static int once=1;
+
+
 TimerCallback* TimerCallback::New()
 {
     TimerCallback *cb = new TimerCallback;
@@ -126,6 +137,10 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
             vtkRenderWindow  *renderWindow = iren->GetRenderWindow();
             vtkRenderer *renderer =renderWindow->GetRenderers()->GetFirstRenderer();
 
+
+
+
+
             if (iren && renderWindow && renderer) {
 
                 //first pedestrian group
@@ -145,9 +160,98 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
                         frame = extern_trajectories_firstSet.getNextFrame();
                     }
 
-                        frameNumber=extern_trajectories_firstSet.getFrameCursor();
 
-                    if(frame==NULL)
+                    frameNumber=extern_trajectories_firstSet.getFrameCursor();
+
+
+                    double now = frameNumber*iren->GetTimerDuration(tid)/1000;
+
+                    // {
+                    //      for (auto tab: extern_trainTimeTables)
+                    //      {
+                    //           VTK_CREATE(vtkPolyDataMapper, mapper);
+                    //           VTK_CREATE(vtkActor, actor);
+                    //      }
+
+                    // }
+                    int countTrains  = 0;
+                    char label[100];
+
+                    for (auto tab: extern_trainTimeTables)
+                        {
+                             // VTK_CREATE(vtkTextActor, textActor);
+                             VTK_CREATE(vtkTextActor3D, textActor);
+                             auto trainType = tab.second->type;
+                             sprintf(label, "%s_%d", trainType.c_str(), tab.second->id);
+                             auto trainId = tab.second->id;
+                             auto trackStart = tab.second->pstart;
+                             auto trackEnd = tab.second->pend;
+                             auto trainStart = tab.second->tstart;
+                             auto trainEnd = tab.second->tend;
+                             auto train = extern_trainTypes[trainType];
+                             auto doors = train->doors;
+                             std::vector<Point> doorPoints;
+                             auto mapper = tab.second->mapper;
+                             auto actor = tab.second->actor;
+                             auto txtActor = tab.second->textActor;
+                             for(auto door: doors)
+                             {
+                                  doorPoints.push_back(door.GetPoint1());
+                                  doorPoints.push_back(door.GetPoint2());
+                             }//doors
+                             if(once)
+                             {
+                                  auto data = getTrainData(trainStart, trainEnd, doorPoints);
+                                  mapper->SetInputData(data);
+                                  actor->SetMapper(mapper);
+                                  actor->GetProperty()->SetLineWidth(10);
+                                  actor->GetProperty()->SetOpacity(0.1);//feels cool!
+                                  actor->GetProperty()->SetColor(
+                                       std::abs(0.9-renderer->GetBackground()[0]),
+                                       std::abs(0.9-renderer->GetBackground()[1]),
+                                       std::abs(1.0-renderer->GetBackground()[2])
+                                       );
+                                  // text
+                                  txtActor->GetTextProperty()->SetOpacity(0.7);
+                                  double pos_x = 50*(trainStart._x + trainEnd._x+0.5);
+                                  double pos_y = 50*(trainStart._y + trainEnd._y+0.5);
+
+                                  txtActor->SetPosition (pos_x, pos_y+2, 20);
+                                  txtActor->SetInput (label);
+                                  txtActor->GetTextProperty()->SetFontSize (30);
+                                  txtActor->GetTextProperty()->SetBold (true);
+                                  txtActor->GetTextProperty()->SetColor (
+                                       std::abs(0.9-renderer->GetBackground()[0]),
+                                       std::abs(0.9-renderer->GetBackground()[1]),
+                                       std::abs(0.5-renderer->GetBackground()[2])
+                                       );
+                                  txtActor->SetVisibility(false);
+                             }
+                             if((now >= tab.second->tin) && (now <= tab.second->tout))
+                             {
+                                  actor->SetVisibility(true);
+                                  txtActor->SetVisibility(true);
+                             }
+                             else
+                             {
+                                  actor->SetVisibility(false);
+                                  txtActor->SetVisibility(false);
+                             }
+                             if(once)
+                             {
+                                  renderer->AddActor(actor);
+                                  renderer->AddActor(txtActor);
+                                  if(countTrains == extern_trainTimeTables.size())
+                                       once = 0;
+                             }
+
+                             countTrains++;
+                        }// time table
+
+
+
+
+                     if(frame==NULL)
                     {
 
                     } else {
@@ -205,7 +309,7 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
                 int* winSize=renderWindow->GetSize();
                 static int  lastWinX=winSize[0]+1; // +1 to trigger a first change
                 static int lastWinY=winSize[1];
-
+                // HHHHHH
                 sprintf(runningTimeText,"Pedestrians: %d      Time: %ld Sec",nPeds,frameNumber*iren->GetTimerDuration(tid)/1000);
                 runningTime->SetInput(runningTimeText);
                 runningTime->Modified();
@@ -252,6 +356,7 @@ void TimerCallback::Execute(vtkObject *caller, unsigned long eventId,
                     emit signalFrameNumber(frameNumber, minFrame);
                     emit signalRunningTime(frameNumber*iren->GetTimerDuration(tid));
                     emit signalRenderingTime(effectivefps);
+
                 }
 
 #ifdef TRAVISTO_FFMPEG
@@ -542,3 +647,60 @@ void TimerCallback::setTextActor(vtkTextActor* ra)
 {
     runningTime=ra;
 }
+
+
+// https://vtk.org/Wiki/VTK/Examples/Cxx/GeometricObjects/ColoredLines
+
+
+vtkSmartPointer<vtkPolyData>  TimerCallback::getTrainData(
+     Point trainStart, Point trainEnd, std::vector<Point> doorPoints)
+{
+     float factor = 100.0;
+
+     double pt[3] = { 1.0, 0.0, 0.0 }; // to convert from Point
+     // Create the polydata where we will store all the geometric data
+     vtkSmartPointer<vtkPolyData> linesPolyData =
+          vtkSmartPointer<vtkPolyData>::New();
+
+     // Create a vtkPoints container and store the points in it
+     vtkSmartPointer<vtkPoints> pts =
+          vtkSmartPointer<vtkPoints>::New();
+
+     pt[0] = factor*trainStart._x; pt[1] = factor*trainStart._y;
+     pts->InsertNextPoint(pt);
+
+     for(auto p: doorPoints)
+     {
+          pt[0] = factor*p._x; pt[1] = factor*p._y;
+           pts->InsertNextPoint(pt);
+     }
+     pt[0] = factor*trainEnd._x; pt[1] = factor*trainEnd._y;
+     pts->InsertNextPoint(pt);
+
+
+     // Add the points to the polydata container
+     linesPolyData->SetPoints(pts);
+
+
+     vtkSmartPointer<vtkCellArray> lines =
+          vtkSmartPointer<vtkCellArray>::New();
+
+
+     // Create the first line (between Origin and P0)
+     for(int i = 0; i<= doorPoints.size(); i+=2 )
+     {
+          vtkSmartPointer<vtkLine> line =
+               vtkSmartPointer<vtkLine>::New();
+          line->GetPointIds()->SetId(0, i);
+          line->GetPointIds()->SetId(1, i+1);
+
+          lines->InsertNextCell(line);
+          lines->InsertNextCell(line);
+          line = nullptr;
+     }
+
+     // Add the lines to the polydata container
+     linesPolyData->SetLines(lines);
+     return linesPolyData;
+
+}
diff --git a/src/TimerCallback.h b/src/TimerCallback.h
index 836aa132a13e226ca8e9bd5721bc3f4a29dfa8b0..c070f8d7ded3f89ed82d972f9e7d22d19df7192c 100644
--- a/src/TimerCallback.h
+++ b/src/TimerCallback.h
@@ -52,6 +52,8 @@ class vtkFFMPEGWriter;
 #include <vtkTensorGlyph.h>
 #include <vtkSmartPointer.h>
 #include <vtkPolyDataMapper.h>
+#include <vtkLineSource.h>
+#include "train.h"
 
 class SyncData;
 class QObject;
@@ -89,6 +91,9 @@ extern PointPlotter* extern_trail_plotter;
 
 extern SyncData extern_trajectories_firstSet;
 
+extern SyncData mysphere;
+extern std::map<std::string, std::shared_ptr<TrainType> > extern_trainTypes;
+extern std::map<int, std::shared_ptr<TrainTimeTable> > extern_trainTimeTables;
 //states if the datasets are loaded.
 extern bool extern_first_dataset_loaded;
 
@@ -126,6 +131,12 @@ public:
     void SetRenderTimerId(int tid);
 
     void setTextActor(vtkTextActor* runningTime);
+     // vtkSmartPointer<vtkActor> setTrainActor(
+     //      Point trainStart, Point trainEnd, std::vector<Point> doorPoints);
+
+     vtkSmartPointer<vtkPolyData> getTrainData(
+          Point trainStart, Point trainEnd, std::vector<Point> doorPoints);
+
 
 private:
     ///updates system global changes, like fullscreen, ffw and soone
diff --git a/src/extern_var.h b/src/extern_var.h
index 99bab85c7c8747354cf28ba80ec3e7b102ac1a98..2d9f1ea36da0dabe6f46c2fc25abd22c58d82b89 100644
--- a/src/extern_var.h
+++ b/src/extern_var.h
@@ -46,10 +46,9 @@
 #include <vtkSmartPointer.h>
 #include <vtkPolyDataMapper.h>
 
-
-
+#include "train.h"
 #define VTK_CREATE(type, name) \
-		vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
+                vtkSmartPointer<type> name = vtkSmartPointer<type>::New()
 
 //external variables
 /// define the speed/rate/pace at which  the trajectories are displayed.
@@ -84,6 +83,9 @@ double extern_scale_pedestrian=0.1;
 // At most three pedestrians groups can be loaded
 ///The first pedestrian group
 Pedestrian** extern_pedestrians_firstSet=NULL;
+vtkSmartPointer<vtkSphereSource> extern_mysphere=nullptr;
+std::map<std::string, std::shared_ptr<TrainType> > extern_trainTypes;
+std::map<int, std::shared_ptr<TrainTimeTable> > extern_trainTimeTables;
 
 
 //vtkSmartPointer<vtkTensorGlyph> extern_glyphs_pedestrians=NULL;
diff --git a/src/general/Macros.h b/src/general/Macros.h
index 92bbd4a9c3cc9a7e3bcd86a7d82d14213f8c7e2b..3f6e32686edb39fffc462f3d00e029994c92759a 100644
--- a/src/general/Macros.h
+++ b/src/general/Macros.h
@@ -25,7 +25,7 @@
  *
  *
  **/
- 
+
 
 #ifndef _MACROS_H
 #define _MACROS_H
@@ -39,9 +39,15 @@
 #include <iostream>
 
 
+enum RoomState {
+     ROOM_CLEAN=0,
+     ROOM_SMOKED=1
+};
+
+
 #ifndef M_PI
 #define M_PI 3.14159265358979323846
-#endif 
+#endif
 
 //fix for osx/linux/win
 #define  _isnan(x) std::isnan(x)
@@ -89,11 +95,6 @@
 #define LIST_EMPTY  -1
 
 
-enum RoomState {
-     ROOM_CLEAN=0,
-     ROOM_SMOKED=1
-};
-
 enum AgentType {
      MALE=0,
      FEMALE,
diff --git a/src/geometry/Building.cpp b/src/geometry/Building.cpp
index 482384d11e61c1c1cc6a524ace77bede227cf7df..8b1433f88197a55cc365d51cdb498ae7ea54cbe7 100644
--- a/src/geometry/Building.cpp
+++ b/src/geometry/Building.cpp
@@ -82,6 +82,35 @@ Building::Building(const std::string& filename, const std::string& rootDir, Rout
 }
 #endif
 
+// bool Building::AddTrainType(std::shared_ptr<TrainType> TT)
+// {
+//       if (_trainTypes.count(TT->type)!=0) {
+//             // Log->Write("WARNING: Duplicate type for train found [%s]",TT->type);
+//       }
+//       _trainTypes[TT->type] = TT;
+//       return true;
+// }
+
+// bool Building::AddTrainTimeTable(std::shared_ptr<TrainTimeTable> TTT)
+// {
+//       if (_trainTimeTables.count(TTT->id)!=0) {
+//             Log->Write("WARNING: Duplicate id for train time table found [%d]",TTT->id);
+//             exit(EXIT_FAILURE);
+//       }
+//       _trainTimeTables[TTT->id] = TTT;
+//       return true;
+// }
+// const std::map<std::string, std::shared_ptr<TrainType> >& Building::GetTrainTypes() const
+// {
+//       return _trainTypes;
+// }
+
+// const std::map<int, std::shared_ptr<TrainTimeTable> >& Building::GetTrainTimeTables() const
+// {
+//       return _trainTimeTables;
+// }
+
+
 Building::~Building()
 {
      //
diff --git a/src/geometry/Building.h b/src/geometry/Building.h
index 7497f78556c3af9a2e2f2d9ce5abf0afd95db6b8..4c4db41ffa16951b887a358e5f5295f78794808c 100644
--- a/src/geometry/Building.h
+++ b/src/geometry/Building.h
@@ -43,6 +43,12 @@
 #include "Obstacle.h"
 #include "Goal.h"
 #include "../tinyxml/tinyxml.h"
+
+// train schedules: Trains get deleted and added.
+
+
+
+
 class RoutingEngine;
 class Pedestrian;
 class Transition;
@@ -67,6 +73,8 @@ private:
      std::map<int, Hline*> _hLines;
      std::map<int, Goal*>_goals;
 
+
+
      /// pedestrians pathway
      bool _savePathway;
      std::ofstream _pathWayStream;
@@ -101,6 +109,9 @@ public:
      Transition* GetTransition(int id) ;
      Transition* ParseTransitionNode(TiXmlElement * xTrans);
 
+
+
+
      /**
       * Not implemented
       */
diff --git a/src/geometry/FacilityGeometry.cpp b/src/geometry/FacilityGeometry.cpp
index 3fbfd5b09b11f1eb53f04e49a6e0102e0f8afc52..4249d9fbb78d75d2d0a54558bd1ab1b39fb173f8 100644
--- a/src/geometry/FacilityGeometry.cpp
+++ b/src/geometry/FacilityGeometry.cpp
@@ -578,7 +578,7 @@ void FacilityGeometry::addObstacles(vtkPolyData* polygonPolyData )
 void FacilityGeometry::addRectangle(double x1, double y1, double x2, double y2, double z, double color1, double color2, string text)
 {
     //if(z!=1)return;
-     const double cellSize=40; //cm
+     const double cellSize=10; //cm
     //	const int dimX=(x2-x1)/cellSize+1;
     //	const int dimY=(y2-y1)/cellSize+1;
 
diff --git a/src/geometry/Room.h b/src/geometry/Room.h
index 7abe606eb14e32783f588e0c3675469e8b093a34..176f86efcaf50d2a5d2aec103c1adeeedb32551c 100644
--- a/src/geometry/Room.h
+++ b/src/geometry/Room.h
@@ -23,7 +23,7 @@
  *
  *
  **/
- 
+
 
 #ifndef _ROOM_H
 #define _ROOM_H
@@ -165,4 +165,3 @@ public:
 };
 
 #endif  /* _ROOM_H */
-
diff --git a/src/train.h b/src/train.h
new file mode 100644
index 0000000000000000000000000000000000000000..804a2f9e2d3494e0ef8936ad837f828a0d4b8402
--- /dev/null
+++ b/src/train.h
@@ -0,0 +1,36 @@
+#ifndef TRAIN_VAR_H_
+#define TRAIN_VAR_H_ 1
+
+#include "geometry/Point.h"
+#include "geometry/Transition.h"
+#include <vtkPolyDataMapper.h>
+#include <vtkTextActor3D.h>
+
+struct TrainTimeTable
+{
+     int id;
+     std::string type;
+     int rid; // room id
+     int sid; // subroom id
+     double tin; // arrival time
+     double tout; //leaving time
+     Point pstart; // track start
+     Point pend; // track end
+     Point tstart; // train start
+     Point tend; // train end
+     int pid; // Platform id
+     bool arrival;
+     bool departure;
+     vtkSmartPointer<vtkPolyDataMapper> mapper;
+     vtkSmartPointer<vtkActor> actor;
+     vtkSmartPointer<vtkTextActor3D> textActor;
+};
+struct TrainType
+{
+     std::string type;
+     int nmax; // agents_max
+     float len; //length
+     std::vector<Transition> doors;
+};
+
+#endif /* TRAIN_H_ */