Simulando consumo de energía en NS3 (II)

Seguimos explicando el modelo de simulación del consumo de energía. Ya explicamos en la primera entrada relativa a la energía los conceptos básicos modelados en NS3. Seguimos trabajando con el ejemplo básico examples/energy/energy-model-example.cc

Si observamos el ejemplo, existen dos funciones añadidas justo antes de la función principal, RemainingEnergy y TotalEnergy:

/// Trace function for remaining energy at node.
void
RemainingEnergy (double oldValue, double remainingEnergy)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
<< "s Current remaining energy = " << remainingEnergy << "J");
}

/// Trace function for total energy consumption at node.
void
TotalEnergy (double oldValue, double totalEnergy)
{
NS_LOG_UNCOND (Simulator::Now ().GetSeconds ()
<< "s Total energy consumed by radio = " << totalEnergy << "J");
}

Estas funciones, como podemos ver, imprimen la energía que queda en la fuente de energía y el total de energía consumida por la radio.

Para invocar estas funciones cuando existe un cambio en la energía restante y/o energía consumida, debemos enlazar las funciones anteriores a los cambios de estado de la fuente de energía y del modelo de energía consumido respectivamente. De esta forma, obtenemos primero una referencia a la fuente de energía con ID 1. A continuación, mediante la función TraceConnectWithoutContext, vinculamos el cambio de estado en RemainingEnergy a una llamada a la misma función, mediante MakeCallBack y un puntero a la función deseada, en este caso RemainingEnergy también:

Ptr basicSourcePtr = DynamicCast (sources.Get (1));
basicSourcePtr->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback (&RemainingEnergy));

A continuación se sigue el mismo proceso obteniendo el modelo de consumo de energía de un dispositivo:

// device energy model
Ptr basicRadioModelPtr =
basicSourcePtr->FindDeviceEnergyModels ("ns3::WifiRadioEnergyModel").Get (0);
NS_ASSERT (basicRadioModelPtr != NULL);
basicRadioModelPtr->TraceConnectWithoutContext ("TotalEnergyConsumption", MakeCallback (&TotalEnergy));

De esta forma se tracean los cambios de estado en las fuentes de energía, que simulan baterías, modelos de energía, que simulan el consumo de las tarjetas de red, y los recolectores de energía que simularían paneles solares, viento, etc.

La función TraceconnectWithoutContext conecta una fuente de trazas (es decir, algo que representa un estado dentro de NS3 y que puede cambiar) con una función. Identificaremos estas fuentes de trazas por que son variables de la plantilla TracedValue, por ejemplo, puedes ver en la definición BasicEnergySource tiene una variable TracedValue m_remainingEnergyJ; que es susceptible de ser traceada mediante una función asociada con TraceconnectWithoutContext asocíandole una función que tenga como argumentos el valor antiguo y nuevo. El tipo de argumentos en este caso será double. La documentación de cada clase proporciona qué TracedSources tiene para usar este mecanismo (e.g. BasicEnergySource).

Topología de los nodos en NS3

Sobre todo en simulaciones que tienen nodos inalámbricos, después de crear los nodos debes posicionarlos para formar tu topología. Topologías habituales en simulaciones son en forma de matriz cuadrada, en línea, en estrella con el nodo que hace de pasarela en el centro, etc.

El emplazamiento de un nodo (X,Y,Z) generalmente se hace con la ayuda de un objeto de la clase MobilityHelper que permite crear escenarios con posiciones donde luego emplazamos nuestros nodos (almacenados en un contenedor del tipo NodeContainer).
Es decir, configuramos una topología concreta con el MobilityHelper y luego instalamos en esa topología los nodos creados y configurados de acuerdo a los requisitos de la simulación.
Una configuración sencilla en matriz 2D sería:

MobilityHelper mobility;
mobility.SetPositionAllocator ("ns3::GridPositionAllocator",
"MinX", DoubleValue (0.0),
"MinY", DoubleValue (0.0),
"DeltaX", DoubleValue (distanceX),
"DeltaY", DoubleValue (distanceY),
"GridWidth", UintegerValue (nodesgridwidth),
"LayoutType", StringValue ("RowFirst"));
mobility.SetMobilityModel ("ns3::ConstantPositionMobilityModel");

En primer lugar se le indica que vamos a crear puntos de acuerdo a ns3::GridPositionAllocator . Esto es importante por que el resto de argumentos que viene a continuación va en función de este primer argumento. El resto indica las coordenadas iniciales (MinX, MinY) en 0,0 , con una separación determinada, en este caso indicado por distanceX y distanceY, con una anchura indicado por la variable nodesgridwidth empezando por las filas (RowFirst). Por último indicamos que los emplazamientos son fijos “ns3::ConstantPositionMobilityModel”.

En el repositorio de este tutorial podemos ver algunos ejemplos de base para topologías habituales. Los parámetros de entrada son configurables por línea de comandos de cara a permitir la simulación automática de varias topologías.

También en simulaciones inalámbricas, una vez emplazados, es posible que quieras mover tus nodos, para lo cual tendrás que configurar el escenario de acuerdo a tu modelo de movilidad

Otra posibilidad que te permite ns3 es la de leer topologías de un archivo donde has almacenado la posición de algunos nodos.Los inputs readers te permiten este tipo de lecturas ad-hoc y generar topologías personalizadas y/o concretas.