# Audit variabili — catena `init_swarm_scenario.m`

Analisi delle variabili inutili o ripetute nei file `.m` non-Simulink del
progetto `swarm_vehicle_agents_4`. Sono esclusi i modelli Simulink e le
funzioni richiamate da Simulink (`astar_path.m`, `smooth_path_spline.m`,
`swarm_planner_helper2.m`, `obstacle_brake_from_base.m`, ecc.): di queste
si è solo verificato *se leggono* campi di `scenario`, non i loro
problemi interni.

Questo è **solo un report**: nessun file è stato modificato.

---

## 1. Sintesi

Il sospetto è confermato: nel passaggio dal modello a 2 gradi di libertà
(controllore cinematico) al modello 8DOF (MPC + Simulink) sono rimasti in
giro molti parametri ormai inutilizzati e diverse costanti duplicate.
In sintesi:

- **6 assegnazioni duplicate/sovrascritte** dentro `init_swarm_scenario.m`;
- **~20 campi di `scenario` scritti e mai letti** da nessun file;
- **diversi campi letti dal demo/planner ma mai definiti** da `init_swarm_scenario.m` (i rami `isfield` risultano sempre falsi);
- **3 costanti fisiche** (raggio ruota, rapporto di trasmissione, massa) ripetute a mano in 3–4 file, con **`T_peak` motore addirittura incoerente** (60 vs 240 Nm);
- **2 file orfani** (`setup_vehicle_model.m`, `plot_followers_paths.m`).

---

## 2. `init_swarm_scenario.m` — assegnazioni duplicate o sovrascritte

| Campo | Righe | Valori | Problema |
|---|---|---|---|
| `scenario.vehicle8.velstart` | L11, L95 | 5 → 5 | Assegnato due volte con lo stesso valore. Basta L11 (serve subito per `scenario.start`). |
| `scenario.control.v_leader_mps` | L184, L193 | 4.0 → 4.0 | Duplicato identico. |
| `scenario.control.v_follower_mps` | L185, L194 | 4.5 → **5.0** | Sovrascritto: il primo valore (4.5) è inutile. |
| `scenario.control.v_recovery_mps` | L186, L195 | 6.0 → **7.0** | Sovrascritto: il primo valore (6.0) è inutile. |
| `scenario.sensor.vision_radius_m` | L126, L208 | 40 → **30** | Sovrascritto: il primo valore (40) è inutile. |
| `scenario.formation.max_offset_tracking_error_m` | L162/L170/L179, L190 | 5/5/5 → **6.0** | Impostato in ogni `case` dello `switch` e poi comunque sovrascritto a 6.0 a L190: i tre `=5` nei `case` sono inutili (e il campo non è mai letto, vedi §3). |

Minore: `scenario.map` è assegnato a L22 e di nuovo a L276; tra le due
righe `scenario.map` non viene mai letto (`build_cost_map` usa solo
`scenario.planning`), quindi l'assegnazione di L22 è ridondante.

---

## 3. Campi di `scenario` scritti e mai letti (codice morto)

Questi campi sono creati in `init_swarm_scenario.m` ma **nessun file** li
legge (né direttamente, né tramite alias tipo `v8 = scenario.vehicle8`).
Sono i residui del controllore cinematico 2DOF, sostituito dall'MPC.

| Campo | Riga | Note |
|---|---|---|
| `scenario.vehicle.length_m` | L30 | Geometria 2DOF; il modello 8DOF usa `vehicle8`. |
| `scenario.vehicle.steering_ratio` | L35 | Mai usato (8DOF usa `vehicle8.Rs`). |
| `scenario.vehicle.gear_cmd` | L36 | Mai usato. |
| `scenario.vehicle8.wr0_scale` | L109 | Mai usato: il demo ricalcola `wr0` inline (vedi §6). |
| `scenario.control.v_leader_mps` | L184/L193 | Velocità del controllore cinematico 2DOF. |
| `scenario.control.v_follower_mps` | L185/L194 | idem. |
| `scenario.control.v_recovery_mps` | L186/L195 | idem. |
| `scenario.control.v_docking_mps` | L188 | idem. |
| `scenario.control.k_speed` | L197 | Guadagno cinematico 2DOF. |
| `scenario.control.k_heading` | L198 | idem. |
| `scenario.control.max_accel_mps2` | L199 | Mai usato (l'MPC ha i suoi vincoli). |
| `scenario.formation.max_offset_tracking_error_m` | L162/170/179/190 | Mai letto da nessuno. |
| `scenario.formation.critical_offset_error_m` | L191 | Mai letto. |
| `scenario.sensor.vision_fov_deg` | L127 | Mai letto. |
| `scenario.sim.plot_every` | L214 | Mai letto. |
| `scenario.planning.waypoint_radius_m` | L226 | Mai letto. |
| `scenario.planning.replan_period_s` | L225 | Mai letto (il replan è gestito a `replan_steps` nel demo). |
| `scenario.communication.range_m` | L130 | Intera struct `communication` mai usata. |
| `scenario.communication.base_latency_s` | L131 | idem. |
| `scenario.communication.k_distance_s_per_m` | L132 | idem. |
| `scenario.communication.obstacle_penalty_s` | L133 | idem. |

Campi invece **usati** (per evitare rimozioni errate): `scenario.vehicle`
mantiene `width_m`, `wheelbase_m`, `track_update_width_m`,
`track_update_length_m`; tutti i campi di `scenario.vehicle8` sono usati
**tranne** `wr0_scale`; `scenario.safety.d_safe_base_m`/`d_safe_max_m`
sono usati da `obstacle_brake_from_base.m`.

---

## 4. Campi letti ma mai definiti da `init_swarm_scenario.m`

Qui il problema è l'opposto: il demo (e il planner) leggono campi che
`init_swarm_scenario.m` non crea mai. Nel demo la lettura è protetta da
`isfield`/`getfield_or`, quindi **il ramo "vero" è sempre falso e si usa
sempre il fallback hardcoded** — codice di fatto inutile e fuorviante.

| Campo letto | Dove | Conseguenza |
|---|---|---|
| `scenario.vehicle.r_wheel_m` | `demo` L121 | Mai definito → si usa sempre `0.317`. |
| `scenario.vehicle.gear_ratio` | `demo` L126 | Mai definito → si usa sempre `10`. |
| `scenario.vehicle.mass_kg` | `demo` L131 | Mai definito → si usa sempre `1300`. |
| `scenario.control.a_brake_mps2` | `demo` L232 | Mai definito → si usa sempre `-3.0`. |
| `scenario.control.v_max_follower_mps` | `demo` L139 | Mai definito → si usa sempre `v_max_mps*1.15`. |
| `scenario.control.Kp_h … Kd_v` (9 guadagni PID) | `demo` (`getfield_or`) | Mai definiti → si usano sempre i default di `getfield_or`. |
| `scenario.formation.line_spacing_m` | `swarm_planner_helper2.m` L515 | Mai definito da `init`. |
| `scenario.formation.triangle_back_m` | `swarm_planner_helper2.m` L520 | idem. |
| `scenario.formation.triangle_lat_m` | `swarm_planner_helper2.m` L525 | idem. |
| `scenario.formation.r_safe_obs_m` | `swarm_planner_helper2.m` L669 | idem. |

Gli ultimi quattro sono i più delicati: `swarm_planner_helper2.m` si
aspetta dei campi di `formation` che `init_swarm_scenario.m` non
produce. Vale la pena verificare che lì ci sia una protezione, altrimenti
è un errore latente.

Minore: `visualize_swarm_phase4.m` ha un fallback su `scenario.sim.dt`,
ma `init` definisce solo `dt8dof`/`dtcontrol`/`dtastar`: quel ramo non
scatta mai.

---

## 5. Costanti fisiche duplicate e sparse (eredità 2DOF → 8DOF)

Stessi parametri fisici riscritti a mano in più file invece di essere
letti da `scenario.vehicle8`. È la fonte di rischio maggiore: se cambi un
valore in un punto, gli altri restano disallineati.

| Grandezza | Valore | Dove è ripetuto |
|---|---|---|
| Raggio ruota | `0.317` | `init` `vehicle8.R0` (L85); `init` `wr0_scale` (L109, scritto due volte nella stessa riga); `motor_map.m` `r_wheel` (L20); `demo` fallback `r_wheel` (L123); `visualize_swarm_phase4.m` fallback `R0` (L410). |
| Rapporto di trasmissione | `10` | `motor_map.m` `gear_ratio` (L21); `design_speed_mpc.m` `tau` (L67); `tune_speed_mpc.m` `tau` (L77); `demo` fallback `gear_ratio` (L128). |
| Massa veicolo | `1300` | `init` `vehicle8.m` (L47); `motor_map.m` `m_veh` (L16); `demo` fallback `m_veh` (L131). |

**Incoerenza da correggere** — coppia di picco motore `T_peak`:

- `motor_map.m` L36: `T_peak = 60` Nm
- `design_speed_mpc.m` L76: `T_peak = 240` Nm (hardcoded, con commento "da motor_map.m")
- `tune_speed_mpc.m` L78: `k_alpha = 60/100` (coerente con 60 Nm)

Di conseguenza `k_alpha` (guadagno acceleratore→coppia) vale `2.4` in
`design_speed_mpc.m` e `0.6` in `tune_speed_mpc.m`: lo stesso MPC viene
tarato su un motore 4 volte più potente di quello simulato. Il commento
in testa a `design_speed_mpc.m` ("BISOGNA PARAMETRIZZARLA CON LA MAPPA
MOTORE") segnala già il problema.

---

## 6. File orfani e duplicazioni tra file

- **`setup_vehicle_model.m`** — non è chiamato da nessun file. Fa
  riferimento ai modelli `'swarm_phase3'` e `'vehicle_8dof'`, che non
  esistono più (i modelli attuali sono `swarm_phase_5`, `Agent`,
  `vehicle`). Il `demo_swarm_phase4.m` esegue lo stesso setup dei Model
  Argument inline, e contiene un blocco `model_args` **identico** a
  quello di questo file. È legacy: archiviabile o eliminabile.

- **`plot_followers_paths.m`** — non è chiamato da nessun file `.m`
  (richiama `swarm_planner_helper2`). Probabile strumento di analisi
  rimasto scollegato: da rivedere o archiviare.

- **`tune_speed_mpc.m`** — script di tuning manuale (non chiamato di
  proposito): legittimo, ma va riallineato sul `T_peak` corretto (§5).

- **`make_vref_filter.m`** — chiamato dal demo come `make_vref_filter()`,
  ma è uno **script**, non una funzione: legge `scenario` dal workspace
  del chiamante e vi lascia variabili sparse (`A_f`, `B_f`, `C_f`, `D_f`,
  `tau`, `num`, `den`, `v_ref_init`). Da valutare la conversione in
  funzione con uscite esplicite. Nota: la sua `tau = 2.0` (costante di
  tempo del filtro) è omonima del `tau` rapporto di trasmissione usato
  altrove — collisione di nomi solo concettuale, ma confondente.

Duplicazioni minori dentro `demo_swarm_phase4.m`:

- `N_VEH = size(scenario.start,1)` calcolato due volte (sezione 3 e
  sezione 10);
- `map_truth = scenario.map` assegnato due volte (sezione 3 e sezione 6);
- `define_swarm_buses` chiamato due volte, prima con `3` letterale poi
  con `N_VEH` (stesso risultato);
- `wr0 = vs / (0.97 * scenario.vehicle8.R0)` ricalcolato inline (sezione
  6): è esattamente la formula che `scenario.vehicle8.wr0_scale`
  incapsulava — usare l'uno o l'altro, non entrambi.

---

## 7. Raccomandazioni operative

1. **`init_swarm_scenario.m`**: rimuovere le 6 assegnazioni
   duplicate/sovrascritte di §2 tenendo solo il valore finale.
2. **Eliminare i campi morti** di §3 (in particolare l'intera struct
   `scenario.communication` e i parametri del controllore cinematico
   2DOF `v_leader/follower/recovery/docking_mps`, `k_speed`, `k_heading`,
   `max_accel_mps2`).
3. **Decidere su §4**: o `init_swarm_scenario.m` definisce davvero quei
   campi (`r_wheel_m`, `gear_ratio`, `mass_kg`, `a_brake_mps2`, i guadagni
   PID, i parametri `formation`), oppure si toglie dal demo la logica
   `isfield`/`getfield_or` e si lasciano i valori fissi. Avere entrambi
   confonde.
4. **Centralizzare le costanti fisiche** di §5: raggio ruota, rapporto di
   trasmissione, massa e `T_peak` dovrebbero vivere in un solo punto
   (idealmente `scenario.vehicle8`) ed essere lette da `design_speed_mpc`,
   `tune_speed_mpc`, `motor_map`, `demo` e `visualize_swarm_phase4`.
5. **Risolvere l'incoerenza `T_peak`** (60 vs 240 Nm) prima di fidarsi
   della taratura dell'MPC.
6. **Archiviare** `setup_vehicle_model.m` (legacy) e chiarire lo stato di
   `plot_followers_paths.m`.

Se vuoi, posso applicare i punti 1, 2 e 6 (le correzioni a rischio zero)
con backup `.bak`; i punti 3–5 invece richiedono una tua scelta sui
valori.
