# APPUNTI DRONE CHALLENGE
### Idee generali
**Target**: gara a Philadelphia
**Deadline**: 15 maggio 2022
**Obiettivo**: bisogna implementare una IA che permetta di pilotare un drone.
In fase di qualifica, il test verrà fatto su un simulatore (Flightmare).
La gara si svolgerà live a Philadelphia e in tale occasione il sw verrà fatto girare su un drone vero.
### Strumenti
+ **ROS**: è un meta-os che viene utilizzato per la programmazione di robot. Fornisce librerie in Python e tools, fornisce vari livelli di astrazione per lo sviluppo di software in robotica.
+ **FLIGHTMARE**: simulatore di volo per qudrirotori (droni volanti a 4 motori), basato su Unity con fisica realistica, fornisce le API per il training parallelo di droni
+ **COMPASS**: libreria per il training non supervisionato di IA
### Installazione
**!!!** Dopo l'installazione tramite il setup.bash del repository RICORDATI di aggiungere alle variabili d'ambiente della bash tramite `~/.bashrc `il path di flightmere, una cosa simile a: `FLIGHTMARE_PATH=/home/cam/Desktop/sim-ros/icra22_competition_ws/src/agile_flight/flightmare`
### Avvio
**!!!** Ricordarsi **sempre** di **disabilitare anaconda** (lanciando `conda deactivate`) e di lanciare `source devel/setup.bash` da `icra22_competition_ws` (Davvero, **SEMPRE**, anche quando apri una nuova bash per lanciare evaluation node)
dopodichè, da `./icra22_competition_ws/src/agile_flight` lanciamo:
`roslaunch envsim visionenv_sim.launch render:=True`
(per far partire tutte le schermate abbiamo dovuto installare `scipy`)
Inoltre abbiamo dovuto aggiornare, dentro a `.bashrc` il valore di `FLIGHTMARE_PATH` (era rimasto quello vecchio, di quando facevamo le prove su un'altra cartella)
poi, in un'altra bash, da `./icra22_competition_ws` lanciamo:
`source devel/setup.bash` (fa cambiare `$PYTHONPATH`)
`python evaluation_node.py`
In un'altra bash ancora abbiamo fatto partire la competizione da `./icra22_competition_ws/src/agile_flight/envtest/ros `lanciando: `python3 run_competition.py`
Per farlo andare, tuttavia, ci servivano torch, ruamel.yaml, stable_baselines3 e numpy versione 1.18 o successive
```
pip3 install torch
pip3 install ruamel.yaml
pip3 install numpy --upgrade
pip3 install stable_baselines3
```
Per far partire la soluzione abbiamo aperto un'ulteriore bash dove ci siamo posizionati su `/icra22_competition_ws` e abbiamo lanciato:
`rostopic pub /kingfisher/start_navigation std_msgs/Empty "{}" -1`
In questo modo il drone va dritto, senza schivare gli ostacoli (implementazione di base fornita dagli organizzatori)
Per implementare la nostra soluzione dobbiamo modificare, all'interno del file `agile_flight/envtest/ros/user_code.py` le due funzioni:
+ `compute_command_vision_based(state, img)` che si basa sulla grafica (più difficile)
+ `compute_command_state_based(state, obstacles, rl_policy=None)` che si basa sullo stato (consigliato)
### IDEE A LEZIONE
* **generalizzazione** dell'ambiente
* **randomizzazione** punto di partenza
* randomizzazione colore
* provare in scenari diversi (garage, città ecc)
* utilizzo di **compass** (da lavorare sulla rete finale MLP che prende in input ciò che viene fuori da compass)
* **scelta dei neuroni** utlimo livello (3 livelli di astrazione. Si pensava di partire dal più astratto fino ad arrivare poi a quello più a basso livello che dà più controllo e permettere performance migliori)
* Scelta del tipo di rete neurale che vogliamo usare (**RNN** o altro - partire da fully contected, pochi layer)
* Consigli sull'algoritmo di training: **DQN** (uno dei primi alg. di RL, problema: dà in output solo azioni discreti, quindi limita.) PPO(valore continuo, a differenza di DQN)
* rimozione di baseline e tentativo di far procedere lo step direttamente da visualenv chiamato trainenv
* studio della[ documentazione](https://flightmare.readthedocs.io/en/latest/) di **flightmare** (fatto dagli organizzatori)
* doc flightmare: funzione "step" sincrona. Consiglio: togliere il binding che fanno loro e provare a fare noi con step
* a ogni step abbiamo uil vettore observation che dobbiamo dare a in poasto a compass che ci dà in output le feature
* Scegliere bene alogoritmo di RL
* Possiamo ignorare il reward che ci danno solo e farlo da noi in PPO.
*
* Simulatore flight goggles basato su Unity.
* Cercare di randomizzare il più possibile, idealmente in ambienti disversi. (Ambientare episodi in scene garage, magazzino ecc)
* Modello(tipologia + funzione di attivazione + iperparametri) + algoritmo di training (SGD) + Funzione di loss(errore di predizione che ho calcolato ad es PPO)(La funzione di loss rappresenta il ponte di aggancio ad esempio da renforcement learning a deep learning, come il Q learning)
### Schema funzionamento wrapper pyybind11

### Compass download instruction
download azcopy from
https://docs.microsoft.com/en-us/azure/storage/common/storage-use-azcopy-v10
```
#activate file on wanted dir
./azcopy copy https://compassrelease.blob.core.windows.net/data/drone_datasets/ ./data/ --recursive
```
```
conda env create -f conda_env.yml //in the compass directory cloned from git
//if it does get stucked in solving enviroment,
//conda config --set channel_priority strict
// if it gets stucked again then
//conda env -n compass //create apposite conda enviroment for compass
// conda activate base
conda update conda
conda activate compass
conda install -c pythorch torchvision
conda install -c conda-forge tensorflow
conda install -c conda-forge termcolor
conda update -n base conda
conda update --all
conda update pytorch torchvision
export COMPASS_CKPT=<path to downloaded pretrained model>
//where path is path to file .pth.tar
//example:export COMPASS_CKPT=/home/mypc/compass/COMPASS/drone-navigation/data/drone_datasets/epoch1.pth.tar
python3 main_velocity.py --gpu 0 --output_dir ./output --arch compass --data_type video --clip_len 3 --train_ann_file_name custom_datagen_t80v20_train_ann.json --val_ann_file_name custom_datagen_t80v20_val_ann.json --lr 1e-4 --scheduler MultiStepLR --disable_random_resize_crop --dataset_dir ./data/drone_datasets --linear_prob --seed 1 --pretrained_encoder_path $COMPASS_CKPT
```
#### runnare compass senza nvidia
##inserire parametro map_location per runnare compass
torch.load(pretrained_path,map_location=torch.device('cpu'))['state_dict']