Ejemplo n.º 1
0
void VelocityModel::ComputeNextTimeStep(double current, double deltaT, Building* building, int periodic)
{
      double delta = 0.5;
      // collect all pedestrians in the simulation.
      const vector< Pedestrian* >& allPeds = building->GetAllPedestrians();

      unsigned long nSize;
      nSize = allPeds.size();

      int nThreads = omp_get_max_threads();
      //nThreads = 1; //debug only
      int partSize;
      partSize = (int) (nSize / nThreads);

      #pragma omp parallel  default(shared) num_threads(nThreads)
      {
           vector< Point > result_acc = vector<Point > ();
           result_acc.reserve(nSize);
           vector< my_pair > spacings = vector<my_pair > ();
           spacings.reserve(nSize); // larger than needed
           spacings.push_back(my_pair(100, 1)); // in case there are no neighbors
           const int threadID = omp_get_thread_num();

           int start = threadID*partSize;
           int end;
           end = (threadID + 1) * partSize - 1;
           if ((threadID == nThreads - 1)) end = (int) (nSize - 1);

           for (int p = start; p <= end; ++p) {

                Pedestrian* ped = allPeds[p];
                Room* room = building->GetRoom(ped->GetRoomID());
                SubRoom* subroom = room->GetSubRoom(ped->GetSubRoomID());

                double normVi = ped->GetV().ScalarProduct(ped->GetV()); //squared
                double HighVel = (ped->GetV0Norm() + delta) * (ped->GetV0Norm() + delta); //(v0+delta)^2
                if (normVi > HighVel && ped->GetV0Norm() > 0) {
                     fprintf(stderr, "WARNING: VelocityModel::ComputeNextTimeStep() actual velocity (%f) of iped %d "
                             "is bigger than desired velocity (%f) at time: %fs\n",
                             sqrt(normVi), ped->GetID(), ped->GetV0Norm(), current);

                     // remove the pedestrian and abort
                     Log->Write("\tERROR: ped [%d] was removed due to high velocity",ped->GetID());
                     building->DeletePedestrian(ped);
                     exit(EXIT_FAILURE);
                }

                Point repPed = Point(0,0);
                vector<Pedestrian*> neighbours;
                building->GetGrid()->GetNeighbourhood(ped,neighbours);

                int size = (int) neighbours.size();
                for (int i = 0; i < size; i++) {
                     Pedestrian* ped1 = neighbours[i];
                     //if they are in the same subroom
                     Point p1 = ped->GetPos();
                     Point p2 = ped1->GetPos();
                     //subrooms to consider when looking for neighbour for the 3d visibility
                     vector<SubRoom*> emptyVector;
                     emptyVector.push_back(subroom);
                     emptyVector.push_back(building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID()));
                     bool isVisible = building->IsVisible(p1, p2, emptyVector, false);
                     if (!isVisible)
                          continue;
                     if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) {
                           repPed += ForceRepPed(ped, ped1, periodic);
                     } else {
                          // or in neighbour subrooms
                          SubRoom* sb2=building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID());
                          if(subroom->IsDirectlyConnectedWith(sb2)) {
                                repPed += ForceRepPed(ped, ped1, periodic);
                          }
                     }
                } // for i
                //repulsive forces to walls and closed transitions that are not my target
                Point repWall = ForceRepRoom(allPeds[p], subroom);

                // calculate new direction ei according to (6)
                Point direction = e0(ped, room) + repPed + repWall;
                for (int i = 0; i < size; i++) {
                      Pedestrian* ped1 = neighbours[i];
                     // calculate spacing
                     // my_pair spacing_winkel = GetSpacing(ped, ped1);
                      if (ped->GetUniqueRoomID() == ped1->GetUniqueRoomID()) {
                            spacings.push_back(GetSpacing(ped, ped1, direction, periodic));
                      } else {
                            // or in neighbour subrooms
                            SubRoom* sb2=building->GetRoom(ped1->GetRoomID())->GetSubRoom(ped1->GetSubRoomID());
                            if(subroom->IsDirectlyConnectedWith(sb2)) {
                                  spacings.push_back(GetSpacing(ped, ped1, direction, periodic));
                            }
                      }
                }
                // @todo: get spacing to walls
                // @todo: update direction every DT?
                
                // if(ped->GetID()==-10)
                //       std::cout << "time: " << ped->GetGlobalTime() << "  |  updateRate  " <<ped->GetUpdateRate() << "   modulo " <<fmod(ped->GetGlobalTime(), ped->GetUpdateRate())<<std::endl; 

                // calculate min spacing
                std::sort(spacings.begin(), spacings.end(), sort_pred());                
                double spacing = spacings[0].first;
                double winkel = spacings[0].second;
                Point tmp;


                // if(fmod(ped->GetGlobalTime(), ped->GetUpdateRate())<0.0001 || (spacing-ped->GetLastE0()._x)>0.01)
                // {
                   
                      // if(ped->GetID()==-10)
                            // std::cout << "Min Spacing "<< spacing << ", " << winkel << std::endl;
                //       ped->SetLastE0(Point(spacing, winkel));
                // }
                // else
                // {
                //       tmp = ped->GetLastE0();
                //       if(ped->GetID()==10)
                //             std::cout << "keep direction "<<tmp._x << ", " << tmp._y << std::endl;
                //       spacing = tmp._x;
                //       winkel = tmp._y;
                // }
                // if(ped->GetID()==-10)
                      // getc(stdin);

                
                // spacing = *std::min_element(std::begin(spacings), std::end(spacings));
                // if(ped->GetID()==10){
                      // fprintf(stderr, "%f %f %f\n", ped->GetGlobalTime(), (repPed+repWall).Norm(), spacing);
                // }
                Point speed = direction.Normalized() * OptimalSpeed(ped, spacing, winkel);
                result_acc.push_back(speed);
                spacings.clear(); //clear for ped p
           } // for p

           //#pragma omp barrier
           // update
           for (int p = start; p <= end; ++p) {
                Pedestrian* ped = allPeds[p];

                Point v_neu = result_acc[p - start];
                Point pos_neu = ped->GetPos() + v_neu * deltaT;

               //Jam is based on the current velocity
                if ( v_neu.Norm() >= ped->GetV0Norm()*0.5) {
                     ped->ResetTimeInJam();
                } else {
                     ped->UpdateTimeInJam();
                }
                //only update the position if the velocity is above a threshold
                if (v_neu.Norm() >= J_EPS_V)
                {
                     ped->SetPhiPed();
                }
                ped->SetPos(pos_neu);
                if(periodic){
                      if(ped->GetPos()._x >= xRight){
                            ped->SetPos(Point(ped->GetPos()._x - (xRight - xLeft), ped->GetPos()._y));
                            //ped->SetID( ped->GetID() + 1);
                      }
                }
                ped->SetV(v_neu);
           }
      }//end parallel
}
Ejemplo n.º 2
0
void Simulation::UpdateRoutesAndLocations()
{
     //pedestrians to be deleted
     //you should better create this in the constructor and allocate it once.
     set<Pedestrian*> pedsToRemove;
//     pedsToRemove.reserve(500); //just reserve some space

     // collect all pedestrians in the simulation.
     const vector<Pedestrian*>& allPeds = _building->GetAllPedestrians();
     const map<int, Goal*>& goals = _building->GetAllGoals();
     auto allRooms = _building->GetAllRooms();

#pragma omp parallel for shared(pedsToRemove, allRooms)
     for (signed int p = 0; p < allPeds.size(); ++p) {
          auto ped = allPeds[p];
          Room* room = _building->GetRoom(ped->GetRoomID());
          SubRoom* sub0 = room->GetSubRoom(ped->GetSubRoomID());

          //set the new room if needed
          if ((ped->GetFinalDestination() == FINAL_DEST_OUT)
                    && (room->GetCaption() == "outside")) {

#pragma omp critical(Simulation_Update_pedsToRemove)
               pedsToRemove.insert(ped);
          } else if ((ped->GetFinalDestination() != FINAL_DEST_OUT)
                    && (goals.at(ped->GetFinalDestination())->Contains(
                              ped->GetPos()))) {
#pragma omp critical(Simulation_Update_pedsToRemove)
               pedsToRemove.insert(ped);
          }

          // reposition in the case the pedestrians "accidently left the room" not via the intended exit.
          // That may happen if the forces are too high for instance
          // the ped is removed from the simulation, if it could not be reassigned
          else if (!sub0->IsInSubRoom(ped))
          {

               bool assigned = false;
               std::function<void(const Pedestrian&)> f = std::bind(&Simulation::UpdateFlowAtDoors, this, std::placeholders::_1);
               assigned = ped->Relocate(f);
               //this will delete agents, that are pushed outside (maybe even if inside obstacles??)

               if (!assigned) {
#pragma omp critical(Simulation_Update_pedsToRemove)
                       pedsToRemove.insert(ped); //the agent left the old room
                    //actualize the eggress time for that room
#pragma omp critical(SetEgressTime)
                    allRooms.at(ped->GetRoomID())->SetEgressTime(ped->GetGlobalTime());

               }
          }
          //finally actualize the route
          if ( !_gotSources && ped->FindRoute() == -1) {
               //a destination could not be found for that pedestrian
               Log->Write("ERROR: \tCould not find a route for pedestrian %d",ped->GetID());
               //ped->FindRoute(); //debug only, plz remove
               std::function<void(const Pedestrian&)> f = std::bind(&Simulation::UpdateFlowAtDoors, this, std::placeholders::_1);
               ped->Relocate(f);
               //exit(EXIT_FAILURE);
#pragma omp critical(Simulation_Update_pedsToRemove)
               {
                    pedsToRemove.insert(ped);
                    Log->incrementDeletedAgents();
               }
          }
     }


#ifdef _USE_PROTOCOL_BUFFER
     if (_hybridSimManager)
     {
          AgentsQueueOut::Add(pedsToRemove);    //this should be critical region (and it is)
     }
     else
#endif
    {

        // remove the pedestrians that have left the building
        for (auto p : pedsToRemove){
            UpdateFlowAtDoors(*p);
            _building->DeletePedestrian(p);
        }
        pedsToRemove.clear();
    }

    //    temporary fix for the safest path router
    //    if (dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1)))
    //    {
    //         SafestPathRouter* spr = dynamic_cast<SafestPathRouter*>(_routingEngine->GetRouter(1));
    //         spr->ComputeAndUpdateDestinations(_allPedestians);
    //    }
}