#ifndef CITYFLOW_ENGINE_H #define CITYFLOW_ENGINE_H #include "flow/flow.h" #include "roadnet/roadnet.h" #include "engine/archive.h" #include "utility/barrier.h" #include #include #include #include #include namespace CityFlow { class Engine { friend class Archive; private: static bool vehicleCmp(const std::pair &a, const std::pair &b) { return a.second > b.second; } std::map> vehiclePool; std::map vehicleMap; std::vector> threadVehiclePool; std::vector> threadRoadPool; std::vector> threadIntersectionPool; std::vector> threadDrivablePool; std::vector flows; RoadNet roadnet; int threadNum; double interval; bool saveReplay; bool saveReplayInConfig; // saveReplay option in config json bool warnings; std::vector> pushBuffer; std::vector laneChangeNotifyBuffer; std::set vehicleRemoveBuffer; rapidjson::Document jsonRoot; std::string stepLog; size_t step = 0; size_t activeVehicleCount = 0; int seed; std::mutex lock; Barrier startBarrier, endBarrier; std::vector threadPool; bool finished = false; std::string dir; std::ofstream logOut; bool rlTrafficLight; bool laneChange; int manuallyPushCnt = 0; int finishedVehicleCnt = 0; double cumulativeTravelTime = 0; private: void vehicleControl(Vehicle &vehicle, std::vector> &buffer); void planRoute(); void getAction(); void updateAction(); void updateLocation(); void updateLeaderAndGap(); void planLaneChange(); void threadController(std::set &vehicles, std::vector &roads, std::vector &intersections, std::vector &drivables); void threadPlanRoute(const std::vector &roads); void threadGetAction(std::set &vehicles); void threadUpdateAction(std::set &vehicles); void threadUpdateLeaderAndGap(const std::vector &drivables); void threadUpdateLocation(const std::vector &drivables); void threadNotifyCross(const std::vector &intersections); void threadInitSegments(const std::vector &roads); void threadPlanLaneChange(const std::set &vehicles); void handleWaiting(); void updateLog(); bool checkWarning(); bool loadRoadNet(const std::string &jsonFile); bool loadFlow(const std::string &jsonFilename); std::vector getRunningVehicles(bool includeWaiting=false) const; void scheduleLaneChange(); void insertShadow(Vehicle *vehicle); public: std::mt19937 rnd; Engine(const std::string &configFile, int threadNum); double getInterval() const { return interval; } bool hasLaneChange() const { return laneChange; } bool loadConfig(const std::string &configFile); void notifyCross(); void nextStep(); bool checkPriority(int priority); void pushVehicle(Vehicle *const vehicle, bool pushToDrivable = true); void setLogFile(const std::string &jsonFile, const std::string &logFile); void initSegments(); ~Engine(); // RL related api void pushVehicle(const std::map &info, const std::vector &roads); size_t getVehicleCount() const; std::vector getVehicles(bool includeWaiting = false) const; std::map getLaneVehicleCount() const; std::map getLaneWaitingVehicleCount() const; std::map> getLaneVehicles(); std::map getVehicleSpeed() const; std::map getVehicleDistance() const; std::string getLeader(const std::string &vehicleId) const; double getCurrentTime() const; double getAverageTravelTime() const; void setTrafficLightPhase(const std::string &id, int phaseIndex); void setReplayLogFile(const std::string &logFile); void setSaveReplay(bool open); void setVehicleSpeed(const std::string &id, double speed); void setRandomSeed(int seed) { rnd.seed(seed); } void reset(bool resetRnd = false); // archive void load(const Archive &archive) { archive.resume(*this); } Archive snapshot() { return Archive(*this); } void loadFromFile(const char *fileName); bool setRoute(const std::string &vehicle_id, const std::vector &anchor_id); std::map getVehicleInfo(const std::string &id) const; }; } #endif //CITYFLOW_ENGINE_H