GFMs Transport
Les Gap Filling Modules Transport calculent les émissions de gaz à effet de serre liées au transport des produits alimentaires de l'origine à la destination. Ces deux modules fonctionnent ensemble : transportation_mode_distance_gfm calcule les distances et les options d'itinéraire, tandis que transportation_decision_gfm sélectionne le mode de transport optimal et génère les flux d'émissions.
Référence rapide
| Propriété | TransportModeDistanceGFM | TransportDecisionGFM |
|---|---|---|
| S'exécute sur | FoodProductFlowNode, FlowNode | Noeuds avec attribut transport |
| Dépendances | OriginGFM, MatchProductNameGFM, UnitWeightConversionGFM, ConservationGFM | TransportModeDistanceGFM |
| Entrée clé | Localisation d'origine, localisation de destination | Distances de transport, périssabilité du produit |
| Sortie | Distances et valeurs CO2 par mode de transport | Mode de transport optimal, noeuds de flux de transport |
| Interface de programmation externe | EcoTransit | Aucune |
Conditions d'exécution
TransportModeDistanceGFM se déclenche lorsque :
- Un
FoodProductFlowNodea une localisation d'origine valide - Le noeud parent a une localisation de destination valide
- Le produit n'est pas marqué comme subdivision
- Aucun mode de transport n'a déjà été spécifié
TransportDecisionGFM se déclenche lorsque :
- Les distances de transport ont été calculées par TransportModeDistanceGFM
- Au moins une distance de transport valide existe (non nulle)
- Le noeud a un noeud enfant pour le produit pré-transporté
Sortie clé
Les modules ajoutent plusieurs composantes au graphe de calcul :
- Pré-acheminement : Transport routier de l'origine au port/aéroport de départ
- Transport principal : Transport primaire via le mode sélectionné (route, mer, air, rail)
- Post-acheminement : Transport routier du port/aéroport d'arrivée à la destination
- Refroidissement/Congélation : Émissions supplémentaires pour le transport à température contrôlée
- Infrastructure : Émissions d'infrastructure de transport par tonne-kilomètre
Méthodologie scientifique
Le modèle de transport calcule les émissions en utilisant une approche à trois étapes avec EcoTransit pour la planification d'itinéraire et les facteurs d'émission.
Options de modes de transport
| Mode | Code EcoTransit | Vitesse de déplacement | Temps de chargement | Prix par km | Prix de chargement |
|---|---|---|---|---|---|
| Route | road | 45 km/h | 3 heures | 0,0497 $/km | 84,62 $ |
| Mer | sea | 26 km/h | 48 heures | 0,0062 $/km | 119,66 $ |
| Air | air | 500 km/h | 6 heures | 0,0062 $/km | 2 085,00 $ |
| Rail | rail | 40 km/h | 24 heures | 0,0186 $/km | 99,58 $ |
Méthodologie de calcul des distances
Le modèle de transport utilise une approche hiérarchique pour calculer les distances :
Intégration EcoTransit
Pour chaque mode de transport, le système interroge EcoTransit en utilisant la méthodologie CCWG-Tradelane (Clean Cargo Working Group) :
ECOTRANSIT_CALCULATION_METHOD = "ccwg-tradelane"
ECOTRANSIT_CALCULATION_YEAR = 2024
Paramètres de requête :
- Coordonnées de départ (centroïde d'origine ou localisation précise)
- Coordonnées de destination (centroïde de destination ou localisation précise)
- Mode de transport (route, mer, air, rail)
- Poids de la cargaison : 1 tonne (émissions normalisées par tonne)
Résolution de localisation avec GADM
Les localisations sont résolues en utilisant GADM (Global Administrative Areas Database) :
- GADM Niveau 1-2 (Pays/Région) : Utilise les coordonnées du centroïde pour les requêtes EcoTransit
- GADM Niveau 3+ (Détaillé) : Revient au centroïde de la région parente de niveau 2
- Stratégie de mise en cache : Les résultats région-à-région sont mis en cache ; pays-à-pays sert de repli
# Format de clé de cache
request_key = f"{start_location_gadm_term.xid}_{end_location_gadm_term.xid}_{mode.value}"
Estimation des distances de pré/post-acheminement
Pour le transport maritime et aérien, les distances de pré- et post-acheminement (transport routier vers/depuis les ports) sont estimées en utilisant :
# Pour le transport dans la même région (origine et destination dans la même région GADM)
estimated_distance = ribbon_factor * direct_distance
# Pour des régions différentes
estimated_distance = max(
sqrt(region_area_km2) * scaling_factor, # Estimation basée sur la surface
distance_from_centroid_to_port # Estimation basée sur le centroïde
) * ribbon_factor
Facteurs d'échelle par mode de transport :
| Mode | Facteur d'échelle pré/post-acheminement | Description |
|---|---|---|
| Mer | 0,29042 | sqrt(surface)/2,43 |
| Air | 0,11782 | sqrt(surface)/5,99 |
| Route (même région) | 0,56905 | Pour le transport local |
Facteur ruban (Indice de détour) :
Le facteur ruban de 1,417 convertit les distances en ligne droite en distances routières réalistes, basé sur la recherche de Ballou et al. (2002).
Calcul des émissions de CO2
Les émissions de CO2 sont extraites directement des réponses EcoTransit en tonnes CO2eq par tonne de cargaison :
# Pour chaque segment de transport
co2_value = section["emissions"]["co2Equivalents"][mode]["_value_1"]
distance = section["emissions"]["distances"][mode]["tankToWheel"]
# Le CO2 de pré/post-acheminement est mis à l'échelle en fonction de la distance estimée
scaled_co2 = ecotransit_co2 * (estimated_distance / ecotransit_distance)
Sélection du mode de transport
Le TransportDecisionGFM sélectionne le mode optimal en :
- Filtrage par périssabilité : Exclure les modes où le temps de trajet dépasse le temps de stockage du produit
- Calcul du coût total : Additionner les coûts de distance et les coûts de chargement pour chaque mode
- Sélection du moins cher : Choisir le mode avec le coût total le plus bas
# Calcul du temps de trajet total
travel_time = distance / travel_speed + loading_time
# Calcul du coût total
total_cost = (distance_price * distance) + loading_price
Contraintes de périssabilité
Les produits avec des contraintes de temps de stockage (réfrigérés, congelés) sont filtrés vers les modes capables de livrer dans la fenêtre de stockage :
# Vérifier si le mode est qualifié
storage_time_hours = product.storage_time * time_conversion_factor
if travel_time < storage_time_hours:
qualifying_modes.append(mode)
Si aucun mode ne répond à la contrainte de stockage, le mode le plus rapide est sélectionné comme repli.
Détails d'implémentation
Distances de transport par défaut
Lorsque l'origine ne peut être déterminée (code FAO de production inconnu), des distances par défaut basées sur l'Argentine vers l'Allemagne via le Portugal sont utilisées :
| Transport | Distance (km) | CO2 (t/t) |
|---|---|---|
| Pré-acheminement (centroïde Argentine vers port) | 666,02 | 0,0952 |
| Transport principal (port Argentine vers port Portugal) | 11 428,68 | 0,1202 |
| Post-acheminement (port Portugal vers centroïde Allemagne) | 2 569,74 | 0,1908 |
| Total | 14 664,44 | 0,4062 |
Gestion des produits non alimentaires
Les produits non alimentaires (identifiés par les termes FoodEx2 EAT-0002 et EAT-0000) sont exclus des calculs de transport.
Transport sur même localisation
Lorsque l'origine et la destination sont dans la même région GADM :
- Appliquer un décalage de 50 km aux coordonnées d'origine et de destination
- Forcer le mode de transport routier
- Calculer la distance en utilisant le facteur ruban
if start_location_gadm_term == end_location_gadm_term:
start_location = add_offset_to_endpoint(start_lon, start_lat, -50_000)
end_location = add_offset_to_endpoint(end_lon, end_lat, 50_000)
pre_defined_mode = ServiceTransportModeEnum.GROUND
Mutations du graphe
Le TransportDecisionGFM crée la structure de graphe suivante :
FoodProductFlowNode (ingrédient)
|
+-- FoodProcessingActivityNode (activité de transport)
|
+-- FoodProductFlowNode (produit pré-transporté)
| |
| +-- [noeuds enfants originaux]
|
+-- PracticeFlowNode (Pré-acheminement)
| +-- TransportActivityNode
| +-- FlowNode (Consommation de carburant)
| +-- PracticeFlowNode (Infrastructure)
|
+-- PracticeFlowNode (Transport principal)
| +-- TransportActivityNode
| +-- FlowNode (Consommation de carburant)
| +-- PracticeFlowNode (Infrastructure)
|
+-- PracticeFlowNode (Post-acheminement)
| +-- TransportActivityNode
| +-- FlowNode (Consommation de carburant)
| +-- PracticeFlowNode (Infrastructure)
|
+-- PracticeFlowNode (Refroidissement/Congélation) [optionnel]
Refroidissement et congélation pendant le transport
Pour les produits marqués comme réfrigérés (J0131) ou congelés (J0136), des émissions de refroidissement supplémentaires sont ajoutées :
# Calculer le temps de trajet pour le mode sélectionné
travel_time_hours = total_distance / travel_speed + loading_time
# Créer un noeud de flux de refroidissement/congélation avec une quantité en kg*heure
cooling_flow_node.amount = travel_time_hours # en unité kg*heure
Référence complète du code
Structure de requête EcoTransit
complex_transport_request = {
"cargo": Cargo(weight=1, unit="ton"),
"transportDate": None, # Dates omises pour éviter les variations temporelles
"accountingVariant": AccountingVariantParameters(
variant="ccwg-tradelane",
year=2024,
),
"section": {
"route": {
"departure": RequestStation(
wgs84=Wgs84Coordinates(departure_longitude, departure_latitude)
),
"destination": RequestStation(
wgs84=Wgs84Coordinates(destination_longitude, destination_latitude)
),
},
"carriage": {
"preCarriage": PreOrPostCarriageParameters(road=RoadParameters()),
"mainCarriage": CarriageParameters(mode_params),
"postCarriage": PreOrPostCarriageParameters(road=RoadParameters()),
},
},
"output": Output(split=OutputSplit(), createKml=False),
}
Traitement de la réponse
La réponse EcoTransit est réduite aux données essentielles pour la mise en cache :
def strip_ecotransit_response(mode: str, response: dict) -> dict:
return {
"mainhaul": {
mode: [
{
"co2eq_value": section["emissions"]["co2Equivalents"][mode]["_value_1"],
"distance": section["emissions"]["distances"][mode]["tankToWheel"],
}
for section in mainhaul_sections
]
},
"mainhaul_start_location": response["mainhaul"][0]["route"]["startLocation"]["wgs84"],
"mainhaul_end_location": response["mainhaul"][-1]["route"]["endLocation"]["wgs84"],
"preCarriage": {ServiceTransportModeEnum.GROUND: [...]},
"postCarriage": {ServiceTransportModeEnum.GROUND: [...]},
}
Calcul des coûts
async def get_minimal_cost_transportation_mode(
transport_modes_distances: TransportModesDistancesProp,
qualified_travel_modes: list,
) -> ServiceTransportModeEnum:
mile_to_km_constant = 0.621371192
# Prix par mile convertis en km
distance_prices = {
ServiceTransportModeEnum.AIR: 0.01 * mile_to_km_constant,
ServiceTransportModeEnum.GROUND: 0.08 * mile_to_km_constant,
ServiceTransportModeEnum.SEA: 0.01 * mile_to_km_constant,
ServiceTransportModeEnum.TRAIN: 0.03 * mile_to_km_constant,
}
loading_prices = {
ServiceTransportModeEnum.AIR: 2085.0,
ServiceTransportModeEnum.GROUND: 84.62,
ServiceTransportModeEnum.SEA: 119.6646,
ServiceTransportModeEnum.TRAIN: 99.578,
}
total_prices = {}
for mode in qualified_travel_modes:
total_price = 0
# Ajouter les coûts de pré/post-acheminement (toujours route)
for carriage in ("pre_carriage", "post_carriage"):
if getattr(distances[mode], carriage).value > 0:
total_price += (
distance_prices[ServiceTransportModeEnum.GROUND]
* getattr(distances[mode], carriage).value
+ loading_prices[ServiceTransportModeEnum.GROUND]
)
# Ajouter le coût du transport principal
total_price += (
distance_prices[mode] * distances[mode].main_carriage.value
+ loading_prices[mode]
)
total_prices[mode] = total_price
return min(total_prices, key=total_prices.get)
Calcul du temps de trajet
@staticmethod
def get_travel_time(distance: float, mode: str) -> float:
travel_speed = { # km/h
ServiceTransportModeEnum.AIR: 500,
ServiceTransportModeEnum.GROUND: 45,
ServiceTransportModeEnum.SEA: 26,
ServiceTransportModeEnum.TRAIN: 40,
}
travel_loading_time = { # heures
ServiceTransportModeEnum.AIR: 6,
ServiceTransportModeEnum.GROUND: 3,
ServiceTransportModeEnum.SEA: 48,
ServiceTransportModeEnum.TRAIN: 24,
}
return distance / travel_speed[mode] + travel_loading_time[mode]
Sources de données
Interface de programmation EcoTransit
EcoTransit World fournit des calculs d'émissions de transport de fret :
- Méthodologie : Cadre GLEC (Global Logistics Emissions Council)
- Variante de calcul : CCWG-Tradelane (Clean Cargo Working Group)
- Couverture : Routes de fret mondiales pour la route, le rail, la mer et l'air
- Année des données : 2024 (configurable)
La méthodologie CCWG ajoute un facteur de correction de 15 % aux distances maritimes, car la distance de la route la plus courte sous-estime généralement les distances réelles parcourues.
Base de données géographique GADM
GADM fournit les limites géographiques et les centroïdes :
- Centroïdes de pays pour le niveau 1
- Centroïdes régionaux pour le niveau 2
- Repli du niveau 3+ vers le parent de niveau 2
Codes FAO pour les cas spéciaux
| Code FAO | Description | Comportement de transport |
|---|---|---|
100000 | Production locale | Pas d'émissions de transport |
200000 | Production par défaut | Distances par défaut utilisées |
300000 | Production de poisson inconnue | Distances par défaut utilisées |
400000 | Échec de correspondance de production | Distances par défaut utilisées |
Exemple de calcul
Scénario : 1 kg d'oranges d'Espagne (Valence) vers la Suisse (Zurich)
Étape 1 : Résoudre les localisations
- Origine : Espagne, région de Valence (GADM : ES.17_1)
- Centroïde : -0,4, 39,5
- Destination : Suisse, Zurich (GADM : CH.26_1)
- Centroïde : 8,5, 47,4
Étape 2 : Interroger EcoTransit
Requêtes effectuées pour les modes route, mer et air :
Réponse route :
{
"mainhaul": {
"road": [
{"distance": 1284.3, "co2eq_value": 0.1156}
]
}
}
Réponse mer :
{
"mainhaul": {
"sea": [
{"distance": 2156.7, "co2eq_value": 0.0345}
]
},
"preCarriage": {"road": [{"distance": 312.4, "co2eq_value": 0.0281}]},
"postCarriage": {"road": [{"distance": 428.6, "co2eq_value": 0.0386}]}
}
Étape 3 : Calculer les options de transport
| Mode | Pré-acheminement | Transport principal | Post-acheminement | Distance totale | CO2 total |
|---|---|---|---|---|---|
| Route | 0 km | 1 284,3 km | 0 km | 1 284,3 km | 0,1156 t |
| Mer | 312,4 km | 2 156,7 km | 428,6 km | 2 897,7 km | 0,1012 t |
Étape 4 : Calculer les coûts
Route :
Coût = (1284,3 * 0,0497) + 84,62 = 148,45 $
Mer :
Pré-acheminement : (312,4 * 0,0497) + 84,62 = 100,14 $
Transport principal : (2156,7 * 0,0062) + 119,66 = 133,03 $
Post-acheminement : (428,6 * 0,0497) + 84,62 = 105,92 $
Total : 339,09 $
Étape 5 : Sélectionner le mode
La route est sélectionnée comme l'option viable la moins chère (148,45 $ vs 339,09 $).
Étape 6 : Créer les noeuds du graphe
- Noeud d'activité de transport créé
- Noeud de flux de transport principal : 1 284,3 km de transport routier
- Noeud de consommation de carburant : 0,1156 t CO2eq
- Noeud d'infrastructure : 1,0 tonne-km
Sortie finale
Le module ajoute des émissions de 0,1156 kg CO2eq par kg d'oranges pour le transport.
Stratégie de mise en cache
Niveaux de cache
- Cache région-à-région : Réponses EcoTransit complètes mises en cache par paires de termes GADM
- Repli pays-à-pays : Utilisé en cas d'absence dans le cache de région
- Cache de réponse réduite : Données minimales pour des recherches rapides (chargées au démarrage)
# Cache de réponse complète (non chargé au démarrage)
await cache.set(request_key, response_data, load_on_boot=False)
# Cache de réponse réduite (chargé au démarrage)
await cache.set(request_key + "_stripped", stripped_data, load_on_boot=True)
Calcul en arrière-plan
En cas d'absence dans le cache :
- Tâche en arrière-plan démarrée pour le calcul région-à-région
- Vérification de la présence dans le cache pays-à-pays
- Utilisation du repli pays si disponible, sinon attente du calcul de région
# Démarrer le calcul en arrière-plan
region_calc_task = asyncio.create_task(
get_transport_mode_responses_cached(origin, destination, mode, cache_only=False)
)
# Vérifier le repli pays
country_result = await get_transport_mode_responses_cached(
origin_country, destination_country, mode, cache_only=True
)
Limitations connues
Couverture géographique
- Dépend de la couverture de la base de données d'itinéraires EcoTransit
- Certaines localisations éloignées peuvent ne pas avoir de routes valides
- Les routes maritimes nécessitent des connexions portuaires valides
Couverture des modes
- Rail : Actuellement fonctionnel mais moins priorisé dans le modèle de coûts
- Voies navigables intérieures : Disponibles dans EcoTransit mais pas encore implémentées
- Ferry : Traité comme transport routier (pas de distinction)
Hypothèses du modèle
- Date de transport non spécifiée pour éviter les variations temporelles des facteurs d'émission
- Facteur de charge supposé à 60 % (par défaut EcoTransit)
- Tout pré/post-acheminement supposé être du transport routier
- Même mix d'infrastructure utilisé mondialement
Contraintes de périssabilité
- S'applique uniquement lorsqu'un tag de temps de stockage est présent sur le produit
- Le mode le plus rapide est sélectionné en repli lorsqu'aucun mode ne répond aux contraintes
- Peut résulter en transport aérien pour les articles hautement périssables
Fraîcheur des données
- Facteurs d'émission EcoTransit mis à jour annuellement
- Les limites GADM peuvent ne pas refléter les changements administratifs récents
- Les prix de transport dans le modèle de coûts peuvent ne pas refléter les taux actuels du marché
Références
-
EcoTransit World. Environmental methodology and data update. https://www.ecotransit.org/
-
Smart Freight Centre (2019). Global Logistics Emissions Council Framework for Logistics Emissions Accounting and Reporting. https://www.smartfreightcentre.org/en/our-programs/global-logistics-emissions-council/
-
Clean Cargo Working Group. Container shipping methodology for calculating emissions. https://www.smartfreightcentre.org/en/our-programs/clean-cargo-1/
-
Ballou, R.H., Rahardja, H., & Sakai, N. (2002). Selected country circuity factors for road travel distance estimation. Transportation Research Part A, 36(9), 843-848.
-
Base de données GADM. Global Administrative Areas. https://gadm.org/
-
FAO. Statistiques commerciales de l'Organisation des Nations Unies pour l'alimentation et l'agriculture. https://www.fao.org/faostat/