Passa al contenuto principale

Transportation GFMs

I Gap Filling Module Trasporto calcolano le emissioni di gas serra dal trasporto dei prodotti alimentari dall'origine alla destinazione. Questi due moduli lavorano insieme: transportation_mode_distance_gfm calcola le distanze e le opzioni di percorso, mentre transportation_decision_gfm seleziona la modalità di trasporto ottimale e genera i flussi di emissione.

Riferimento Rapido​

ProprietàTransportModeDistanceGFMTransportDecisionGFM
Eseguito suFoodProductFlowNode, FlowNodeNodi con attributo transport
DipendenzeOriginGFM, MatchProductNameGFM, UnitWeightConversionGFM, ConservationGFMTransportModeDistanceGFM
Input ChiaveLocalità di origine, località di destinazioneDistanze di trasporto, deperibilità del prodotto
OutputDistanze e valori CO2 per modalità di trasportoModalità di trasporto ottimale, nodi di flusso del trasporto
Interfaccia di programmazione esternaEcoTransitNessuna

Quando Vengono Eseguiti​

TransportModeDistanceGFM si attiva quando:

  1. Un FoodProductFlowNode ha una località di origine valida
  2. Il nodo genitore ha una località di destinazione valida
  3. Il prodotto non e marcato come suddivisione
  4. Nessuna modalità di trasporto è già stata specificata

TransportDecisionGFM si attiva quando:

  1. Le distanze di trasporto sono state calcolate da TransportModeDistanceGFM
  2. Esiste almeno una distanza di trasporto valida (diversa da zero)
  3. Il nodo ha un nodo figlio per il prodotto pre-trasportato

Output Chiave​

I moduli aggiungono molteplici componenti al grafo di calcolo:

  • Pre-trasporto: Trasporto su strada dall'origine al porto/aeroporto di partenza
  • Trasporto principale: Trasporto primario tramite modalità selezionata (strada, mare, aria, ferrovia)
  • Post-trasporto: Trasporto su strada dal porto/aeroporto di arrivo alla destinazione
  • Raffreddamento/Congelamento: Emissioni aggiuntive per trasporto a temperatura controllata
  • Infrastruttura: Emissioni dell'infrastruttura di trasporto per tonnellata-chilometro

Metodologia Scientifica​

Il modello di trasporto calcola le emissioni usando un approccio di trasporto a tre fasi con EcoTransit per la pianificazione del percorso e i fattori di emissione.

Opzioni di Modalità di Trasporto​

ModalitàCodice EcoTransitVelocità di ViaggioTempo di CaricoPrezzo per kmPrezzo di Carico
Stradaroad45 km/h3 ore$0,0497/km$84,62
Maresea26 km/h48 ore$0,0062/km$119,66
Ariaair500 km/h6 ore$0,0062/km$2.085,00
Ferroviarail40 km/h24 ore$0,0186/km$99,58

Metodologia di Calcolo della Distanza​

Il modello di trasporto usa un approccio gerarchico per calcolare le distanze:

Integrazione EcoTransit​

Per ogni modalità di trasporto, il sistema interroga EcoTransit usando la metodologia CCWG-Tradelane (Clean Cargo Working Group):

ECOTRANSIT_CALCULATION_METHOD = "ccwg-tradelane"
ECOTRANSIT_CALCULATION_YEAR = 2024

Parametri della Richiesta:

  • Coordinate di partenza (centroide dell'origine o posizione precisa)
  • Coordinate di destinazione (centroide della destinazione o posizione precisa)
  • Modalità di trasporto (strada, mare, aria, ferrovia)
  • Peso del carico: 1 tonnellata (emissioni normalizzate per tonnellata)

Risoluzione della Località con GADM​

Le località sono risolte usando GADM (Database delle Aree Amministrative Globali):

  1. GADM Livello 1-2 (Paese/Regione): Usa coordinate del centroide per le interrogazioni EcoTransit
  2. GADM Livello 3+ (Dettagliato): Ritorna al centroide della regione genitore di livello 2
  3. Strategia di Cache: I risultati regione-a-regione sono memorizzati in cache; paese-a-paese serve come fallback
# Formato della chiave di cache
request_key = f"{start_location_gadm_term.xid}_{end_location_gadm_term.xid}_{mode.value}"

Stima della Distanza di Pre/Post Trasporto​

Per il trasporto marittimo e aereo, le distanze di pre e post trasporto (trasporto su strada da/verso i porti) sono stimate usando:

# Per trasporto nella stessa regione (origine e destinazione nella stessa regione GADM)
estimated_distance = ribbon_factor * direct_distance

# Per regioni diverse
estimated_distance = max(
sqrt(region_area_km2) * scaling_factor, # Stima basata sull'area
distance_from_centroid_to_port # Stima basata sul centroide
) * ribbon_factor

Fattori di Scala per Modalità di Trasporto:

ModalitàFattore di Scala Pre/Post TrasportoDescrizione
Mare0,29042sqrt(area)/2,43
Aria0,11782sqrt(area)/5,99
Strada (stessa regione)0,56905Per trasporto locale

Fattore di Deviazione (Indice di Deviazione):

Il fattore di deviazione di 1,417 converte le distanze in linea retta in distanze stradali realistiche, basato sulla ricerca di Ballou et al. (2002).

Calcolo delle Emissioni di CO2​

Le emissioni di CO2 sono estratte direttamente dalle risposte EcoTransit in tonnellate di CO2eq per tonnellata di carico:

# Per ogni segmento di trasporto
co2_value = section["emissions"]["co2Equivalents"][mode]["_value_1"]
distance = section["emissions"]["distances"][mode]["tankToWheel"]

# La CO2 di pre/post trasporto e scalata in base alla distanza stimata
scaled_co2 = ecotransit_co2 * (estimated_distance / ecotransit_distance)

Selezione della Modalità di Trasporto​

Il TransportDecisionGFM seleziona la modalità ottimale tramite:

  1. Filtro per Deperibilità: Esclude le modalità dove il tempo di viaggio supera il tempo di conservazione del prodotto
  2. Calcola il Costo Totale: Somma i costi di distanza e i costi di carico per ogni modalità
  3. Seleziona il Più Economico: Sceglie la modalità con il costo totale più basso
# Calcolo del tempo di viaggio totale
travel_time = distance / travel_speed + loading_time

# Calcolo del costo totale
total_cost = (distance_price * distance) + loading_price

Vincoli di Deperibilità​

I prodotti con vincoli di tempo di conservazione (refrigerati, congelati) sono filtrati alle modalità che possono consegnare entro la finestra di conservazione:

# Verifica se la modalita e qualificata
storage_time_hours = product.storage_time * time_conversion_factor
if travel_time < storage_time_hours:
qualifying_modes.append(mode)

Se nessuna modalità si qualifica entro il vincolo di conservazione, viene selezionata la modalità più veloce come fallback.


Dettagli di Implementazione​

Distanze di Trasporto Predefinite​

Quando l'origine non può essere determinata (codice FAO produzione sconosciuto), vengono usate distanze predefinite basate sul percorso Argentina-Germania via Portogallo:

TrasportoDistanza (km)CO2 (t/t)
Pre-trasporto (centroide Argentina a porto)666,020,0952
Trasporto principale (porto Argentina a porto Portogallo)11.428,680,1202
Post-trasporto (porto Portogallo a centroide Germania)2.569,740,1908
Totale14.664,440,4062

Gestione dei Prodotti Non Alimentari​

I prodotti non alimentari (identificati dai termini FoodEx2 EAT-0002 e EAT-0000) sono esclusi dai calcoli di trasporto.

Trasporto nella Stessa Località​

Quando origine e destinazione sono nella stessa regione GADM:

  1. Applica un offset di 50km alle coordinate di origine e destinazione
  2. Forza la modalità di trasporto su strada
  3. Calcola la distanza usando il fattore di deviazione
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

Modifiche al Grafo​

Il TransportDecisionGFM crea la seguente struttura del grafo:

FoodProductFlowNode (ingrediente)
|
+-- FoodProcessingActivityNode (attivita di trasporto)
|
+-- FoodProductFlowNode (prodotto pre-trasportato)
| |
| +-- [nodi figli originali]
|
+-- PracticeFlowNode (Pre-trasporto)
| +-- TransportActivityNode
| +-- FlowNode (Consumo carburante)
| +-- PracticeFlowNode (Infrastruttura)
|
+-- PracticeFlowNode (Trasporto principale)
| +-- TransportActivityNode
| +-- FlowNode (Consumo carburante)
| +-- PracticeFlowNode (Infrastruttura)
|
+-- PracticeFlowNode (Post-trasporto)
| +-- TransportActivityNode
| +-- FlowNode (Consumo carburante)
| +-- PracticeFlowNode (Infrastruttura)
|
+-- PracticeFlowNode (Raffreddamento/Congelamento) [opzionale]

Raffreddamento e Congelamento Durante il Trasporto​

Per i prodotti etichettati come refrigerati (J0131) o congelati (J0136), vengono aggiunte emissioni di raffreddamento aggiuntive:

# Calcola il tempo di viaggio per la modalita selezionata
travel_time_hours = total_distance / travel_speed + loading_time

# Crea il nodo di flusso raffreddamento/congelamento con quantita in kg*ora
cooling_flow_node.amount = travel_time_hours # in unita kg*ora

Riferimento Codice Completo​

Struttura della Richiesta EcoTransit​

complex_transport_request = {
"cargo": Cargo(weight=1, unit="ton"),
"transportDate": None, # Date omesse per evitare variazioni temporali
"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),
}

Elaborazione della Risposta​

La risposta EcoTransit viene ridotta ai dati essenziali per la memorizzazione in 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: [...]},
}

Calcolo del Costo​

async def get_minimal_cost_transportation_mode(
transport_modes_distances: TransportModesDistancesProp,
qualified_travel_modes: list,
) -> ServiceTransportModeEnum:
mile_to_km_constant = 0.621371192

# Prezzi per miglio convertiti in 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

# Aggiungi costi di pre/post trasporto (sempre su strada)
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]
)

# Aggiungi costo del trasporto principale
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)

Calcolo del Tempo di Viaggio​

@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 = { # ore
ServiceTransportModeEnum.AIR: 6,
ServiceTransportModeEnum.GROUND: 3,
ServiceTransportModeEnum.SEA: 48,
ServiceTransportModeEnum.TRAIN: 24,
}

return distance / travel_speed[mode] + travel_loading_time[mode]

Fonti dei Dati​

Interfaccia di programmazione EcoTransit​

EcoTransit World fornisce calcoli delle emissioni del trasporto merci:

  • Metodologia: GLEC Framework (Global Logistics Emissions Council)
  • Variante di calcolo: CCWG-Tradelane (Clean Cargo Working Group)
  • Copertura: Rotte merci globali per strada, ferrovia, mare e aria
  • Anno dei dati: 2024 (configurabile)

La metodologia CCWG aggiunge un fattore di correzione del 15% alle distanze marittime, poiché la distanza del percorso più breve tipicamente sottostima le distanze effettivamente percorse.

Database Geografico GADM​

GADM fornisce confini geografici e centroidi:

  • Centroidi dei paesi per il livello 1
  • Centroidi regionali per il livello 2
  • Fallback dal livello 3+ al genitore di livello 2

Codici FAO per Casi Speciali​

Codice FAODescrizioneComportamento Trasporto
100000Produzione localeNessuna emissione di trasporto
200000Produzione predefinitaVengono usate distanze predefinite
300000Produzione pesce sconosciutoVengono usate distanze predefinite
400000Abbinamento produzione fallitoVengono usate distanze predefinite

Esempio di Calcolo​

Scenario: 1 kg di arance dalla Spagna (Valencia) alla Svizzera (Zurigo)

Passo 1: Risolvere le Località​

  • Origine: Spagna, regione Valencia (GADM: ES.17_1)
    • Centroide: -0,4, 39,5
  • Destinazione: Svizzera, Zurigo (GADM: CH.26_1)
    • Centroide: 8,5, 47,4

Passo 2: Interrogare EcoTransit​

Interrogazioni effettuate per modalità strada, mare e aria:

Risposta Strada:

{
"mainhaul": {
"road": [
{"distance": 1284.3, "co2eq_value": 0.1156}
]
}
}

Risposta Mare:

{
"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}]}
}

Passo 3: Calcolare le Opzioni di Trasporto​

ModalitàPre-trasportoTrasporto principalePost-trasportoDistanza TotaleCO2 Totale
Strada0 km1.284,3 km0 km1.284,3 km0,1156 t
Mare312,4 km2.156,7 km428,6 km2.897,7 km0,1012 t

Passo 4: Calcolare i Costi​

Strada:

Costo = (1284,3 * 0,0497) + 84,62 = $148,45

Mare:

Pre-trasporto: (312,4 * 0,0497) + 84,62 = $100,14
Trasporto principale: (2156,7 * 0,0062) + 119,66 = $133,03
Post-trasporto: (428,6 * 0,0497) + 84,62 = $105,92
Totale: $339,09

Passo 5: Selezionare la Modalità​

La strada viene selezionata come l'opzione più economica e praticabile ($148,45 vs $339,09).

Passo 6: Creare i Nodi del Grafo​

  1. Nodo attività di trasporto creato
  2. Nodo di flusso trasporto principale: 1.284,3 km trasporto su strada
  3. Nodo consumo carburante: 0,1156 t CO2eq
  4. Nodo infrastruttura: 1,0 tonnellata-km

Output Finale​

Il modulo aggiunge emissioni di 0,1156 kg CO2eq per kg di arance per il trasporto.


Strategia di Cache​

Livelli di Cache​

  1. Cache regione-a-regione: Risposte EcoTransit complete memorizzate per coppie di termini GADM
  2. Fallback paese-a-paese: Usato quando si verifica un miss nella cache regionale
  3. Cache risposta ridotta: Dati minimi per ricerche rapide (caricati all'avvio)
# Cache risposta completa (non caricata all'avvio)
await cache.set(request_key, response_data, load_on_boot=False)

# Cache risposta ridotta (caricata all'avvio)
await cache.set(request_key + "_stripped", stripped_data, load_on_boot=True)

Calcolo in Background​

Quando si verifica un miss nella cache:

  1. Avvia un task in background per il calcolo regione-a-regione
  2. Verifica se c'e un hit nella cache paese-a-paese
  3. Usa il fallback del paese se disponibile, altrimenti attendi il calcolo regionale
# Avvia calcolo in background
region_calc_task = asyncio.create_task(
get_transport_mode_responses_cached(origin, destination, mode, cache_only=False)
)

# Verifica fallback del paese
country_result = await get_transport_mode_responses_cached(
origin_country, destination_country, mode, cache_only=True
)

Limitazioni Note​

Copertura Geografica​

  • Dipende dalla copertura del database delle rotte EcoTransit
  • Alcune località remote potrebbero non avere rotte valide
  • Le rotte marittime richiedono connessioni portuali valide

Copertura delle Modalità​

  • Ferrovia: Attualmente funzionale ma meno prioritaria nel modello di costo
  • Vie d'acqua interne: Disponibile in EcoTransit ma non ancora implementato
  • Traghetto: Gestito come trasporto su strada (nessuna distinzione)

Ipotesi del Modello​

  • Data di trasporto non specificata per evitare variazioni temporali nei fattori di emissione
  • Fattore di carico assunto al 60% (predefinito EcoTransit)
  • Tutto il pre/post trasporto assunto come trasporto su strada
  • Stesso mix infrastrutturale usato globalmente

Vincoli di Deperibilità​

  • Si applica solo quando il tag del tempo di conservazione e presente sul prodotto
  • La modalità più veloce selezionata come fallback quando nessuna modalità soddisfa i vincoli
  • Può risultare in trasporto aereo per articoli altamente deperibili

Freschezza dei Dati​

  • Fattori di emissione EcoTransit aggiornati annualmente
  • I confini GADM potrebbero non riflettere recenti cambiamenti amministrativi
  • I prezzi di trasporto nel modello di costo potrebbero non riflettere le tariffe di mercato attuali

Riferimenti​

  1. EcoTransit World. Environmental methodology and data update. https://www.ecotransit.org/

  2. 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/

  3. Clean Cargo Working Group. Container shipping methodology for calculating emissions. https://www.smartfreightcentre.org/en/our-programs/clean-cargo-1/

  4. 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.

  5. GADM Database. Global Administrative Areas. https://gadm.org/

  6. FAO. Food and Agriculture Organization trade statistics. https://www.fao.org/faostat/