Synchronization

Synchronization between simulated devices is modeled by Trigger Models. Simulated device instances sharing the same Trigger Model instance are considered time-synchronized with each other, but not with other simulated devices that do not share the same Trigger Model.

        %%{init: {"flowchart":{"useMaxWidth": false}}}%%
flowchart LR

subgraph Synchronization
   direction TB
   trigger[TriggerModel] --> trigger_realization[TriggerRealization]
end

device_a[Simulated Device]
device_b[         ⋮         ]:::invis
device_c[Simulated Device]

trigger_realization --> device_a
trigger_realization --> device_b
trigger_realization --> device_c

classDef invis fill-opacity:0,stroke-opacity:0,font-weight:bold;

click trigger href "simulation.synchronization.TriggerModel.html"
click trigger_realization href "simulation.synchronization.TriggerRealization.html"
click device_a href "simulation.simulated_device.html"
click device_b href "simulation.simulated_device.html"
click device_c href "simulation.simulated_device.html"
    

During the generation of each simulation drop, the Trigger Model instance is realized once for all simulated devices sharing the same instance, resulting in a single Trigger Realization.

Note that, as the name suggests, HermesPy’s synchronization model is considered to be at the trigger level of transmitting and receiving devices, meaning propagation delays due to channel models linking synchronized devices must still be compensated by appropriate equalization routines. The currently available Trigger Model implementations are:

Trigger Model

Description

Random Trigger

Random triggering within a given time interval.

Sample Offset Trigger

Static triggering at a given sample offset.

Time Offset Trigger

Static triggering at a given time offset.

Static Trigger

Static triggering with no offset. This is the default.

Consider a scenario featuring four wireless devices, with two devices respectively linked, interfering with each other on partially overlapping frequency bands.

1# Create a new simulation featuring two sets of two linked, synchronized devices
2simulation = Simulation()
3
4# Create devices
5device_A_Tx = simulation.new_device(carrier_frequency=3.7e9)
6device_A_Rx = simulation.new_device(carrier_frequency=3.7e9)
7device_B_Tx = simulation.new_device(carrier_frequency=3.9e9)
8device_B_Rx = simulation.new_device(carrier_frequency=3.9e9)

The exchanged waveforms are identical, however, devices are considered to be only synchronized to their linked partners.

 1# Link devices
 2link_A = SimplexLink(waveform=deepcopy(waveform))
 3link_B = SimplexLink(waveform=deepcopy(waveform))
 4device_A_Tx.transmitters.add(link_A)
 5device_A_Rx.receivers.add(link_A)
 6device_B_Tx.transmitters.add(link_B)
 7device_B_Rx.receivers.add(link_B)
 8
 9# Specify trigger models
10trigger_model_A = TriggerModel()
11device_A_Tx.trigger_model = trigger_model_A
12device_A_Rx.trigger_model = trigger_model_A
13
14trigger_model_B = TriggerModel()
15device_B_Tx.trigger_model = trigger_model_B
16device_B_Rx.trigger_model = trigger_model_B

Of course, the abstract TriggerModel in the above snippet must be replaced by the desired implementation from the list above. By generating a single drop of the simulation and plotting the bit error rates of the two devices, we may visualize the impact of partially overlapping commuication frames in time-domain due to the interference in between the two links.

 1# Configure BER evaluators for each link
 2ber_A = BitErrorEvaluator(link_A, link_A)
 3ber_B = BitErrorEvaluator(link_B, link_B)
 4
 5# Generate drop
 6_ = simulation.scenario.drop()
 7
 8# Visualize BERs that should spike at the frame overlaps
 9ber_A.evaluate().visualize(title='Link A Bit Error Rate')
10ber_B.evaluate().visualize(title='Link B Bit Error Rate')