Skip to content
Snippets Groups Projects
traci-node-manager.h 6.28 KiB
Newer Older
/* -*- 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_NODE_MANAGER_H
#define TRACI_NODE_MANAGER_H

#include <string>
#include <vector>
#include <map>

#include <ns3/node.h>
#include <ns3/node-container.h>
#include <ns3/simulator.h>
#include <ns3/event-id.h>

#include "traci.h"
#include "traci-manager.h"
#include "traci-node-manager-impl.h"
#include "traci-object-acceptor.h"
#include "traci-roi-manager.h"

namespace ns3 {

namespace traci {

/*!
 * @brief A simple node lifetime policy doing nothing.
 */
struct NoOpNodeLifetimePolicy
{
  static void HandleActivateNode (Ptr<Node> n, Ptr<traci::Vehicle>) {}
  static void HandleShutdownNode (Ptr<Node> n) {}
};

}  // namespace traci


/*!
 * @brief Basic node manager that must be extended with a lifetime policy for nodes.
 *
 * This  implementation of the node manager has the option to set a
 * region of interest to limit the area with active nodes to a configurable
 * rectangle. Nodes will only be activated if they are inside the region or
 * after they entered. They will be deactivated as soon as they leave. This
 * should safe simulation time in large scenarios.
 *
 * However, this does not work well with multiple vehicle handlers should be
 * used at a TraCiManager since we have to greedily handle all vehicles to
 * decide later if or when they enter or leave the area. Thus, it should only
 * be used as the lowest priority handler. Otherwise, handlers after one with
 * a region of interest set will not be invoked ever.
 */
template<class NodeLifetimePolicy = traci::NoOpNodeLifetimePolicy>
class TraCiNodeManager : public TraCiManager::VehicleHandler,
                         public NodeLifetimePolicy
{
public:

  /*!
   * @brief Create a new node manager.
   *
   * Not providing a specific acceptor will lead to a "accept all"
   * behavior.
   *
   * @param acceptor   Acceptor to use to filter object ids.
   */
  explicit TraCiNodeManager (Ptr<TraCiObjectAcceptor> acceptor = 0)
    : m_manager (Create<TraCiNodeManagerImpl> ()),
      m_acceptor (acceptor)
  {
    m_roi.SetRoiEnterSignal(
	[this](Ptr<traci::Vehicle> v) { DoHandleActivation (v); });
    m_roi.SetRoiLeaveSignal(
    	[this](Ptr<traci::Vehicle> v)
	{ NS_ASSERT (v); DoHandleShutdown (v->GetId ()); });
  }

  //! Set the acceptor to use for object selection.
  void
  SetObjectAcceptor (Ptr<TraCiObjectAcceptor> acceptor)
  {
    m_acceptor = acceptor;
  }

  /*!
   * @brief Set the region of interest
   * @param regionOfInterest	Region of interest to set
   */
  void
  SetRegionOfInterest (const traci::RoiManager::Region& regionOfInterest)
  {
    m_roi.SetRegionOfInterest (regionOfInterest);
  }

  //! Enable/disable setup of the TraCiMobilityModel.
  void
  EnableMobilityModel (bool isEnabled)
  {
    m_manager->EnableMobilityModel (isEnabled);
  }

  void
  AddNode (Ptr<Node> n)
  {
    m_manager->AddNode (n);
  }

  void
  AddNodes (NodeContainer nodes)
  {
    m_manager->AddNodes (nodes);
  }

  bool
  IsNodeActive (Ptr<Node> n) const
  {
    return m_manager->IsNodeActive (n);
  }

  bool
  IsNodeActive (uint32_t nodeId) const
  {
    return m_manager->IsNodeActive (nodeId);
  }

  NodeContainer
  GetActiveNodes () const
  {
    return m_manager->GetActiveNodes();
  }

  uint32_t
  GetNActiveNodes () const
  {
    return m_manager->GetNActiveNodes ();
  }

  /*
   * TraCiManager::VehicleHandler methods
   */
  bool
  HandleDeparture (Ptr<traci::Vehicle> vehicle) override
  {
    /*
     * We will only use the ROI if it has a valid region.
     * Otherwise, we will directly call activate/shutdown.
     */
    if (m_roi.HasRegionOfInterest ())
      {
	m_roi.AddVehicle(vehicle);

	// We do not know if we accept or not...
	// ... we will keep it this way to terminate further processing.
	return true;
      }
    else
      {
	return DoHandleActivation (vehicle);
      }
  }

  void
  HandleArrival (std::string objectId) override
  {
    /*
     * We will only use the ROI if it has a valid region.
     * Otherwise, we will directly call activate/shutdown.
     */
    if (m_roi.HasRegionOfInterest ())
      {
	m_roi.RemoveVehicle (objectId);
      }
    else
      {
	DoHandleShutdown (objectId);
      }
  }

  virtual void
  HandleSimulationStep (Ptr<TraCi> traci)
  {
    m_roi.CheckForUpdates ();
  }

private:

  /*!
   * @brief Activate the object with the provided traci instance
   * @param objectId	Object id to activate
   * @param traci	Traci to  use for activation
   * @return True if activated, false if not
   */
  bool
  DoHandleActivation (Ptr<traci::Vehicle> vehicle)
  {
    // we will accept everything if no acceptor is set
    if (!m_acceptor || m_acceptor->AcceptObject (vehicle->GetId ()))
      {
	// activate / prepare node
	Ptr<Node> node = m_manager->ActivateNode (vehicle);

	// start node
	if (node)
	  {
	    NodeLifetimePolicy::HandleActivateNode (node, vehicle);
	    // we took care of it
	    return true;
	  }
      }

    return false;
  }

  void
  DoHandleShutdown (std::string objectId)
  {
    // get node from impl
    Ptr<Node> node = m_manager->ShutdownNode (objectId);

    if (node)
      {
	NodeLifetimePolicy::HandleShutdownNode (node);
      }
  }

  /*!
   * @brief Manager implementation (non-template based part).
   */
  Ptr<TraCiNodeManagerImpl> m_manager;

  /*!
   * @brief Acceptor to work only on a subset of the provided objects.
   */
  Ptr<TraCiObjectAcceptor> m_acceptor;

  /*!
   * @brief  Region of interest manager.
   *
   * Vehicles will only be activated in the area, set region to 0 to disable
   */
  traci::RoiManager m_roi;
};

} // namespace ns3

#endif /* TRACI_NODE_MANAGER_H */