Campagnes
Un scénario unique répond à une question sur une situation. Une mission est une suite de situations, et une étude de conception en est une famille. Le type de scénario campaign compose les types existants en une seule exécution sans en réimplémenter aucun : chaque membre est une table de scénario ordinaire portant son propre kind, répartie via api::run_toml exactement comme kshana <file>.toml l'exécuterait, et la campagne se contente de relire des nombres dans les documents de résultats.
Une campagne est MODELLED. Ses identités de composition sont testées (ci-dessous), mais enchaîner des phases est un choix de modélisation, et chaque phase ne vaut que ce que vaut le type qui l'a exécutée.
Exécutez-en une comme n'importe quel autre scénario :
kshana scenarios/campaign-jam-spoof-holdover-integrity.toml
# writes .result.json, .chart.svg, .report.html and .report.json next to the file
Une campagne peut contenir n'importe quelle combinaison de quatre sections ; une campagne sans aucune s'exécute et son résumé indique qu'elle n'a rien composé.
[[phases]] : une mission enchaînée sur une seule chronologie#
Chaque phase exécute un ou plusieurs scénarios sur une fenêtre d'une chronologie de mission partagée, par exemple une horloge en holdover et un système de navigation inertielle (INS) en roue libre au même moment. Les sorties de chaque exécution sont lues dans des canaux nommés, placées à l'instant de début de la phase et rééchantillonnées sur une grille commune ([timeline] step_s) par blocage d'ordre zéro : un instant de la grille prend le dernier échantillon de l'exécution de la phase propriétaire situé à cet instant ou avant, et vaut null lorsqu'aucune exécution de cette phase ne fournit le canal.
| Canal | Unité | Ce que c'est | Source prédéfinie |
|---|---|---|---|
time_error_ns |
ns | erreur de temps de l'horloge | clock: <side>.series[].error_ns; spoof: <side>.series[].offset_ns |
guard_ns |
ns | garde d'erreur de temps | le threshold_ns propre à l'exécution |
cn0_dbhz |
dB-Hz | rapport moyen effectif porteuse sur densité de bruit (C/N0) sur les satellites visibles | jamming : moyenne de epochs[].sats[].cn0_effective_dbhz |
cn0_floor_dbhz |
dB-Hz | plancher de perte de poursuite | jamming : le tracking_threshold_dbhz du scénario, lorsqu'il en indique un |
tracking |
nombre | satellites toujours poursuivis | jamming: epochs[].tracking |
protection_level_m |
m | niveau de protection vertical | integrity: epochs[].vpl_m |
alert_limit_m |
m | limite d'alerte verticale | integrity: al_v_m |
position_error_m |
m | erreur de position | gnss-ins: <side>.series[].error_m |
position_threshold_m |
m | seuil d'erreur de position | gnss-ins: threshold_m |
alarm |
1 | 1 tant qu'un moniteur de la phase alarme | voir ci-dessous |
<side> vaut classical sauf si l'exécution définit side = "quantum". Toute autre grandeur est lue avec une entrée [[phases.runs.series]] explicite : un chemin temporel avec un [] nommant les lignes (epochs[].t), un chemin de valeur partageant ces lignes ou un scalaire diffusé à chaque ligne (le préfixe input: lit le scénario de l'exécution au lieu de son résultat), une réduction facultative (mean, min, max, count) pour plusieurs valeurs sous une même ligne, une échelle, et une unité pour un canal que la campagne ne connaît pas.
Les alarmes proviennent de trois sources, combinées par un OU logique au sein d'une phase :
- des indicateurs prédéfinis lus dans l'exécution :
jammingalarme tant que moins de quatre satellites sont poursuivis (sa propre définition de la disponibilité) ;integrityalarme aux époques qu'il marque comme indisponibles ; - des règles prédéfinies sur les canaux de la phase, évaluées après
carry:clockalarme tant que l'erreur de temps absolue dépasseguard_ns;gnss-instant que l'erreur de position dépasseposition_threshold_m; les règles explicites vont dans[[phases.runs.alarms]]; - des événements d'alarme :
spoofen déclenche un audetect_time_sde son moniteur assisté par l'horloge ;spoof-detecten déclenche un au début de la phase lorsque sa décision fusionnée alerte.
L'état est transmis entre les phases de trois manières explicites :
carry = ["time_error_ns"]ajoute la valeur du canal à la fin de la phase précédente aux valeurs de cette phase pour ce canal. La phase d'horloge qu'un leurreur a tirée est le point de départ du holdover. Ajouter le décalage est exact pour la phase d'horloge, qui intègre la fréquence ; pour une erreur de position, cela suppose que les deux erreurs sont colinéaires, le cas pessimiste.[[phases.handoff]]écrit un nombre issu de la phase précédente (channel:<name>pour la valeur finale d'un canal, ou tout chemin de résultat d'une exécution précédente) dans une clé pointée du scénario de cette phase avant son exécution, avec une échelle et un décalage facultatifs.end_at = "<result path>"termine la phase à un instant calculé par une exécution, plafonné àduration_s. La mission intégrée termine sa phase de leurrage àclassical.detect_time_s.
skip_s écarte les premières secondes de la chronologie propre d'une exécution (une montée en régime) avant l'instant zéro de la phase.
La mission intégrée#
scenarios/campaign-jam-spoof-holdover-integrity.toml exécute 18 scénarios membres sur six phases, sur une grille de 10 s :
| Phase | Exécutions | Ce que montre la chronologie |
|---|---|---|
| nominal, 600 s | clock, jamming (sans brouilleur), integrity |
erreur de temps 0 ns ; C/N0 43,0 dB-Hz contre un plancher de 25 dB-Hz ; niveau de protection vertical de 9,1 à 21,6 m contre une limite d'alerte de 50 m |
| brouillage, 600 s | identique, brouilleur à -30 dBW, 1 km | le C/N0 chute à 27,7 dB-Hz, les 8 satellites restent tous poursuivis |
leurrage, terminé à 370 s par end_at |
spoof (rampe de temps de 0,1 ns/s), spoof-detect, jamming |
l'erreur de temps monte en rampe jusqu'à 36 ns ; le détecteur radiofréquence alarme au début de la phase, le moniteur assisté par l'horloge à 370 s |
| holdover, 1800 s | clock (refusé, reporte 37,0 ns), gnss-ins (unité tactique en roue libre), jamming à 10 dBW |
tous les satellites perdus (C/N0 d'environ -12 dB-Hz) ; erreur de temps de 36,4 à 62,7 ns contre la garde de 50 ns ; erreur de position jusqu'à 24 km |
| integrity-alarm, 600 s | clock (reporte 59,6 ns), jamming et integrity avec un masque de 25 deg |
5 satellites poursuivis ; niveau de protection de 19 à 135 m, absent à 18 instants de grille sur 60 ; l'erreur de temps reportée, de 52,1 à 61,7 ns, reste au-dessus de la garde de 50 ns, si bien que l'alarme est active pendant toute la phase |
| recovery, 600 s | clock, jamming (sans brouilleur), integrity |
erreur de temps revenue à 0 ns ; alarme silencieuse |
Les exécutions d'integrity utilisent la trajectoire utilisateur propre à l'exemple (une trajectoire circulaire à 0,4 km d'altitude), et non le site fixe du récepteur de brouillage, et le masque de 25 deg remplace le ciel partiel d'un récepteur en réacquisition. Ce sont des choix de scénario, indiqués dans le fichier.
Une mission pilotée par le spectre en bande L#
scenarios/campaign-spectrum-holdover-integrity.toml exécute 8 scénarios membres sur trois phases, sur une grille de 1 s, le C/N0 de GPS L1 C/A et de Galileo E1 étant lu dans le type spectrum (voir SPECTRUM.md) plutôt que dans la table par satellite du type jamming. Les brouilleurs sont ceux de scenarios/l-band-waterfall-jamming.toml.
| Phase | Exécutions | Ce que montre la chronologie |
|---|---|---|
début, terminé à 10 s par end_at |
clock, spectrum (chirp à partir de 10 s), integrity |
L1 C/A 43,48 et E1 44,73 dB-Hz ; la phase se termine à la première perte de L1 C/A de l'exécution spectre elle-même (timeline.bands[0].first_loss_t_s) ; niveau de protection de 21,6 m contre 50 m |
| holdover, 600 s | clock (refusé, reporte l'erreur de début, 0 ns ici), spectrum (chirp actif) |
L1 C/A 3,38 et E1 4,44 dB-Hz, tous deux sous le plancher de 25 dB-Hz ; erreur de temps de -0.07 à 5,06 ns contre la garde de 50 ns ; alarme active |
| galileo-fallback, 300 s | clock (resynchronisée), spectrum (tonalité CW sur la porteuse L1), integrity sur un Walker 24/3/1 de type Galileo |
L1 C/A maintenu à 17,98 dB-Hz, E1 revenu à 44,73 dB-Hz ; niveau de protection de 6,1 à 17,7 m ; alarme silencieuse |
Le retour de E1 sous la tonalité CW repose sur le traitement à spectre continu du type spectre : la tonalité se situe dans le zéro du spectre MBOC et ne couple rien. Une vraie tonalité se couplerait par les raies spectrales du code ; cela est indiqué dans le fichier et dans SPECTRUM.md.
[sweep] : une grille de paramètres sur n'importe quel type#
Une à trois clés de scénario pointées, chacune sur une plage linéaire ou logarithmique, sur les mêmes valeurs d'axe que celles qu'utilise le type sweep-nd. Chaque axe a un nom et une unité ; chaque métrique a un nom et un chemin de résultat, et son unité est lue dans le bloc d'unités du type balayé, sauf si la campagne en déclare une. Avec runs > 1, chaque nœud est un ensemble Monte Carlo à graine (réalisation k à la graine du nœud plus k), rapporté avec les statistiques ci-dessous. scenarios/campaign-sweep-jammer-power.toml balaie un brouilleur situé à 1 km du récepteur de -50 à +10 dBW : le rapport moyen brouilleur sur signal varie d'exactement 1 dB par dB (12,2 à 72,2 dB), et la disponibilité passe de 1 à 0 entre -30 et -25 dBW.
Une clé pointée peut indexer par position un tableau de tables : system.2.sisre_m est le sisre_m de la troisième table [[system]], et case.0.system.0.shell.0.altitude_km descend de trois niveaux.
[monte_carlo] : un ensemble à graine#
La réalisation k exécute le scénario avec sa clé de graine fixée à base_seed + k, la convention déjà utilisée par l'ensemble d'horloge, de sorte que l'ensemble se reproduit exactement. Chaque métrique rapporte la moyenne, l'écart type de la population, les 5e, 50e et 95e percentiles au rang le plus proche, un intervalle de confiance à 95 % par bootstrap percentile à graine fixe sur la moyenne (2000 rééchantillonnages) et, par défaut, chaque échantillon dans l'ordre des graines. Les chemins de résultat peuvent indexer des tableaux : classical.series[-1].error_ns est le dernier échantillon.
[compose] : plusieurs scénarios sous des conditions partagées#
Des valeurs partagées nommées (un nombre ou un tableau de nombres, avec une unité) sont écrites dans chaque membre aux clés auxquelles il les lie, de sorte que les membres ne peuvent pas être en désaccord sur la condition partagée. Chaque membre s'exécute et, pour chaque métrique, le résumé combiné donne la plus petite, la plus grande et la moyenne des valeurs sur les membres, en nommant le meilleur et le pire. scenarios/campaign-shared-jammer-sea-road.toml place un brouilleur de 8 dBW entre un navire dans le golfe de Finlande (à environ 30 km) et une voiture sur une route côtière d'Helsinki (à environ 50 km) : le navire perd tous les satellites (rapport moyen brouilleur sur signal de 39,0 dB) tandis que la voiture en garde au moins quatre (34,6 dB).
[optimize] : la meilleure valeur d'une métrique#
Une à trois clés de scénario pointées, chacune bornée à [lo, hi] sur une échelle lin ou log, sont explorées pour trouver la meilleure valeur d'une métrique (goal = "minimize", "maximize" ou "target", qui minimise la distance à target).
Il existe deux méthodes :
method = "grid"exécute chaque nœud d'une grille destepspar clé, sur les valeurs d'axe du balayage.method = "nelder-mead"(par défaut) exécute un simplexe de Nelder–Mead déterministe en coordonnées normalisées à [0, 1] par clé. Les points d'essai sont projetés sur la boîte. La section acceptemax_evals, unstepinitial et les tolérances d'arrêtftoletxtol.
Une exécution dont la métrique est absente ou non finie obtient le pire score, et elle est conservée dans la trace. Avec runs > 1, la métrique est la moyenne sur les mêmes graines à chaque évaluation. Le résultat donne best_coords, best_metric, best_score, evals, stop_reason et chaque évaluation dans trace.
scenarios/campaign-optimize-link-budget.toml recherche la portée et le débit de données pour une marge de liaison de 3 dB. L'optimum est local à la boîte et au point de départ. Il est MODELLED, jamais une affirmation globale.
Le protocole et ses seuils fixés à l'avance figurent dans docs/design/evidence/cap32-optimize/. Le test est tests/campaign_optimize_reference.rs. Les résultats :
- une résolution de cible 1-D concorde avec la forme fermée à 6e-15 près ;
- la méthode de grille concorde bit à bit avec une boucle de force brute indépendante ;
- le simplexe fait au moins aussi bien que la grille de 41 × 41, en environ un dixième de ses exécutions.
Le seuil 1-D du tour 1 est enregistré NOT MET : la boîte fixée à l'avance excluait la solution.
Reproductibilité#
Chaque résultat de campagne porte scenario_hash, le SHA-256 (Secure Hash Algorithm 2, empreinte de 256 bits) de la forme JavaScript Object Notation (JSON) canonique du document de campagne (l'ordre des clés et la mise en forme ne la modifient pas), et un bloc reproducibility avec le nombre d'exécutions membres et run_digest, un SHA-256 calculé sur l'empreinte de chaque résultat membre dans l'ordre de répartition. Deux exécutions de même empreinte ont produit des résultats membres identiques octet pour octet. Chaque exécution de phase enregistre aussi son type, son propre scenario_hash lorsque le type en a un, et le SHA-256 de son document de résultats. Chaque nombre du document a une entrée d'unités.
Le cœur est séquentiel et ne lit aucun fichier, de sorte qu'une campagne s'exécute sans changement dans la version WebAssembly. Les campagnes ne peuvent pas contenir de campagnes.
Exports#
--export sur une campagne écrit chaque scénario membre doté d'une géométrie sous forme d'un jeu de fichiers distinct, l'étiquette du membre étant insérée avant le suffixe de format : chaque exécution de phase (<phase>, ou <phase>-<k> lorsque la phase compte plusieurs exécutions), le scénario de base du balayage (sweep), le scénario Monte Carlo (monte-carlo) et chaque membre composé (avec sa propre étiquette, et les valeurs partagées qu'il lie y sont écrites). Un membre identique à un précédent n'est écrit qu'une fois ; les transmissions et les valeurs de balayage ou de graine appliquées à l'exécution ne figurent pas dans les scénarios exportés.
kshana scenarios/campaign-shared-jammer-sea-road.toml --export kml
# after the usual result, chart and report files:
# wrote scenarios/campaign-shared-jammer-sea-road.ship-strait.kml
# wrote scenarios/campaign-shared-jammer-sea-road.car-coast-road.kml
Un format qu'aucun des membres ne peut décrire est refusé, avec cette raison. Le tableau par scénario figure dans INTEROP.md.
Campagnes LEO-PNT#
Quinze campagnes intégrées cadrent des questions de positionnement, de navigation et de synchronisation temporelle (PNT) en orbite terrestre basse (LEO) ; LEO-PNT.md décrit ce que montre chacune. Ce qu'exécute chacune, tel que la ligne de commande le résume :
| Scénario | Mode | Question |
|---|---|---|
leo-focus-data-services.toml |
composition, 4 membres | données de service du message de navigation selon la longueur de trame |
leo-focus-fused-pnt-sisre.toml |
balayage de leo-pvt, 7 nœuds |
positionnement fusionné MEO et LEO selon l'erreur de distance du signal dans l'espace (SISRE) LEO |
leo-focus-indoor-uhf.toml |
composition, 2 membres | LEO-PNT en intérieur selon la bande et la classe de bâtiment |
leo-focus-iot-eirp.toml |
balayage de leo-pass, 9 nœuds |
énergie par position de l'Internet des objets (IoT) selon la puissance d'émission UHF LEO |
leo-focus-ntn-bandwidth.toml |
balayage de ntn-positioning, 9 nœuds |
positionnement par réseau non terrestre (NTN) selon la largeur de bande du signal de référence |
leo-focus-ppp-altitude.toml |
balayage de leo-ppp, 3 nœuds |
convergence du positionnement précis par point (PPP) selon l'altitude d'une couche LEO de 192 satellites |
leo-resilience-gnss-jammed-leo-carries.toml |
chaîne, 3 phases sur 2100 s | Global Navigation Satellite System (GNSS) brouillé, la couche LEO porte l'utilisateur, intégrité maintenue |
leo-resilience-multiband-diversity.toml |
balayage de spectrum, 13 nœuds |
diversité de bandes LEO face à un brouilleur à barrage en bande L |
leo-resilience-spoof-monitors.toml |
composition, 4 membres | les moniteurs de leurrage face à quatre leurreurs |
leo-vertical-5g-network-timing.toml |
chaîne, 1 phase sur 86 400 s | synchronisation temporelle de stations de base 5G : holdover et temps LEO |
leo-vertical-asset-tracking-iot.toml |
chaîne, 3 phases sur 1440 s | suivi de conteneurs avec UHF LEO : énergie par position le long d'un trajet |
leo-vertical-autonomous-vehicle.toml |
chaîne, 2 phases sur 1500 s | un véhicule autonome dans un canyon urbain avec une couche LEO |
leo-vertical-autonomous-vehicle-skyline.toml |
chaîne, 2 phases sur 1800 s | le même canyon urbain avec un angle de coupure plat de 35 deg et avec un horizon city-street |
leo-vertical-critical-infrastructure-timing.toml |
chaîne, 2 phases sur 87 000 s | synchronisation temporelle d'infrastructures critiques : holdover avec temps LEO |
leo-vertical-polar-arctic.toml |
chaîne, 3 phases sur 10 800 s | utilisateurs polaires et arctiques avec une couche LEO polaire |
leo-vertical-rail-maritime.toml |
chaîne, 3 phases sur 2520 s | utilisateurs ferroviaires et maritimes avec une couche LEO |
MEO désigne l'orbite terrestre moyenne, UHF les ultra hautes fréquences et 5G la cinquième génération de réseaux mobiles.
Ce qui est vérifié#
tests/campaign_composition_reference.rs fixe les identités de composition :
- Une campagne à une phase reproduit bit à bit l'exécution autonome. Pour
clock,integrityetjamming, le document de résultats du membre est identique octet pour octet àrun_tomlsur le fichier de scénario, son empreinte est celle que rapporte la campagne et, avec la grille au pas propre de l'exécution, chaque valeur alignée est égale à la valeur de la série autonome (le C/N0 de brouillage est égal à la moyenne calculée indépendamment à partir du document autonome). - Un balayage à un nœud et une composition à un membre relisent exactement le nombre de l'exécution autonome.
- Un ensemble à graine fixe est stable octet pour octet, et la réalisation
kest exactement l'exécution autonome àseed + k; le hachage de la campagne ignore l'ordre des clés. - Un cas analytique.
scenarios/campaign-monte-carlo-clock-holdover.tomlexécute 200 graines d'une horloge atomique à puce avec du seul bruit blanc de fréquence (q_wf = 9e-20 s^2/s, Microchip SA.45s sigma_y(1 s) = 3e-10), synchronisée à 590 s et en roue libre jusqu'à 3600 s. L'erreur de temps finale est gaussienne, de moyenne 0 et d'écart type sqrt(q_wf * 3010 s) = 16,459 ns (la marche aléatoire de la phase sous bruit blanc de fréquence, National Institute of Standards and Technology (NIST) Technical Note 1337). L'intervalle rapporté, [-2.52, 1,59] ns, contient la vraie moyenne 0 ; l'écart type de l'échantillon, 14,93 ns, donne une statistique du khi-deux de 164,5 sur 199 degrés de liberté, à l'intérieur de l'intervalle bilatéral à 99 % [151,37, 254,14]. Avec 3000 graines, le même scénario donne 16,31 ns. - La chaîne pilotée par le spectre relit les nombres autonomes : la phase de début dure exactement le temps de première perte de l'exécution spectre, et chaque valeur L1 C/A et E1 de la chronologie est égale, à 1e-9 dB près, à la ligne de l'exemple autonome de cascade pour le même état de brouilleur (nominal, chirp seul, tonalité CW seule).
- La chaîne transmet l'état comme documenté : la phase de leurrage dure exactement le temps de détection de l'exécution de leurrage, le holdover reporte exactement le décalage de l'exécution de leurrage à la détection, la récupération ne reporte rien, et l'alarme est active partout où le niveau de protection est absent ou dépasse la limite d'alerte.
Ces contrôles vérifient que la composition ne change rien de ce qu'elle ne devrait pas changer. Ils ne valident pas une mission enchaînée par rapport à une mission mesurée, ce qui explique que les trois lignes de campagne de VERIFICATION-MATRIX.md soient MODELLED.