diff --git a/Simulation.cpp b/Simulation.cpp
index 68d06b9345fa0e0b3223e39a57af46ff252aaa3c..7ecb3979d1882a5fc207bff0df6958f27c8914de 100644
--- a/Simulation.cpp
+++ b/Simulation.cpp
@@ -476,8 +476,6 @@ double Simulation::RunBody(double maxSimTime)
         ProcessAgentsQueue();
 
         if (t>Pedestrian::GetMinPremovementTime()) {
-            //@todo: @ar.graf: here we could place router-tasks (calc new maps) that can use multiple cores AND we have 't'
-
             //update the linked cells
             _building->UpdateGrid();
 
@@ -487,8 +485,15 @@ double Simulation::RunBody(double maxSimTime)
             //update the events
             _em->ProcessEvent();
 
-            //update doorticks
-            //UpdateDoorticks();
+            //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);
+                }
+            }
 
             //update the routes and locations
             UpdateRoutesAndLocations();
diff --git a/general/Macros.h b/general/Macros.h
index 8891dfeae3522ed3d614a88464bac7da485858d2..dab0622fa67c574602b143ce0c6720110fe7f3e8 100644
--- a/general/Macros.h
+++ b/general/Macros.h
@@ -187,6 +187,7 @@ enum FloorfieldMode {
      FF_FULL_LINE,
      FF_WALL_AVOID,
      FF_HOMO_SPEED,
+     FF_PED_SPEED,
      FF_ROOM_SCALE,
      FF_SUBROOM_SCALE
 };
diff --git a/geometry/Building.cpp b/geometry/Building.cpp
index 6fec58b11a0777bd25fa688f44950925b65c40d7..085cf8df182526738c18d49b537925e9b98c81b5 100644
--- a/geometry/Building.cpp
+++ b/geometry/Building.cpp
@@ -706,12 +706,9 @@ std::vector<Point> Building::GetBoundaryVertices() const
 
 bool Building::SanityCheck()
 {
-     Log->Write("INFO: \tChecking the geometry for artifacts");
+     Log->Write("INFO: \tChecking the geometry for artifacts: (Ignore Warnings, if ff_[...] router is used!)");
      bool status = true;
 
-     //only for ffRouter
-     return status;
-
      for(auto&& itr_room: _rooms)
      {
           for(auto&& itr_subroom: itr_room.second->GetAllSubRooms())
diff --git a/pedestrian/Pedestrian.cpp b/pedestrian/Pedestrian.cpp
index 9bdc9594dc99ff3d5c2856f49c8e0a6e8c98c1be..b493e77180e017e5eec54c54fd01e4c2c184354d 100644
--- a/pedestrian/Pedestrian.cpp
+++ b/pedestrian/Pedestrian.cpp
@@ -981,7 +981,7 @@ Router* Pedestrian::GetRouter() const
 int Pedestrian::FindRoute()
 {
      if( ! _router) {
-          Log->Write("ERROR:\t one or more routers does not exit! Check your router_ids");
+          Log->Write("ERROR:\t one or more routers does not exist! Check your router_ids");
           return -1;
      }
      //bool isinsub = (_building->GetAllRooms().at(this->GetRoomID())->GetSubRoom(this->GetSubRoomID())->IsInSubRoom(this));
diff --git a/routing/RoutingEngine.cpp b/routing/RoutingEngine.cpp
index d00252fc60675682ed689933551380b4edf98ed3..10001c9331adefd22879fd99139e5aecdad67395 100644
--- a/routing/RoutingEngine.cpp
+++ b/routing/RoutingEngine.cpp
@@ -95,7 +95,7 @@ Router* RoutingEngine::GetRouter(RoutingStrategy strategy) const
           if(router->GetStrategy()==strategy)
                return router;
      }
-     Log->Write("ERROR: \t Could not Find any router with Strategy:  [%d].",strategy);
+     //Log->Write("ERROR: \t Could not Find any router with Strategy:  [%d].",strategy);
      return /*(Router*)*/ nullptr;
 }
 
diff --git a/routing/ff_router/UnivFFviaFM.cpp b/routing/ff_router/UnivFFviaFM.cpp
index 1cf2643271e5c7ddd9b7b328b4c891f24597e7e7..8aa46d0745fc24d84b5e0aae0b83b7ba1d43dcff 100644
--- a/routing/ff_router/UnivFFviaFM.cpp
+++ b/routing/ff_router/UnivFFviaFM.cpp
@@ -8,12 +8,13 @@
 #include "../../geometry/Building.h"
 #include "../../geometry/Room.h"
 #include "../../geometry/SubRoom.h"
+#include "../../pedestrian/Pedestrian.h"
 #include "mesh/RectGrid.h"
 
 
 UnivFFviaFM::~UnivFFviaFM() {
      if (_grid) delete _grid;
-     size_t speedsize = _speedFieldSelector.size();
+     //size_t speedsize = _speedFieldSelector.size();
      for (auto speedPtr : _speedFieldSelector) {
           if (speedPtr) delete[] speedPtr;
      }
@@ -78,15 +79,24 @@ UnivFFviaFM::UnivFFviaFM(Room* roomArg, Configuration* const confArg, double hx,
           const std::vector<Transition*> tmpTrans = subRoomPtr->GetAllTransitions();
 
           int uidNotConst = 0;
+          bool isOpen = false;
           for (auto& cross : tmpCross) {
                uidNotConst = cross->GetUniqueID();
-               if (tmpDoors.count(uidNotConst) == 0) {
+               isOpen = cross->IsOpen();
+               if (!isOpen) {
+                    //will be added twice! is it a problem?
+                    lines.emplace_back((Line)*cross);
+               } else if ((tmpDoors.count(uidNotConst) == 0)) {
                     tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *cross));
                }
           }
           for (auto& trans : tmpTrans) {
                uidNotConst = trans->GetUniqueID();
-               if (tmpDoors.count(uidNotConst) == 0) {
+               isOpen = trans->IsOpen();
+               if (!isOpen) {
+                    //will be added twice! is it a problem?
+                    lines.emplace_back((Line)*trans);
+               } else if (tmpDoors.count(uidNotConst) == 0) {
                     tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *trans));
                }
           }
@@ -129,13 +139,24 @@ UnivFFviaFM::UnivFFviaFM(SubRoom* subRoomArg, Configuration* const confArg, doub
      const std::vector<Transition*> tmpTrans = subRoomArg->GetAllTransitions();
 
      int uidNotConst = 0;
+     bool isOpen = false;
      for (auto& cross : tmpCross) {
           uidNotConst = cross->GetUniqueID();
-          tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *cross));
+          isOpen = cross->IsOpen();
+          if (!isOpen) {
+               lines.emplace_back((Line)*cross);
+          } else {
+               tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *cross));
+          }
      }
      for (auto& trans : tmpTrans) {
           uidNotConst = trans->GetUniqueID();
-          tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *trans));
+          isOpen = trans->IsOpen();
+          if (!isOpen) {
+               lines.emplace_back((Line)*trans);
+          } else {
+               tmpDoors.emplace(std::make_pair(uidNotConst, (Line) *trans));
+          }
      }
 
      //this will interpret "useWallDistances" as best as possible. Users should clearify with "setSpeedMode" before calling "AddTarget"
@@ -163,8 +184,11 @@ void UnivFFviaFM::create(std::vector<Line>& walls, std::map<int, Line>& doors, s
      _speedFieldSelector.emplace(_speedFieldSelector.begin()+INITIAL_SPEED, new double[_nPoints]);
      std::fill(_speedFieldSelector[INITIAL_SPEED], _speedFieldSelector[INITIAL_SPEED]+_nPoints, 1.0);
 
-     //allocate _initalSpeed and maybe _modifiedSpeed
-     if ((mode == FF_WALL_AVOID) || (useWallDistances)) {
+     _speedFieldSelector.emplace(_speedFieldSelector.begin()+REDU_WALL_SPEED, nullptr);
+     _speedFieldSelector.emplace(_speedFieldSelector.begin()+PED_SPEED, nullptr);
+
+     //allocate _modifiedSpeed
+     if ((_speedmode == FF_WALL_AVOID) || (useWallDistances)) {
           double* cost_alias_walldistance = new double[_nPoints];
           _costFieldWithKey[0] = cost_alias_walldistance;
           Point* gradient_alias_walldirection = new Point[_nPoints];
@@ -184,7 +208,7 @@ void UnivFFviaFM::create(std::vector<Line>& walls, std::map<int, Line>& doors, s
           //_uids.emplace_back(0);
 
           double* temp_reduWallSpeed = new double[_nPoints];
-          if (_speedFieldSelector.size() > 1) { //free memory before overwriting
+          if (_speedFieldSelector[REDU_WALL_SPEED]) { //free memory before overwriting
                delete[] _speedFieldSelector[REDU_WALL_SPEED];
           }
           _speedFieldSelector[REDU_WALL_SPEED] = temp_reduWallSpeed;
@@ -193,14 +217,10 @@ void UnivFFviaFM::create(std::vector<Line>& walls, std::map<int, Line>& doors, s
           createReduWallSpeed(temp_reduWallSpeed);
      }
 
-     //the memory will be allocated in "addTarget". for parallel processing, we might change it to allocate before the
-     //parallel region and call a fct "addTarget(int, [ptr_to_preallocated mem])"
-     for (auto targetUID : targetUIDs ) {
-          addTarget(targetUID);
-     }    //loop over targets
-
-
-
+     // parallel call
+     if (!targetUIDs.empty()) {
+          addTargetsParallel(targetUIDs);
+     }
 }
 
 void UnivFFviaFM::createRectGrid(std::vector<Line>& walls, std::map<int, Line>& doors, double spacing) {
@@ -301,8 +321,8 @@ void UnivFFviaFM::markSubroom(const Point& insidePoint, SubRoom* const value) {
           wavefront.erase(current);
           _gridCode[current] = INSIDE;
 
-          directNeighbor _neigh = _grid->getNeighbors(current);
-          long aux = _neigh.key[0];
+          _neigh = _grid->getNeighbors(current);
+          aux = _neigh.key[0];
           if ((aux != -2) && (_gridCode[aux] == INSIDE || _gridCode[aux] == OUTSIDE) && _subrooms[aux] == nullptr) {
                wavefront.insert(aux);
                _subrooms[aux] = value;
@@ -338,6 +358,106 @@ void UnivFFviaFM::createReduWallSpeed(double* reduWallSpeed){
           }
      }
 }
+
+void UnivFFviaFM::recreateAllForQuickest() {
+     //allocate if neccessary (should not be!)
+     for (int doorUID : _uids) {
+          if (!_costFieldWithKey[doorUID]) {
+               _costFieldWithKey[doorUID] = new double[_nPoints];
+          }
+          if (_user == DISTANCE_MEASUREMENTS_ONLY) {
+               if (_directionFieldWithKey.count(doorUID) != 0 && _directionFieldWithKey[doorUID]){
+                    delete[] _directionFieldWithKey[doorUID];
+               }
+               _directionFieldWithKey[doorUID] = nullptr;
+          }
+          if (_user == DISTANCE_AND_DIRECTIONS_USED) {
+               //check if not in map OR (in map but) nullptr)
+               if ((_directionFieldWithKey.count(doorUID) == 0) || (!_directionFieldWithKey[doorUID])) {
+                    _directionFieldWithKey[doorUID] = new Point[_nPoints];
+               }
+          }
+     }
+
+     //parallel region
+#pragma omp parallel
+     {
+#pragma omp for
+          for (unsigned int i = 0; i < _doors.size(); ++i) {
+               auto doorPair = _doors.begin();
+               std::advance(doorPair, i);
+               addTarget(doorPair->first, _costFieldWithKey[doorPair->first], _directionFieldWithKey[doorPair->first]);
+          }
+     };
+}
+
+void UnivFFviaFM::createPedSpeed(Pedestrian *const *pedsArg, int nsize, int modechoice, double radius) {
+     long int delta = radius / _grid->Gethx();
+     long int posIndex = 0;
+     long int pos_i = 0;
+     long int pos_j = 0;
+     long int i_start = 0;
+     long int j_start = 0;
+     long int i_end = 0;
+     long int j_end = 0;
+     long int iStride = _grid->GetiMax();
+     double indexDistance = 0.0;
+
+//     if (nsize == 0) {
+//          Log->Write("WARNING: \tcreatePedSpeed: nsize is ZERO");
+//     } else {
+//          Log->Write("INFO: \t\tNumber of Peds used in createPedSpeed: %d",nsize);
+//     }
+
+     if ((modechoice == quickest) && (!_speedFieldSelector[PED_SPEED])) {
+          _speedFieldSelector[PED_SPEED] = new double[_grid->GetnPoints()];
+     }
+
+     //we assume, that this function is only used by router and is not using REDU_WALL_SPEED
+     for (long int i = 0; i < _grid->GetnPoints(); ++i) {
+          _speedFieldSelector[PED_SPEED][i] = _speedFieldSelector[INITIAL_SPEED][i];
+     }
+
+     for (int i = 0; i < nsize; ++i) {
+          //the following check is not 3D proof, we require the caller of this function to provide a list with "valid"
+          //pedestrian-pointer
+          if (!_grid->includesPoint(pedsArg[i]->GetPos())) {
+               continue;
+          }
+          /*this value defines the jam-speed threshold*/
+//        if (pedsArg[i]->GetEllipse().GetV().Norm() >  0.8*pedsArg[i]->GetEllipse().GetV0()) {
+//            continue;
+//        }
+          posIndex = _grid->getKeyAtPoint(pedsArg[i]->GetPos());
+          pos_i = _grid->get_i_fromKey(posIndex);
+          pos_j = _grid->get_j_fromKey(posIndex);
+
+          i_start = ((pos_i - delta) < 0)               ? 0               : (pos_i - delta);
+          i_end   = ((pos_i + delta) >= iStride) ? iStride-1 : (pos_i + delta);
+
+          j_start = ((pos_j - delta) < 0)               ? 0               : (pos_j - delta);
+          j_end   = ((pos_j + delta) >= _grid->GetjMax()) ? _grid->GetjMax()-1 : (pos_j + delta);
+
+          for     (long int curr_i = i_start; curr_i < i_end; ++curr_i) {
+               for (long int curr_j = j_start; curr_j < j_end; ++curr_j) {
+                    //indexDistance holds the square
+                    indexDistance = ( (curr_i - pos_i)*(curr_i - pos_i) + (curr_j - pos_j)*(curr_j - pos_j) );
+                    //now using indexDistance to store the (speed) reduction value
+                    //indexDistance = (delta*delta) - (indexDistance);
+                    //if (indexDistance < 0) { indexDistance = 0.;}
+                    //scale to [0 .. 1]
+                    //indexDistance = indexDistance/(delta*delta);
+
+                    //densityspeed[curr_j*grid->GetiMax() + curr_i] = (indexDistance > (delta*delta)) ? densityspeed[curr_j*grid->GetiMax() + curr_i] : .001;
+                    if (indexDistance < (delta*delta)) {
+                         //std::cout << "c h a n g i n g   ";
+                         _speedFieldSelector[PED_SPEED][curr_j*iStride + curr_i] = 0.2;
+                    }
+               }
+          }
+     }
+}
+
 void UnivFFviaFM::drawLinesOnGrid(std::map<int, Line>& doors, int *const grid) {
      for (auto&& doorPair : doors) {
           int tempUID = doorPair.first;
@@ -957,18 +1077,20 @@ void UnivFFviaFM::addTarget(const int uid, double* costarrayDBL, Point* gradarra
      }
      Line tempTargetLine = Line(_doors[uid]);
      Point tempCenterPoint = Point(tempTargetLine.GetCentre());
-     if (tempTargetLine.GetLength() > 0.6) { //shorten line from both Points to avoid targeting edges of real door
-          const Point& p1 = tempTargetLine.GetPoint1();
-          const Point& p2 = tempTargetLine.GetPoint2();
-          double length = tempTargetLine.GetLength();
-          double u = 0.2/length;
-          tempTargetLine = Line(p1 + (p2-p1)*u, p1 + (p2-p1)*(1-u), 0);
-     } else if (tempTargetLine.GetLength() > 0.2) {
-          const Point& p1 = tempTargetLine.GetPoint1();
-          const Point& p2 = tempTargetLine.GetPoint2();
-          double length = tempTargetLine.GetLength();
-          double u = 0.05/length;
-          tempTargetLine = Line(p1 + (p2-p1)*u, p1 + (p2-p1)*(1-u), 0);
+     if (_mode == LINESEGMENT) {
+          if (tempTargetLine.GetLength() > 0.6) { //shorten line from both Points to avoid targeting edges of real door
+               const Point &p1 = tempTargetLine.GetPoint1();
+               const Point &p2 = tempTargetLine.GetPoint2();
+               double length = tempTargetLine.GetLength();
+               double u = 0.2 / length;
+               tempTargetLine = Line(p1 + (p2 - p1) * u, p1 + (p2 - p1) * (1 - u), 0);
+          } else if (tempTargetLine.GetLength() > 0.2) {
+               const Point &p1 = tempTargetLine.GetPoint1();
+               const Point &p2 = tempTargetLine.GetPoint2();
+               double length = tempTargetLine.GetLength();
+               double u = 0.05 / length;
+               tempTargetLine = Line(p1 + (p2 - p1) * u, p1 + (p2 - p1) * (1 - u), 0);
+          }
      }
 
      //this allocation must be on shared heap! to be accessible by any thread later (should be shared in openmp)
@@ -1008,6 +1130,8 @@ void UnivFFviaFM::addTarget(const int uid, double* costarrayDBL, Point* gradarra
           calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[REDU_WALL_SPEED]);
      } else if (_speedmode == FF_HOMO_SPEED) {
           calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[INITIAL_SPEED]);
+     } else if (_speedmode == FF_PED_SPEED) {
+          calcFF(newArrayDBL, newArrayPt, _speedFieldSelector[PED_SPEED]);
      }
 #pragma omp critical(_uids)
      _uids.emplace_back(uid);
@@ -1027,6 +1151,9 @@ void UnivFFviaFM::addAllTargets() {
 }
 
 void UnivFFviaFM::addAllTargetsParallel() {
+     //Reason: freeing and reallocating takes time. We do not use already allocated memory, because we do not know if it
+     //        is shared memory. Maybe this is not neccessary - maybe reconsider. This way, it is safe. If this function
+     //        is called from a parallel region, we all go to hell.
      //free old memory
      for (auto memoryDBL : _costFieldWithKey) {
           if (memoryDBL.first == 0) continue;          //do not free distancemap
@@ -1059,6 +1186,39 @@ void UnivFFviaFM::addAllTargetsParallel() {
      };
 }
 
+void UnivFFviaFM::addTargetsParallel(std::vector<int> wantedDoors) {
+     //free old memory (but not the distancemap with key == 0)
+     for (int targetUID : wantedDoors) {
+          if ((targetUID != 0) && _costFieldWithKey.count(targetUID) && _costFieldWithKey[targetUID]) {
+               delete[] _costFieldWithKey[targetUID];
+          }
+          if ((targetUID != 0) && _directionFieldWithKey.count(targetUID) && _directionFieldWithKey[targetUID]) {
+               delete[] _directionFieldWithKey[targetUID];
+          }
+     }
+     //allocate new memory
+     for (int targetUID : wantedDoors) {
+          _costFieldWithKey[targetUID] = new double[_nPoints];
+          if (_user == DISTANCE_MEASUREMENTS_ONLY) {
+               _directionFieldWithKey[targetUID] = nullptr;
+          }
+          if (_user == DISTANCE_AND_DIRECTIONS_USED) {
+               _directionFieldWithKey[targetUID] = new Point[_nPoints];
+          }
+     }
+
+     //parallel region
+#pragma omp parallel
+     {
+#pragma omp for
+          for (unsigned int i = 0; i < wantedDoors.size(); ++i) {
+               auto doorUID = wantedDoors.begin();
+               std::advance(doorUID, i);
+               addTarget(*doorUID, _costFieldWithKey[*doorUID], _directionFieldWithKey[*doorUID]);
+          }
+     };
+}
+
 SubRoom** UnivFFviaFM::getSubRoomFF(){
      return _subrooms;
 }
@@ -1085,6 +1245,9 @@ void UnivFFviaFM::setMode(int modeArg) {
 
 void UnivFFviaFM::setSpeedMode(int speedModeArg) {
      _speedmode = speedModeArg;
+     if (_speedmode == FF_PED_SPEED && !_speedFieldSelector[PED_SPEED]) {
+          _speedFieldSelector[PED_SPEED] = new double[_nPoints];
+     }
 }
 
 
diff --git a/routing/ff_router/UnivFFviaFM.h b/routing/ff_router/UnivFFviaFM.h
index 8bcb80a8f5d6cec405c3f524d58da9ac585a6492..f4424f9a797403eceee66c1c2b208d8488207f11 100644
--- a/routing/ff_router/UnivFFviaFM.h
+++ b/routing/ff_router/UnivFFviaFM.h
@@ -42,6 +42,7 @@
 #include <float.h>
 #include "../../general/Macros.h"
 
+class Pedestrian;
 class Room;
 class SubRoom;
 class Building;
@@ -87,6 +88,7 @@ public:
      UnivFFviaFM(SubRoom* subRoomArg, Configuration* const confArg, double hx, double wallAvoid, bool useWallDistances, std::vector<int> wantedDoors);
      void create(std::vector<Line>& walls, std::map<int, Line>& doors, std::vector<int> targetUIDs, int mode,
                  double spacing, double wallAvoidDist, bool useWallDistances);
+     void recreateAllForQuickest();
      UnivFFviaFM() {};
      UnivFFviaFM(UnivFFviaFM&){};
      virtual ~UnivFFviaFM();
@@ -95,6 +97,7 @@ public:
      void addTarget(const int uid, double* costarray = nullptr, Point* gradarray = nullptr);
      void addAllTargets();
      void addAllTargetsParallel();
+     void addTargetsParallel(std::vector<int> wantedDoors);
      std::vector<int> getKnownDoorUIDs();
      void setUser(int userArg);
      void setMode(int modeArg);
@@ -118,6 +121,7 @@ public:
      void processGeometry(std::vector<Line>&walls, std::map<int, Line>& doors);
      void markSubroom(const Point& insidePoint, SubRoom* const value);
      void createReduWallSpeed(double* reduWallSpeed);
+     void createPedSpeed(Pedestrian* const * pedsArg, int nsize, int modechoice, double radius);
 
      void drawLinesOnGrid(std::map<int, Line>& doors, int *const grid);
      template <typename T>
diff --git a/routing/ff_router/ffRouter.cpp b/routing/ff_router/ffRouter.cpp
index 4249c21d115a2ce3f41b72cbe7c4ebbe19ab432b..46e4c66c3bbc1c7d22af422c8b24d39a2d693049 100644
--- a/routing/ff_router/ffRouter.cpp
+++ b/routing/ff_router/ffRouter.cpp
@@ -185,7 +185,7 @@ bool FFRouter::Init(Building* building)
 //               } else {
 //                    locffptr = new LocalFloorfieldViaFM(pairRoomIt->second.get(), building, 0.125, 0.125, 0.0, false);
 //               }
-          locffptr->setUser(DISTANCE_AND_DIRECTIONS_USED);
+          locffptr->setUser(DISTANCE_MEASUREMENTS_ONLY);
           locffptr->setMode(CENTERPOINT);
           locffptr->setSpeedMode(FF_HOMO_SPEED);
           locffptr->addAllTargetsParallel();
@@ -198,6 +198,10 @@ bool FFRouter::Init(Building* building)
 
      // nowait, because the parallel region ends directly afterwards
 //#pragma omp for nowait
+     //@todo: @ar.graf: it would be easier to browse thru doors of each field directly after "addAllTargetsParallel" as
+     //                 we do only want doors of same subroom anyway. BUT the router would have to switch from room-scope
+     //                 to subroom-scope. Nevertheless, we could omit the room info (used to acces correct field), if we
+     //                 do it like in "ReInit()".
      for (unsigned int i = 0; i < roomAndCroTrVector.size(); ++i) {
           auto rctIt = roomAndCroTrVector.begin();
           std::advance(rctIt, i);
@@ -337,7 +341,68 @@ bool FFRouter::Init(Building* building)
 
 bool FFRouter::ReInit()
 {
-     return false;
+     //cleanse maps
+     _distMatrix.clear();
+     _pathsMatrix.clear();
+
+     //init, yet no distances, only create map entries
+     for(auto& id1 : _allDoorUIDs) {
+          for(auto& id2 : _allDoorUIDs){
+               std::pair<int, int> key   = std::make_pair(id1, id2);
+               double              value = (id1 == id2)? 0.0 : DBL_MAX;
+               //distMatrix[i][j] = 0,   if i==j
+               //distMatrix[i][j] = max, else
+               _distMatrix.insert(std::make_pair( key , value));
+               //pathsMatrix[i][j] = i or j ? (follow wiki:path_reconstruction, it should be j)
+               _pathsMatrix.insert(std::make_pair( key , id2 ));
+               _subroomMatrix.insert(std::make_pair(key, nullptr));
+          }
+     }
+
+     for (auto floorfield : _locffviafm) {
+          floorfield.second->setSpeedMode(FF_PED_SPEED);
+          //@todo: ar.graf: create a list of local ped-ptr instead of giving all peds-ptr
+          floorfield.second->createPedSpeed(_building->GetAllPedestrians().data(), _building->GetAllPedestrians().size(), _mode, 1.);
+          floorfield.second->recreateAllForQuickest();
+          std::vector<int> allDoors(floorfield.second->getKnownDoorUIDs());
+          for (auto firstDoor : allDoors) {
+               for (auto secondDoor : allDoors) {
+                    if (secondDoor <= firstDoor) continue; // calculate every path only once
+                    // if the two doors are not within the same subroom, do not consider (ar.graf)
+                    // should fix problems of oscillation caused by doorgaps in the distancegraph
+                    int thisUID1 = (_CroTrByUID.at(firstDoor)->GetSubRoom1()) ? _CroTrByUID.at(firstDoor)->GetSubRoom1()->GetUID() : -1 ;
+                    int thisUID2 = (_CroTrByUID.at(firstDoor)->GetSubRoom2()) ? _CroTrByUID.at(firstDoor)->GetSubRoom2()->GetUID() : -2 ;
+                    int otherUID1 = (_CroTrByUID.at(secondDoor)->GetSubRoom1()) ? _CroTrByUID.at(secondDoor)->GetSubRoom1()->GetUID() : -3 ;
+                    int otherUID2 = (_CroTrByUID.at(secondDoor)->GetSubRoom2()) ? _CroTrByUID.at(secondDoor)->GetSubRoom2()->GetUID() : -4 ;
+
+                    if (
+                              (thisUID1 != otherUID1) &&
+                              (thisUID1 != otherUID2) &&
+                              (thisUID2 != otherUID1) &&
+                              (thisUID2 != otherUID2)      ) {
+                         continue;
+                    }
+
+                    double tempDistance = floorfield.second->getCostToDestination(firstDoor, _CroTrByUID.at(secondDoor)->GetCentre());
+                    if (tempDistance < floorfield.second->getGrid()->Gethx()) {
+                         //Log->Write("WARNING:\tDistance of doors %d and %d is too small: %f",*otherDoor, *innerPtr, tempDistance);
+                         //Log->Write("^^^^^^^^\tIf there are scattered subrooms, which are not connected, this is ok.");
+                         continue;
+                    }
+                    std::pair<int, int> key_ij = std::make_pair(secondDoor, firstDoor);
+                    std::pair<int, int> key_ji = std::make_pair(firstDoor, secondDoor);
+                    if (_distMatrix.at(key_ij) > tempDistance) {
+                         _distMatrix.erase(key_ij);
+                         _distMatrix.erase(key_ji);
+                         _distMatrix.insert(std::make_pair(key_ij, tempDistance));
+                         _distMatrix.insert(std::make_pair(key_ji, tempDistance));
+                    }
+               } //secondDoor(s)
+          } //firstDoor(s)
+     } //allRooms
+     FloydWarshall();
+     _plzReInit = false;
+     return true;
 }
 
 
@@ -359,13 +424,8 @@ int FFRouter::FindExit(Pedestrian* p)
 //     }
      if (_mode == quickest) {
           //new version: recalc densityspeed every x seconds
-          if (p->GetGlobalTime() > _timeToRecalc) {
-               _timeToRecalc += _recalc_interval;                      //@todo: ar.graf: change "5" to value of config file/classmember
-//               for (auto localfield : _locffviafm) { //@todo: ar.graf: create a list of local ped-ptr instead of giving all peds-ptr
-//                    localfield.second->setSpeedThruPeds(_building->GetAllPedestrians().data(), _building->GetAllPedestrians().size(), _mode, 1.);
-//                    localfield.second->deleteAllFFs();
-//               }
-               ReInit();
+          if ((p->GetGlobalTime() > _timeToRecalc) && (p->GetGlobalTime() > Pedestrian::GetMinPremovementTime() + _recalc_interval)) {
+               _plzReInit = true;
           }
      }
      double minDist = DBL_MAX;
@@ -649,4 +709,12 @@ void FFRouter::SetMode(std::string s)
 
      _mode = global_shortest;
      return;
+}
+
+bool FFRouter::MustReInit() {
+     return _plzReInit;
+}
+
+void FFRouter::SetRecalc(double t) {
+     _timeToRecalc = t + _recalc_interval;
 }
\ No newline at end of file
diff --git a/routing/ff_router/ffRouter.h b/routing/ff_router/ffRouter.h
index b0b866460286e89819ada94c38aa2f168dba07dc..cc875752c880f98476ade6bc5cfae6f5f14f3d75 100644
--- a/routing/ff_router/ffRouter.h
+++ b/routing/ff_router/ffRouter.h
@@ -137,12 +137,11 @@ public:
      virtual bool Init(Building* building);
 
      /*!
-      * \brief ReInit the router (must be called after each event (open/close change)
+      * \brief ReInit the router if quickest router is used. Current position of agents is considered.
       *
       * ReInit() will reconstruct the graph (nodes = doors, edges = costs) and
       * find shortest paths via Floyd-Warshall. It will reconstruct the floorfield to
-      * evaluate the best doors to certain goals as they could change. Further on it
-      * will take the information of former floorfields, if useful.
+      * evaluate the best doors to certain goals as they could change.
       *
       *
       * \param[in] [name of input parameter] [its description]
@@ -181,6 +180,8 @@ public:
       * \brief set mode (shortest, quickest, ...)
       */
       void SetMode(std::string s);
+      bool MustReInit();
+      void SetRecalc(double t);
 
 private:
 
@@ -206,6 +207,7 @@ protected:
      int _mode;
      double _timeToRecalc = 0.;
      double _recalc_interval;
+     bool _plzReInit = false;
      bool _hasSpecificGoals;
      bool _targetWithinSubroom;
      // If we use CentrePointDistance (i.e. CentrePointLocalFFViaFM), some algorithms can maybe be simplified