Skip to content

Advanced Topics

Configuration Directory Layout

Each scenario folder contains modular .ini files. The top-level .ini file includes them and defines concrete [Config ...] blocks:

File Purpose
configurations/BlindTx.ini Abstract MAC configurations for blind transmission
configurations/SatDetect.ini Abstract MAC configurations for satellite detection mode
configurations/BandSelection.ini Carrier frequency and bandwidth settings
configurations/Constellations.ini Which constellation file to include
configurations/DevicePositionning.ini Terminal deployment (latitude, longitude, radius)
configurations/Services.ini Packet generation rates and service types
configurations/SimulationLength.ini sim-time-limit for each service scenario
configurations/StatisticRecording.ini Which vectors and scalars to record

Concrete scenarios are assembled by extending multiple abstract configs:

[Config MyRun]
extends = TenDevices, BlindKineis, ServiceEveryHour, UHF, ConstellationIridium

Implementation Details

Topology Control (src/Global/Topology_Control/)

TopologyControlBase provides the satellite and ground-station registries, link creation/teardown primitives, and the periodic update timer. Subclasses override initTopology() and updateTopology().

ConstellationTopologyControl is the main subclass. On each update cycle it:

  1. Calls updateIntraSatelliteLinks() — connects each satellite to the next one in its plane.
  2. Calls updateInterSatelliteLinks() — connects adjacent planes using the Walker inter-plane spacing parameter (disabled near the poles when using ISLState::DISABLED).
  3. Calls updateGroundstationLinks() — for each satellite/ground-station pair, computes the elevation using getElevationAndDistance() and creates or removes the ground link accordingly.
  4. Calls updateLoraDevices() — updates the set of satellites currently in view of each terminal; this drives the MAC layer's satellite-detection logic.

The geographic pre-filter (maxGroundRangeDeg) avoids calling the full SGP4 look-angle computation for satellite/station pairs that are obviously too far apart, which significantly reduces CPU time for large constellations.

KiWan MAC (src/Nodes/_10_Terminal/_20_Data_Link/Ter_Dlk_KiWan.h)

The MAC maintains a pool of TxServer objects (numConcurrentTx of them). Each server is responsible for one packet and progresses through the states SERVER_FREE → SERVER_SLOT_WAIT → SERVER_DETECTING → SERVER_TRANSMITTING.

When a packet arrives from the application layer, it is assigned to a free server. The server computes the start time of its first slot (aligned to a shared grid base time), schedules eventSlotStart, and waits.

At each slot start the server either transmits immediately (blind mode) or enters the detection sub-state. In detection mode it schedules eventStartDetection, listens for a satellite preamble, and either proceeds to transmission or skips the slot.

The fallback mechanism maintains a sliding window of recent detection outcomes. When the success rate falls below fallbackTargetRatio - fallbackDisableMarginPercent, the server switches to blind transmission for the remaining slots. When the rate recovers above fallbackTargetRatio + fallbackEnableMarginPercent, it re-enables detection (subject to an exponential backoff delay).

Satellite Routing (src/Nodes/_20_Satellite/_30_Network/)

Sat_Net_StoreAndForward — handles packets by checking whether any ground station link is currently active. If yes, it forwards the packet directly. If no, it stores it in a Sat_Net_SdrModel FIFO buffer (capacity: maxStoredPackets). When a topology change connects a ground station, a 1 ms forwarding timer paces stored packets out one by one to avoid overloading the packet handler.

Sat_Net_DDRARouting — maintains a cost matrix over the ISL graph (provided by ConstellationTopologyControl::getCostMatrix()). On each topology change it runs Dijkstra from its own node to all destinations. When a link is congested (queue above queueThreshold), it broadcasts a control packet to inform neighbors, which update their local cost matrix and recalculate routes.

Custom Physical Layer (src/Global/Channel/, src/Global/Transceiver/)

CustomPHYAnalogModel::computeReceptionPower() computes the received signal power as:

P_rx = P_tx + G_tx_pattern + G_rx(elevation) - PL(distance, exponent) - obstruction

where G_rx(elevation) is evaluated as a·elev² + b·elev + c from the three configurable coefficients.

CustomReceiver then checks the resulting C/N₀ against a threshold (cn0ThresholdForPU) or a CSV lookup table (loadCn0PerMapFile) that maps load and C/N₀ to a packet error rate.


Adding a Custom Antenna Pattern

CustomAntenna loads a gain-vs-elevation CSV at initialization. Create the file:

elevation_deg,gain_dbi
-90,0.0
0,0.0
15,1.5
30,3.0
45,4.5
60,5.0
90,5.5

Reference it in the .ini file:

*.terminal[*].phy.radio.antenna.patternFile = "devices/my_antenna.csv"

Adding a Custom MAC Scheme

  1. Create a new class inheriting from Base_MacProtocol (in src/Global/Base/_20_Data_Link/):
#include "Global/Base/_20_Data_Link/Base_MacProtocol.h"

class MyMac : public Base_MacProtocol {
    void handleUpperMessage(cMessage *msg) override;
    void handleLowerMessage(cMessage *msg) override;
    void handleSelfMessage(cMessage *msg) override;
    MacAddress getAddress() override;
};
  1. Create the corresponding .ned file declaring the module and its parameters.

  2. Register the module in OMNeT++ by adding Define_Module(MyMac); in the .cc file.

  3. Enable it in the .ini file:

*.terminal[*].dlk.mac.typename = "MyMac"

Adding a Custom Propagation Model

Extend CustomPHYPathLoss or LoRaPathLossOulu and override computePathLoss(). Register the new module in a .ned file and enable it:

**.radioMedium.pathLoss.typename = "MyPathLoss"

Batch Simulations

Launch all runs for a configuration in parallel:

opp_runall -j $(nproc) -c MySweep Custom_default.ini

To check progress:

opp_runall -p Custom_default.ini -c MySweep

Parameter count grows combinatorially. Run short tests first to validate configurations before committing to full-length simulations.


Troubleshooting

No packets received

  • Check that the satellite passes over the terminal during the simulation window. Use the GUI animation to confirm.
  • Check the minimumElevationTermSat threshold; a value that is too high will reject most passes.
  • Verify that Ntx and ttwDuration are large enough to cover at least one satellite pass.

Simulation crashes on start

  • The results/ directory must exist before the simulation runs. Create it: mkdir -p results.
  • Verify that all include paths in the .ini file resolve correctly relative to the scenario folder.

Parameter not taking effect

  • OMNeT++ applies parameters in order; later settings override earlier ones. Check that the correct [Config ...] block is being run.
  • Use *.module.param (single star) when targeting a specific level; **.param (double star) matches anywhere.