/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */ /* * Copyright (c) 2012 Fraunhofer ESK * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation; * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Author: Karsten Roscher <karsten.roscher@esk.fraunhofer.de> */ #ifndef TRACI_MANAGER_H #define TRACI_MANAGER_H #include <ns3/object.h> #include <ns3/ptr.h> #include <ns3/simple-ref-count.h> #include <ns3/nstime.h> #include "traci-types.h" #include "traci-vehicle.h" namespace ns3 { class TraCi; /*! * @brief Class managing simulation steps and arrival and departure of vehicles. * * The manager will schedule an update event for every simulation step and * inform handlers about arrived and departed vehicles. */ class TraCiManager : public Object { public: static TypeId GetTypeId (void); TraCiManager (); ~TraCiManager (); void Start (Time when = Seconds (0)); void Stop (Time when); //! Set TraCi instance to use. void SetTraCi (Ptr<TraCi> traci); //! Set time for one simulation step. void SetSimulationStep (Time step); /*! * @brief Enable/disable automatic time sync on start. * * This will adjust for an offset in times between ns-3 and SUMO in the * beginning in case SUMO was started with a custom beginning time. * * @param enabled True to enable */ void SetTimeSyncOnStart (bool enabled); /*! * @brief Enable/disable automatic departure of vehicles already running on start. * * This will help in case a simulation state was loaded and all vehicles * already on their way should be handles as well. * * @param enabled True to enable */ void SetDepartAlreadyRunningOnStart (bool enabled); /*! * @brief Enable/disable automatic detection of the simulation step size * @param enabled True to enable */ void SetUseStepSizeFromTraciHost (bool enabled); /*! * @brief Base class for node departure/arrival handlers. * * Multiple handlers can be registered at the manager and will be * called in order of their priority. If a handler took care of a * vehicle (HandleDeparture returned true) the process will stop. * * HandleArrival will be called for all registered handlers, even if * they did not indicate that the took care of the object. This allows * multiple handlers to track the lifetime of a vehicle even if they * do not want to terminate further mapping. */ class VehicleHandler : public SimpleRefCount<VehicleHandler> { public: virtual ~VehicleHandler () {} /*! * @brief Handle the departure of a vehicle. * @param vehicle Departed vehicle * @return True if this handler took care of the vehicle. */ virtual bool HandleDeparture (Ptr<traci::Vehicle> vehicle) = 0; /*! * @brief Handle the arrival of a vehicle. * @param vehicleId Id of the arrived vehicle */ virtual void HandleArrival (std::string vehicleId) = 0; /*! * @brief Handle the execution of a simulation step * * This will be invoked after a simulation step executed by the * remote TraCI instance. It is not mandatory to implement this. */ virtual void HandleSimulationStep (Ptr<TraCi> traci) {} }; /*! * @brief Add a vehicle handler with the provided priority. * * Higher values mean a higher priority. The order of invocation * for handlers with the same priority is undefined. * * @param handler Handler to add. * @param priority Priority for the handler. */ void AddHandler (Ptr<VehicleHandler> handler, int priority); /*! * @brief Remove the provided handler. * @param handler Handler to remove. */ void RemoveHandler (Ptr<VehicleHandler> handler); private: void DoStart (); void DoStop (); /*! * @brief Execute a simulation step (will be invoked as event callback). */ void ExecuteSimulationStep (); /*! * @brief Update available nodes. */ void UpdateAvailableNodes (); /*! * @brief Handle arrived vehicles. * @param arrived List of identifiers of arrived vehicles. */ void HandleArrivedVehicles (const traci::StringList& arrived); /*! * @brief Handle a single arrived vehicle * @param objectId Id of the arrived vehicle */ void HandleArrivedVehicle (std::string objectId); /*! * @brief Handle departed vehicles. * @param departed List of identifiers of departed vehicles. */ void HandleDepartedVehicles (const traci::StringList& departed); /*! * @brief Handle a single departed vehicle * @param objectId Id of the departed vehicle * @return True if the vehicle found a handler */ bool HandleDepartedVehicle (std::string objectId); //! Time for one simulation step Time m_simulationStep; //! Flag indicating if the time should be synced on start. bool m_syncTimeOnStart; //! Flag indicating if nodes already running at the beginning should be treated as departed now. bool m_departAlreadyRunningOnStart; //! Flag indicating if the step size of the traci host should be used bool m_useStepSizeFromTraciHost; //! Time SUMO is ahead of ns-3 Time m_sumoOffset; //! Traci instance used. Ptr<TraCi> m_traci; //! Event for a simulation step EventId m_simulationEvent; EventId m_startEvent; EventId m_stopEvent; //! A vehicle handler entry consisting of a priority and a pointer to the handler. typedef std::pair<int, Ptr<VehicleHandler> > HandlerEntry; typedef std::vector<HandlerEntry> HandlerList; HandlerList m_handlers; }; /*! * @brief A simple vehicle handler providing a callback based interface. * * If you prefer using callbacks, you can use this handler. It will * forward the requests to the provided callbacks. */ class CallbackVehicleHandler : public TraCiManager::VehicleHandler { public: virtual bool HandleDeparture (Ptr<traci::Vehicle> vehicle); virtual void HandleArrival (std::string vehicleId); typedef Callback<bool, Ptr<traci::Vehicle> > DepartureCallback; typedef Callback<void, std::string> ArrivalCallback; void SetArrivalCallback (ArrivalCallback cb); void SetDepartureCallback (DepartureCallback cb); private: ArrivalCallback m_arrived; DepartureCallback m_departed; }; } // namespace ns3 #endif